0d19815579a0646b70559f4ffa7bdb436180647d
[platform/upstream/libwebsockets.git] / lib / hpack.c
1 /*
2  * Official static header table for HPACK
3  *        +-------+-----------------------------+---------------+
4           | 1     | :authority                  |               |
5           | 2     | :method                     | GET           |
6           | 3     | :method                     | POST          |
7           | 4     | :path                       | /             |
8           | 5     | :path                       | /index.html   |
9           | 6     | :scheme                     | http          |
10           | 7     | :scheme                     | https         |
11           | 8     | :status                     | 200           |
12           | 9     | :status                     | 204           |
13           | 10    | :status                     | 206           |
14           | 11    | :status                     | 304           |
15           | 12    | :status                     | 400           |
16           | 13    | :status                     | 404           |
17           | 14    | :status                     | 500           |
18           | 15    | accept-charset              |               |
19           | 16    | accept-encoding             | gzip, deflate |
20           | 17    | accept-language             |               |
21           | 18    | accept-ranges               |               |
22           | 19    | accept                      |               |
23           | 20    | access-control-allow-origin |               |
24           | 21    | age                         |               |
25           | 22    | allow                       |               |
26           | 23    | authorization               |               |
27           | 24    | cache-control               |               |
28           | 25    | content-disposition         |               |
29           | 26    | content-encoding            |               |
30           | 27    | content-language            |               |
31           | 28    | content-length              |               |
32           | 29    | content-location            |               |
33           | 30    | content-range               |               |
34           | 31    | content-type                |               |
35           | 32    | cookie                      |               |
36           | 33    | date                        |               |
37           | 34    | etag                        |               |
38           | 35    | expect                      |               |
39           | 36    | expires                     |               |
40           | 37    | from                        |               |
41           | 38    | host                        |               |
42           | 39    | if-match                    |               |
43           | 40    | if-modified-since           |               |
44           | 41    | if-none-match               |               |
45           | 42    | if-range                    |               |
46           | 43    | if-unmodified-since         |               |
47           | 44    | last-modified               |               |
48           | 45    | link                        |               |
49           | 46    | location                    |               |
50           | 47    | max-forwards                |               |
51           | 48    | proxy-authenticate          |               |
52           | 49    | proxy-authorization         |               |
53           | 50    | range                       |               |
54           | 51    | referer                     |               |
55           | 52    | refresh                     |               |
56           | 53    | retry-after                 |               |
57           | 54    | server                      |               |
58           | 55    | set-cookie                  |               |
59           | 56    | strict-transport-security   |               |
60           | 57    | transfer-encoding           |               |
61           | 58    | user-agent                  |               |
62           | 59    | vary                        |               |
63           | 60    | via                         |               |
64           | 61    | www-authenticate            |               |
65           +-------+-----------------------------+---------------+
66 */
67
68 static const unsigned char static_token[] = {
69         0,
70         WSI_TOKEN_HTTP_COLON_AUTHORITY,
71         WSI_TOKEN_HTTP_COLON_METHOD,
72         WSI_TOKEN_HTTP_COLON_METHOD,
73         WSI_TOKEN_HTTP_COLON_PATH,
74         WSI_TOKEN_HTTP_COLON_PATH,
75         WSI_TOKEN_HTTP_COLON_SCHEME,
76         WSI_TOKEN_HTTP_COLON_SCHEME,
77         WSI_TOKEN_HTTP_COLON_STATUS,
78         WSI_TOKEN_HTTP_COLON_STATUS,
79         WSI_TOKEN_HTTP_COLON_STATUS,
80         WSI_TOKEN_HTTP_COLON_STATUS,
81         WSI_TOKEN_HTTP_COLON_STATUS,
82         WSI_TOKEN_HTTP_COLON_STATUS,
83         WSI_TOKEN_HTTP_COLON_STATUS,
84         WSI_TOKEN_HTTP_ACCEPT_CHARSET,
85         WSI_TOKEN_HTTP_ACCEPT_ENCODING,
86         WSI_TOKEN_HTTP_ACCEPT_LANGUAGE,
87         WSI_TOKEN_HTTP_ACCEPT_RANGES,
88         WSI_TOKEN_HTTP_ACCEPT,
89         WSI_TOKEN_HTTP_ACCESS_CONTROL_ALLOW_ORIGIN,
90         WSI_TOKEN_HTTP_AGE,
91         WSI_TOKEN_HTTP_ALLOW,
92         WSI_TOKEN_HTTP_AUTHORIZATION,
93         WSI_TOKEN_HTTP_CACHE_CONTROL,
94         WSI_TOKEN_HTTP_CONTENT_DISPOSITION,
95         WSI_TOKEN_HTTP_CONTENT_ENCODING,
96         WSI_TOKEN_HTTP_CONTENT_LANGUAGE,
97         WSI_TOKEN_HTTP_CONTENT_LENGTH,
98         WSI_TOKEN_HTTP_CONTENT_LOCATION,
99         WSI_TOKEN_HTTP_CONTENT_RANGE,
100         WSI_TOKEN_HTTP_CONTENT_TYPE,
101         WSI_TOKEN_HTTP_COOKIE,
102         WSI_TOKEN_HTTP_DATE,
103         WSI_TOKEN_HTTP_ETAG,
104         WSI_TOKEN_HTTP_EXPECT,
105         WSI_TOKEN_HTTP_EXPIRES,
106         WSI_TOKEN_HTTP_FROM,
107         WSI_TOKEN_HTTP_HOST,
108         WSI_TOKEN_HTTP_IF_MATCH,
109         WSI_TOKEN_HTTP_IF_MODIFIED_SINCE,
110         WSI_TOKEN_HTTP_IF_NONE_MATCH,
111         WSI_TOKEN_HTTP_IF_RANGE,
112         WSI_TOKEN_HTTP_IF_UNMODIFIED_SINCE,
113         WSI_TOKEN_HTTP_LAST_MODIFIED,
114         WSI_TOKEN_HTTP_LINK,
115         WSI_TOKEN_HTTP_LOCATION,
116         WSI_TOKEN_HTTP_MAX_FORWARDS,
117         WSI_TOKEN_HTTP_PROXY_AUTHENTICATE,
118         WSI_TOKEN_HTTP_PROXY_AUTHORIZATION,
119         WSI_TOKEN_HTTP_RANGE,
120         WSI_TOKEN_HTTP_REFERER,
121         WSI_TOKEN_HTTP_REFRESH,
122         WSI_TOKEN_HTTP_RETRY_AFTER,
123         WSI_TOKEN_HTTP_SERVER,
124         WSI_TOKEN_HTTP_SET_COOKIE,
125         WSI_TOKEN_HTTP_STRICT_TRANSPORT_SECURITY,
126         WSI_TOKEN_HTTP_TRANSFER_ENCODING,
127         WSI_TOKEN_HTTP_USER_AGENT,
128         WSI_TOKEN_HTTP_VARY,
129         WSI_TOKEN_HTTP_VIA,
130         WSI_TOKEN_HTTP_WWW_AUTHENTICATE,
131 };
132
133 static const char * const http2_canned[] = {
134         "",
135         "",
136         "GET",
137         "POST",
138         "/",
139         "/index.html",
140         "http",
141         "https",
142         "200",
143         "204",
144         "206",
145         "300",
146         "304",
147         "400",
148         "404",
149         "500",
150         "",
151         "gzip, deflate"
152 };
153
154 #include "huftable.h"
155
156 int lextable_decode(int pos, char c)
157 {
158         int q = pos + !!c;
159
160         if (lextable_terms[q >> 3] & (1 << (q & 7))) /* terminal */
161                 return lextable[q] | 0x8000;
162
163         return pos + (lextable[q] << 1);
164 }
165
166 static int lws_add_header(int header, const char *payload, int len)
167 {
168         wsi->u.ah.frag_index[header]
169 }
170
171 int lws_hpack_interpret(struct libwebsocket *wsi, unsigned char c)
172 {
173         switch (wsi->u.http2.hpack) {
174         case HPKS_TYPE:
175                 if (c & 0x80) { /* indexed header field only */
176                         wsi->u.http2.header_index = c & 0x7f;
177                         /* stay at same state */
178                         break;
179                 }
180                 if (c & 0x40) { /* literal header incr idx */
181                         if (c == 0x40) { /* literal name */
182                                 wsi->u.http2.header_index = 0;
183                                 wsi->u.http2.hpack
184                                 wsi->u.http2.hpack = HPKS_HLEN;
185                                 break;
186                         }
187                         /* indexed name */
188                         wsi->u.http2.header_index = c & 0x3f;
189                         wsi->u.http2.hpack = HPKS_HLEN;
190                         break;
191                 }
192                 switch(c & 0xf0) {
193                 case 0: /* literal header without indexing */
194                         if (c == 0) { /* literal name */
195                                 wsi->u.http2.hpack = HPKS_NAME_HLEN;
196                                 break;
197                         }
198                         /* indexed name */
199                         wsi->u.http2.header_index = c & 0xf;
200                         wsi->u.http2.hpack = HPKS_VALUE_HLEN;
201                         break;
202                 case 0x10: /* literal header never indexed */
203                         if (c == 0x10) { /* literal name */
204                                 wsi->u.http2.header_index = 0;
205                                 wsi->u.http2.hpack = HPKS_NAME_HLEN;
206                                 break;
207                         }
208                         /* indexed name */
209                         wsi->u.http2.header_index = c & 0xf;
210                         wsi->u.http2.hpack = HPKS_NAME_HLEN;
211                         break;
212                 case 0x20:
213                 case 0x30: /* header table size update */
214                         /* = c & 0x1f */
215                         /* stay at same state */
216                         break;
217                 }
218                 break;  
219         case HPKS_HLEN:
220                 wsi->u.http2.huff = !!(c & 0x80);
221                 wsi->u.http2.hpack_len = c & 0x7f;
222                 if (wsi->u.http2.hpack_len < 127) {
223                         wsi->u.http2.hpack = HPKS_NAME_DATA;
224                         break;
225                 }
226                 wsi->u.http2.hpack_m = 0;
227                 wsi->u.http2.hpack = HPKS_NAME_HLEN_EXT;
228                 break;
229         case HPKS_HLEN_EXT:
230                 wsi->u.http2.hpack_len += (c & 0x7f) << wsi->u.http2.hpack_m;
231                 wsi->u.http2.hpack_m += 7;
232                 if (!(c & 0x80))
233                         wsi->u.http2.hpack = HPKS_NAME_DATA;
234                 break;
235
236         case HPKS_DATA:
237
238         }
239 }