#ifndef __HTTP2_H__ #define __HTTP2_H__ #include #include #define HTTP2_SETTINGS_MAX_PARAM_ID 1024 #define HTTP2_MAX_FRAME_SIZE 16777215 #define HTTP2_INITIAL_WINDOW_SIZE 65535 #define HTTP2_MAX_CONCURRENT_STREAMS 100 #define HTTP2_DEFAULT_HEADER_TABLE_SIZE 4096 #define HTTP2_FRAME_FLAG_END_STREAM 0x1 #define HTTP2_FRAME_FLAG_END_HEADERS 0x4 #define HTTP2_FRAME_FLAG_PADDED 0x8 #define HTTP2_FRAME_FLAG_PRIORITY 0x20 #define HTTP2_FRAME_FLAG_ACK 0x1 typedef enum { HTTP2_FRAME_DATA = 0x0, HTTP2_FRAME_HEADERS = 0x1, HTTP2_FRAME_PRIORITY = 0x2, HTTP2_FRAME_RST_STREAM = 0x3, HTTP2_FRAME_SETTINGS = 0x4, HTTP2_FRAME_PUSH_PROMISE = 0x5, HTTP2_FRAME_PING = 0x6, HTTP2_FRAME_GOAWAY = 0x7, HTTP2_FRAME_WINDOW_UPDATE = 0x8, HTTP2_FRAME_CONTINUATION = 0x9 } HTTP2_Frame_Type; typedef enum { HTTP2_ERROR_NO_ERROR = 0x0, HTTP2_ERROR_PROTOCOL_ERROR = 0x1, HTTP2_ERROR_INTERNAL_ERROR = 0x2, HTTP2_ERROR_FLOW_CONTROL_ERROR = 0x3, HTTP2_ERROR_SETTINGS_TIMEOUT = 0x4, HTTP2_ERROR_STREAM_CLOSED = 0x5, HTTP2_ERROR_FRAME_SIZE_ERROR = 0x6, HTTP2_ERROR_REFUSED_STREAM = 0x7, HTTP2_ERROR_CANCEL = 0x8, HTTP2_ERROR_COMPRESSION_ERROR = 0x9, HTTP2_ERROR_CONNECT_ERROR = 0xa, HTTP2_ERROR_ENHANCE_YOUR_CLAIM = 0xb, HTTP2_ERROR_INADEQUATE_SECURITY = 0xc, HTTP2_ERROR_HTTP_1_1_REQUIRED = 0xd } HTTP2_Error_Code; typedef enum { HTTP2_STREAM_STATE_IDLE = 0, HTTP2_STREAM_STATE_OPEN, HTTP2_STREAM_STATE_HALF_CLOSED_LOCAL, HTTP2_STREAM_STATE_HALF_CLOSED_REMOTE, HTTP2_STREAM_STATE_RESERVED_LOCAL, HTTP2_STREAM_STATE_RESERVED_REMOTE, HTTP2_STREAM_STATE_CLOSED } HTTP2_Stream_State; typedef enum { HTTP2_SETTINGS_HEADER_TABLE_SIZE = 0x1, HTTP2_SETTINGS_ENABLE_PUSH = 0x2, HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS = 0x3, HTTP2_SETTINGS_INITIAL_WINDOW_SIZE = 0x4, HTTP2_SETTINGS_MAX_FRAME_SIZE = 0x5, HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE = 0x6 } HTTP2_Settings_Id; typedef struct { uint8_t *data; size_t size; size_t capacity; } HTTP2_Buffer; typedef struct { uint32_t stream_id; HTTP2_Stream_State state; uint8_t priority; int endpoint_closed; } HTTP2_Stream; typedef struct { HTTP2_Stream streams[HTTP2_MAX_CONCURRENT_STREAMS]; size_t stream_count; uint32_t last_stream_id; uint8_t priority; } HTTP2_Streams; typedef struct { uint8_t *data; size_t len; size_t cap; } HTTP2_Dynamic_Table; typedef struct { HTTP2_Dynamic_Table dynamic_table; uint32_t max_size; uint32_t current_size; } HTTP2_Encoder_Context; typedef struct { HTTP2_Dynamic_Table dynamic_table; uint32_t max_size; uint32_t current_size; int mirror; } HTTP2_Decoder_Context; typedef struct { uint32_t stream_id; uint8_t exclusive; uint32_t stream_dependency; uint8_t weight; } HTTP2_Priority_Spec; typedef struct { HTTP2_Frame_Type type; uint8_t flags; uint32_t stream_id; uint32_t length; uint8_t payload[HTTP2_MAX_FRAME_SIZE]; } HTTP2_Frame; typedef struct { int sockfd; HTTP2_Buffer read_buffer; HTTP2_Buffer write_buffer; HTTP2_Streams streams; uint32_t local_settings[HTTP2_SETTINGS_MAX_PARAM_ID]; uint32_t remote_settings[HTTP2_SETTINGS_MAX_PARAM_ID]; uint32_t last_settings_stream_id; uint32_t last_stream_id; int is_server; int hpack_initialized; HTTP2_Encoder_Context encoder; HTTP2_Decoder_Context decoder; uint32_t next_stream_id; uint32_t remote_concurrent_streams; uint32_t local_window_size; uint32_t remote_window_size; } HTTP2_Connection; int http2_init(void); HTTP2_Connection *http2_connection_new(void); int http2_connection_init(HTTP2_Connection *conn, int sockfd, int is_server); void http2_connection_free(HTTP2_Connection *conn); void http2_connection_close(HTTP2_Connection *conn); int http2_send_preface(HTTP2_Connection *conn); int http2_recv_preface(HTTP2_Connection *conn); int http2_encode_frame(HTTP2_Frame *frame, HTTP2_Frame_Type type, uint32_t stream_id, uint8_t flags, const uint8_t *payload, size_t payload_len); int http2_decode_frame(HTTP2_Frame *frame, const uint8_t *data, size_t len); int http2_recv_frame(HTTP2_Connection *conn, HTTP2_Frame *frame); int http2_send_frame(HTTP2_Connection *conn, HTTP2_Frame *frame); int http2_encode_settings(HTTP2_Connection *conn, uint32_t *settings, size_t count); int http2_decode_settings(const HTTP2_Frame *frame, uint32_t *settings, size_t *count); int http2_encode_priority(HTTP2_Priority_Spec *prio, uint8_t *out, size_t *out_len); int http2_decode_priority(const uint8_t *data, size_t len, HTTP2_Priority_Spec *prio); int http2_hpack_encode_init(HTTP2_Encoder_Context *ctx, uint32_t max_size); int http2_hpack_decode_init(HTTP2_Decoder_Context *ctx, uint32_t max_size); void http2_hpack_encode_free(HTTP2_Encoder_Context *ctx); void http2_hpack_decode_free(HTTP2_Decoder_Context *ctx); int http2_hpack_encode(HTTP2_Encoder_Context *ctx, const char **headers, size_t headers_len, uint8_t *out, size_t *out_len); int http2_hpack_decode(HTTP2_Decoder_Context *ctx, const uint8_t *data, size_t len, char **headers, size_t *headers_len); int http2_encode_headers(HTTP2_Connection *conn, const char **headers, size_t headers_len, uint8_t *out, size_t *out_len); int http2_decode_headers(HTTP2_Connection *conn, const uint8_t *data, size_t len, char **headers, size_t *headers_len); int http2_encode_priority_frame(uint32_t stream_id, HTTP2_Priority_Spec *prio, uint8_t *out, size_t *out_len); int http2_encode_rst_stream(uint32_t stream_id, HTTP2_Error_Code error, uint8_t *out, size_t *out_len); int http2_encode_ping(HTTP2_Connection *conn, uint8_t *data, uint8_t flags, uint8_t *out, size_t *out_len); int http2_encode_goaway(uint32_t last_stream_id, HTTP2_Error_Code error, const uint8_t *additional_debug, size_t debug_len, uint8_t *out, size_t *out_len); int http2_encode_window_update(uint32_t stream_id, uint32_t increment, uint8_t *out, size_t *out_len); int http2_parse_frame_type(const char *name); const char *http2_frame_type_to_str(HTTP2_Frame_Type type); const char *http2_error_to_str(HTTP2_Error_Code error); #endif