cMCP/http2.h

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