websocket: Tune maximum received length
[src/app-framework-binder.git] / src / websock.c
1 /*
2  * Copyright (C) 2016, 2017 "IoT.bzh"
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /*
18  * This work is a far adaptation of apache-websocket:
19  *   origin:  https://github.com/disconnect/apache-websocket
20  *   commit:  cfaef071223f11ba016bff7e1e4b7c9e5df45b50
21  *   Copyright 2010-2012 self.disconnect (APACHE-2)
22  */
23
24 #include <stdlib.h>
25 #include <stdint.h>
26 #include <errno.h>
27 #include <string.h>
28 #include <sys/uio.h>
29
30 #include "websock.h"
31
32 #define BLOCK_DATA_SIZE              4096
33 #if !defined(WEBSOCKET_DEFAULT_MAXLENGTH)
34 #  define WEBSOCKET_DEFAULT_MAXLENGTH 1048500  /* 76 less than 1M, probably enougth for headers */
35 #endif
36
37 #define FRAME_GET_FIN(BYTE)         (((BYTE) >> 7) & 0x01)
38 #define FRAME_GET_RSV1(BYTE)        (((BYTE) >> 6) & 0x01)
39 #define FRAME_GET_RSV2(BYTE)        (((BYTE) >> 5) & 0x01)
40 #define FRAME_GET_RSV3(BYTE)        (((BYTE) >> 4) & 0x01)
41 #define FRAME_GET_OPCODE(BYTE)      ( (BYTE)       & 0x0F)
42 #define FRAME_GET_MASK(BYTE)        (((BYTE) >> 7) & 0x01)
43 #define FRAME_GET_PAYLOAD_LEN(BYTE) ( (BYTE)       & 0x7F)
44
45 #define FRAME_SET_FIN(BYTE)         (((BYTE) & 0x01) << 7)
46 #define FRAME_SET_RSV1(BYTE)        (((BYTE) & 0x01) << 6)
47 #define FRAME_SET_RSV2(BYTE)        (((BYTE) & 0x01) << 5)
48 #define FRAME_SET_RSV3(BYTE)        (((BYTE) & 0x01) << 4)
49 #define FRAME_SET_OPCODE(BYTE)      ((BYTE) & 0x0F)
50 #define FRAME_SET_MASK(BYTE)        (((BYTE) & 0x01) << 7)
51 #define FRAME_SET_LENGTH(X64, IDX)  (unsigned char)((sizeof(X64)) <= (IDX) ? 0 : (((X64) >> ((IDX)*8)) & 0xFF))
52
53 #define OPCODE_CONTINUATION 0x0
54 #define OPCODE_TEXT         0x1
55 #define OPCODE_BINARY       0x2
56 #define OPCODE_CLOSE        0x8
57 #define OPCODE_PING         0x9
58 #define OPCODE_PONG         0xA
59
60 #define STATE_INIT    0
61 #define STATE_START   1
62 #define STATE_LENGTH  2
63 #define STATE_DATA    3
64
65 static size_t default_maxlength = WEBSOCKET_DEFAULT_MAXLENGTH;
66
67 struct websock {
68         int state;
69         uint64_t maxlength;
70         int lenhead, szhead;
71         uint64_t length;
72         uint32_t mask;
73         unsigned char header[14];       /* 2 + 8 + 4 */
74         const struct websock_itf *itf;
75         void *closure;
76 };
77
78 static ssize_t ws_writev(struct websock *ws, const struct iovec *iov, int iovcnt)
79 {
80         return ws->itf->writev(ws->closure, iov, iovcnt);
81 }
82
83 static ssize_t ws_readv(struct websock *ws, const struct iovec *iov, int iovcnt)
84 {
85         return ws->itf->readv(ws->closure, iov, iovcnt);
86 }
87
88 #if 0
89 static ssize_t ws_write(struct websock *ws, const void *buffer, size_t buffer_size)
90 {
91         struct iovec iov;
92         iov.iov_base = (void *)buffer;  /* const cast */
93         iov.iov_len = buffer_size;
94         return ws_writev(ws, &iov, 1);
95 }
96 #endif
97
98 static ssize_t ws_read(struct websock *ws, void *buffer, size_t buffer_size)
99 {
100         struct iovec iov;
101         iov.iov_base = buffer;
102         iov.iov_len = buffer_size;
103         return ws_readv(ws, &iov, 1);
104 }
105
106 static int websock_send_internal_v(struct websock *ws, unsigned char first, const struct iovec *iovec, int count)
107 {
108         struct iovec iov[32];
109         int i, j;
110         size_t pos, size, len;
111         ssize_t rc;
112         unsigned char header[32];
113
114         /* checks count */
115         if (count < 0 || (count + 1) > (int)(sizeof iov / sizeof * iov)) {
116                 errno = EINVAL;
117                 return -1;
118         }
119
120         /* computes the size */
121         size = 0;
122         i = 1;
123         for (j = 0 ; j < count ; j++) {
124                 iov[i].iov_base = iovec[j].iov_base;
125                 len = iovec[j].iov_len;
126                 if (len != 0) {
127                         iov[i].iov_len = len;
128                         size += len;
129                         i++;
130                 }
131         }
132
133         /* makes the header */
134         pos = 0;
135         header[pos++] = first;
136         size = (uint64_t) size;
137         if (size < 126) {
138                 header[pos++] = FRAME_SET_MASK(0) | FRAME_SET_LENGTH(size, 0);
139         } else {
140                 if (size < 65536) {
141                         header[pos++] = FRAME_SET_MASK(0) | 126;
142                 } else {
143                         header[pos++] = FRAME_SET_MASK(0) | 127;
144                         header[pos++] = FRAME_SET_LENGTH(size, 7);
145                         header[pos++] = FRAME_SET_LENGTH(size, 6);
146                         header[pos++] = FRAME_SET_LENGTH(size, 5);
147                         header[pos++] = FRAME_SET_LENGTH(size, 4);
148                         header[pos++] = FRAME_SET_LENGTH(size, 3);
149                         header[pos++] = FRAME_SET_LENGTH(size, 2);
150                 }
151                 header[pos++] = FRAME_SET_LENGTH(size, 1);
152                 header[pos++] = FRAME_SET_LENGTH(size, 0);
153         }
154
155         /* allocates the vec */
156         iov[0].iov_base = header;
157         iov[0].iov_len = pos;
158         rc = ws_writev(ws, iov, i);
159
160         return rc < 0 ? -1 : 0;
161 }
162
163 static int websock_send_internal(struct websock *ws, unsigned char first, const void *buffer, size_t size)
164 {
165         struct iovec iov;
166
167         iov.iov_base = (void *)buffer;
168         iov.iov_len = size;
169         return websock_send_internal_v(ws, first, &iov, 1);
170 }
171
172 static inline int websock_send_v(struct websock *ws, int last, int rsv1, int rsv2, int rsv3, int opcode, const struct iovec *iovec, int count)
173 {
174         unsigned char first = (unsigned char)(FRAME_SET_FIN(last)
175                                 | FRAME_SET_RSV1(rsv1)
176                                 | FRAME_SET_RSV1(rsv2)
177                                 | FRAME_SET_RSV1(rsv3)
178                                 | FRAME_SET_OPCODE(opcode));
179         return websock_send_internal_v(ws, first, iovec, count);
180 }
181
182 static inline int websock_send(struct websock *ws, int last, int rsv1, int rsv2, int rsv3, int opcode, const void *buffer, size_t size)
183 {
184         unsigned char first = (unsigned char)(FRAME_SET_FIN(last)
185                                 | FRAME_SET_RSV1(rsv1)
186                                 | FRAME_SET_RSV1(rsv2)
187                                 | FRAME_SET_RSV1(rsv3)
188                                 | FRAME_SET_OPCODE(opcode));
189         return websock_send_internal(ws, first, buffer, size);
190 }
191
192 int websock_close_empty(struct websock *ws)
193 {
194         return websock_close(ws, WEBSOCKET_CODE_NOT_SET, NULL, 0);
195 }
196
197 int websock_close(struct websock *ws, uint16_t code, const void *data, size_t length)
198 {
199         unsigned char buffer[2];
200         struct iovec iov[2];
201
202         if (code == WEBSOCKET_CODE_NOT_SET && length == 0)
203                 return websock_send(ws, 1, 0, 0, 0, OPCODE_CLOSE, NULL, 0);
204
205         /* checks the length */
206         if (length > 123) {
207                 errno = EINVAL;
208                 return -1;
209         }
210
211         /* prepare the buffer */
212         buffer[0] = (unsigned char)((code >> 8) & 0xFF);
213         buffer[1] = (unsigned char)(code & 0xFF);
214
215         /* Send server-side closing handshake */
216         iov[0].iov_base = (void *)buffer;
217         iov[0].iov_len = 2;
218         iov[1].iov_base = (void *)data;
219         iov[1].iov_len = length;
220         return websock_send_v(ws, 1, 0, 0, 0, OPCODE_CLOSE, iov, 2);
221 }
222
223 int websock_ping(struct websock *ws, const void *data, size_t length)
224 {
225         /* checks the length */
226         if (length > 125) {
227                 errno = EINVAL;
228                 return -1;
229         }
230
231         return websock_send(ws, 1, 0, 0, 0, OPCODE_PING, data, length);
232 }
233
234 int websock_pong(struct websock *ws, const void *data, size_t length)
235 {
236         /* checks the length */
237         if (length > 125) {
238                 errno = EINVAL;
239                 return -1;
240         }
241
242         return websock_send(ws, 1, 0, 0, 0, OPCODE_PONG, data, length);
243 }
244
245 int websock_text(struct websock *ws, int last, const void *text, size_t length)
246 {
247         return websock_send(ws, last, 0, 0, 0, OPCODE_TEXT, text, length);
248 }
249
250 int websock_text_v(struct websock *ws, int last, const struct iovec *iovec, int count)
251 {
252         return websock_send_v(ws, last, 0, 0, 0, OPCODE_TEXT, iovec, count);
253 }
254
255 int websock_binary(struct websock *ws, int last, const void *data, size_t length)
256 {
257         return websock_send(ws, last, 0, 0, 0, OPCODE_BINARY, data, length);
258 }
259
260 int websock_binary_v(struct websock *ws, int last, const struct iovec *iovec, int count)
261 {
262         return websock_send_v(ws, last, 0, 0, 0, OPCODE_BINARY, iovec, count);
263 }
264
265 int websock_continue(struct websock *ws, int last, const void *data, size_t length)
266 {
267         return websock_send(ws, last, 0, 0, 0, OPCODE_CONTINUATION, data, length);
268 }
269
270 int websock_continue_v(struct websock *ws, int last, const struct iovec *iovec, int count)
271 {
272         return websock_send_v(ws, last, 0, 0, 0, OPCODE_CONTINUATION, iovec, count);
273 }
274
275 int websock_error(struct websock *ws, uint16_t code, const void *data, size_t size)
276 {
277         int rc = websock_close(ws, code, data, size);
278         if (ws->itf->on_error != NULL)
279                 ws->itf->on_error(ws->closure, code, data, size);
280         return rc;
281 }
282
283 static int read_header(struct websock *ws)
284 {
285         if (ws->lenhead < ws->szhead) {
286                 ssize_t rbc =
287                     ws_read(ws, &ws->header[ws->lenhead], (size_t)(ws->szhead - ws->lenhead));
288                 if (rbc < 0)
289                         return -1;
290                 ws->lenhead += (int)rbc;
291         }
292         return 0;
293 }
294
295 static int check_control_header(struct websock *ws)
296 {
297         /* sanity checks */
298         if (FRAME_GET_RSV1(ws->header[0]) != 0)
299                 return 0;
300         if (FRAME_GET_RSV2(ws->header[0]) != 0)
301                 return 0;
302         if (FRAME_GET_RSV3(ws->header[0]) != 0)
303                 return 0;
304         if (FRAME_GET_PAYLOAD_LEN(ws->header[1]) > 125)
305                 return 0;
306         if (FRAME_GET_OPCODE(ws->header[0]) == OPCODE_CLOSE)
307                 return FRAME_GET_PAYLOAD_LEN(ws->header[1]) != 1;
308         return 1;
309 }
310
311 int websock_dispatch(struct websock *ws, int loop)
312 {
313         uint16_t code;
314 loop:
315         switch (ws->state) {
316         case STATE_INIT:
317                 ws->lenhead = 0;
318                 ws->szhead = 2;
319                 ws->state = STATE_START;
320                 /*@fallthrough@*/
321
322         case STATE_START:
323                 /* read the header */
324                 if (read_header(ws))
325                         return -1;
326                 else if (ws->lenhead < ws->szhead)
327                         return 0;
328                 /* fast track */
329                 switch (FRAME_GET_OPCODE(ws->header[0])) {
330                 case OPCODE_CONTINUATION:
331                 case OPCODE_TEXT:
332                 case OPCODE_BINARY:
333                         break;
334                 case OPCODE_CLOSE:
335                         if (!check_control_header(ws))
336                                 goto protocol_error;
337                         if (FRAME_GET_PAYLOAD_LEN(ws->header[1]))
338                                 ws->szhead += 2;
339                         break;
340                 case OPCODE_PING:
341                 case OPCODE_PONG:
342                         if (!check_control_header(ws))
343                                 goto protocol_error;
344                 default:
345                         break;
346                 }
347                 /* update heading size */
348                 switch (FRAME_GET_PAYLOAD_LEN(ws->header[1])) {
349                 case 127:
350                         ws->szhead += 6;
351                         /*@fallthrough@*/
352                 case 126:
353                         ws->szhead += 2;
354                         /*@fallthrough@*/
355                 default:
356                         ws->szhead += 4 * FRAME_GET_MASK(ws->header[1]);
357                 }
358                 ws->state = STATE_LENGTH;
359                 /*@fallthrough@*/
360
361         case STATE_LENGTH:
362                 /* continue to read the header */
363                 if (read_header(ws))
364                         return -1;
365                 else if (ws->lenhead < ws->szhead)
366                         return 0;
367
368                 /* compute length */
369                 switch (FRAME_GET_PAYLOAD_LEN(ws->header[1])) {
370                 case 127:
371                         ws->length = (((uint64_t) ws->header[2]) << 56)
372                             | (((uint64_t) ws->header[3]) << 48)
373                             | (((uint64_t) ws->header[4]) << 40)
374                             | (((uint64_t) ws->header[5]) << 32)
375                             | (((uint64_t) ws->header[6]) << 24)
376                             | (((uint64_t) ws->header[7]) << 16)
377                             | (((uint64_t) ws->header[8]) << 8)
378                             | (uint64_t) ws->header[9];
379                         break;
380                 case 126:
381                         ws->length = (((uint64_t) ws->header[2]) << 8)
382                             | (uint64_t) ws->header[3];
383                         break;
384                 default:
385                         ws->length = FRAME_GET_PAYLOAD_LEN(ws->header[1]);
386                         break;
387                 }
388                 if (FRAME_GET_OPCODE(ws->header[0]) == OPCODE_CLOSE && ws->length != 0)
389                         ws->length -= 2;
390                 if (ws->length > ws->maxlength)
391                         goto too_long_error;
392
393                 /* compute mask */
394                 if (FRAME_GET_MASK(ws->header[1])) {
395                         ((unsigned char *)&ws->mask)[0] = ws->header[ws->szhead - 4];
396                         ((unsigned char *)&ws->mask)[1] = ws->header[ws->szhead - 3];
397                         ((unsigned char *)&ws->mask)[2] = ws->header[ws->szhead - 2];
398                         ((unsigned char *)&ws->mask)[3] = ws->header[ws->szhead - 1];
399                 } else
400                         ws->mask = 0;
401
402                 /* all heading fields are known, process */
403                 ws->state = STATE_DATA;
404                 if (ws->itf->on_extension != NULL) {
405                         if (ws->itf->on_extension(ws->closure,
406                                         FRAME_GET_FIN(ws->header[0]),
407                                         FRAME_GET_RSV1(ws->header[0]),
408                                         FRAME_GET_RSV2(ws->header[0]),
409                                         FRAME_GET_RSV3(ws->header[0]),
410                                         FRAME_GET_OPCODE(ws->header[0]),
411                                         (size_t) ws->length)) {
412                                 return 0;
413                         }
414                 }
415
416                 /* not an extension case */
417                 if (FRAME_GET_RSV1(ws->header[0]) != 0)
418                         goto protocol_error;
419                 if (FRAME_GET_RSV2(ws->header[0]) != 0)
420                         goto protocol_error;
421                 if (FRAME_GET_RSV3(ws->header[0]) != 0)
422                         goto protocol_error;
423
424                 /* handle */
425                 switch (FRAME_GET_OPCODE(ws->header[0])) {
426                 case OPCODE_CONTINUATION:
427                         ws->itf->on_continue(ws->closure,
428                                              FRAME_GET_FIN(ws->header[0]),
429                                              (size_t) ws->length);
430                         if (!loop)
431                                 return 0;
432                         break;
433                 case OPCODE_TEXT:
434                         ws->itf->on_text(ws->closure,
435                                          FRAME_GET_FIN(ws->header[0]),
436                                          (size_t) ws->length);
437                         if (!loop)
438                                 return 0;
439                         break;
440                 case OPCODE_BINARY:
441                         ws->itf->on_binary(ws->closure,
442                                            FRAME_GET_FIN(ws->header[0]),
443                                            (size_t) ws->length);
444                         if (!loop)
445                                 return 0;
446                         break;
447                 case OPCODE_CLOSE:
448                         if (ws->length == 0)
449                                 code = WEBSOCKET_CODE_NOT_SET;
450                         else {
451                                 code = (uint16_t)(ws->header[ws->szhead - 2] & 0xff);
452                                 code = (uint16_t)(code << 8);
453                                 code = (uint16_t)(code | (uint16_t)(ws->header[ws->szhead - 1] & 0xff));
454                         }
455                         ws->itf->on_close(ws->closure, code, (size_t) ws->length);
456                         return 0;
457                 case OPCODE_PING:
458                         if (ws->itf->on_ping)
459                                 ws->itf->on_ping(ws->closure, ws->length);
460                         else {
461                                 websock_drop(ws);
462                                 websock_pong(ws, NULL, 0);
463                         }
464                         ws->state = STATE_INIT;
465                         if (!loop)
466                                 return 0;
467                         break;
468                 case OPCODE_PONG:
469                         if (ws->itf->on_pong)
470                                 ws->itf->on_pong(ws->closure, ws->length);
471                         else
472                                 websock_drop(ws);
473                         ws->state = STATE_INIT;
474                         if (!loop)
475                                 return 0;
476                         break;
477                 default:
478                         goto protocol_error;
479                 }
480                 break;
481
482         case STATE_DATA:
483                 if (ws->length)
484                         return 0;
485                 ws->state = STATE_INIT;
486                 break;
487         }
488         goto loop;
489
490  too_long_error:
491         websock_error(ws, WEBSOCKET_CODE_MESSAGE_TOO_LARGE, NULL, 0);
492         return 0;
493
494  protocol_error:
495         websock_error(ws, WEBSOCKET_CODE_PROTOCOL_ERROR, NULL, 0);
496         return 0;
497 }
498
499 static void unmask(struct websock * ws, void *buffer, size_t size)
500 {
501         uint32_t mask, *b32;
502         uint8_t m, *b8;
503
504         mask = ws->mask;
505         b8 = buffer;
506         while (size && ((sizeof(uint32_t) - 1) & (uintptr_t) b8)) {
507                 m = ((uint8_t *) & mask)[0];
508                 ((uint8_t *) & mask)[0] = ((uint8_t *) & mask)[1];
509                 ((uint8_t *) & mask)[1] = ((uint8_t *) & mask)[2];
510                 ((uint8_t *) & mask)[2] = ((uint8_t *) & mask)[3];
511                 ((uint8_t *) & mask)[3] = m;
512                 *b8++ ^= m;
513                 size--;
514         }
515         b32 = (uint32_t *) b8;
516         while (size >= sizeof(uint32_t)) {
517                 *b32++ ^= mask;
518                 size -= sizeof(uint32_t);
519         }
520         b8 = (uint8_t *) b32;
521         while (size) {
522                 m = ((uint8_t *) & mask)[0];
523                 ((uint8_t *) & mask)[0] = ((uint8_t *) & mask)[1];
524                 ((uint8_t *) & mask)[1] = ((uint8_t *) & mask)[2];
525                 ((uint8_t *) & mask)[2] = ((uint8_t *) & mask)[3];
526                 ((uint8_t *) & mask)[3] = m;
527                 *b8++ ^= m;
528                 size--;
529         }
530         ws->mask = mask;
531 }
532
533 ssize_t websock_read(struct websock * ws, void *buffer, size_t size)
534 {
535         ssize_t rc;
536
537         if (ws->state != STATE_DATA)
538                 return 0;
539
540         if (size > ws->length)
541                 size = (size_t) ws->length;
542
543         rc = ws_read(ws, buffer, size);
544         if (rc > 0) {
545                 size = (size_t) rc;
546                 ws->length -= size;
547
548                 if (ws->mask != 0)
549                         unmask(ws, buffer, size);
550         }
551         return rc;
552 }
553
554 int websock_drop(struct websock *ws)
555 {
556         char buffer[8000];
557
558         while (ws->length)
559                 if (websock_read(ws, buffer, sizeof buffer) < 0)
560                         return -1;
561         return 0;
562 }
563
564 struct websock *websock_create_v13(const struct websock_itf *itf, void *closure)
565 {
566         struct websock *result = calloc(1, sizeof *result);
567         if (result) {
568                 result->itf = itf;
569                 result->closure = closure;
570                 result->maxlength = default_maxlength;
571         }
572         return result;
573 }
574
575 void websock_destroy(struct websock *ws)
576 {
577         free(ws);
578 }
579
580 void websock_set_default_max_length(size_t maxlen)
581 {
582         default_maxlength = maxlen;
583 }
584
585 void websock_set_max_length(struct websock *ws, size_t maxlen)
586 {
587         ws->maxlength = (uint64_t)maxlen;
588 }