1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-16 00:00:07 +01:00
libwebsockets/lib/hpack.c
Andy Green ecc2e72ca1 http2 add hpack decode support
Signed-off-by: Andy Green <andy.green@linaro.org>
2014-10-10 06:15:02 +08:00

239 lines
8.1 KiB
C

/*
* Official static header table for HPACK
* +-------+-----------------------------+---------------+
| 1 | :authority | |
| 2 | :method | GET |
| 3 | :method | POST |
| 4 | :path | / |
| 5 | :path | /index.html |
| 6 | :scheme | http |
| 7 | :scheme | https |
| 8 | :status | 200 |
| 9 | :status | 204 |
| 10 | :status | 206 |
| 11 | :status | 304 |
| 12 | :status | 400 |
| 13 | :status | 404 |
| 14 | :status | 500 |
| 15 | accept-charset | |
| 16 | accept-encoding | gzip, deflate |
| 17 | accept-language | |
| 18 | accept-ranges | |
| 19 | accept | |
| 20 | access-control-allow-origin | |
| 21 | age | |
| 22 | allow | |
| 23 | authorization | |
| 24 | cache-control | |
| 25 | content-disposition | |
| 26 | content-encoding | |
| 27 | content-language | |
| 28 | content-length | |
| 29 | content-location | |
| 30 | content-range | |
| 31 | content-type | |
| 32 | cookie | |
| 33 | date | |
| 34 | etag | |
| 35 | expect | |
| 36 | expires | |
| 37 | from | |
| 38 | host | |
| 39 | if-match | |
| 40 | if-modified-since | |
| 41 | if-none-match | |
| 42 | if-range | |
| 43 | if-unmodified-since | |
| 44 | last-modified | |
| 45 | link | |
| 46 | location | |
| 47 | max-forwards | |
| 48 | proxy-authenticate | |
| 49 | proxy-authorization | |
| 50 | range | |
| 51 | referer | |
| 52 | refresh | |
| 53 | retry-after | |
| 54 | server | |
| 55 | set-cookie | |
| 56 | strict-transport-security | |
| 57 | transfer-encoding | |
| 58 | user-agent | |
| 59 | vary | |
| 60 | via | |
| 61 | www-authenticate | |
+-------+-----------------------------+---------------+
*/
static const unsigned char static_token[] = {
0,
WSI_TOKEN_HTTP_COLON_AUTHORITY,
WSI_TOKEN_HTTP_COLON_METHOD,
WSI_TOKEN_HTTP_COLON_METHOD,
WSI_TOKEN_HTTP_COLON_PATH,
WSI_TOKEN_HTTP_COLON_PATH,
WSI_TOKEN_HTTP_COLON_SCHEME,
WSI_TOKEN_HTTP_COLON_SCHEME,
WSI_TOKEN_HTTP_COLON_STATUS,
WSI_TOKEN_HTTP_COLON_STATUS,
WSI_TOKEN_HTTP_COLON_STATUS,
WSI_TOKEN_HTTP_COLON_STATUS,
WSI_TOKEN_HTTP_COLON_STATUS,
WSI_TOKEN_HTTP_COLON_STATUS,
WSI_TOKEN_HTTP_COLON_STATUS,
WSI_TOKEN_HTTP_ACCEPT_CHARSET,
WSI_TOKEN_HTTP_ACCEPT_ENCODING,
WSI_TOKEN_HTTP_ACCEPT_LANGUAGE,
WSI_TOKEN_HTTP_ACCEPT_RANGES,
WSI_TOKEN_HTTP_ACCEPT,
WSI_TOKEN_HTTP_ACCESS_CONTROL_ALLOW_ORIGIN,
WSI_TOKEN_HTTP_AGE,
WSI_TOKEN_HTTP_ALLOW,
WSI_TOKEN_HTTP_AUTHORIZATION,
WSI_TOKEN_HTTP_CACHE_CONTROL,
WSI_TOKEN_HTTP_CONTENT_DISPOSITION,
WSI_TOKEN_HTTP_CONTENT_ENCODING,
WSI_TOKEN_HTTP_CONTENT_LANGUAGE,
WSI_TOKEN_HTTP_CONTENT_LENGTH,
WSI_TOKEN_HTTP_CONTENT_LOCATION,
WSI_TOKEN_HTTP_CONTENT_RANGE,
WSI_TOKEN_HTTP_CONTENT_TYPE,
WSI_TOKEN_HTTP_COOKIE,
WSI_TOKEN_HTTP_DATE,
WSI_TOKEN_HTTP_ETAG,
WSI_TOKEN_HTTP_EXPECT,
WSI_TOKEN_HTTP_EXPIRES,
WSI_TOKEN_HTTP_FROM,
WSI_TOKEN_HTTP_HOST,
WSI_TOKEN_HTTP_IF_MATCH,
WSI_TOKEN_HTTP_IF_MODIFIED_SINCE,
WSI_TOKEN_HTTP_IF_NONE_MATCH,
WSI_TOKEN_HTTP_IF_RANGE,
WSI_TOKEN_HTTP_IF_UNMODIFIED_SINCE,
WSI_TOKEN_HTTP_LAST_MODIFIED,
WSI_TOKEN_HTTP_LINK,
WSI_TOKEN_HTTP_LOCATION,
WSI_TOKEN_HTTP_MAX_FORWARDS,
WSI_TOKEN_HTTP_PROXY_AUTHENTICATE,
WSI_TOKEN_HTTP_PROXY_AUTHORIZATION,
WSI_TOKEN_HTTP_RANGE,
WSI_TOKEN_HTTP_REFERER,
WSI_TOKEN_HTTP_REFRESH,
WSI_TOKEN_HTTP_RETRY_AFTER,
WSI_TOKEN_HTTP_SERVER,
WSI_TOKEN_HTTP_SET_COOKIE,
WSI_TOKEN_HTTP_STRICT_TRANSPORT_SECURITY,
WSI_TOKEN_HTTP_TRANSFER_ENCODING,
WSI_TOKEN_HTTP_USER_AGENT,
WSI_TOKEN_HTTP_VARY,
WSI_TOKEN_HTTP_VIA,
WSI_TOKEN_HTTP_WWW_AUTHENTICATE,
};
static const char * const http2_canned[] = {
"",
"",
"GET",
"POST",
"/",
"/index.html",
"http",
"https",
"200",
"204",
"206",
"300",
"304",
"400",
"404",
"500",
"",
"gzip, deflate"
};
#include "huftable.h"
int lextable_decode(int pos, char c)
{
int q = pos + !!c;
if (lextable_terms[q >> 3] & (1 << (q & 7))) /* terminal */
return lextable[q] | 0x8000;
return pos + (lextable[q] << 1);
}
static int lws_add_header(int header, const char *payload, int len)
{
wsi->u.ah.frag_index[header]
}
int lws_hpack_interpret(struct libwebsocket *wsi, unsigned char c)
{
switch (wsi->u.http2.hpack) {
case HPKS_TYPE:
if (c & 0x80) { /* indexed header field only */
wsi->u.http2.header_index = c & 0x7f;
/* stay at same state */
break;
}
if (c & 0x40) { /* literal header incr idx */
if (c == 0x40) { /* literal name */
wsi->u.http2.header_index = 0;
wsi->u.http2.hpack
wsi->u.http2.hpack = HPKS_HLEN;
break;
}
/* indexed name */
wsi->u.http2.header_index = c & 0x3f;
wsi->u.http2.hpack = HPKS_HLEN;
break;
}
switch(c & 0xf0) {
case 0: /* literal header without indexing */
if (c == 0) { /* literal name */
wsi->u.http2.hpack = HPKS_NAME_HLEN;
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;
break;
}
/* indexed name */
wsi->u.http2.header_index = c & 0xf;
wsi->u.http2.hpack = HPKS_NAME_HLEN;
break;
case 0x20:
case 0x30: /* header table size update */
/* = c & 0x1f */
/* stay at same state */
break;
}
break;
case HPKS_HLEN:
wsi->u.http2.huff = !!(c & 0x80);
wsi->u.http2.hpack_len = c & 0x7f;
if (wsi->u.http2.hpack_len < 127) {
wsi->u.http2.hpack = HPKS_NAME_DATA;
break;
}
wsi->u.http2.hpack_m = 0;
wsi->u.http2.hpack = HPKS_NAME_HLEN_EXT;
break;
case HPKS_HLEN_EXT:
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;
break;
case HPKS_DATA:
}
}