#ifndef SRC_NODE_CRYPTO_CLIENTHELLO_H_ #define SRC_NODE_CRYPTO_CLIENTHELLO_H_ #include "node.h" #include // size_t #include // nullptr namespace node { class ClientHelloParser { public: ClientHelloParser() : state_(kEnded), onhello_cb_(nullptr), onend_cb_(nullptr), cb_arg_(nullptr), session_size_(0), session_id_(nullptr), servername_size_(0), servername_(nullptr), ocsp_request_(0), tls_ticket_size_(0), tls_ticket_(nullptr) { Reset(); } class ClientHello { public: inline uint8_t session_size() const { return session_size_; } inline const uint8_t* session_id() const { return session_id_; } inline bool has_ticket() const { return has_ticket_; } inline uint8_t servername_size() const { return servername_size_; } inline const uint8_t* servername() const { return servername_; } inline int ocsp_request() const { return ocsp_request_; } private: uint8_t session_size_; const uint8_t* session_id_; bool has_ticket_; uint8_t servername_size_; const uint8_t* servername_; int ocsp_request_; friend class ClientHelloParser; }; typedef void (*OnHelloCb)(void* arg, const ClientHello& hello); typedef void (*OnEndCb)(void* arg); void Parse(const uint8_t* data, size_t avail); inline void Reset(); inline void Start(OnHelloCb onhello_cb, OnEndCb onend_cb, void* onend_arg); inline void End(); inline bool IsPaused() const; inline bool IsEnded() const; private: static const size_t kMaxTLSFrameLen = 16 * 1024 + 5; static const size_t kMaxSSLExFrameLen = 32 * 1024; static const uint8_t kServernameHostname = 0; static const uint8_t kStatusRequestOCSP = 1; static const size_t kMinStatusRequestSize = 5; enum ParseState { kWaiting, kTLSHeader, kPaused, kEnded }; enum FrameType { kChangeCipherSpec = 20, kAlert = 21, kHandshake = 22, kApplicationData = 23, kOther = 255 }; enum HandshakeType { kClientHello = 1 }; enum ExtensionType { kServerName = 0, kStatusRequest = 5, kTLSSessionTicket = 35 }; bool ParseRecordHeader(const uint8_t* data, size_t avail); void ParseHeader(const uint8_t* data, size_t avail); void ParseExtension(ExtensionType type, const uint8_t* data, size_t len); bool ParseTLSClientHello(const uint8_t* data, size_t avail); ParseState state_; OnHelloCb onhello_cb_; OnEndCb onend_cb_; void* cb_arg_; size_t frame_len_; size_t body_offset_; size_t extension_offset_; uint8_t session_size_; const uint8_t* session_id_; uint16_t servername_size_; const uint8_t* servername_; uint8_t ocsp_request_; uint16_t tls_ticket_size_; const uint8_t* tls_ticket_; }; } // namespace node #endif // SRC_NODE_CRYPTO_CLIENTHELLO_H_