| /* ==================================================================== |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * ==================================================================== |
| */ |
| |
| #ifndef SERF_PROTOCOL_HTTP2_PRIVATE_H |
| #define SERF_PROTOCOL_HTTP2_PRIVATE_H |
| |
| #include "serf.h" |
| #include "serf_private.h" |
| |
| #ifdef _DEBUG |
| #include <assert.h> |
| #define SERF_H2_assert(x) assert(x) |
| #else |
| #define SERF_H2_assert(x) ((void)0) |
| #endif |
| |
| #define SERF_LOGHTTP2 \ |
| SERF_LOGCOMP_PROTOCOL, (__FILE__ ":" APR_STRINGIFY(__LINE__)) |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| /* ********** HTTP2 Frame types ********** */ |
| |
| /* The standard maximum framesize. Always supported */ |
| #define HTTP2_DEFAULT_MAX_FRAMESIZE 16384 |
| /* The default stream and connection window size before updates */ |
| #define HTTP2_DEFAULT_WINDOW_SIZE 65535 |
| #define HTTP2_DEFAULT_MAX_CONCURRENT 0xFFFFFFFF |
| #define HTTP2_DEFAULT_HPACK_TABLE_SIZE 4096 |
| |
| #define HTTP2_PRIORITY_DATA_SIZE 5 |
| #define HTTP2_RST_DATA_SIZE 4 |
| #define HTTP2_PROMISE_DATA_SIZE 4 |
| #define HTTP2_PING_DATA_SIZE 8 |
| #define HTTP2_GOWAWAY_DATA_SIZE 8 |
| #define HTTP2_WINDOW_UPDATE_DATA_SIZE 4 |
| |
| #define HTTP2_SETTING_SIZE 6 |
| |
| #define HTTP2_WINDOW_MAX_ALLOWED 0x7FFFFFFF |
| |
| /* Frame type is an 8 bit unsigned integer */ |
| |
| /* http://tools.ietf.org/html/rfc7540#section-11.2 */ |
| #define HTTP2_FRAME_TYPE_DATA 0x00 |
| #define HTTP2_FRAME_TYPE_HEADERS 0x01 |
| #define HTTP2_FRAME_TYPE_PRIORITY 0x02 |
| #define HTTP2_FRAME_TYPE_RST_STREAM 0x03 |
| #define HTTP2_FRAME_TYPE_SETTINGS 0x04 |
| #define HTTP2_FRAME_TYPE_PUSH_PROMISE 0x05 |
| #define HTTP2_FRAME_TYPE_PING 0x06 |
| #define HTTP2_FRAME_TYPE_GOAWAY 0x07 |
| #define HTTP2_FRAME_TYPE_WINDOW_UPDATE 0x08 |
| #define HTTP2_FRAME_TYPE_CONTINUATION 0x09 |
| /* https://httpwg.github.io/http-extensions/alt-svc.html |
| documents that frame 0x0A will most likely be assigned |
| to ALT-SVC */ |
| |
| /* ********** HTTP2 Flags ********** */ |
| |
| |
| /* Defined on SETTINGS and PING */ |
| #define HTTP2_FLAG_ACK 0x01 |
| /* Defined on DATA and HEADERS */ |
| #define HTTP2_FLAG_END_STREAM 0x01 |
| /* Defined on HEADERS and CONTINUATION */ |
| #define HTTP2_FLAG_END_HEADERS 0x04 |
| /* Defined on DATA and HEADERS */ |
| #define HTTP2_FLAG_PADDED 0x08 |
| /* Defined on HEADERS */ |
| #define HTTP2_FLAG_PRIORITY 0x20 |
| |
| |
| /* ********** HTTP2 Settings ********** */ |
| |
| /* Settings are 16 bit unsigned integers*/ |
| #define HTTP2_SETTING_HEADER_TABLE_SIZE 0x0001 /* default: 4096 */ |
| #define HTTP2_SETTING_ENABLE_PUSH 0x0002 /* default: 1 */ |
| #define HTTP2_SETTING_MAX_CONCURRENT_STREAMS 0x0003 /* default: (infinite) */ |
| #define HTTP2_SETTING_INITIAL_WINDOW_SIZE 0x0004 /* default: 65535 */ |
| #define HTTP2_SETTING_MAX_FRAME_SIZE 0x0005 /* default: 16384 */ |
| #define HTTP2_SETTING_MAX_HEADER_LIST_SIZE 0x0006 /* default: (infinite) */ |
| |
| /* https://tools.ietf.org/html/rfc7540#section-3.5 */ |
| #define HTTP2_CONNECTION_PREFIX "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" |
| |
| |
| /* Maximum size for a headerline in HPACK */ |
| #define HTTP2_MAX_HEADER_ENTRYSIZE 0x20000 /* 128 KByte */ |
| |
| |
| /* ------------------------------------- */ |
| typedef struct serf_http2_protocol_t serf_http2_protocol_t; |
| typedef struct serf_http2_stream_data_t serf_http2_stream_data_t; |
| |
| typedef struct serf_http2_stream_t |
| { |
| struct serf_http2_protocol_t *h2; |
| serf_bucket_alloc_t *alloc; |
| |
| /* Opaque implementation details */ |
| serf_http2_stream_data_t *data; |
| |
| /* Linked list of currently existing streams */ |
| struct serf_http2_stream_t *next; |
| struct serf_http2_stream_t *prev; |
| |
| apr_uint32_t lr_window; /* local->remote */ |
| apr_uint32_t rl_window; /* remote->local */ |
| |
| apr_uint32_t rl_window_upd_below; |
| apr_uint32_t rl_window_upd_to; |
| |
| /* -1 until allocated. Odd is client side initiated, even server side */ |
| apr_int32_t streamid; |
| |
| enum |
| { |
| H2S_INIT = 0, |
| H2S_IDLE, |
| H2S_RESERVED_REMOTE, |
| H2S_RESERVED_LOCAL, |
| H2S_OPEN, |
| H2S_HALFCLOSED_REMOTE, |
| H2S_HALFCLOSED_LOCAL, |
| H2S_CLOSED |
| } status; |
| |
| /* Used while receiving a promise stream */ |
| struct serf_http2_stream_t *new_reserved_stream; |
| |
| /* TODO: Priority, etc. */ |
| struct serf_http2_stream_t *next_writable, *prev_writable; |
| } serf_http2_stream_t; |
| |
| typedef apr_status_t (* serf_http2_processor_t)(void *baton, |
| serf_http2_protocol_t *h2, |
| serf_bucket_t *body); |
| |
| /* Enques an http2 frame for output */ |
| apr_status_t |
| serf_http2__enqueue_frame(serf_http2_protocol_t *h2, |
| serf_bucket_t *frame, |
| bool flush); |
| |
| /* Creates a new stream */ |
| serf_http2_stream_t * |
| serf_http2__stream_create(serf_http2_protocol_t *h2, |
| apr_int32_t streamid, |
| apr_uint32_t lr_window, |
| apr_uint32_t rl_window, |
| serf_bucket_alloc_t *alloc); |
| |
| |
| apr_status_t |
| serf_http2__enqueue_stream_reset(serf_http2_protocol_t *h2, |
| apr_int32_t streamid, |
| apr_status_t reason); |
| |
| /* Allocates a new stream id for a stream. |
| BATON is a serf_http2_stream_t * instance. |
| |
| Passed to serf__bucket_http2_frame_create when writing for |
| a stream. |
| */ |
| void |
| serf_http2__allocate_stream_id(void *baton, |
| apr_int32_t *streamid); |
| |
| void |
| serf_http2__stream_cleanup(serf_http2_stream_t *stream); |
| |
| void |
| serf_http2__stream_pre_cleanup(serf_http2_stream_t *stream); |
| |
| |
| serf_http2_stream_t * |
| serf_http2__stream_get(serf_http2_protocol_t *h2, |
| apr_int32_t streamid, |
| bool create_for_remote, |
| bool move_first); |
| |
| /* Sets up STREAM to handle the next request from CONN */ |
| apr_status_t |
| serf_http2__stream_setup_next_request(serf_http2_stream_t *stream, |
| serf_connection_t *conn, |
| apr_size_t max_payload_size, |
| serf_hpack_table_t *hpack_tbl); |
| |
| apr_status_t |
| serf_http2__setup_incoming_request(serf_incoming_request_t **in_request, |
| serf_incoming_request_setup_t *req_setup, |
| void **req_setup_baton, |
| serf_http2_protocol_t *h2); |
| |
| /* Gets current l->r max payload size */ |
| apr_size_t |
| serf_http2__max_payload_size(serf_http2_protocol_t *h2); |
| |
| apr_size_t serf_http2__alloc_window(serf_http2_protocol_t *h2, |
| serf_http2_stream_t *stream, |
| apr_size_t requested); |
| |
| void serf_http2__return_window(serf_http2_protocol_t *h2, |
| serf_http2_stream_t *stream, |
| apr_size_t returned); |
| |
| void serf_http2__ensure_writable(serf_http2_stream_t *stream); |
| |
| apr_status_t |
| serf_http2__stream_reset(serf_http2_stream_t *stream, |
| apr_status_t reason, |
| bool local_reset); |
| |
| void serf_http2__stream_cancel_request(serf_http2_stream_t *stream, |
| serf_request_t *rq, |
| apr_status_t reason); |
| |
| void serf_http2__stream_prioritize_request(serf_http2_stream_t *stream, |
| serf_request_t *rq, bool exclusive); |
| |
| serf_bucket_t * |
| serf_http2__stream_handle_hpack(serf_http2_stream_t *stream, |
| serf_bucket_t *bucket, |
| unsigned char frametype, |
| bool end_stream, |
| apr_size_t max_entry_size, |
| serf_hpack_table_t *hpack_tbl, |
| serf_config_t *config, |
| serf_bucket_alloc_t *allocator); |
| |
| serf_bucket_t * |
| serf_http2__stream_handle_data(serf_http2_stream_t *stream, |
| serf_bucket_t *bucket, |
| unsigned char frametype, |
| bool end_stream, |
| serf_config_t *config, |
| serf_bucket_alloc_t *allocator); |
| |
| apr_status_t |
| serf_http2__stream_processor(void *baton, |
| serf_http2_protocol_t *h2, |
| serf_bucket_t *bucket); |
| |
| apr_status_t |
| serf_http2__stream_write_data(serf_http2_stream_t *stream); |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif |