return pos + (lextable[q] << 1);
}
-static int lws_hpack_update_table_size(struct libwebsocket *wsi, int idx)
+static int lws_hpack_update_table_size(struct lws *wsi, int idx)
{
lwsl_info("hpack set table size %d\n", idx);
return 0;
}
-static int lws_frag_start(struct libwebsocket *wsi, int hdr_token_idx)
+static int lws_frag_start(struct lws *wsi, int hdr_token_idx)
{
struct allocated_headers * ah = wsi->u.http2.http.ah;
- if (!hdr_token_idx)
+ if (!hdr_token_idx) {
+ lwsl_err("%s: zero hdr_token_idx\n", __func__);
return 1;
-
- if (ah->next_frag_index >= ARRAY_SIZE(ah->frag_index))
+ }
+
+ if (ah->nfrag >= ARRAY_SIZE(ah->frag_index)) {
+ lwsl_err("%s: frag index %d too big\n", __func__, ah->nfrag);
return 1;
-
- ah->frags[ah->next_frag_index].offset = ah->pos;
- ah->frags[ah->next_frag_index].len = 0;
- ah->frags[ah->next_frag_index].next_frag_index = 0;
+ }
+
+ ah->frags[ah->nfrag].offset = ah->pos;
+ ah->frags[ah->nfrag].len = 0;
+ ah->frags[ah->nfrag].nfrag = 0;
+
+ ah->frag_index[hdr_token_idx] = ah->nfrag;
- ah->frag_index[hdr_token_idx] = ah->next_frag_index;
-
return 0;
}
-static int lws_frag_append(struct libwebsocket *wsi, unsigned char c)
+static int lws_frag_append(struct lws *wsi, unsigned char c)
{
struct allocated_headers * ah = wsi->u.http2.http.ah;
ah->data[ah->pos++] = c;
- ah->frags[ah->next_frag_index].len++;
-
- return ah->pos >= sizeof(ah->data);
+ ah->frags[ah->nfrag].len++;
+
+ return ah->pos >= wsi->context->max_http_header_data;
}
-static int lws_frag_end(struct libwebsocket *wsi)
+static int lws_frag_end(struct lws *wsi)
{
if (lws_frag_append(wsi, 0))
return 1;
- wsi->u.http2.http.ah->next_frag_index++;
+ wsi->u.http2.http.ah->nfrag++;
return 0;
}
-static void lws_dump_header(struct libwebsocket *wsi, int hdr)
+static void lws_dump_header(struct lws *wsi, int hdr)
{
char s[200];
int len = lws_hdr_copy(wsi, s, sizeof(s) - 1, hdr);
lwsl_info(" hdr tok %d (%s) = '%s'\n", hdr, lws_token_to_string(hdr), s);
}
-static int lws_token_from_index(struct libwebsocket *wsi, int index, char **arg, int *len)
+static int
+lws_token_from_index(struct lws *wsi, int index, char **arg, int *len)
{
struct hpack_dynamic_table *dyn;
-
+
/* dynamic table only belongs to network wsi */
-
+
wsi = lws_http2_get_network_wsi(wsi);
-
+
dyn = wsi->u.http2.hpack_dyn_table;
if (index < ARRAY_SIZE(static_token))
if (!dyn)
return 0;
-
+
index -= ARRAY_SIZE(static_token);
if (index >= dyn->num_entries)
return 0;
-
+
if (arg && len) {
*arg = dyn->args + dyn->entries[index].arg_offset;
*len = dyn->entries[index].arg_len;
}
-
+
return dyn->entries[index].token;
}
-static int lws_hpack_add_dynamic_header(struct libwebsocket *wsi, int token, char *arg, int len)
+static int
+lws_hpack_add_dynamic_header(struct lws *wsi, int token, char *arg, int len)
{
struct hpack_dynamic_table *dyn;
int ret = 1;
-
+
wsi = lws_http2_get_network_wsi(wsi);
dyn = wsi->u.http2.hpack_dyn_table;
if (!dyn)
return 1;
wsi->u.http2.hpack_dyn_table = dyn;
-
+
dyn->args = lws_malloc(1024);
if (!dyn->args)
goto bail1;
goto bail2;
dyn->num_entries = 20;
}
-
+
if (dyn->next == dyn->num_entries)
return 1;
-
+
if (dyn->args_length - dyn->pos < len)
return 1;
-
+
dyn->entries[dyn->next].token = token;
dyn->entries[dyn->next].arg_offset = dyn->pos;
if (len)
memcpy(dyn->args + dyn->pos, arg, len);
dyn->entries[dyn->next].arg_len = len;
-
- lwsl_info("%s: added dynamic hdr %d, token %d (%s), len %d\n", __func__, dyn->next, token, lws_token_to_string(token), len);
-
+
+ lwsl_info("%s: added dynamic hdr %d, token %d (%s), len %d\n",
+ __func__, dyn->next, token, lws_token_to_string(token), len);
+
dyn->pos += len;
dyn->next++;
-
+
return 0;
bail2:
return ret;
}
-static int lws_write_indexed_hdr(struct libwebsocket *wsi, int idx)
+static int lws_write_indexed_hdr(struct lws *wsi, int idx)
{
const char *p;
int tok = lws_token_from_index(wsi, idx, NULL, 0);
- lwsl_info("writing indexed hdr %d (tok %d '%s')\n", idx, tok, lws_token_to_string(tok));
+ lwsl_info("writing indexed hdr %d (tok %d '%s')\n", idx, tok,
+ lws_token_to_string(tok));
if (lws_frag_start(wsi, tok))
return 1;
}
if (lws_frag_end(wsi))
return 1;
-
+
lws_dump_header(wsi, tok);
return 0;
}
-int lws_hpack_interpret(struct libwebsocket_context *context,
- struct libwebsocket *wsi, unsigned char c)
+int lws_hpack_interpret(struct lws *wsi, unsigned char c)
{
unsigned int prev;
unsigned char c1;
int n;
+ lwsl_debug(" state %d\n", wsi->u.http2.hpack);
+
switch (wsi->u.http2.hpack) {
case HPKS_OPT_PADDING:
wsi->u.http2.padding = c;
/* weight */
wsi->u.http2.hpack = HPKS_TYPE;
break;
-
+
case HPKS_TYPE:
-
+
if (wsi->u.http2.count > (wsi->u.http2.length - wsi->u.http2.padding)) {
lwsl_info("padding eat\n");
break;
}
-
+
if (c & 0x80) { /* indexed header field only */
/* just a possibly-extended integer */
wsi->u.http2.hpack_type = HPKT_INDEXED_HDR_7;
+ lwsl_debug("HKPS_TYPE setting header_index %d\n", c & 0x7f);
wsi->u.http2.header_index = c & 0x7f;
if ((c & 0x7f) == 0x7f) {
wsi->u.http2.hpack_len = c & 0x7f;
wsi->u.http2.hpack = HPKS_IDX_EXT;
break;
}
+ lwsl_debug("HKPS_TYPE: %d\n", c & 0x7f);
if (lws_write_indexed_hdr(wsi, c & 0x7f))
return 1;
/* stay at same state */
* H + possibly-extended value length
* literal value
*/
+ lwsl_debug("HKPS_TYPE 2 setting header_index %d\n", 0);
wsi->u.http2.header_index = 0;
if (c == 0x40) { /* literal name */
wsi->u.http2.hpack_type = HPKT_LITERAL_HDR_VALUE_INCR;
wsi->u.http2.hpack = HPKS_IDX_EXT;
break;
}
+ lwsl_debug("HKPS_TYPE 3 setting header_index %d\n", c & 0x3f);
wsi->u.http2.header_index = c & 0x3f;
wsi->u.http2.value = 1;
wsi->u.http2.hpack = HPKS_HLEN;
switch(c & 0xf0) {
case 0x10: /* literal header never index */
case 0: /* literal header without indexing */
- /*
+ /*
* follows 0x40 except 4-bit hdr idx
* and don't add to index
*/
wsi->u.http2.value = 0;
break;
}
+ //lwsl_debug("indexed\n");
/* indexed name */
wsi->u.http2.hpack_type = HPKT_INDEXED_HDR_4_VALUE;
wsi->u.http2.header_index = 0;
wsi->u.http2.hpack = HPKS_IDX_EXT;
break;
}
+ //lwsl_err("HKPS_TYPE 5 setting header_index %d\n", c & 0xf);
wsi->u.http2.header_index = c & 0xf;
wsi->u.http2.value = 1;
wsi->u.http2.hpack = HPKS_HLEN;
break;
}
break;
-
+
case HPKS_IDX_EXT:
wsi->u.http2.hpack_len += (c & 0x7f) << wsi->u.http2.hpack_m;
wsi->u.http2.hpack_m += 7;
if (!(c & 0x80)) {
switch (wsi->u.http2.hpack_type) {
case HPKT_INDEXED_HDR_7:
+ //lwsl_err("HKPS_IDX_EXT hdr idx %d\n", wsi->u.http2.hpack_len);
if (lws_write_indexed_hdr(wsi, wsi->u.http2.hpack_len))
return 1;
wsi->u.http2.hpack = HPKS_TYPE;
break;
default:
+ // lwsl_err("HKPS_IDX_EXT setting header_index %d\n",
+ // wsi->u.http2.hpack_len);
wsi->u.http2.header_index = wsi->u.http2.hpack_len;
wsi->u.http2.value = 1;
wsi->u.http2.hpack = HPKS_HLEN;
if (wsi->u.http2.hpack_len < 0x7f) {
pre_data:
if (wsi->u.http2.value) {
- if (lws_frag_start(wsi,
- lws_token_from_index(wsi,
- wsi->u.http2.header_index, NULL, NULL)))
+ if (wsi->u.http2.header_index)
+ if (lws_frag_start(wsi, lws_token_from_index(wsi,
+ wsi->u.http2.header_index,
+ NULL, NULL))) {
+ // lwsl_notice("%s: hlen failed\n", __func__);
return 1;
+ }
} else
wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART;
wsi->u.http2.hpack = HPKS_DATA;
wsi->u.http2.hpack_m = 0;
wsi->u.http2.hpack = HPKS_HLEN_EXT;
break;
-
+
case HPKS_HLEN_EXT:
wsi->u.http2.hpack_len += (c & 0x7f) <<
wsi->u.http2.hpack_m;
for (n = 0; n < 8; n++) {
if (wsi->u.http2.huff) {
prev = wsi->u.http2.hpack_pos;
- wsi->u.http2.hpack_pos =
- huftable_decode(
+ wsi->u.http2.hpack_pos = huftable_decode(
wsi->u.http2.hpack_pos,
- (c >> 7) & 1);
+ (c >> 7) & 1);
c <<= 1;
if (wsi->u.http2.hpack_pos == 0xffff)
return 1;
continue;
c1 = wsi->u.http2.hpack_pos & 0x7fff;
wsi->u.http2.hpack_pos = 0;
-
+
if (!c1 && prev == HUFTABLE_0x100_PREV)
; /* EOT */
} else {
c1 = c;
}
if (wsi->u.http2.value) { /* value */
- if (lws_frag_append(wsi, c1))
- return 1;
+ if (wsi->u.http2.header_index)
+ if (lws_frag_append(wsi, c1))
+ return 1;
} else { /* name */
- if (lws_parse(context, wsi, c1))
+ if (lws_parse(wsi, c1))
return 1;
-
+
}
}
if (--wsi->u.http2.hpack_len == 0) {
-
+
switch (wsi->u.http2.hpack_type) {
case HPKT_LITERAL_HDR_VALUE_INCR:
case HPKT_INDEXED_HDR_6_VALUE_INCR: // !!!
- if (lws_hpack_add_dynamic_header(wsi, lws_token_from_index(wsi, wsi->u.http2.header_index, NULL, NULL), NULL, 0))
+ if (lws_hpack_add_dynamic_header(wsi,
+ lws_token_from_index(wsi,
+ wsi->u.http2.header_index,
+ NULL, NULL), NULL, 0))
return 1;
break;
default:
break;
}
-
+
n = 8;
if (wsi->u.http2.value) {
if (lws_frag_end(wsi))
return 1;
-
- lws_dump_header(wsi, lws_token_from_index(wsi, wsi->u.http2.header_index, NULL, NULL));
- if (wsi->u.http2.count + wsi->u.http2.padding == wsi->u.http2.length)
+ // lwsl_err("data\n");
+ lws_dump_header(wsi, lws_token_from_index(
+ wsi, wsi->u.http2.header_index,
+ NULL, NULL));
+ if (wsi->u.http2.count + wsi->u.http2.padding ==
+ wsi->u.http2.length)
wsi->u.http2.hpack = HKPS_OPT_DISCARD_PADDING;
else
wsi->u.http2.hpack = HPKS_TYPE;
} else { /* name */
- if (wsi->u.hdr.parser_state < WSI_TOKEN_COUNT)
-
+ //if (wsi->u.hdr.parser_state < WSI_TOKEN_COUNT)
+
wsi->u.http2.value = 1;
wsi->u.http2.hpack = HPKS_HLEN;
}
wsi->u.http2.hpack = HPKS_TYPE;
break;
}
-
+
return 0;
}
-static int lws_http2_num(int starting_bits, unsigned long num, unsigned char **p, unsigned char *end)
+static int lws_http2_num(int starting_bits, unsigned long num,
+ unsigned char **p, unsigned char *end)
{
int mask = (1 << starting_bits) - 1;
*((*p)++) |= num;
return *p >= end;
}
-
+
*((*p)++) |= mask;
if (*p >= end)
return 1;
-
+
num -= mask;
while (num >= 128) {
*((*p)++) = 0x80 | (num & 0x7f);
return 1;
num >>= 7;
}
-
+
return 0;
}
-int lws_add_http2_header_by_name(struct libwebsocket_context *context,
- struct libwebsocket *wsi,
- const unsigned char *name,
- const unsigned char *value,
- int length,
- unsigned char **p,
- unsigned char *end)
+int lws_add_http2_header_by_name(struct lws *wsi,
+ const unsigned char *name,
+ const unsigned char *value, int length,
+ unsigned char **p, unsigned char *end)
{
int len;
-
+
lwsl_info("%s: %p %s:%s\n", __func__, *p, name, value);
-
+
len = strlen((char *)name);
if (len)
if (name[len - 1] == ':')
*(*p) = 0; /* non-HUF */
if (lws_http2_num(7, length, p, end))
return 1;
-
+
memcpy(*p, value, length);
*p += length;
-
+
return 0;
}
-int lws_add_http2_header_by_token(struct libwebsocket_context *context,
- struct libwebsocket *wsi,
- enum lws_token_indexes token,
- const unsigned char *value,
- int length,
- unsigned char **p,
- unsigned char *end)
+int lws_add_http2_header_by_token(struct lws *wsi, enum lws_token_indexes token,
+ const unsigned char *value, int length,
+ unsigned char **p, unsigned char *end)
{
const unsigned char *name;
name = lws_token_to_string(token);
if (!name)
return 1;
-
- return lws_add_http2_header_by_name(context, wsi, name, value, length, p, end);
+
+ return lws_add_http2_header_by_name(wsi, name, value, length, p, end);
}
-int lws_add_http2_header_status(struct libwebsocket_context *context,
- struct libwebsocket *wsi,
- unsigned int code,
- unsigned char **p,
- unsigned char *end)
+int lws_add_http2_header_status(struct lws *wsi,
+ unsigned int code, unsigned char **p,
+ unsigned char *end)
{
unsigned char status[10];
int n;
-
+
wsi->u.http2.send_END_STREAM = !!(code >= 400);
-
+
n = sprintf((char *)status, "%u", code);
- if (lws_add_http2_header_by_token(context, wsi, WSI_TOKEN_HTTP_COLON_STATUS, status, n, p, end))
+ if (lws_add_http2_header_by_token(wsi, WSI_TOKEN_HTTP_COLON_STATUS,
+ status, n, p, end))
+
return 1;
return 0;