client: protect against possible NULL deref path
[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 lws *
42 lws_http2_wsi_from_id(struct lws *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 lws *
55 lws_create_server_child_wsi(struct lws_context *context, struct lws *parent_wsi,
56                             unsigned int sid)
57 {
58         struct lws *wsi = lws_create_new_server_wsi(context);
59
60         if (!wsi)
61                 return NULL;
62
63         /* no more children allowed by parent */
64         if (parent_wsi->u.http2.child_count + 1 ==
65             parent_wsi->u.http2.peer_settings.setting[
66                         LWS_HTTP2_SETTINGS__MAX_CONCURRENT_STREAMS])
67                 return NULL;
68
69         lws_http2_init(&wsi->u.http2.peer_settings);
70         lws_http2_init(&wsi->u.http2.my_settings);
71         wsi->u.http2.stream_id = sid;
72         wsi->u.http2.my_stream_id = sid;
73
74         wsi->u.http2.parent_wsi = parent_wsi;
75         wsi->u.http2.next_child_wsi = parent_wsi->u.http2.next_child_wsi;
76         parent_wsi->u.http2.next_child_wsi = wsi;
77         parent_wsi->u.http2.child_count++;
78
79         wsi->u.http2.my_priority = 16;
80         wsi->u.http2.tx_credit = 65535;
81
82         wsi->state = LWSS_HTTP2_ESTABLISHED;
83         wsi->mode = parent_wsi->mode;
84
85         wsi->protocol = &context->protocols[0];
86         lws_ensure_user_space(wsi);
87
88         lwsl_info("%s: %p new child %p, sid %d, user_space=%p\n", __func__,
89                   parent_wsi, wsi, sid, wsi->user_space);
90
91         return wsi;
92 }
93
94 int lws_remove_server_child_wsi(struct lws_context *context, struct lws *wsi)
95 {
96         struct lws **w = &wsi->u.http2.parent_wsi;
97         do {
98                 if (*w == wsi) {
99                         *w = wsi->u.http2.next_child_wsi;
100                         (wsi->u.http2.parent_wsi)->u.http2.child_count--;
101                         return 0;
102                 }
103
104                 w = &((*w)->u.http2.next_child_wsi);
105         } while (*w);
106
107         lwsl_err("%s: can't find %p\n", __func__, wsi);
108         return 1;
109 }
110
111 int
112 lws_http2_interpret_settings_payload(struct http2_settings *settings,
113                                      unsigned char *buf, int len)
114 {
115         unsigned int a, b;
116
117         if (!len)
118                 return 0;
119
120         if (len < LWS_HTTP2_SETTINGS_LENGTH)
121                 return 1;
122
123         while (len >= LWS_HTTP2_SETTINGS_LENGTH) {
124                 a = (buf[0] << 8) | buf[1];
125                 if (a < LWS_HTTP2_SETTINGS__COUNT) {
126                         b = buf[2] << 24 | buf[3] << 16 | buf[4] << 8 | buf[5];
127                         settings->setting[a] = b;
128                         lwsl_info("http2 settings %d <- 0x%x\n", a, b);
129                 }
130                 len -= LWS_HTTP2_SETTINGS_LENGTH;
131                 buf += LWS_HTTP2_SETTINGS_LENGTH;
132         }
133
134         if (len)
135                 return 1;
136
137         return 0;
138 }
139
140 struct lws *lws_http2_get_network_wsi(struct lws *wsi)
141 {
142         while (wsi->u.http2.parent_wsi)
143                 wsi = wsi->u.http2.parent_wsi;
144
145         return wsi;
146 }
147
148 int lws_http2_frame_write(struct lws *wsi, int type, int flags,
149                           unsigned int sid, unsigned int len, unsigned char *buf)
150 {
151         struct lws *wsi_eff = lws_http2_get_network_wsi(wsi);
152         unsigned char *p = &buf[-LWS_HTTP2_FRAME_HEADER_LENGTH];
153         int n;
154
155         *p++ = len >> 16;
156         *p++ = len >> 8;
157         *p++ = len;
158         *p++ = type;
159         *p++ = flags;
160         *p++ = sid >> 24;
161         *p++ = sid >> 16;
162         *p++ = sid >> 8;
163         *p++ = sid;
164
165         lwsl_info("%s: %p (eff %p). type %d, flags 0x%x, sid=%d, len=%d\n",
166                   __func__, wsi, wsi_eff, type, flags, sid, len,
167                   wsi->u.http2.tx_credit);
168
169         if (type == LWS_HTTP2_FRAME_TYPE_DATA) {
170                 if (wsi->u.http2.tx_credit < len)
171                         lwsl_err("%s: %p: sending payload len %d"
172                                  " but tx_credit only %d!\n", len,
173                                  wsi->u.http2.tx_credit);
174                 wsi->u.http2.tx_credit -= len;
175         }
176
177         n = lws_issue_raw(wsi_eff, &buf[-LWS_HTTP2_FRAME_HEADER_LENGTH],
178                           len + LWS_HTTP2_FRAME_HEADER_LENGTH);
179         if (n >= LWS_HTTP2_FRAME_HEADER_LENGTH)
180                 return n - LWS_HTTP2_FRAME_HEADER_LENGTH;
181
182         return n;
183 }
184
185 static void lws_http2_settings_write(struct lws *wsi, int n, unsigned char *buf)
186 {
187         *buf++ = n >> 8;
188         *buf++ = n;
189         *buf++ = wsi->u.http2.my_settings.setting[n] >> 24;
190         *buf++ = wsi->u.http2.my_settings.setting[n] >> 16;
191         *buf++ = wsi->u.http2.my_settings.setting[n] >> 8;
192         *buf = wsi->u.http2.my_settings.setting[n];
193 }
194
195 static const char * https_client_preface =
196         "PRI * HTTP/2.0\x0d\x0a\x0d\x0aSM\x0d\x0a\x0d\x0a";
197
198 int
199 lws_http2_parser(struct lws *wsi, unsigned char c)
200 {
201         struct lws_context *context = wsi->context;
202         struct lws *swsi;
203         int n;
204
205         switch (wsi->state) {
206         case LWSS_HTTP2_AWAIT_CLIENT_PREFACE:
207                 if (https_client_preface[wsi->u.http2.count++] != c)
208                         return 1;
209
210                 if (!https_client_preface[wsi->u.http2.count]) {
211                         lwsl_info("http2: %p: established\n", wsi);
212                         wsi->state = LWSS_HTTP2_ESTABLISHED_PRE_SETTINGS;
213                         wsi->u.http2.count = 0;
214                         wsi->u.http2.tx_credit = 65535;
215
216                         /*
217                          * we must send a settings frame -- empty one is OK...
218                          * that must be the first thing sent by server
219                          * and the peer must send a SETTINGS with ACK flag...
220                          */
221
222                         lws_set_protocol_write_pending(wsi,
223                                                        LWS_PPS_HTTP2_MY_SETTINGS);
224                 }
225                 break;
226
227         case LWSS_HTTP2_ESTABLISHED_PRE_SETTINGS:
228         case LWSS_HTTP2_ESTABLISHED:
229                 if (wsi->u.http2.frame_state == LWS_HTTP2_FRAME_HEADER_LENGTH) { // payload
230                         wsi->u.http2.count++;
231                         wsi->u.http2.stream_wsi->u.http2.count = wsi->u.http2.count;
232                         /* applies to wsi->u.http2.stream_wsi which may be wsi*/
233                         switch(wsi->u.http2.type) {
234                         case LWS_HTTP2_FRAME_TYPE_SETTINGS:
235                                 wsi->u.http2.stream_wsi->u.http2.one_setting[wsi->u.http2.count % LWS_HTTP2_SETTINGS_LENGTH] = c;
236                                 if (wsi->u.http2.count % LWS_HTTP2_SETTINGS_LENGTH == LWS_HTTP2_SETTINGS_LENGTH - 1)
237                                         if (lws_http2_interpret_settings_payload(
238                                              &wsi->u.http2.stream_wsi->u.http2.peer_settings,
239                                              wsi->u.http2.one_setting,
240                                              LWS_HTTP2_SETTINGS_LENGTH))
241                                                 return 1;
242                                 break;
243                         case LWS_HTTP2_FRAME_TYPE_CONTINUATION:
244                         case LWS_HTTP2_FRAME_TYPE_HEADERS:
245                                 lwsl_info(" %02X\n", c);
246                                 if (lws_hpack_interpret(wsi->u.http2.stream_wsi, c))
247                                         return 1;
248                                 break;
249                         case LWS_HTTP2_FRAME_TYPE_GOAWAY:
250                                 if (wsi->u.http2.count >= 5 && wsi->u.http2.count <= 8) {
251                                         wsi->u.http2.hpack_e_dep <<= 8;
252                                         wsi->u.http2.hpack_e_dep |= c;
253                                         if (wsi->u.http2.count == 8) {
254                                                 lwsl_info("goaway err 0x%x\n", wsi->u.http2.hpack_e_dep);
255                                         }
256                                 }
257                                 wsi->u.http2.GOING_AWAY = 1;
258                                 break;
259                         case LWS_HTTP2_FRAME_TYPE_DATA:
260                                 break;
261                         case LWS_HTTP2_FRAME_TYPE_PRIORITY:
262                                 break;
263                         case LWS_HTTP2_FRAME_TYPE_RST_STREAM:
264                                 break;
265                         case LWS_HTTP2_FRAME_TYPE_PUSH_PROMISE:
266                                 break;
267                         case LWS_HTTP2_FRAME_TYPE_PING:
268                                 if (wsi->u.http2.flags & LWS_HTTP2_FLAG_SETTINGS_ACK) { // ack
269                                 } else { /* they're sending us a ping request */
270                                         if (wsi->u.http2.count > 8)
271                                                 return 1;
272                                         wsi->u.http2.ping_payload[wsi->u.http2.count - 1] = c;
273                                 }
274                                 break;
275                         case LWS_HTTP2_FRAME_TYPE_WINDOW_UPDATE:
276                                 wsi->u.http2.hpack_e_dep <<= 8;
277                                 wsi->u.http2.hpack_e_dep |= c;
278                                 break;
279                         }
280                         if (wsi->u.http2.count != wsi->u.http2.length)
281                                 break;
282
283                         /* end of frame */
284
285                         wsi->u.http2.frame_state = 0;
286                         wsi->u.http2.count = 0;
287                         swsi = wsi->u.http2.stream_wsi;
288                         /* set our initial window size */
289                         if (!wsi->u.http2.initialized) {
290                                 wsi->u.http2.tx_credit = wsi->u.http2.peer_settings.setting[LWS_HTTP2_SETTINGS__INITIAL_WINDOW_SIZE];
291                                 lwsl_info("initial tx credit on master conn %p: %d\n", wsi, wsi->u.http2.tx_credit);
292                                 wsi->u.http2.initialized = 1;
293                         }
294                         switch (wsi->u.http2.type) {
295                         case LWS_HTTP2_FRAME_TYPE_HEADERS:
296                                 /* service the http request itself */
297                                 lwsl_info("servicing initial http request, wsi=%p, stream wsi=%p\n", wsi, wsi->u.http2.stream_wsi);
298                                 n = lws_http_action(swsi);
299                                 (void)n;
300                                 lwsl_info("  action result %d\n", n);
301                                 break;
302                         case LWS_HTTP2_FRAME_TYPE_PING:
303                                 if (wsi->u.http2.flags & LWS_HTTP2_FLAG_SETTINGS_ACK) { // ack
304                                 } else { /* they're sending us a ping request */
305                                         lws_set_protocol_write_pending(wsi, LWS_PPS_HTTP2_PONG);
306                                 }
307                                 break;
308                         case LWS_HTTP2_FRAME_TYPE_WINDOW_UPDATE:
309                                 wsi->u.http2.hpack_e_dep &= ~(1 << 31);
310                                 if ((long long)swsi->u.http2.tx_credit + (unsigned long long)wsi->u.http2.hpack_e_dep > (~(1 << 31)))
311                                         return 1; /* actually need to close swsi not the whole show */
312                                 swsi->u.http2.tx_credit += wsi->u.http2.hpack_e_dep;
313                                 if (swsi->u.http2.waiting_tx_credit && swsi->u.http2.tx_credit > 0) {
314                                         lwsl_info("%s: %p: waiting_tx_credit -> wait on writeable\n", __func__, wsi);
315                                         swsi->u.http2.waiting_tx_credit = 0;
316                                         lws_callback_on_writable(swsi);
317                                 }
318                                 break;
319                         }
320                         break;
321                 }
322                 switch (wsi->u.http2.frame_state++) {
323                 case 0:
324                         wsi->u.http2.length = c;
325                         break;
326                 case 1:
327                 case 2:
328                         wsi->u.http2.length <<= 8;
329                         wsi->u.http2.length |= c;
330                         break;
331                 case 3:
332                         wsi->u.http2.type = c;
333                         break;
334                 case 4:
335                         wsi->u.http2.flags = c;
336                         break;
337                 case 5:
338                 case 6:
339                 case 7:
340                 case 8:
341                         wsi->u.http2.stream_id <<= 8;
342                         wsi->u.http2.stream_id |= c;
343                         break;
344                 }
345                 if (wsi->u.http2.frame_state == LWS_HTTP2_FRAME_HEADER_LENGTH) { /* frame header complete */
346                         lwsl_info("frame: type 0x%x, flags 0x%x, sid 0x%x, len 0x%x\n",
347                                   wsi->u.http2.type, wsi->u.http2.flags, wsi->u.http2.stream_id, wsi->u.http2.length);
348                         wsi->u.http2.count = 0;
349
350                         wsi->u.http2.stream_wsi = wsi;
351                         if (wsi->u.http2.stream_id)
352                                 wsi->u.http2.stream_wsi = lws_http2_wsi_from_id(wsi, wsi->u.http2.stream_id);
353
354                         switch (wsi->u.http2.type) {
355                         case LWS_HTTP2_FRAME_TYPE_SETTINGS:
356                                 /* nonzero sid on settings is illegal */
357                                 if (wsi->u.http2.stream_id)
358                                         return 1;
359
360                                 if (wsi->u.http2.flags & LWS_HTTP2_FLAG_SETTINGS_ACK) { // ack
361                                 } else
362                                         /* non-ACK coming in means we must ACK it */
363                                         lws_set_protocol_write_pending(wsi, LWS_PPS_HTTP2_ACK_SETTINGS);
364                                 break;
365                         case LWS_HTTP2_FRAME_TYPE_PING:
366                                 if (wsi->u.http2.stream_id)
367                                         return 1;
368                                 if (wsi->u.http2.length != 8)
369                                         return 1;
370                                 break;
371                         case LWS_HTTP2_FRAME_TYPE_CONTINUATION:
372                                 if (wsi->u.http2.END_HEADERS)
373                                         return 1;
374                                 goto update_end_headers;
375
376                         case LWS_HTTP2_FRAME_TYPE_HEADERS:
377                                 lwsl_info("LWS_HTTP2_FRAME_TYPE_HEADERS: stream_id = %d\n", wsi->u.http2.stream_id);
378                                 if (!wsi->u.http2.stream_id)
379                                         return 1;
380                                 if (!wsi->u.http2.stream_wsi)
381                                         wsi->u.http2.stream_wsi = lws_create_server_child_wsi(context, wsi, wsi->u.http2.stream_id);
382
383                                 /* END_STREAM means after servicing this, close the stream */
384                                 wsi->u.http2.END_STREAM = !!(wsi->u.http2.flags & LWS_HTTP2_FLAG_END_STREAM);
385                                 lwsl_info("%s: headers END_STREAM = %d\n",__func__, wsi->u.http2.END_STREAM);
386 update_end_headers:
387                                 /* no END_HEADERS means CONTINUATION must come */
388                                 wsi->u.http2.END_HEADERS = !!(wsi->u.http2.flags & LWS_HTTP2_FLAG_END_HEADERS);
389
390                                 swsi = wsi->u.http2.stream_wsi;
391                                 if (!swsi)
392                                         return 1;
393
394
395                                 /* prepare the hpack parser at the right start */
396
397                                 swsi->u.http2.flags = wsi->u.http2.flags;
398                                 swsi->u.http2.length = wsi->u.http2.length;
399                                 swsi->u.http2.END_STREAM = wsi->u.http2.END_STREAM;
400
401                                 if (swsi->u.http2.flags & LWS_HTTP2_FLAG_PADDED)
402                                         swsi->u.http2.hpack = HPKS_OPT_PADDING;
403                                 else
404                                         if (swsi->u.http2.flags & LWS_HTTP2_FLAG_PRIORITY) {
405                                                 swsi->u.http2.hpack = HKPS_OPT_E_DEPENDENCY;
406                                                 swsi->u.http2.hpack_m = 4;
407                                         } else
408                                                 swsi->u.http2.hpack = HPKS_TYPE;
409                                 lwsl_info("initial hpack state %d\n", swsi->u.http2.hpack);
410                                 break;
411                         case LWS_HTTP2_FRAME_TYPE_WINDOW_UPDATE:
412                                 if (wsi->u.http2.length != 4)
413                                         return 1;
414                                 break;
415                         }
416                         if (wsi->u.http2.length == 0)
417                                 wsi->u.http2.frame_state = 0;
418
419                 }
420                 break;
421         }
422
423         return 0;
424 }
425
426 int lws_http2_do_pps_send(struct lws_context *context, struct lws *wsi)
427 {
428         unsigned char settings[LWS_PRE + 6 * LWS_HTTP2_SETTINGS__COUNT];
429         struct lws *swsi;
430         int n, m = 0;
431
432         lwsl_debug("%s: %p: %d\n", __func__, wsi, wsi->pps);
433
434         switch (wsi->pps) {
435         case LWS_PPS_HTTP2_MY_SETTINGS:
436                 for (n = 1; n < LWS_HTTP2_SETTINGS__COUNT; n++)
437                         if (wsi->u.http2.my_settings.setting[n] != lws_http2_default_settings.setting[n]) {
438                                 lws_http2_settings_write(wsi, n,
439                                                          &settings[LWS_PRE + m]);
440                                 m += sizeof(wsi->u.http2.one_setting);
441                         }
442                 n = lws_http2_frame_write(wsi, LWS_HTTP2_FRAME_TYPE_SETTINGS,
443                                           0, LWS_HTTP2_STREAM_ID_MASTER, m,
444                                           &settings[LWS_PRE]);
445                 if (n != m) {
446                         lwsl_info("send %d %d\n", n, m);
447                         return 1;
448                 }
449                 break;
450         case LWS_PPS_HTTP2_ACK_SETTINGS:
451                 /* send ack ... always empty */
452                 n = lws_http2_frame_write(wsi, LWS_HTTP2_FRAME_TYPE_SETTINGS,
453                         1, LWS_HTTP2_STREAM_ID_MASTER, 0,
454                         &settings[LWS_PRE]);
455                 if (n) {
456                         lwsl_err("ack tells %d\n", n);
457                         return 1;
458                 }
459                 /* this is the end of the preface dance then? */
460                 if (wsi->state == LWSS_HTTP2_ESTABLISHED_PRE_SETTINGS) {
461                         wsi->state = LWSS_HTTP2_ESTABLISHED;
462
463                         wsi->u.http.fd = LWS_INVALID_FILE;
464
465                         if (lws_is_ssl(lws_http2_get_network_wsi(wsi))) {
466                                 lwsl_info("skipping nonexistant ssl upgrade headers\n");
467                                 break;
468                         }
469
470                         /*
471                          * we need to treat the headers from this upgrade
472                          * as the first job.  These need to get
473                          * shifted to stream ID 1
474                          */
475                         lwsl_info("%s: setting up sid 1\n", __func__);
476
477                         swsi = wsi->u.http2.stream_wsi = lws_create_server_child_wsi(context, wsi, 1);
478                         /* pass on the initial headers to SID 1 */
479                         swsi->u.http.ah = wsi->u.http.ah;
480                         wsi->u.http.ah = NULL;
481
482                         lwsl_info("%s: inherited headers %p\n", __func__, swsi->u.http.ah);
483                         swsi->u.http2.tx_credit = wsi->u.http2.peer_settings.setting[LWS_HTTP2_SETTINGS__INITIAL_WINDOW_SIZE];
484                         lwsl_info("initial tx credit on conn %p: %d\n", swsi, swsi->u.http2.tx_credit);
485                         swsi->u.http2.initialized = 1;
486                         /* demanded by HTTP2 */
487                         swsi->u.http2.END_STREAM = 1;
488                         lwsl_info("servicing initial http request\n");
489                         return lws_http_action(swsi);
490                 }
491                 break;
492         case LWS_PPS_HTTP2_PONG:
493                 memcpy(&settings[LWS_PRE], wsi->u.http2.ping_payload, 8);
494                 n = lws_http2_frame_write(wsi, LWS_HTTP2_FRAME_TYPE_PING,
495                                           LWS_HTTP2_FLAG_SETTINGS_ACK,
496                                           LWS_HTTP2_STREAM_ID_MASTER, 8,
497                                           &settings[LWS_PRE]);
498                 if (n != 8) {
499                         lwsl_info("send %d %d\n", n, m);
500                         return 1;
501                 }
502                 break;
503         default:
504                 break;
505         }
506
507         return 0;
508 }
509
510 struct lws * lws_http2_get_nth_child(struct lws *wsi, int n)
511 {
512         do {
513                 wsi = wsi->u.http2.next_child_wsi;
514                 if (!wsi)
515                         return NULL;
516         } while (n--);
517
518         return wsi;
519 }