http2 hpack basic decode ok including huff
Signed-off-by: Andy Green <andy.green@linaro.org>
This commit is contained in:
parent
ecc2e72ca1
commit
2add6340d5
10 changed files with 374 additions and 82 deletions
|
@ -296,6 +296,7 @@ endif()
|
|||
if (LWS_WITH_HTTP2)
|
||||
list(APPEND SOURCES
|
||||
lib/http2.c
|
||||
lib/hpack.c
|
||||
lib/ssl-http2.c
|
||||
)
|
||||
endif()
|
||||
|
|
285
lib/hpack.c
285
lib/hpack.c
|
@ -1,3 +1,26 @@
|
|||
/*
|
||||
* lib/hpack.c
|
||||
*
|
||||
* Copyright (C) 2014 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation:
|
||||
* version 2.1 of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "private-libwebsockets.h"
|
||||
|
||||
/*
|
||||
* Official static header table for HPACK
|
||||
* +-------+-----------------------------+---------------+
|
||||
|
@ -104,7 +127,7 @@ static const unsigned char static_token[] = {
|
|||
WSI_TOKEN_HTTP_EXPECT,
|
||||
WSI_TOKEN_HTTP_EXPIRES,
|
||||
WSI_TOKEN_HTTP_FROM,
|
||||
WSI_TOKEN_HTTP_HOST,
|
||||
WSI_TOKEN_HOST,
|
||||
WSI_TOKEN_HTTP_IF_MATCH,
|
||||
WSI_TOKEN_HTTP_IF_MODIFIED_SINCE,
|
||||
WSI_TOKEN_HTTP_IF_NONE_MATCH,
|
||||
|
@ -130,6 +153,8 @@ static const unsigned char static_token[] = {
|
|||
WSI_TOKEN_HTTP_WWW_AUTHENTICATE,
|
||||
};
|
||||
|
||||
/* some of the entries imply values as well as header names */
|
||||
|
||||
static const char * const http2_canned[] = {
|
||||
"",
|
||||
"",
|
||||
|
@ -142,7 +167,6 @@ static const char * const http2_canned[] = {
|
|||
"200",
|
||||
"204",
|
||||
"206",
|
||||
"300",
|
||||
"304",
|
||||
"400",
|
||||
"404",
|
||||
|
@ -151,9 +175,11 @@ static const char * const http2_canned[] = {
|
|||
"gzip, deflate"
|
||||
};
|
||||
|
||||
/* see minihuf.c */
|
||||
|
||||
#include "huftable.h"
|
||||
|
||||
int lextable_decode(int pos, char c)
|
||||
static int huftable_decode(int pos, char c)
|
||||
{
|
||||
int q = pos + !!c;
|
||||
|
||||
|
@ -163,77 +189,282 @@ int lextable_decode(int pos, char c)
|
|||
return pos + (lextable[q] << 1);
|
||||
}
|
||||
|
||||
static int lws_add_header(int header, const char *payload, int len)
|
||||
static int lws_hpack_update_table_size(struct libwebsocket *wsi, int idx)
|
||||
{
|
||||
wsi->u.ah.frag_index[header]
|
||||
lwsl_info("hpack set table size %d\n", idx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lws_hpack_interpret(struct libwebsocket *wsi, unsigned char c)
|
||||
static int lws_frag_start(struct libwebsocket *wsi, int hdr_token_idx)
|
||||
{
|
||||
struct allocated_headers * ah = wsi->u.http2.http.ah;
|
||||
|
||||
if (!hdr_token_idx)
|
||||
return 1;
|
||||
|
||||
if (ah->next_frag_index >= ARRAY_SIZE(ah->frag_index))
|
||||
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->frag_index[hdr_token_idx] = ah->next_frag_index;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lws_frag_append(struct libwebsocket *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);
|
||||
}
|
||||
|
||||
static int lws_frag_end(struct libwebsocket *wsi)
|
||||
{
|
||||
if (lws_frag_append(wsi, 0))
|
||||
return 1;
|
||||
|
||||
wsi->u.http2.http.ah->next_frag_index++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lws_dump_header(struct libwebsocket *wsi, int hdr)
|
||||
{
|
||||
char s[200];
|
||||
int len = lws_hdr_copy(wsi, s, sizeof(s) - 1, hdr);
|
||||
s[len] = '\0';
|
||||
lwsl_info(" hdr tok %d '%s'\n", hdr, s);
|
||||
}
|
||||
|
||||
static int lws_token_from_index(struct libwebsocket *wsi, int index)
|
||||
{
|
||||
if (index < ARRAY_SIZE(static_token))
|
||||
return static_token[index];
|
||||
|
||||
// dynamic indexes
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lws_add_indexed_hdr(struct libwebsocket *wsi, int idx)
|
||||
{
|
||||
const char *p;
|
||||
int tok = lws_token_from_index(wsi, idx);
|
||||
|
||||
lwsl_info("adding indexed hdr %d (tok %d)\n", idx, tok);
|
||||
|
||||
if (lws_frag_start(wsi, tok))
|
||||
return 1;
|
||||
|
||||
if (idx < ARRAY_SIZE(http2_canned)) {
|
||||
p = http2_canned[idx];
|
||||
while (*p)
|
||||
if (lws_frag_append(wsi, *p++))
|
||||
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)
|
||||
{
|
||||
unsigned int prev;
|
||||
unsigned char c1;
|
||||
int n;
|
||||
|
||||
switch (wsi->u.http2.hpack) {
|
||||
case HPKS_TYPE:
|
||||
if (c & 0x80) { /* indexed header field only */
|
||||
/* just a possibly-extended integer */
|
||||
wsi->u.http2.hpack_type = HPKT_INDEXED_HDR_7;
|
||||
wsi->u.http2.header_index = c & 0x7f;
|
||||
if ((c & 0x7f) == 0x7f) {
|
||||
wsi->u.http2.hpack_len = c & 0x7f;
|
||||
wsi->u.http2.hpack_m = 0;
|
||||
wsi->u.http2.hpack = HPKS_IDX_EXT;
|
||||
break;
|
||||
}
|
||||
if (lws_add_indexed_hdr(wsi, c & 0x7f))
|
||||
return 1;
|
||||
/* stay at same state */
|
||||
break;
|
||||
}
|
||||
if (c & 0x40) { /* literal header incr idx */
|
||||
/*
|
||||
* [possibly-extended hdr idx (6) | new literal hdr name]
|
||||
* H + possibly-extended value length
|
||||
* literal value
|
||||
*/
|
||||
wsi->u.http2.header_index = 0;
|
||||
if (c == 0x40) { /* literal name */
|
||||
wsi->u.http2.header_index = 0;
|
||||
wsi->u.http2.hpack
|
||||
wsi->u.http2.hpack_type = HPKT_LITERAL_HDR_VALUE_INCR;
|
||||
wsi->u.http2.value = 0;
|
||||
wsi->u.http2.hpack = HPKS_HLEN;
|
||||
break;
|
||||
}
|
||||
/* indexed name */
|
||||
wsi->u.http2.hpack_type = HPKT_INDEXED_HDR_6_VALUE_INCR;
|
||||
if ((c & 0x3f) == 0x3f) {
|
||||
wsi->u.http2.hpack_len = c & 0x3f;
|
||||
wsi->u.http2.hpack_m = 0;
|
||||
wsi->u.http2.hpack = HPKS_IDX_EXT;
|
||||
break;
|
||||
}
|
||||
wsi->u.http2.header_index = c & 0x3f;
|
||||
wsi->u.http2.value = 1;
|
||||
wsi->u.http2.hpack = HPKS_HLEN;
|
||||
break;
|
||||
}
|
||||
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
|
||||
*/
|
||||
if (c == 0) { /* literal name */
|
||||
wsi->u.http2.hpack = HPKS_NAME_HLEN;
|
||||
wsi->u.http2.hpack_type = HPKT_LITERAL_HDR_VALUE;
|
||||
wsi->u.http2.hpack = HPKS_HLEN;
|
||||
wsi->u.http2.value = 0;
|
||||
break;
|
||||
}
|
||||
/* indexed name */
|
||||
wsi->u.http2.header_index = c & 0xf;
|
||||
wsi->u.http2.hpack = HPKS_VALUE_HLEN;
|
||||
break;
|
||||
case 0x10: /* literal header never indexed */
|
||||
if (c == 0x10) { /* literal name */
|
||||
wsi->u.http2.header_index = 0;
|
||||
wsi->u.http2.hpack = HPKS_NAME_HLEN;
|
||||
wsi->u.http2.hpack_type = HPKT_INDEXED_HDR_4_VALUE;
|
||||
wsi->u.http2.header_index = 0;
|
||||
if ((c & 0xf) == 0xf) {
|
||||
wsi->u.http2.hpack_len = c & 0xf;
|
||||
wsi->u.http2.hpack_m = 0;
|
||||
wsi->u.http2.hpack = HPKS_IDX_EXT;
|
||||
break;
|
||||
}
|
||||
/* indexed name */
|
||||
wsi->u.http2.header_index = c & 0xf;
|
||||
wsi->u.http2.hpack = HPKS_NAME_HLEN;
|
||||
wsi->u.http2.value = 1;
|
||||
wsi->u.http2.hpack = HPKS_HLEN;
|
||||
break;
|
||||
|
||||
case 0x20:
|
||||
case 0x30: /* header table size update */
|
||||
/* = c & 0x1f */
|
||||
/* stay at same state */
|
||||
/* possibly-extended size value (5) */
|
||||
wsi->u.http2.hpack_type = HPKT_SIZE_5;
|
||||
if ((c & 0x1f) == 0x1f) {
|
||||
wsi->u.http2.hpack_len = c & 0x1f;
|
||||
wsi->u.http2.hpack_m = 0;
|
||||
wsi->u.http2.hpack = HPKS_IDX_EXT;
|
||||
break;
|
||||
}
|
||||
lws_hpack_update_table_size(wsi, c & 0x1f);
|
||||
/* stay at HPKS_TYPE state */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case HPKS_HLEN:
|
||||
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:
|
||||
if (lws_add_indexed_hdr(wsi, wsi->u.http2.hpack_len))
|
||||
return 1;
|
||||
wsi->u.http2.hpack = HPKS_TYPE;
|
||||
break;
|
||||
default:
|
||||
wsi->u.http2.header_index = wsi->u.http2.hpack_len;
|
||||
wsi->u.http2.value = 1;
|
||||
wsi->u.http2.hpack = HPKS_HLEN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case HPKS_HLEN: /* [ H | 7+ ] */
|
||||
wsi->u.http2.huff = !!(c & 0x80);
|
||||
wsi->u.http2.hpack_pos = 0;
|
||||
wsi->u.http2.hpack_len = c & 0x7f;
|
||||
if (wsi->u.http2.hpack_len < 127) {
|
||||
wsi->u.http2.hpack = HPKS_NAME_DATA;
|
||||
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)))
|
||||
return 1;
|
||||
} else
|
||||
wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART;
|
||||
wsi->u.http2.hpack = HPKS_DATA;
|
||||
break;
|
||||
}
|
||||
wsi->u.http2.hpack_m = 0;
|
||||
wsi->u.http2.hpack = HPKS_NAME_HLEN_EXT;
|
||||
wsi->u.http2.hpack = HPKS_HLEN_EXT;
|
||||
break;
|
||||
|
||||
case HPKS_HLEN_EXT:
|
||||
wsi->u.http2.hpack_len += (c & 0x7f) << wsi->u.http2.hpack_m;
|
||||
wsi->u.http2.hpack_len += (c & 0x7f) <<
|
||||
wsi->u.http2.hpack_m;
|
||||
wsi->u.http2.hpack_m += 7;
|
||||
if (!(c & 0x80))
|
||||
wsi->u.http2.hpack = HPKS_NAME_DATA;
|
||||
goto pre_data;
|
||||
|
||||
break;
|
||||
|
||||
case HPKS_DATA:
|
||||
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,
|
||||
(c >> 7) & 1);
|
||||
c <<= 1;
|
||||
if (wsi->u.http2.hpack_pos == 0xffff)
|
||||
return 1;
|
||||
if (!(wsi->u.http2.hpack_pos & 0x8000))
|
||||
continue;
|
||||
c1 = wsi->u.http2.hpack_pos & 0x7fff;
|
||||
wsi->u.http2.hpack_pos = 0;
|
||||
|
||||
if (!c1 && prev == HUFTABLE_0x100_PREV)
|
||||
; /* EOT */
|
||||
} else {
|
||||
n = 8;
|
||||
c1 = c;
|
||||
}
|
||||
if (wsi->u.http2.value) { /* value */
|
||||
if (lws_frag_append(wsi, c1))
|
||||
return 1;
|
||||
} else { /* name */
|
||||
if (libwebsocket_parse(context, wsi, c1))
|
||||
return 1;
|
||||
|
||||
}
|
||||
}
|
||||
if (--wsi->u.http2.hpack_len == 0) {
|
||||
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));
|
||||
|
||||
wsi->u.http2.hpack = HPKS_TYPE;
|
||||
} else { /* name */
|
||||
if (wsi->u.hdr.parser_state < WSI_TOKEN_COUNT)
|
||||
|
||||
wsi->u.http2.value = 1;
|
||||
wsi->u.http2.hpack = HPKS_HLEN;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
51
lib/http2.c
51
lib/http2.c
|
@ -66,6 +66,7 @@ lws_create_server_child_wsi(struct libwebsocket_context *context, struct libwebs
|
|||
lws_http2_init(&wsi->u.http2.peer_settings);
|
||||
lws_http2_init(&wsi->u.http2.my_settings);
|
||||
wsi->u.http2.stream_id = sid;
|
||||
wsi->u.http2.my_stream_id = sid;
|
||||
|
||||
wsi->u.http2.parent_wsi = parent_wsi;
|
||||
wsi->u.http2.next_child_wsi = parent_wsi->u.http2.next_child_wsi;
|
||||
|
@ -129,8 +130,12 @@ lws_http2_interpret_settings_payload(struct http2_settings *settings, unsigned c
|
|||
|
||||
int lws_http2_frame_write(struct libwebsocket *wsi, int type, int flags, unsigned int sid, unsigned int len, unsigned char *buf)
|
||||
{
|
||||
struct libwebsocket *wsi_eff = wsi;
|
||||
unsigned char *p = &buf[-LWS_HTTP2_FRAME_HEADER_LENGTH];
|
||||
int n;
|
||||
|
||||
while (wsi_eff->u.http2.parent_wsi)
|
||||
wsi_eff = wsi_eff->u.http2.parent_wsi;
|
||||
|
||||
*p++ = len >> 16;
|
||||
*p++ = len >> 8;
|
||||
|
@ -142,10 +147,10 @@ int lws_http2_frame_write(struct libwebsocket *wsi, int type, int flags, unsigne
|
|||
*p++ = sid >> 8;
|
||||
*p++ = sid;
|
||||
|
||||
lwsl_info("%s: %p. type %d, flags 0x%x, sid=%d, len=%d\n",
|
||||
__func__, wsi, type, flags, sid, len);
|
||||
lwsl_info("%s: %p (eff %p). type %d, flags 0x%x, sid=%d, len=%d\n",
|
||||
__func__, wsi, wsi_eff, type, flags, sid, len);
|
||||
|
||||
n = lws_issue_raw(wsi, &buf[-LWS_HTTP2_FRAME_HEADER_LENGTH], len + LWS_HTTP2_FRAME_HEADER_LENGTH);
|
||||
n = lws_issue_raw(wsi_eff, &buf[-LWS_HTTP2_FRAME_HEADER_LENGTH], len + LWS_HTTP2_FRAME_HEADER_LENGTH);
|
||||
if (n >= LWS_HTTP2_FRAME_HEADER_LENGTH)
|
||||
return n - LWS_HTTP2_FRAME_HEADER_LENGTH;
|
||||
|
||||
|
@ -169,7 +174,8 @@ int
|
|||
lws_http2_parser(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, unsigned char c)
|
||||
{
|
||||
struct libwebsocket *wsi_new;
|
||||
int n;
|
||||
//dstruct libwebsocket *wsi_new;
|
||||
|
||||
switch (wsi->state) {
|
||||
case WSI_STATE_HTTP2_AWAIT_CLIENT_PREFACE:
|
||||
|
@ -206,19 +212,31 @@ lws_http2_parser(struct libwebsocket_context *context,
|
|||
return 1;
|
||||
break;
|
||||
case LWS_HTTP2_FRAME_TYPE_HEADERS:
|
||||
|
||||
if (lws_hpack_interpret(context, wsi->u.http2.stream_wsi, c))
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
wsi->u.http2.count++;
|
||||
if (wsi->u.http2.count == wsi->u.http2.length) {
|
||||
wsi->u.http2.frame_state = 0;
|
||||
wsi->u.http2.count = 0;
|
||||
/* set our initial window size */
|
||||
if (!wsi->u.http2.initialized) {
|
||||
wsi->u.http2.tx_credit = wsi->u.http2.peer_settings.setting[LWS_HTTP2_SETTINGS__INITIAL_WINDOW_SIZE];
|
||||
lwsl_info("initial tx credit on master conn %p: %d\n", wsi, wsi->u.http2.tx_credit);
|
||||
wsi->u.http2.initialized = 1;
|
||||
}
|
||||
if (wsi->u.http2.count != wsi->u.http2.length)
|
||||
break;
|
||||
|
||||
/* end of frame */
|
||||
|
||||
wsi->u.http2.frame_state = 0;
|
||||
wsi->u.http2.count = 0;
|
||||
/* set our initial window size */
|
||||
if (!wsi->u.http2.initialized) {
|
||||
wsi->u.http2.tx_credit = wsi->u.http2.peer_settings.setting[LWS_HTTP2_SETTINGS__INITIAL_WINDOW_SIZE];
|
||||
lwsl_info("initial tx credit on master conn %p: %d\n", wsi, wsi->u.http2.tx_credit);
|
||||
wsi->u.http2.initialized = 1;
|
||||
}
|
||||
switch (wsi->u.http2.type) {
|
||||
case LWS_HTTP2_FRAME_TYPE_HEADERS:
|
||||
/* service the http request itself */
|
||||
lwsl_info("servicing initial http request\n");
|
||||
n = lws_http_action(context, wsi->u.http2.stream_wsi);
|
||||
lwsl_info(" action result %d\n", n);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -264,6 +282,7 @@ lws_http2_parser(struct libwebsocket_context *context,
|
|||
}
|
||||
break;
|
||||
case LWS_HTTP2_FRAME_TYPE_HEADERS:
|
||||
lwsl_info("LWS_HTTP2_FRAME_TYPE_HEADERS: stream_id = %d\n", wsi->u.http2.stream_id);
|
||||
if (!wsi->u.http2.stream_id)
|
||||
return 1;
|
||||
wsi->u.http2.stream_wsi = lws_http2_wsi_from_id(wsi, wsi->u.http2.stream_id);
|
||||
|
@ -318,10 +337,6 @@ int lws_http2_do_pps_send(struct libwebsocket_context *context, struct libwebsoc
|
|||
wsi->state = WSI_STATE_HTTP2_ESTABLISHED;
|
||||
|
||||
wsi->u.http.fd = LWS_INVALID_FILE;
|
||||
|
||||
/* service the http request itself */
|
||||
//lwsl_info("servicing initial http request\n");
|
||||
//n = lws_http_action(context, wsi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -525,3 +525,6 @@ static unsigned char lextable[] = {
|
|||
0xcc, 0x30, 0xfc, 0xcf, 0x3c, 0xf0, 0x0c, 0xcf,
|
||||
0xd0, 0x03, 0x3f, 0x33, 0xff, 0xff, 0xc3, 0xf3,
|
||||
};
|
||||
|
||||
/* state that points to 0x100 for disambiguation with 0x0 */
|
||||
#define HUFTABLE_0x100_PREV 118
|
||||
|
|
|
@ -326,7 +326,18 @@ enum lws_token_indexes {
|
|||
WSI_TOKEN_KEY,
|
||||
WSI_TOKEN_VERSION,
|
||||
WSI_TOKEN_SWORIGIN,
|
||||
|
||||
WSI_TOKEN_HTTP_URI_ARGS,
|
||||
|
||||
/* use token storage to stash these */
|
||||
|
||||
_WSI_TOKEN_CLIENT_SENT_PROTOCOLS,
|
||||
_WSI_TOKEN_CLIENT_PEER_ADDRESS,
|
||||
_WSI_TOKEN_CLIENT_URI,
|
||||
_WSI_TOKEN_CLIENT_HOST,
|
||||
_WSI_TOKEN_CLIENT_ORIGIN,
|
||||
|
||||
#ifdef LWS_USE_HTTP2
|
||||
WSI_TOKEN_HTTP_COLON_AUTHORITY,
|
||||
WSI_TOKEN_HTTP_COLON_METHOD,
|
||||
WSI_TOKEN_HTTP_COLON_PATH,
|
||||
|
@ -366,17 +377,8 @@ enum lws_token_indexes {
|
|||
WSI_TOKEN_HTTP_VARY,
|
||||
WSI_TOKEN_HTTP_VIA,
|
||||
WSI_TOKEN_HTTP_WWW_AUTHENTICATE,
|
||||
#endif
|
||||
|
||||
WSI_TOKEN_HTTP_URI_ARGS,
|
||||
|
||||
/* use token storage to stash these */
|
||||
|
||||
_WSI_TOKEN_CLIENT_SENT_PROTOCOLS,
|
||||
_WSI_TOKEN_CLIENT_PEER_ADDRESS,
|
||||
_WSI_TOKEN_CLIENT_URI,
|
||||
_WSI_TOKEN_CLIENT_HOST,
|
||||
_WSI_TOKEN_CLIENT_ORIGIN,
|
||||
|
||||
/* always last real token index*/
|
||||
WSI_TOKEN_COUNT,
|
||||
/* parser state additions */
|
||||
|
|
|
@ -482,6 +482,7 @@ again:
|
|||
fprintf(stderr, " trying %d\n", n);
|
||||
|
||||
while (m < huf_literal[n].len) {
|
||||
prev = walk;
|
||||
walk = lextable_decode(walk, code_bit(n, m));
|
||||
|
||||
if (walk == 0xffff) {
|
||||
|
@ -491,8 +492,15 @@ again:
|
|||
|
||||
if (walk & 0x8000) {
|
||||
y = walk & 0x7fff;
|
||||
if (y == 0 && m == 29)
|
||||
if (y == 0 && m == 29) {
|
||||
y |= 0x100;
|
||||
fprintf(stdout,
|
||||
"\n/* state that points to "
|
||||
"0x100 for disambiguation with "
|
||||
"0x0 */\n"
|
||||
"#define HUFTABLE_0x100_PREV "
|
||||
"%d\n", prev);
|
||||
}
|
||||
break;
|
||||
}
|
||||
m++;
|
||||
|
|
|
@ -434,10 +434,14 @@ send_raw:
|
|||
case LWS_WRITE_PING:
|
||||
#ifdef LWS_USE_HTTP2
|
||||
if (wsi->mode == LWS_CONNMODE_HTTP2_SERVING) {
|
||||
unsigned char flags = 0;
|
||||
|
||||
n = LWS_HTTP2_FRAME_TYPE_DATA;
|
||||
if (protocol == LWS_WRITE_HTTP_HEADERS)
|
||||
if (protocol == LWS_WRITE_HTTP_HEADERS) {
|
||||
n = LWS_HTTP2_FRAME_TYPE_HEADERS;
|
||||
return lws_http2_frame_write(wsi, n, 0, wsi->u.http2.my_stream_id, len, buf);
|
||||
flags = LWS_HTTP2_FLAGS__HEADER__END_HEADER;
|
||||
}
|
||||
return lws_http2_frame_write(wsi, n, flags, wsi->u.http2.my_stream_id, len, buf);
|
||||
}
|
||||
#endif
|
||||
return lws_issue_raw(wsi, (unsigned char *)buf - pre,
|
||||
|
|
|
@ -578,6 +578,7 @@ struct _lws_http_mode_related {
|
|||
int content_remain;
|
||||
};
|
||||
|
||||
|
||||
#ifdef LWS_USE_HTTP2
|
||||
|
||||
enum lws_http2_settings {
|
||||
|
@ -610,6 +611,8 @@ enum lws_http2_wellknown_frame_types {
|
|||
#define LWS_HTTP2_FRAME_HEADER_LENGTH 9
|
||||
#define LWS_HTTP2_SETTINGS_LENGTH 6
|
||||
|
||||
#define LWS_HTTP2_FLAGS__HEADER__END_HEADER 4
|
||||
|
||||
struct http2_settings {
|
||||
unsigned int setting[LWS_HTTP2_SETTINGS__COUNT];
|
||||
};
|
||||
|
@ -617,12 +620,23 @@ struct http2_settings {
|
|||
enum http2_hpack_state {
|
||||
HPKS_TYPE,
|
||||
|
||||
HPKS_IDX_EXT,
|
||||
|
||||
HPKS_HLEN,
|
||||
HPKS_HLEN_EXT,
|
||||
|
||||
HPKS_DATA,
|
||||
};
|
||||
|
||||
enum http2_hpack_type {
|
||||
HPKT_INDEXED_HDR_7,
|
||||
HPKT_INDEXED_HDR_6_VALUE_INCR,
|
||||
HPKT_LITERAL_HDR_VALUE_INCR,
|
||||
HPKT_INDEXED_HDR_4_VALUE,
|
||||
HPKT_LITERAL_HDR_VALUE,
|
||||
HPKT_SIZE_5
|
||||
};
|
||||
|
||||
struct _lws_http2_related {
|
||||
/*
|
||||
* having this first lets us also re-use all HTTP union code
|
||||
|
@ -649,8 +663,10 @@ struct _lws_http2_related {
|
|||
|
||||
/* hpack */
|
||||
enum http2_hpack_state hpack;
|
||||
enum http2_hpack_type hpack_type;
|
||||
unsigned int header_index;
|
||||
unsigned int hpack_len;
|
||||
unsigned short hpack_pos;
|
||||
unsigned char hpack_m;
|
||||
unsigned int huff:1;
|
||||
unsigned int value:1;
|
||||
|
@ -904,6 +920,9 @@ LWS_EXTERN int lws_http2_do_pps_send(struct libwebsocket_context *context, struc
|
|||
LWS_EXTERN int lws_http2_frame_write(struct libwebsocket *wsi, int type, int flags, unsigned int sid, unsigned int len, unsigned char *buf);
|
||||
LWS_EXTERN struct libwebsocket *
|
||||
lws_http2_wsi_from_id(struct libwebsocket *wsi, unsigned int sid);
|
||||
LWS_EXTERN int lws_hpack_interpret(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi,
|
||||
unsigned char c);
|
||||
#endif
|
||||
|
||||
LWS_EXTERN int
|
||||
|
|
39
lib/server.c
39
lib/server.c
|
@ -183,6 +183,9 @@ int lws_http_action(struct libwebsocket_context *context,
|
|||
|
||||
if (!lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI) &&
|
||||
!lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI) &&
|
||||
#ifdef LWS_USE_HTTP2
|
||||
!lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COLON_PATH) &&
|
||||
#endif
|
||||
!lws_hdr_total_length(wsi, WSI_TOKEN_OPTIONS_URI)) {
|
||||
lwsl_warn("Missing URI in HTTP request\n");
|
||||
goto bail_nuke_ah;
|
||||
|
@ -197,25 +200,33 @@ int lws_http_action(struct libwebsocket_context *context,
|
|||
if (libwebsocket_ensure_user_space(wsi))
|
||||
goto bail_nuke_ah;
|
||||
|
||||
#ifdef LWS_USE_HTTP2
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COLON_PATH)) {
|
||||
uri_ptr = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_PATH);
|
||||
uri_len = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COLON_PATH);
|
||||
lwsl_info("HTTP2 request for '%s'\n", uri_ptr);
|
||||
goto got_uri;
|
||||
}
|
||||
#endif
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_OPTIONS_URI)) {
|
||||
uri_ptr = lws_hdr_simple_ptr(wsi, WSI_TOKEN_OPTIONS_URI);
|
||||
uri_len = lws_hdr_total_length(wsi, WSI_TOKEN_OPTIONS_URI);
|
||||
lwsl_info("HTTP OPTIONS request for '%s'\n", uri_ptr);
|
||||
goto got_uri;
|
||||
}
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI)) {
|
||||
uri_ptr = lws_hdr_simple_ptr(wsi, WSI_TOKEN_POST_URI);
|
||||
uri_len = lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI);
|
||||
lwsl_info("HTTP POST request for '%s'\n", uri_ptr);
|
||||
goto got_uri;
|
||||
}
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI)) {
|
||||
uri_ptr = lws_hdr_simple_ptr(wsi, WSI_TOKEN_GET_URI);
|
||||
uri_len = lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI);
|
||||
lwsl_info("HTTP GET request for '%s'\n",
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_GET_URI));
|
||||
}
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI)) {
|
||||
lwsl_info("HTTP POST request for '%s'\n",
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_POST_URI));
|
||||
uri_ptr = lws_hdr_simple_ptr(wsi, WSI_TOKEN_POST_URI);
|
||||
uri_len = lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI);
|
||||
}
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_OPTIONS_URI)) {
|
||||
lwsl_info("HTTP OPTIONS request for '%s'\n",
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_OPTIONS_URI));
|
||||
uri_ptr = lws_hdr_simple_ptr(wsi, WSI_TOKEN_OPTIONS_URI);
|
||||
uri_len = lws_hdr_total_length(wsi, WSI_TOKEN_OPTIONS_URI);
|
||||
lwsl_info("HTTP GET request for '%s'\n", uri_ptr);
|
||||
}
|
||||
|
||||
got_uri:
|
||||
/* HTTP header had a content length? */
|
||||
|
||||
wsi->u.http.content_length = 0;
|
||||
|
|
|
@ -112,21 +112,16 @@ dump_handshake_info(struct libwebsocket *wsi)
|
|||
/*[WSI_TOKEN_OPTIONS_URI] =*/ "options uri",
|
||||
/*[WSI_TOKEN_HOST] =*/ "Host",
|
||||
/*[WSI_TOKEN_CONNECTION] =*/ "Connection",
|
||||
/*[WSI_TOKEN_KEY1] =*/ "key 1",
|
||||
/*[WSI_TOKEN_KEY2] =*/ "key 2",
|
||||
/*[WSI_TOKEN_PROTOCOL] =*/ "Protocol",
|
||||
/*[WSI_TOKEN_UPGRADE] =*/ "Upgrade",
|
||||
/*[WSI_TOKEN_ORIGIN] =*/ "Origin",
|
||||
/*[WSI_TOKEN_DRAFT] =*/ "Draft",
|
||||
/*[WSI_TOKEN_CHALLENGE] =*/ "Challenge",
|
||||
|
||||
/* new for 04 */
|
||||
/*[WSI_TOKEN_KEY] =*/ "Key",
|
||||
/*[WSI_TOKEN_VERSION] =*/ "Version",
|
||||
/*[WSI_TOKEN_SWORIGIN] =*/ "Sworigin",
|
||||
|
||||
/* new for 05 */
|
||||
/*[WSI_TOKEN_EXTENSIONS] =*/ "Extensions",
|
||||
/*[WSI_TOKEN_KEY1] =*/ "key 1",
|
||||
/*[WSI_TOKEN_KEY2] =*/ "key 2",
|
||||
|
||||
/*[WSI_TOKEN_PROTOCOL] =*/ "Protocol",
|
||||
|
||||
/* client receives these */
|
||||
/*[WSI_TOKEN_ACCEPT] =*/ "Accept",
|
||||
|
@ -148,9 +143,12 @@ dump_handshake_info(struct libwebsocket *wsi)
|
|||
"Date:",
|
||||
"Range:",
|
||||
"Referer:",
|
||||
/* new for 04 */
|
||||
/*[WSI_TOKEN_KEY] =*/ "Key",
|
||||
/*[WSI_TOKEN_VERSION] =*/ "Version",
|
||||
/*[WSI_TOKEN_SWORIGIN] =*/ "Sworigin",
|
||||
"Uri-Args:",
|
||||
|
||||
/*[WSI_TOKEN_MUXURL] =*/ "MuxURL",
|
||||
};
|
||||
char buf[256];
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue