| /* |
| Copyright: Boaz segev, 2016-2017 |
| License: MIT |
| |
| Feel free to copy, use and enjoy according to the license provided. |
| */ |
| #ifndef H_HTTP2_PARSER_H |
| /** |
| HTTP/2 Parser / Formatter (under development) |
| ========================= |
| |
| This parser / formatter is intended to be an implementation independent module |
| that can be used by other projects as well. |
| |
| This module takes the very limited responsibility of wrapping and unwrapping |
| HTTP/2 frames while maintaining the protocol's integrity. |
| |
| The module does NOT handle HPACK unpacking (performed by the seperate hpack |
| module), stream_id (request / response) management or anything else. |
| |
| The module only handles HTTP/2 frames and basic protocol integrity tasks. |
| |
| Data is written directly to a buffer provied by the parser. When a frame in |
| unwarpped, an appropriate callback is called. |
| |
| An example for creating a parser object: |
| |
| struct http2_callbacks_s http2_callbacks = |
| {.on_ping = my_on_ping_callback }; // fill in... |
| |
| http2_parser_pt = http2_parser_create(.callbacks = &http2_callbacks, |
| .udata = (void*)((intptr_t)fd)); |
| |
| An example for parsing data from a socket: |
| |
| int read2parser(http2_parser_pt p, int fd) { |
| while(1) { |
| void * buffer = http2_parser_buffer(p); |
| size_t len = http2_parser_capacity(p); |
| ssize_t incoming = read(fd, buffer, len); |
| if( incoming <= 0 ) // fix this |
| return -1; |
| http2_parser_review(p, incoming); |
| } |
| } |
| |
| Review the `struct http2_callbacks_s` for a list of possible callbacks. |
| */ |
| #define H_HTTP2_PARSER_H |
| #include <stdio.h> |
| #include <stdlib.h> |
| |
| /** possible HTTP/2 error values. */ |
| enum http2_err_enum { |
| H2ERR_OK = 0, |
| H2ERR_NO_ERROR = 0, |
| H2ERR_PROTOCOL_ERROR = 0x1, |
| H2ERR_INTERNAL_ERROR = 0x2, |
| H2ERR_FLOW_CONTROL_ERROR = 0x3, |
| H2ERR_SETTINGS_TIMEOUT = 0x4, |
| H2ERR_STREAM_CLOSED = 0x5, |
| H2ERR_FRAME_SIZE_ERROR = 0x6, |
| H2ERR_REFUSED_STREAM = 0x7, |
| H2ERR_REFUSED_STREAM_PRE_APP = 0x8, |
| H2ERR_COMPRESSION_ERROR = 0x9, |
| H2ERR_CONNECT_ERROR = 0xa, |
| H2ERR_ENHANCE_YOUR_CALM = 0xb, |
| H2ERR_INADEQUATE_SECURITY = 0xc, |
| H2ERR_HTTP_1_1_REQUIRED = 0xd |
| }; |
| |
| /** possible HTTP/2 SETTINGS frame values. */ |
| enum http2_setting_enum { |
| SETTINGS_HEADER_TABLE_SIZE = 0x1, |
| SETTINGS_ENABLE_PUSH = 0x2, |
| SETTINGS_MAX_CONCURRENT_STREAMS = 0x3, |
| SETTINGS_INITIAL_WINDOW_SIZE = 0x4, |
| SETTINGS_MAX_FRAME_SIZE = 0x5, |
| SETTINGS_MAX_HEADER_LIST_SIZE = 0x6, |
| }; |
| |
| /** an opaque parser pointer type for the HTTP 2 parser. */ |
| typedef struct http2_parser_s *http2_parser_pt; |
| |
| /** Callbacks used for handling HTTP/2 data. */ |
| struct http2_callbacks_s { |
| /* a callback for data arriving (the message body or part of it). */ |
| void (*on_body)(http2_parser_pt p, void *udata, uint32_t stream_id, |
| void *body, size_t length); |
| |
| /* a callback indicating that the specified `stream_id` can be processed. */ |
| void (*on_finalized)(http2_parser_pt p, void *udata, uint32_t stream_id); |
| |
| /* a callback indicating a request to update a stream's priority. */ |
| void (*on_priority)(http2_parser_pt p, void *udata, uint32_t stream_id, |
| uint32_t dependance_stream_id, |
| uint8_t exclusive_dependancy, uint8_t weight); |
| |
| /* a callback a request to reset an existing stream (disregard). */ |
| void (*on_reset_stream)(http2_parser_pt p, void *udata, uint32_t stream_id, |
| uint32_t error_code); |
| |
| /* a callback indicating a settings update request or acknowledgment. */ |
| void (*on_settings)(http2_parser_pt p, void *udata, uint16_t identifier, |
| uint32_t value, uint8_t is_ack); |
| |
| /* a callback indicating an HTTP/2 ping or pong event. */ |
| void (*on_ping)(http2_parser_pt p, void *udata, uint64_t payload, |
| uint8_t is_ack); |
| }; |
| |
| /** Arguments for the `http2_parser_create` function */ |
| struct http2_parser_create_args_s { |
| /* a link to a callback structure. missing callbacks default to no_op. */ |
| struct http2_callbacks_s *callbacks; |
| /* the maximum frame size will be pre-allocated as the HTTP/2 buffer. */ |
| uint32_t max_frame_size; |
| /* a user opaque pointer, passed along to any callbacks. */ |
| void *udata; |
| }; |
| |
| /** creates an HTTP/2 parser */ |
| http2_parser_pt http2_parser_create(struct http2_parser_create_args_s args); |
| |
| /** a macro for named arguments semantics. */ |
| #define http2_parser_create(...) \ |
| http2_parser_create((struct http2_parser_create_args_s){__VA_ARGS__}) |
| |
| /** destroy an HTTP/2 parser (uses reference counting). */ |
| void http2_parser_destroy(http2_parser_pt); |
| |
| /** |
| * Gets the current position in the HTTP/2 parser's buffer. |
| * |
| * This changes with every read according to the amount of data the parser |
| * requires to complete it's next step. |
| */ |
| void *http2_parser_buffer(http2_parser_pt); |
| |
| /** |
| * Gets the current capacity for the HTTP/2 parser's buffer. |
| * |
| * This changes with every read according to the amount of data the parser |
| * requires to complete it's next step. |
| */ |
| size_t http2_parser_capacity(http2_parser_pt); |
| |
| /** |
| * Signals the parser to process incominng data `length` long. |
| * |
| * This updates the `http2_parser_buffer` and `http2_parser_capacity` values. |
| * |
| * Returns 0 on success. If an error occured (i.e., too much data was supplied |
| * or a protocol error), returns -1. |
| */ |
| enum http2_err_enum http2_parser_review(http2_parser_pt, size_t length); |
| |
| #endif |