181 lines
5.9 KiB
C
181 lines
5.9 KiB
C
#ifndef __HTTP2_H__
|
|
#define __HTTP2_H__
|
|
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
|
|
#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 |