28#include <nghttp2/nghttp2.h>
41 if (!(
n & 0xffff0000u)) {
45 if (!(
n & 0xff000000u)) {
49 if (!(
n & 0xf0000000u)) {
53 if (!(
n & 0xc0000000u)) {
57 if (!(
n & 0x80000000u)) {
65 const char *
data,
size_t datalen)
71 const char *
sep = (
i &&
i % 16 == 0)?
"\n" :
" ";
73 "%2x%s", ((
unsigned int)
data[
i]&0xff),
sep);
84 for (
i = 0;
i <
len; ++
i) {
86 if (
s[
i] >=
'a' &&
s[
i] <=
'z') {
92 else if (
s[
i] ==
'-') {
100#define N6 (unsigned int)-1
104 N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
105 N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
106 N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6, 62,
N6,
N6,
107 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
N6,
N6,
N6,
N6,
N6,
N6,
108 N6, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
109 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
N6,
N6,
N6,
N6, 63,
110 N6, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
111 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
N6,
N6,
N6,
N6,
N6,
112 N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
113 N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
114 N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
115 N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
116 N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
117 N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
118 N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
119 N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6,
N6
122 'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
123 'K',
'L',
'M',
'N',
'O',
'P',
'Q',
'R',
'S',
'T',
124 'U',
'V',
'W',
'X',
'Y',
'Z',
'a',
'b',
'c',
'd',
125 'e',
'f',
'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n',
126 'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
127 'y',
'z',
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
128 '8',
'9',
'-',
'_',
' ',
' ',
' ',
' ',
' ',
' ',
131#define BASE64URL_CHAR(x) BASE64URL_CHARS[ (unsigned int)(x) & 0x3fu ]
136 const unsigned char *
e = (
const unsigned char *)encoded;
137 const unsigned char *
p =
e;
151 for (;
i <
mlen;
i += 4) {
156 *
d++ = (
unsigned char)(
n >> 16);
157 *
d++ = (
unsigned char)(
n >> 8 & 0xffu);
158 *
d++ = (
unsigned char)(
n & 0xffu);
165 *
d++ = (
unsigned char)(
n >> 16);
172 *
d++ = (
unsigned char)(
n >> 16);
173 *
d++ = (
unsigned char)(
n >> 8 & 0xffu);
187 const unsigned char *
udata = (
const unsigned char*)
data;
191 for (
i = 0;
i <
len-2;
i+= 3) {
200 if (
i == (
len - 1)) {
222 return (
unsigned int)(*((
int*)
key));
280 int id = *((
int*)((
char *)
val + ih->
ioff));
300 if (
ctx->len <
ctx->max) {
317 for (
i = 0;
i <
ctx.len; ++
i) {
345 return q->
nelts == 0;
418 while (
i != q->
head) {
451 for (
i = 0;
i <
max; ++
i) {
593 fifo->capacity = capacity;
636 while (
fifo->count == 0) {
658 else if (
fifo->count ==
fifo->capacity) {
660 while (
fifo->count ==
fifo->capacity) {
677 if (
fifo->count == 1) {
794 if (
fifo->count == 0) {
797 else if (
i ==
fifo->out) {
804 else if (((
i + 1) %
fifo->capacity) ==
fifo->in) {
811 else if (
i >
fifo->out) {
814 (
i -
fifo->out) *
sizeof(
void*));
825 (
fifo->in -
i - 1) *
sizeof(
void*));
866 return (
fifo->head +
n) %
fifo->capacity;
884 for (
i = 0;
i <
fifo->count; ++
i) {
923 fifo->capacity = capacity;
961 while (
fifo->count == 0) {
983 else if (
fifo->count ==
fifo->capacity) {
985 while (
fifo->count ==
fifo->capacity) {
1000 if (
fifo->count == 1) {
1037 if (
fifo->count > 0) {
1039 if (
fifo->count+1 ==
fifo->capacity) {
1074 switch (fn(
id,
ctx)) {
1101 if (
fifo->aborted) {
1106 for (
i = 0;
i <
fifo->count; ++
i) {
1154 ctx->bytes +=
ctx->pair_extra;
1163 ctx.pair_extra = pair_extra;
1285 -1 : (
long)
b->length));
1291 const char *
tag,
const char *
sep,
1295 const char *
sp =
"";
1377 total +=
sizeof(*b);
1378 if (
b->length > 0) {
1396 (*((
size_t*)
ctx))++;
1404 if (
p == token && *
p ==
':') {
1418 while(
nv->valuelen && (
nv->value[0] ==
' ' ||
nv->value[0] ==
'\t')) {
1419 nv->value++;
nv->valuelen--;
1421 while(
nv->valuelen && (
nv->value[
nv->valuelen-1] ==
' '
1422 ||
nv->value[
nv->valuelen-1] ==
'\t')) {
1442 "h2_request: head field '%s: %s' has invalid char %s",
1449 "h2_request: head field '%s: %s' has invalid char %s",
1456 nv->namelen = strlen(
key);
1481 ctx.unsafe = unsafe;
1508#if AP_HAS_RESPONSE_BUCKETS
1526 const char *
keys[] = {
1554 const char *
keys[] = {
1570 const char *
keys[] = {
1601#define H2_DEF_LITERAL(n) { (n), (sizeof(n)-1) }
1602#define H2_LIT_ARGS(a) (a),H2_ALEN(a)
1652 if (
lit->len ==
nv->namelen
1665 nv.namelen = strlen(
name);
1680 nv.namelen = strlen(
name);
1690 nv.namelen = strlen(
name);
1708 else if (
nv->namelen ==
sizeof(
"cookie")-1
1727 else if (
nv->namelen ==
sizeof(
"host")-1
1772 size_t s_len =
sizeof(scratch)/
sizeof(scratch[0]);
1774 switch (
frame->hd.type) {
1777 "DATA[length=%d, flags=%d, stream=%d, padlen=%d]",
1779 frame->hd.stream_id, (
int)
frame->data.padlen);
1783 "HEADERS[length=%d, hend=%d, stream=%d, eos=%d]",
1784 (
int)
frame->hd.length,
1786 frame->hd.stream_id,
1791 "PRIORITY[length=%d, flags=%d, stream=%d]",
1792 (
int)
frame->hd.length,
1797 "RST_STREAM[length=%d, flags=%d, stream=%d]",
1798 (
int)
frame->hd.length,
1804 "SETTINGS[ack=1, stream=%d]",
1805 frame->hd.stream_id);
1808 "SETTINGS[length=%d, stream=%d]",
1813 "PUSH_PROMISE[length=%d, hend=%d, stream=%d]",
1814 (
int)
frame->hd.length,
1816 frame->hd.stream_id);
1820 "PING[length=%d, ack=%d, stream=%d]",
1821 (
int)
frame->hd.length,
1823 frame->hd.stream_id);
1830 scratch[
len] =
'\0';
1832 "last_stream=%d]",
frame->goaway.error_code,
1833 scratch,
frame->goaway.last_stream_id);
1837 "WINDOW_UPDATE[stream=%d, incr=%d]",
1838 frame->hd.stream_id,
1839 frame->window_update.window_size_increment);
1843 "type=%d[length=%d, flags=%d, stream=%d]",
1900 if (
nr !=
sizeof(
rb))
1915#if AP_HAS_RESPONSE_BUCKETS
const char apr_size_t len
apr_size_t const unsigned char unsigned int unsigned int d
APR Condition Variable Routines.
APR Thread Mutex Routines.
#define APR_BUCKET_REMOVE(e)
#define APR_BUCKET_IS_HEAP(e)
#define APR_BUCKET_IS_METADATA(e)
#define APR_BRIGADE_INSERT_TAIL(b, e)
#define apr_bucket_split(e, point)
apr_file_t apr_off_t start
#define APR_BUCKET_NEXT(e)
#define APR_BRIGADE_EMPTY(b)
#define APR_BRIGADE_SENTINEL(b)
#define apr_bucket_delete(e)
#define APR_BUCKET_IS_EOS(e)
apr_brigade_flush void * ctx
#define apr_bucket_copy(e, c)
#define APR_BRIGADE_FIRST(b)
#define APR_BUCKET_IS_POOL(e)
#define apr_bucket_read(e, str, len, block)
const char apr_ssize_t slen
const char apr_int32_t apr_uint32_t * nv
const char apr_hash_t ** values
const char * ap_scan_http_token(const char *ptr)
int ap_cstr_casecmp(const char *s1, const char *s2)
#define AP_DEBUG_ASSERT(exp)
int ap_find_token(apr_pool_t *p, const char *line, const char *tok)
const char * ap_scan_http_field_content(const char *ptr)
apr_uint32_t apr_uint32_t cmp
const char int apr_pool_t * pool
apr_seek_where_t apr_off_t * offset
const char apr_uint32_t * id
#define apr_pcalloc(p, size)
apr_int64_t apr_interval_time_t
apr_size_t apr_size_t max
#define H2_HDR_CONFORMANCE_UNSAFE
#define H2_HDR_CONFORMANCE
static apr_status_t fifo_pull(h2_fifo *fifo, void **pelem, int block)
void h2_iq_sort(h2_iqueue *q, h2_iq_cmp *cmp, void *ctx)
static const char * inv_field_value_chr(const char *token)
void h2_ihash_clear(h2_ihash_t *ih)
size_t h2_util_hex_dump(char *buffer, size_t maxlen, const char *data, size_t datalen)
static literal IgnoredResponseTrailers[]
void h2_ihash_add(h2_ihash_t *ih, void *val)
static void fit_bucket_into(apr_bucket *b, apr_off_t *plen)
static apr_status_t ififo_push(h2_ififo *fifo, int id, int block)
static apr_status_t ififo_peek(h2_ififo *fifo, h2_ififo_peek_fn *fn, void *ctx, int block)
apr_status_t h2_append_brigade(apr_bucket_brigade *to, apr_bucket_brigade *from, apr_off_t *plen, int *peos, h2_bucket_gate *should_append)
apr_status_t h2_util_wait_on_pipe(apr_file_t *pipe)
apr_status_t h2_fifo_peek(h2_fifo *fifo, h2_fifo_peek_fn *fn, void *ctx)
int h2_iq_add(h2_iqueue *q, int sid, h2_iq_cmp *cmp, void *ctx)
apr_status_t h2_ififo_try_peek(h2_ififo *fifo, h2_ififo_peek_fn *fn, void *ctx)
h2_iqueue * h2_iq_create(apr_pool_t *pool, int capacity)
apr_status_t h2_brigade_copy_length(apr_bucket_brigade *dest, apr_bucket_brigade *src, apr_off_t length)
apr_status_t h2_res_create_ngheader(h2_ngheader **ph, apr_pool_t *p, h2_headers *headers)
static apr_status_t ififo_pull(h2_ififo *fifo, int *pi, int block)
static literal IgnoredRequestTrailers[]
int h2_ignore_req_trailer(const char *name, size_t len)
static int inth_index(h2_ififo *fifo, int n)
apr_status_t h2_ififo_term(h2_ififo *fifo)
void h2_util_drain_pipe(apr_file_t *pipe)
static apr_status_t fifo_push_int(h2_fifo *fifo, void *elem, int block)
static int collect_iter(void *x, void *val)
#define H2_DEF_LITERAL(n)
static const unsigned int BASE64URL_UINT6[]
#define BASE64URL_CHAR(x)
int h2_util_ignore_resp_header(const char *name)
void h2_ihash_remove_val(h2_ihash_t *ih, void *val)
size_t h2_iq_mshift(h2_iqueue *q, int *pint, size_t max)
apr_status_t h2_fifo_try_pull(h2_fifo *fifo, void **pelem)
void h2_ihash_remove(h2_ihash_t *ih, int id)
static int add_header(ngh_ctx *ctx, const char *key, const char *value)
static int iq_bubble_down(h2_iqueue *q, int i, int bottom, h2_iq_cmp *cmp, void *ctx)
int h2_iq_contains(h2_iqueue *q, int sid)
static literal IgnoredRequestHeaders[]
apr_status_t h2_ififo_try_push(h2_ififo *fifo, int id)
h2_ihash_t * h2_ihash_create(apr_pool_t *pool, size_t offset_of_int)
apr_status_t h2_fifo_create(h2_fifo **pfifo, apr_pool_t *pool, int capacity)
int h2_iq_empty(h2_iqueue *q)
static apr_status_t fifo_destroy(void *data)
static apr_status_t fifo_peek(h2_fifo *fifo, h2_fifo_peek_fn *fn, void *ctx, int block)
apr_status_t h2_ififo_peek(h2_ififo *fifo, h2_ififo_peek_fn *fn, void *ctx)
const char * h2_util_base64url_encode(const char *data, apr_size_t dlen, apr_pool_t *pool)
static apr_status_t ififo_remove(h2_ififo *fifo, int id)
int h2_iq_append(h2_iqueue *q, int sid)
static int count_bytes(void *x, const char *key, const char *value)
apr_size_t h2_util_bucket_print(char *buffer, apr_size_t bmax, apr_bucket *b, const char *sep)
apr_status_t h2_fifo_set_create(h2_fifo **pfifo, apr_pool_t *pool, int capacity)
apr_status_t h2_brigade_concat_length(apr_bucket_brigade *dest, apr_bucket_brigade *src, apr_off_t length)
apr_status_t h2_res_create_ngtrailer(h2_ngheader **ph, apr_pool_t *p, h2_headers *headers)
static apr_status_t fifo_push(h2_fifo *fifo, void *elem, int block)
static int count_header(void *ctx, const char *key, const char *value)
void h2_util_camel_case_header(char *s, size_t len)
static apr_status_t check_not_empty(h2_fifo *fifo, int block)
void * h2_ihash_get(h2_ihash_t *ih, int id)
static void iq_grow(h2_iqueue *q, int nlen)
apr_status_t h2_fifo_try_peek(h2_fifo *fifo, h2_fifo_peek_fn *fn, void *ctx)
static int index_of(h2_fifo *fifo, void *elem)
apr_status_t h2_ififo_remove(h2_ififo *fifo, int id)
static int h2_req_ignore_header(nghttp2_nv *nv)
static const char * inv_field_name_chr(const char *token)
static apr_status_t req_add_header(apr_table_t *headers, apr_pool_t *pool, nghttp2_nv *nv, size_t max_field_len, int *pwas_added)
static int contains_name(const literal *lits, size_t llen, nghttp2_nv *nv)
static apr_status_t ipull_head(h2_ififo *fifo, int *pi, int block)
static int ihash_iter(void *ctx, const void *key, apr_ssize_t klen, const void *val)
static int is_unsafe(h2_headers *h)
apr_status_t h2_ififo_create(h2_ififo **pfifo, apr_pool_t *pool, int capacity)
int h2_fifo_count(h2_fifo *fifo)
apr_status_t h2_fifo_term(h2_fifo *fifo)
int h2_util_frame_print(const nghttp2_frame *frame, char *buffer, size_t maxlen)
int h2_ignore_resp_trailer(const char *name, size_t len)
apr_status_t h2_req_add_header(apr_table_t *headers, apr_pool_t *pool, const char *name, size_t nlen, const char *value, size_t vlen, size_t max_field_len, int *pwas_added)
static void strip_field_value_ws(nghttp2_nv *nv)
int h2_ihash_iter(h2_ihash_t *ih, h2_ihash_iter_t *fn, void *ctx)
static unsigned int ihash(const char *key, apr_ssize_t *klen)
apr_status_t h2_fifo_pull(h2_fifo *fifo, void **pelem)
int h2_iq_remove(h2_iqueue *q, int sid)
size_t h2_ihash_shift(h2_ihash_t *ih, void **buffer, size_t max)
static apr_status_t ififo_push_int(h2_ififo *fifo, int id, int block)
static literal IgnoredResponseHeaders[]
unsigned int h2_ihash_count(h2_ihash_t *ih)
apr_status_t h2_req_create_ngheader(h2_ngheader **ph, apr_pool_t *p, const struct h2_request *req)
int h2_ififo_count(h2_ififo *fifo)
int h2_push_policy_determine(apr_table_t *headers, apr_pool_t *p, int push_enabled)
static void iq_swap(h2_iqueue *q, int i, int j)
apr_status_t h2_fifo_push(h2_fifo *fifo, void *elem)
apr_status_t h2_fifo_remove(h2_fifo *fifo, void *elem)
apr_size_t h2_util_base64url_decode(const char **decoded, const char *encoded, apr_pool_t *pool)
static const unsigned char BASE64URL_CHARS[]
unsigned char h2_log2(int n)
static apr_status_t pull_head(h2_fifo *fifo, void **pelem, int block)
apr_off_t h2_brigade_mem_size(apr_bucket_brigade *bb)
apr_size_t h2_util_table_bytes(apr_table_t *t, apr_size_t pair_extra)
static int iindex_of(h2_ififo *fifo, int id)
static apr_status_t icheck_not_empty(h2_ififo *fifo, int block)
static int iq_bubble_up(h2_iqueue *q, int i, int top, h2_iq_cmp *cmp, void *ctx)
apr_status_t h2_ififo_set_create(h2_ififo **pfifo, apr_pool_t *pool, int capacity)
apr_status_t h2_ififo_push(h2_ififo *fifo, int id)
static apr_status_t ififo_destroy(void *data)
void h2_iq_clear(h2_iqueue *q)
int h2_ihash_empty(h2_ihash_t *ih)
apr_status_t h2_ififo_try_pull(h2_ififo *fifo, int *pi)
static apr_status_t icreate_int(h2_ififo **pfifo, apr_pool_t *pool, int capacity, int as_set)
static int add_table_header(void *ctx, const char *key, const char *value)
static apr_status_t ngheader_create(h2_ngheader **ph, apr_pool_t *p, int unsafe, size_t key_count, const char *keys[], const char *values[], apr_table_t *headers)
int h2_iq_shift(h2_iqueue *q)
int h2_iq_count(h2_iqueue *q)
apr_status_t h2_fifo_try_push(h2_fifo *fifo, void *elem)
apr_status_t h2_ififo_pull(h2_ififo *fifo, int *pi)
static apr_status_t create_int(h2_fifo **pfifo, apr_pool_t *pool, int capacity, int as_set)
apr_size_t h2_util_bb_print(char *buffer, apr_size_t bmax, const char *tag, const char *sep, apr_bucket_brigade *bb)
int h2_iq_cmp(int i1, int i2, void *ctx)
int h2_bucket_gate(apr_bucket *b)
int h2_ihash_iter_t(void *ctx, void *val)
h2_fifo_op_t h2_ififo_peek_fn(int head, void *ctx)
h2_fifo_op_t h2_fifo_peek_fn(void *head, void *ctx)
apr_thread_cond_t * not_empty
apr_thread_mutex_t * lock
apr_thread_cond_t * not_full
apr_thread_cond_t * not_empty
apr_thread_mutex_t * lock
apr_thread_cond_t * not_full
h2_proxy_ihash_iter_t * iter
typedef int(WSAAPI *apr_winapi_fpt_WSAPoll)(IN OUT LPWSAPOLLFD fdArray