http2 add hpack decode support
[platform/upstream/libwebsockets.git] / lib / http2.c
1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010-2013 Andy Green <andy@warmcat.com>
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public
8  *  License as published by the Free Software Foundation:
9  *  version 2.1 of the License.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19  *  MA  02110-1301  USA
20  */
21
22
23 #include "private-libwebsockets.h"
24
25 const struct http2_settings lws_http2_default_settings = { {
26         0,
27         /* LWS_HTTP2_SETTINGS__HEADER_TABLE_SIZE */             4096,
28         /* LWS_HTTP2_SETTINGS__ENABLE_PUSH */                      1,
29         /* LWS_HTTP2_SETTINGS__MAX_CONCURRENT_STREAMS */         100,
30         /* LWS_HTTP2_SETTINGS__INITIAL_WINDOW_SIZE */          65535,
31         /* LWS_HTTP2_SETTINGS__MAX_FRAME_SIZE */               16384,
32         /* LWS_HTTP2_SETTINGS__MAX_HEADER_LIST_SIZE */            ~0,
33 }};
34
35
36 void lws_http2_init(struct http2_settings *settings)
37 {
38         memcpy(settings, lws_http2_default_settings.setting, sizeof(*settings));
39 }
40
41 struct libwebsocket *
42 lws_http2_wsi_from_id(struct libwebsocket *wsi, unsigned int sid)
43 {
44         do {
45                 if (wsi->u.http2.my_stream_id == sid)
46                         return wsi;
47                 
48                 wsi = wsi->u.http2.next_child_wsi;
49         } while (wsi);
50         
51         return NULL;
52 }
53
54 struct libwebsocket *
55 lws_create_server_child_wsi(struct libwebsocket_context *context, struct libwebsocket *parent_wsi, unsigned int sid)
56 {
57         struct libwebsocket *wsi = libwebsocket_create_new_server_wsi(context);
58         
59         if (!wsi)
60                 return NULL;
61         
62         /* no more children allowed by parent */
63         if (parent_wsi->u.http2.child_count + 1 == parent_wsi->u.http2.peer_settings.setting[LWS_HTTP2_SETTINGS__MAX_CONCURRENT_STREAMS])
64                 return NULL;
65         
66         lws_http2_init(&wsi->u.http2.peer_settings);
67         lws_http2_init(&wsi->u.http2.my_settings);
68         wsi->u.http2.stream_id = sid;
69
70         wsi->u.http2.parent_wsi = parent_wsi;
71         wsi->u.http2.next_child_wsi = parent_wsi->u.http2.next_child_wsi;
72         parent_wsi->u.http2.next_child_wsi = wsi;
73         parent_wsi->u.http2.child_count++;
74         
75         wsi->u.http2.my_priority = 16;
76         
77         wsi->state = WSI_STATE_HTTP2_ESTABLISHED;
78         wsi->mode = parent_wsi->mode;
79
80         lwsl_info("%s: %p new child %p, sid %d\n", __func__, parent_wsi, wsi, sid);
81         
82         return wsi;
83 }
84
85 int lws_remove_server_child_wsi(struct libwebsocket_context *context, struct libwebsocket *wsi)
86 {
87         struct libwebsocket **w = &wsi->u.http2.parent_wsi;
88         do {
89                 if (*w == wsi) {
90                         *w = wsi->u.http2.next_child_wsi;
91                         (wsi->u.http2.parent_wsi)->u.http2.child_count--;
92                         return 0;
93                 }
94                 
95                 w = &((*w)->u.http2.next_child_wsi);
96         } while (*w);
97         
98         lwsl_err("%s: can't find %p\n", __func__, wsi);
99         return 1;
100 }
101
102 int
103 lws_http2_interpret_settings_payload(struct http2_settings *settings, unsigned char *buf, int len)
104 {
105         unsigned int a, b;
106         
107         if (!len)
108                 return 0;
109         
110         if (len < LWS_HTTP2_SETTINGS_LENGTH)
111                 return 1;
112         
113         while (len >= LWS_HTTP2_SETTINGS_LENGTH) {
114                 a = (buf[0] << 8) | buf[1];
115                 if (a < LWS_HTTP2_SETTINGS__COUNT) {
116                         b = buf[2] << 24 | buf[3] << 16 | buf[4] << 8 | buf[5];
117                         settings->setting[a] = b;
118                         lwsl_info("http2 settings %d <- 0x%x\n", a, b);
119                 }
120                 len -= LWS_HTTP2_SETTINGS_LENGTH;
121                 buf += LWS_HTTP2_SETTINGS_LENGTH;
122         }
123         
124         if (len)
125                 return 1;
126         
127         return 0;
128 }
129
130 int lws_http2_frame_write(struct libwebsocket *wsi, int type, int flags, unsigned int sid, unsigned int len, unsigned char *buf)
131 {
132         unsigned char *p = &buf[-LWS_HTTP2_FRAME_HEADER_LENGTH];
133         int n;
134
135         *p++ = len >> 16;
136         *p++ = len >> 8;
137         *p++ = len;
138         *p++ = type;
139         *p++ = flags;
140         *p++ = sid >> 24;
141         *p++ = sid >> 16;
142         *p++ = sid >> 8;
143         *p++ = sid;
144         
145         lwsl_info("%s: %p. type %d, flags 0x%x, sid=%d, len=%d\n",
146                   __func__, wsi, type, flags, sid, len);
147
148         n = lws_issue_raw(wsi, &buf[-LWS_HTTP2_FRAME_HEADER_LENGTH], len + LWS_HTTP2_FRAME_HEADER_LENGTH);
149         if (n >= LWS_HTTP2_FRAME_HEADER_LENGTH)
150                 return n - LWS_HTTP2_FRAME_HEADER_LENGTH;
151         
152         return n;
153 }
154
155 static void lws_http2_settings_write(struct libwebsocket *wsi, int n, unsigned char *buf)
156 {
157         *buf++ = n >> 8;
158         *buf++ = n;
159         *buf++ = wsi->u.http2.my_settings.setting[n] >> 24;
160         *buf++ = wsi->u.http2.my_settings.setting[n] >> 16;
161         *buf++ = wsi->u.http2.my_settings.setting[n] >> 8;
162         *buf = wsi->u.http2.my_settings.setting[n];
163 }
164
165 static const char const * https_client_preface =
166         "PRI * HTTP/2.0\x0d\x0a\x0d\x0aSM\x0d\x0a\x0d\x0a";
167
168 int
169 lws_http2_parser(struct libwebsocket_context *context,
170                      struct libwebsocket *wsi, unsigned char c)
171 {
172         struct libwebsocket *wsi_new;
173
174         switch (wsi->state) {
175         case WSI_STATE_HTTP2_AWAIT_CLIENT_PREFACE:
176                 if (https_client_preface[wsi->u.http2.count++] != c)
177                         return 1;
178
179                 if (!https_client_preface[wsi->u.http2.count]) {
180                         lwsl_err("http2: %p: established\n", wsi);
181                         wsi->state = WSI_STATE_HTTP2_ESTABLISHED_PRE_SETTINGS;
182                         wsi->u.http2.count = 0;
183                         
184                         /* 
185                          * we must send a settings frame -- empty one is OK...
186                          * that must be the first thing sent by server
187                          * and the peer must send a SETTINGS with ACK flag...
188                          */
189                         
190                         lws_set_protocol_write_pending(context, wsi, LWS_PPS_HTTP2_MY_SETTINGS);
191                 }
192                 break;
193
194         case WSI_STATE_HTTP2_ESTABLISHED_PRE_SETTINGS:
195         case WSI_STATE_HTTP2_ESTABLISHED:
196                 if (wsi->u.http2.frame_state == LWS_HTTP2_FRAME_HEADER_LENGTH) { // payload
197                         /* applies to wsi->u.http2.stream_wsi which may be wsi*/
198                         switch(wsi->u.http2.type) {
199                         case LWS_HTTP2_FRAME_TYPE_SETTINGS:
200                                 wsi->u.http2.stream_wsi->u.http2.one_setting[wsi->u.http2.count % LWS_HTTP2_SETTINGS_LENGTH] = c;
201                                 if (wsi->u.http2.count % LWS_HTTP2_SETTINGS_LENGTH == LWS_HTTP2_SETTINGS_LENGTH - 1)
202                                         if (lws_http2_interpret_settings_payload(
203                                              &wsi->u.http2.stream_wsi->u.http2.peer_settings,
204                                              wsi->u.http2.one_setting,
205                                              LWS_HTTP2_SETTINGS_LENGTH))
206                                                 return 1;
207                                 break;
208                         case LWS_HTTP2_FRAME_TYPE_HEADERS:
209                                 
210                                 break;
211                         }
212                         wsi->u.http2.count++;
213                         if (wsi->u.http2.count == wsi->u.http2.length) {
214                                 wsi->u.http2.frame_state = 0;
215                                 wsi->u.http2.count = 0;
216                                 /* set our initial window size */
217                                 if (!wsi->u.http2.initialized) {
218                                         wsi->u.http2.tx_credit = wsi->u.http2.peer_settings.setting[LWS_HTTP2_SETTINGS__INITIAL_WINDOW_SIZE];
219                                         lwsl_info("initial tx credit on master conn %p: %d\n", wsi, wsi->u.http2.tx_credit);
220                                         wsi->u.http2.initialized = 1;
221                                 }
222                         }
223                         break;
224                 }
225                 switch (wsi->u.http2.frame_state++) {
226                 case 0:
227                         wsi->u.http2.length = c;
228                         break;
229                 case 1:
230                 case 2:
231                         wsi->u.http2.length <<= 8;
232                         wsi->u.http2.length |= c;
233                         break;
234                 case 3:
235                         wsi->u.http2.type = c;
236                         break;
237                 case 4:
238                         wsi->u.http2.flags = c;
239                         break;
240                 case 5:
241                 case 6:
242                 case 7:
243                 case 8:
244                         wsi->u.http2.stream_id <<= 8;
245                         wsi->u.http2.stream_id |= c;
246                         wsi->u.http2.stream_wsi = wsi;
247                         break;
248                 }
249                 if (wsi->u.http2.frame_state == LWS_HTTP2_FRAME_HEADER_LENGTH) { /* frame header complete */
250                         lwsl_info("frame: type 0x%x, flags 0x%x, sid 0x%x, len 0x%x\n",
251                                   wsi->u.http2.type, wsi->u.http2.flags, wsi->u.http2.stream_id, wsi->u.http2.length);
252                         wsi->u.http2.count = 0;
253                         
254                         
255                         switch (wsi->u.http2.type) {
256                         case LWS_HTTP2_FRAME_TYPE_SETTINGS:
257                                 /* nonzero sid on settings is illegal */
258                                 if (wsi->u.http2.stream_id)
259                                         return 1;
260                                 
261                                 if (wsi->u.http2.flags & 1) { // ack
262                                 } else {
263                                         lws_set_protocol_write_pending(context, wsi, LWS_PPS_HTTP2_ACK_SETTINGS);
264                                 }
265                                 break;
266                         case LWS_HTTP2_FRAME_TYPE_HEADERS:
267                                 if (!wsi->u.http2.stream_id)
268                                         return 1;
269                                 wsi->u.http2.stream_wsi = lws_http2_wsi_from_id(wsi, wsi->u.http2.stream_id);
270                                 if (!wsi->u.http2.stream_wsi)
271                                         wsi->u.http2.stream_wsi = lws_create_server_child_wsi(context, wsi, wsi->u.http2.stream_id);
272
273                                 if (!wsi->u.http2.stream_wsi)
274                                         return 1;
275                         }
276                         if (wsi->u.http2.length == 0)
277                                 wsi->u.http2.frame_state = 0;
278
279                 }
280                 break;
281         }
282         
283         return 0;
284 }
285
286 int lws_http2_do_pps_send(struct libwebsocket_context *context, struct libwebsocket *wsi)
287 {
288         unsigned char settings[LWS_SEND_BUFFER_PRE_PADDING + 6 * LWS_HTTP2_SETTINGS__COUNT];
289         int n, m = 0;
290
291         switch (wsi->pps) {
292         case LWS_PPS_HTTP2_MY_SETTINGS:
293                 for (n = 1; n < LWS_HTTP2_SETTINGS__COUNT; n++)
294                         if (wsi->u.http2.my_settings.setting[n] != lws_http2_default_settings.setting[n]) {
295                                 lws_http2_settings_write(wsi, n,
296                                                          &settings[LWS_SEND_BUFFER_PRE_PADDING + m]);
297                                 m += sizeof(wsi->u.http2.one_setting);
298                         }
299                 n = lws_http2_frame_write(wsi, LWS_HTTP2_FRAME_TYPE_SETTINGS,
300                                           0, LWS_HTTP2_STREAM_ID_MASTER, m,
301                                           &settings[LWS_SEND_BUFFER_PRE_PADDING]);
302                 if (n != m) {
303                         lwsl_info("send %d %d\n", n, m);
304                         return 1;
305                 }
306                 break;
307         case LWS_PPS_HTTP2_ACK_SETTINGS:
308                 /* send ack ... always empty */
309                 n = lws_http2_frame_write(wsi, LWS_HTTP2_FRAME_TYPE_SETTINGS,
310                         1, LWS_HTTP2_STREAM_ID_MASTER, 0,
311                         &settings[LWS_SEND_BUFFER_PRE_PADDING]);
312                 if (n) {
313                         lwsl_err("ack tells %d\n", n);
314                         return 1;
315                 }
316                 /* this is the end of the preface dance then? */
317                 if (wsi->state == WSI_STATE_HTTP2_ESTABLISHED_PRE_SETTINGS) {
318                         wsi->state = WSI_STATE_HTTP2_ESTABLISHED;
319                         
320                         wsi->u.http.fd = LWS_INVALID_FILE;
321                         
322                         /* service the http request itself */
323                         //lwsl_info("servicing initial http request\n");
324                         //n = lws_http_action(context, wsi);
325
326                         return 0;
327                 }
328                 break;
329         default:
330                 break;
331         }
332         
333         return 0;
334 }