optimize-random-device-open.patch
[profile/ivi/libwebsockets.git] / lib / parsers.c
1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010 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 #include "private-libwebsockets.h"
23
24 const struct lws_tokens lws_tokens[WSI_TOKEN_COUNT] = {
25         [WSI_TOKEN_GET_URI]     = { "GET ",                      4 },
26         [WSI_TOKEN_HOST]        = { "Host:",                     5 },
27         [WSI_TOKEN_CONNECTION]  = { "Connection:",              11 },
28         [WSI_TOKEN_KEY1]        = { "Sec-WebSocket-Key1:",      19 },
29         [WSI_TOKEN_KEY2]        = { "Sec-WebSocket-Key2:",      19 },
30         [WSI_TOKEN_PROTOCOL]    = { "Sec-WebSocket-Protocol:",  23 },
31         [WSI_TOKEN_UPGRADE]     = { "Upgrade:",                  8 },
32         [WSI_TOKEN_EXTENSIONS]  = { "Sec-WebSocket-Extensions:", 25 },
33         [WSI_TOKEN_ORIGIN]      = { "Origin:",                   7 },
34         [WSI_TOKEN_DRAFT]       = { "Sec-WebSocket-Draft:",     20 },
35         [WSI_TOKEN_CHALLENGE]   = { "\x0d\x0a",                  2 },
36
37         [WSI_TOKEN_KEY]         = { "Sec-WebSocket-Key:",       18 },
38         [WSI_TOKEN_VERSION]     = { "Sec-WebSocket-Version:",   22 },
39
40         [WSI_TOKEN_ACCEPT]      = { "Sec-WebSocket-Accept:",    21 },
41         [WSI_TOKEN_NONCE]       = { "Sec-WebSocket-Nonce:",     20 },
42         [WSI_TOKEN_HTTP]        = { "HTTP/1.1 ",                 9 },
43         [WSI_TOKEN_SWORIGIN]    = { "Sec-WebSocket-Origin:",    21 },
44
45 };
46
47 int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c)
48 {
49         int n;
50
51         switch (wsi->parser_state) {
52         case WSI_TOKEN_GET_URI:
53         case WSI_TOKEN_HOST:
54         case WSI_TOKEN_CONNECTION:
55         case WSI_TOKEN_KEY1:
56         case WSI_TOKEN_KEY2:
57         case WSI_TOKEN_PROTOCOL:
58         case WSI_TOKEN_UPGRADE:
59         case WSI_TOKEN_ORIGIN:
60         case WSI_TOKEN_SWORIGIN:
61         case WSI_TOKEN_DRAFT:
62         case WSI_TOKEN_CHALLENGE:
63         case WSI_TOKEN_KEY:
64         case WSI_TOKEN_VERSION:
65         case WSI_TOKEN_ACCEPT:
66         case WSI_TOKEN_NONCE:
67         case WSI_TOKEN_EXTENSIONS:
68         case WSI_TOKEN_HTTP:
69                 debug("WSI_TOKEN_(%d) '%c'\n", wsi->parser_state, c);
70
71                 /* collect into malloc'd buffers */
72                 /* optional space swallow */
73                 if (!wsi->utf8_token[wsi->parser_state].token_len && c == ' ')
74                         break;
75
76                 /* special case space terminator for get-uri */
77                 if (wsi->parser_state == WSI_TOKEN_GET_URI && c == ' ') {
78                         wsi->utf8_token[wsi->parser_state].token[
79                            wsi->utf8_token[wsi->parser_state].token_len] = '\0';
80                         wsi->parser_state = WSI_TOKEN_SKIPPING;
81                         break;
82                 }
83
84                 /* allocate appropriate memory */
85                 if (wsi->utf8_token[wsi->parser_state].token_len ==
86                                                    wsi->current_alloc_len - 1) {
87                         /* need to extend */
88                         wsi->current_alloc_len += LWS_ADDITIONAL_HDR_ALLOC;
89                         if (wsi->current_alloc_len >= LWS_MAX_HEADER_LEN) {
90                                 /* it's waaay to much payload, fail it */
91                                 strcpy(wsi->utf8_token[wsi->parser_state].token,
92                                    "!!! Length exceeded maximum supported !!!");
93                                 wsi->parser_state = WSI_TOKEN_SKIPPING;
94                                 break;
95                         }
96                         wsi->utf8_token[wsi->parser_state].token =
97                                realloc(wsi->utf8_token[wsi->parser_state].token,
98                                                         wsi->current_alloc_len);
99                 }
100
101                 /* bail at EOL */
102                 if (wsi->parser_state != WSI_TOKEN_CHALLENGE && c == '\x0d') {
103                         wsi->utf8_token[wsi->parser_state].token[
104                            wsi->utf8_token[wsi->parser_state].token_len] = '\0';
105                         wsi->parser_state = WSI_TOKEN_SKIPPING_SAW_CR;
106                         break;
107                 }
108
109                 wsi->utf8_token[wsi->parser_state].token[
110                             wsi->utf8_token[wsi->parser_state].token_len++] = c;
111
112                 /* per-protocol end of headers management */
113
114                 if (wsi->parser_state != WSI_TOKEN_CHALLENGE)
115                         break;
116
117                 /* -76 has no version header */
118                 if (!wsi->utf8_token[WSI_TOKEN_VERSION].token_len &&
119                               wsi->utf8_token[wsi->parser_state].token_len != 8)
120                         break;
121
122                 /* <= 03 has old handshake with version header */
123                 if (wsi->utf8_token[WSI_TOKEN_VERSION].token_len &&
124                          atoi(wsi->utf8_token[WSI_TOKEN_VERSION].token) < 4 &&
125                               wsi->utf8_token[wsi->parser_state].token_len != 8)
126                         break;
127
128                 /* For any supported protocol we have enough payload */
129
130                 debug("Setting WSI_PARSING_COMPLETE\n");
131                 wsi->parser_state = WSI_PARSING_COMPLETE;
132                 break;
133
134                 /* collecting and checking a name part */
135         case WSI_TOKEN_NAME_PART:
136                 debug("WSI_TOKEN_NAME_PART '%c'\n", c);
137
138                 if (wsi->name_buffer_pos == sizeof(wsi->name_buffer) - 1) {
139                         /* name bigger than we can handle, skip until next */
140                         wsi->parser_state = WSI_TOKEN_SKIPPING;
141                         break;
142                 }
143                 wsi->name_buffer[wsi->name_buffer_pos++] = c;
144                 wsi->name_buffer[wsi->name_buffer_pos] = '\0';
145
146                 for (n = 0; n < WSI_TOKEN_COUNT; n++) {
147                         if (wsi->name_buffer_pos != lws_tokens[n].token_len)
148                                 continue;
149                         if (strcmp(lws_tokens[n].token, wsi->name_buffer))
150                                 continue;
151                         debug("known hdr '%s'\n", wsi->name_buffer);
152                         wsi->parser_state = WSI_TOKEN_GET_URI + n;
153                         wsi->current_alloc_len = LWS_INITIAL_HDR_ALLOC;
154
155                         wsi->utf8_token[wsi->parser_state].token =
156                                                  malloc(wsi->current_alloc_len);
157                         wsi->utf8_token[wsi->parser_state].token_len = 0;
158                         n = WSI_TOKEN_COUNT;
159                 }
160
161                 /* colon delimiter means we just don't know this name */
162
163                 if (wsi->parser_state == WSI_TOKEN_NAME_PART && c == ':') {
164                         debug("skipping unknown header '%s'\n",
165                                                               wsi->name_buffer);
166                         wsi->parser_state = WSI_TOKEN_SKIPPING;
167                         break;
168                 }
169
170                 if (wsi->parser_state != WSI_TOKEN_CHALLENGE)
171                         break;
172
173                 /* don't look for payload when it can just be http headers */
174
175                 if (!wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len) {
176                         /* they're HTTP headers, not websocket upgrade! */
177                         debug("Setting WSI_PARSING_COMPLETE "
178                                                          "from http headers\n");
179                         wsi->parser_state = WSI_PARSING_COMPLETE;
180                 }
181
182                 /* 04 version has no packet content after end of hdrs */
183
184                 if (wsi->utf8_token[WSI_TOKEN_VERSION].token_len &&
185                          atoi(wsi->utf8_token[WSI_TOKEN_VERSION].token) >= 4) {
186                         debug("04 header completed\n");
187                         wsi->parser_state = WSI_PARSING_COMPLETE;
188                 }
189
190                 /* client parser? */
191
192                 if (wsi->ietf_spec_revision >= 4) {
193                         debug("04 header completed\n");
194                         wsi->parser_state = WSI_PARSING_COMPLETE;
195                 }
196
197                 break;
198
199                 /* skipping arg part of a name we didn't recognize */
200         case WSI_TOKEN_SKIPPING:
201                 debug("WSI_TOKEN_SKIPPING '%c'\n", c);
202                 if (c == '\x0d')
203                         wsi->parser_state = WSI_TOKEN_SKIPPING_SAW_CR;
204                 break;
205         case WSI_TOKEN_SKIPPING_SAW_CR:
206                 debug("WSI_TOKEN_SKIPPING_SAW_CR '%c'\n", c);
207                 if (c == '\x0a')
208                         wsi->parser_state = WSI_TOKEN_NAME_PART;
209                 else
210                         wsi->parser_state = WSI_TOKEN_SKIPPING;
211                 wsi->name_buffer_pos = 0;
212                 break;
213                 /* we're done, ignore anything else */
214         case WSI_PARSING_COMPLETE:
215                 debug("WSI_PARSING_COMPLETE '%c'\n", c);
216                 break;
217
218         default:        /* keep gcc happy */
219                 break;
220         }
221
222         return 0;
223 }
224
225 unsigned char
226 xor_no_mask(struct libwebsocket *wsi, unsigned char c)
227 {
228         return c;
229 }
230
231 unsigned char
232 xor_mask_04(struct libwebsocket *wsi, unsigned char c)
233 {
234         c ^= wsi->masking_key_04[wsi->frame_mask_index++];
235         if (wsi->frame_mask_index == 20)
236                 wsi->frame_mask_index = 0;
237
238         return c;
239 }
240
241 unsigned char
242 xor_mask_05(struct libwebsocket *wsi, unsigned char c)
243 {
244         return c ^ wsi->frame_masking_nonce_04[(wsi->frame_mask_index++) & 3];
245 }
246
247
248
249 static int libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c)
250 {
251         int n;
252         unsigned char buf[20 + 4];
253
254         switch (wsi->lws_rx_parse_state) {
255         case LWS_RXPS_NEW:
256
257                 switch (wsi->ietf_spec_revision) {
258                 /* Firefox 4.0b6 likes this as of 30 Oct */
259                 case 0:
260                         if (c == 0xff)
261                                 wsi->lws_rx_parse_state = LWS_RXPS_SEEN_76_FF;
262                         if (c == 0) {
263                                 wsi->lws_rx_parse_state =
264                                                        LWS_RXPS_EAT_UNTIL_76_FF;
265                                 wsi->rx_user_buffer_head = 0;
266                         }
267                         break;
268                 case 4:
269                 case 5:
270                         wsi->all_zero_nonce = 1;
271                         wsi->frame_masking_nonce_04[0] = c;
272                         if (c)
273                                 wsi->all_zero_nonce = 0;
274                         wsi->lws_rx_parse_state = LWS_RXPS_04_MASK_NONCE_1;
275                         break;
276                 default:
277                         fprintf(stderr, "libwebsocket_rx_sm doesn't know "
278                             "about spec version %d\n", wsi->ietf_spec_revision);
279                         break;
280                 }
281                 break;
282         case LWS_RXPS_04_MASK_NONCE_1:
283                 wsi->frame_masking_nonce_04[1] = c;
284                 if (c)
285                         wsi->all_zero_nonce = 0;
286                 wsi->lws_rx_parse_state = LWS_RXPS_04_MASK_NONCE_2;
287                 break;
288         case LWS_RXPS_04_MASK_NONCE_2:
289                 wsi->frame_masking_nonce_04[2] = c;
290                 if (c)
291                         wsi->all_zero_nonce = 0;
292                 wsi->lws_rx_parse_state = LWS_RXPS_04_MASK_NONCE_3;
293                 break;
294         case LWS_RXPS_04_MASK_NONCE_3:
295                 wsi->frame_masking_nonce_04[3] = c;
296                 if (c)
297                         wsi->all_zero_nonce = 0;
298
299                 if (wsi->protocol->owning_server->options &
300                                            LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK)
301                         goto post_mask;
302
303                 if (wsi->ietf_spec_revision > 4)
304                         goto post_sha1;
305
306                 /*
307                  * we are able to compute the frame key now
308                  * it's a SHA1 of ( frame nonce we were just sent, concatenated
309                  * with the connection masking key we computed at handshake
310                  * time ) -- yeah every frame from the client invokes a SHA1
311                  * for no real reason so much for lightweight.
312                  */
313
314                 buf[0] = wsi->frame_masking_nonce_04[0];
315                 buf[1] = wsi->frame_masking_nonce_04[1];
316                 buf[2] = wsi->frame_masking_nonce_04[2];
317                 buf[3] = wsi->frame_masking_nonce_04[3];
318
319                 memcpy(buf + 4, wsi->masking_key_04, 20);
320
321                 /*
322                  * wsi->frame_mask_04 will be our recirculating 20-byte XOR key
323                  * for this frame
324                  */
325
326                 SHA1((unsigned char *)buf, 4 + 20, wsi->frame_mask_04);
327
328 post_sha1:
329
330                 /*
331                  * start from the zero'th byte in the XOR key buffer since
332                  * this is the start of a frame with a new key
333                  */
334
335                 wsi->frame_mask_index = 0;
336
337 post_mask:
338                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_1;
339                 break;
340
341         /*
342          *  04 logical framing from the spec (all this is masked when incoming
343          *  and has to be unmasked)
344          *
345          * We ignore the possibility of extension data because we don't
346          * negotiate any extensions at the moment.
347          *
348          *    0                   1                   2                   3
349          *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
350          *   +-+-+-+-+-------+-+-------------+-------------------------------+
351          *   |F|R|R|R| opcode|R| Payload len |    Extended payload length    |
352          *   |I|S|S|S|  (4)  |S|     (7)     |             (16/63)           |
353          *   |N|V|V|V|       |V|             |   (if payload len==126/127)   |
354          *   | |1|2|3|       |4|             |                               |
355          *   +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
356          *   |     Extended payload length continued, if payload len == 127  |
357          *   + - - - - - - - - - - - - - - - +-------------------------------+
358          *   |                               |         Extension data        |
359          *   +-------------------------------+ - - - - - - - - - - - - - - - +
360          *   :                                                               :
361          *   +---------------------------------------------------------------+
362          *   :                       Application data                        :
363          *   +---------------------------------------------------------------+
364          *
365          *  We pass payload through to userland as soon as we get it, ignoring
366          *  FIN.  It's up to userland to buffer it up if it wants to see a
367          *  whole unfragmented block of the original size (which may be up to
368          *  2^63 long!)
369          */
370
371         case LWS_RXPS_04_FRAME_HDR_1:
372                 /*
373                  * 04 spec defines the opcode like this: (1, 2, and 3 are
374                  * "control frame" opcodes which may not be fragmented or
375                  * have size larger than 126)
376                  *
377                  *       frame-opcode           =
378                  *             %x0 ; continuation frame
379                  *              / %x1 ; connection close
380                  *              / %x2 ; ping
381                  *              / %x3 ; pong
382                  *              / %x4 ; text frame
383                  *              / %x5 ; binary frame
384                  *              / %x6-F ; reserved
385                  *
386                  *              FIN (b7)
387                  */
388
389                 c = wsi->xor_mask(wsi, c);
390
391                 if (c & 0x70) {
392                         fprintf(stderr,
393                                       "Frame has extensions set illegally 1\n");
394                         /* kill the connection */
395                         return -1;
396                 }
397
398                 wsi->opcode = c & 0xf;
399                 wsi->final = !!((c >> 7) & 1);
400
401                 if (wsi->final &&
402                         wsi->opcode == LWS_WS_OPCODE_04__CONTINUATION &&
403                                                    wsi->rx_packet_length == 0) {
404                         fprintf(stderr,
405                                       "Frame starts with final continuation\n");
406                         /* kill the connection */
407                         return -1;
408                 }
409
410                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN;
411                 break;
412
413         case LWS_RXPS_04_FRAME_HDR_LEN:
414                 c = wsi->xor_mask(wsi, c);
415
416                 if (c & 0x80) {
417                         fprintf(stderr, "Frame has extensions "
418                                                            "set illegally 2\n");
419                         /* kill the connection */
420                         return -1;
421                 }
422
423                 switch (c) {
424                 case 126:
425                         /* control frames are not allowed to have big lengths */
426                         switch (wsi->opcode) {
427                         case LWS_WS_OPCODE_04__CLOSE:
428                         case LWS_WS_OPCODE_04__PING:
429                         case LWS_WS_OPCODE_04__PONG:
430                                 fprintf(stderr, "Control frame asking for "
431                                                 "extended length is illegal\n");
432                                 /* kill the connection */
433                                 return -1;
434                         default:
435                                 break;
436                         }
437                         wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_2;
438                         break;
439                 case 127:
440                         /* control frames are not allowed to have big lengths */
441                         switch (wsi->opcode) {
442                         case LWS_WS_OPCODE_04__CLOSE:
443                         case LWS_WS_OPCODE_04__PING:
444                         case LWS_WS_OPCODE_04__PONG:
445                                 fprintf(stderr, "Control frame asking for "
446                                                 "extended length is illegal\n");
447                                 /* kill the connection */
448                                 return -1;
449                         default:
450                                 break;
451                         }
452                         wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_8;
453                         break;
454                 default:
455                         wsi->rx_packet_length = c;
456                         wsi->lws_rx_parse_state =
457                                         LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
458                         break;
459                 }
460                 break;
461
462         case LWS_RXPS_04_FRAME_HDR_LEN16_2:
463                 c = wsi->xor_mask(wsi, c);
464
465                 wsi->rx_packet_length = c << 8;
466                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_1;
467                 break;
468
469         case LWS_RXPS_04_FRAME_HDR_LEN16_1:
470                 c = wsi->xor_mask(wsi, c);
471
472                 wsi->rx_packet_length |= c;
473                 wsi->lws_rx_parse_state =
474                                         LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
475                 break;
476
477         case LWS_RXPS_04_FRAME_HDR_LEN64_8:
478                 c = wsi->xor_mask(wsi, c);
479                 if (c & 0x80) {
480                         fprintf(stderr, "b63 of length must be zero\n");
481                         /* kill the connection */
482                         return -1;
483                 }
484 #if defined __LP64__
485                 wsi->rx_packet_length = ((size_t)c) << 56;
486 #else
487                 wsi->rx_packet_length = 0;
488 #endif
489                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_7;
490                 break;
491
492         case LWS_RXPS_04_FRAME_HDR_LEN64_7:
493 #if defined __LP64__
494                 wsi->rx_packet_length |= ((size_t)wsi->xor_mask(wsi, c)) << 48;
495 #endif
496                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_6;
497                 break;
498
499         case LWS_RXPS_04_FRAME_HDR_LEN64_6:
500 #if defined __LP64__
501                 wsi->rx_packet_length |= ((size_t)wsi->xor_mask(wsi, c)) << 40;
502 #endif
503                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_5;
504                 break;
505
506         case LWS_RXPS_04_FRAME_HDR_LEN64_5:
507 #if defined __LP64__
508                 wsi->rx_packet_length |= ((size_t)wsi->xor_mask(wsi, c)) << 32;
509 #endif
510                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_4;
511                 break;
512
513         case LWS_RXPS_04_FRAME_HDR_LEN64_4:
514                 wsi->rx_packet_length |= ((size_t)wsi->xor_mask(wsi, c)) << 24;
515                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_3;
516                 break;
517
518         case LWS_RXPS_04_FRAME_HDR_LEN64_3:
519                 wsi->rx_packet_length |= ((size_t)wsi->xor_mask(wsi, c)) << 16;
520                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_2;
521                 break;
522
523         case LWS_RXPS_04_FRAME_HDR_LEN64_2:
524                 wsi->rx_packet_length |= ((size_t)wsi->xor_mask(wsi, c)) << 8;
525                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_1;
526                 break;
527
528         case LWS_RXPS_04_FRAME_HDR_LEN64_1:
529                 wsi->rx_packet_length |= ((size_t)wsi->xor_mask(wsi, c));
530                 wsi->lws_rx_parse_state =
531                                         LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
532                 break;
533
534         case LWS_RXPS_EAT_UNTIL_76_FF:
535                 if (c == 0xff) {
536                         wsi->lws_rx_parse_state = LWS_RXPS_NEW;
537                         goto issue;
538                 }
539                 wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING +
540                                               (wsi->rx_user_buffer_head++)] = c;
541
542                 if (wsi->rx_user_buffer_head != MAX_USER_RX_BUFFER)
543                         break;
544 issue:
545                 if (wsi->protocol->callback)
546                         wsi->protocol->callback(wsi, LWS_CALLBACK_RECEIVE,
547                           wsi->user_space,
548                           &wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING],
549                           wsi->rx_user_buffer_head);
550                 wsi->rx_user_buffer_head = 0;
551                 break;
552         case LWS_RXPS_SEEN_76_FF:
553                 if (c)
554                         break;
555
556                 debug("Seen that client is requesting "
557                                 "a v76 close, sending ack\n");
558                 buf[0] = 0xff;
559                 buf[1] = 0;
560                 n = libwebsocket_write(wsi, buf, 2, LWS_WRITE_HTTP);
561                 if (n < 0) {
562                         fprintf(stderr, "ERROR writing to socket");
563                         return -1;
564                 }
565                 debug("  v76 close ack sent, server closing skt\n");
566                 /* returning < 0 will get it closed in parent */
567                 return -1;
568
569         case LWS_RXPS_PULLING_76_LENGTH:
570                 break;
571
572         case LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED:
573                 if (wsi->all_zero_nonce && wsi->ietf_spec_revision >= 5)
574                         wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING +
575                                (wsi->rx_user_buffer_head++)] = c;
576                 else
577                         wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING +
578                                (wsi->rx_user_buffer_head++)] =
579                                                           wsi->xor_mask(wsi, c);
580
581                 if (--wsi->rx_packet_length == 0) {
582                         wsi->lws_rx_parse_state = LWS_RXPS_NEW;
583                         goto spill;
584                 }
585                 if (wsi->rx_user_buffer_head != MAX_USER_RX_BUFFER)
586                         break;
587 spill:
588                 /*
589                  * is this frame a control packet we should take care of at this
590                  * layer?  If so service it and hide it from the user callback
591                  */
592
593                 switch (wsi->opcode) {
594                 case LWS_WS_OPCODE_04__CLOSE:
595                         /* parrot the close packet payload back */
596                         n = libwebsocket_write(wsi, (unsigned char *)
597                            &wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING],
598                                      wsi->rx_user_buffer_head, LWS_WRITE_CLOSE);
599                         wsi->state = WSI_STATE_RETURNED_CLOSE_ALREADY;
600                         /* close the connection */
601                         return -1;
602
603                 case LWS_WS_OPCODE_04__PING:
604                         /* parrot the ping packet payload back as a pong */
605                         n = libwebsocket_write(wsi, (unsigned char *)
606                             &wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING],
607                                     wsi->rx_user_buffer_head, LWS_WRITE_PONG);
608                         /* ... then just drop it */
609                         wsi->rx_user_buffer_head = 0;
610                         return 0;
611
612                 case LWS_WS_OPCODE_04__PONG:
613                         /* keep the statistics... */
614                         wsi->pings_vs_pongs--;
615                         /* ... then just drop it */
616                         wsi->rx_user_buffer_head = 0;
617                         return 0;
618
619                 default:
620                         break;
621                 }
622
623                 /*
624                  * No it's real payload, pass it up to the user callback.
625                  * It's nicely buffered with the pre-padding taken care of
626                  * so it can be sent straight out again using libwebsocket_write
627                  */
628
629                 wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING +
630                                                wsi->rx_user_buffer_head] = '\0';
631
632                 if (wsi->protocol->callback)
633                         wsi->protocol->callback(wsi, LWS_CALLBACK_RECEIVE,
634                                                 wsi->user_space,
635                           &wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING],
636                                                       wsi->rx_user_buffer_head);
637                 wsi->rx_user_buffer_head = 0;
638                 break;
639         }
640
641         return 0;
642 }
643
644
645 int libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c)
646 {
647         int n;
648         unsigned char buf[20 + 4];
649         int callback_action = LWS_CALLBACK_CLIENT_RECEIVE;
650
651         switch (wsi->lws_rx_parse_state) {
652         case LWS_RXPS_NEW:
653
654                 switch (wsi->ietf_spec_revision) {
655                 /* Firefox 4.0b6 likes this as of 30 Oct */
656                 case 0:
657                         if (c == 0xff)
658                                 wsi->lws_rx_parse_state = LWS_RXPS_SEEN_76_FF;
659                         if (c == 0) {
660                                 wsi->lws_rx_parse_state =
661                                                        LWS_RXPS_EAT_UNTIL_76_FF;
662                                 wsi->rx_user_buffer_head = 0;
663                         }
664                         break;
665                 case 4:
666                 case 5:
667         /*
668          *  04 logical framing from the spec (all this is masked when
669          *  incoming and has to be unmasked)
670          *
671          * We ignore the possibility of extension data because we don't
672          * negotiate any extensions at the moment.
673          *
674          *    0                   1                   2                   3
675          *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
676          *   +-+-+-+-+-------+-+-------------+-------------------------------+
677          *   |F|R|R|R| opcode|R| Payload len |    Extended payload length    |
678          *   |I|S|S|S|  (4)  |S|     (7)     |             (16/63)           |
679          *   |N|V|V|V|       |V|             |   (if payload len==126/127)   |
680          *   | |1|2|3|       |4|             |                               |
681          *   +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
682          *   |     Extended payload length continued, if payload len == 127  |
683          *   + - - - - - - - - - - - - - - - +-------------------------------+
684          *   |                               |         Extension data        |
685          *   +-------------------------------+ - - - - - - - - - - - - - - - +
686          *   :                                                               :
687          *   +---------------------------------------------------------------+
688          *   :                       Application data                        :
689          *   +---------------------------------------------------------------+
690          *
691          *  We pass payload through to userland as soon as we get it, ignoring
692          *  FIN.  It's up to userland to buffer it up if it wants to see a
693          *  whole unfragmented block of the original size (which may be up to
694          *  2^63 long!)
695          */
696
697                 /*
698                  * 04 spec defines the opcode like this: (1, 2, and 3 are
699                  * "control frame" opcodes which may not be fragmented or
700                  * have size larger than 126)
701                  *
702                  *       frame-opcode           =
703                  *                %x0 ; continuation frame
704                  *              / %x1 ; connection close
705                  *              / %x2 ; ping
706                  *              / %x3 ; pong
707                  *              / %x4 ; text frame
708                  *              / %x5 ; binary frame
709                  *              / %x6-F ; reserved
710                  *
711                  *              FIN (b7)
712                  */
713
714                         if (c & 0x70) {
715                                 fprintf(stderr, "Frame has extensions set "
716                                    "illegally on first framing byte %02X\n", c);
717                                 /* kill the connection */
718                                 return -1;
719                         }
720
721                         wsi->opcode = c & 0xf;
722                         wsi->final = !!((c >> 7) & 1);
723
724                         if (wsi->final &&
725                             wsi->opcode == LWS_WS_OPCODE_04__CONTINUATION &&
726                                                    wsi->rx_packet_length == 0) {
727                                 fprintf(stderr,
728                                       "Frame starts with final continuation\n");
729                                 /* kill the connection */
730                                 return -1;
731                         }
732
733                         wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN;
734                         break;
735                 default:
736                         fprintf(stderr, "client_rx_sm doesn't know how "
737                                 "to handle spec version %02d\n",
738                                                        wsi->ietf_spec_revision);
739                         break;
740                 }
741                 break;
742
743
744         case LWS_RXPS_04_FRAME_HDR_LEN:
745
746                 if (c & 0x80) {
747                         fprintf(stderr,
748                                       "Frame has extensions set illegally 4\n");
749                         /* kill the connection */
750                         return -1;
751                 }
752
753                 switch (c) {
754                 case 126:
755                         /* control frames are not allowed to have big lengths */
756                         switch (wsi->opcode) {
757                         case LWS_WS_OPCODE_04__CLOSE:
758                         case LWS_WS_OPCODE_04__PING:
759                         case LWS_WS_OPCODE_04__PONG:
760                                 fprintf(stderr, "Control frame asking for "
761                                                 "extended length is illegal\n");
762                                 /* kill the connection */
763                                 return -1;
764                         default:
765                                 break;
766                         }
767                         wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_2;
768                         break;
769                 case 127:
770                         /* control frames are not allowed to have big lengths */
771                         switch (wsi->opcode) {
772                         case LWS_WS_OPCODE_04__CLOSE:
773                         case LWS_WS_OPCODE_04__PING:
774                         case LWS_WS_OPCODE_04__PONG:
775                                 fprintf(stderr, "Control frame asking for "
776                                                 "extended length is illegal\n");
777                                 /* kill the connection */
778                                 return -1;
779                         default:
780                                 break;
781                         }
782                         wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_8;
783                         break;
784                 default:
785                         wsi->rx_packet_length = c;
786                         wsi->lws_rx_parse_state =
787                                         LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
788                         break;
789                 }
790                 break;
791
792         case LWS_RXPS_04_FRAME_HDR_LEN16_2:
793                 wsi->rx_packet_length = c << 8;
794                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_1;
795                 break;
796
797         case LWS_RXPS_04_FRAME_HDR_LEN16_1:
798                 wsi->rx_packet_length |= c;
799                 wsi->lws_rx_parse_state =
800                                         LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
801                 break;
802
803         case LWS_RXPS_04_FRAME_HDR_LEN64_8:
804                 if (c & 0x80) {
805                         fprintf(stderr, "b63 of length must be zero\n");
806                         /* kill the connection */
807                         return -1;
808                 }
809 #if defined __LP64__
810                 wsi->rx_packet_length = ((size_t)c) << 56;
811 #else
812                 wsi->rx_packet_length = 0;
813 #endif
814                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_7;
815                 break;
816
817         case LWS_RXPS_04_FRAME_HDR_LEN64_7:
818 #if defined __LP64__
819                 wsi->rx_packet_length |= ((size_t)c) << 48;
820 #endif
821                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_6;
822                 break;
823
824         case LWS_RXPS_04_FRAME_HDR_LEN64_6:
825 #if defined __LP64__
826                 wsi->rx_packet_length |= ((size_t)c) << 40;
827 #endif
828                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_5;
829                 break;
830
831         case LWS_RXPS_04_FRAME_HDR_LEN64_5:
832 #if defined __LP64__
833                 wsi->rx_packet_length |= ((size_t)c) << 32;
834 #endif
835                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_4;
836                 break;
837
838         case LWS_RXPS_04_FRAME_HDR_LEN64_4:
839                 wsi->rx_packet_length |= ((size_t)c) << 24;
840                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_3;
841                 break;
842
843         case LWS_RXPS_04_FRAME_HDR_LEN64_3:
844                 wsi->rx_packet_length |= ((size_t)c) << 16;
845                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_2;
846                 break;
847
848         case LWS_RXPS_04_FRAME_HDR_LEN64_2:
849                 wsi->rx_packet_length |= ((size_t)c) << 8;
850                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_1;
851                 break;
852
853         case LWS_RXPS_04_FRAME_HDR_LEN64_1:
854                 wsi->rx_packet_length |= (size_t)c;
855                 wsi->lws_rx_parse_state =
856                                         LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
857                 break;
858
859         case LWS_RXPS_EAT_UNTIL_76_FF:
860                 if (c == 0xff) {
861                         wsi->lws_rx_parse_state = LWS_RXPS_NEW;
862                         goto issue;
863                 }
864                 wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING +
865                                               (wsi->rx_user_buffer_head++)] = c;
866
867                 if (wsi->rx_user_buffer_head != MAX_USER_RX_BUFFER)
868                         break;
869 issue:
870                 if (wsi->protocol->callback)
871                         wsi->protocol->callback(wsi,
872                                                 LWS_CALLBACK_CLIENT_RECEIVE,
873                                                 wsi->user_space,
874                           &wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING],
875                                                       wsi->rx_user_buffer_head);
876                 wsi->rx_user_buffer_head = 0;
877                 break;
878         case LWS_RXPS_SEEN_76_FF:
879                 if (c)
880                         break;
881
882                 debug("Seen that client is requesting "
883                                 "a v76 close, sending ack\n");
884                 buf[0] = 0xff;
885                 buf[1] = 0;
886                 n = libwebsocket_write(wsi, buf, 2, LWS_WRITE_HTTP);
887                 if (n < 0) {
888                         fprintf(stderr, "ERROR writing to socket");
889                         return -1;
890                 }
891                 debug("  v76 close ack sent, server closing skt\n");
892                 /* returning < 0 will get it closed in parent */
893                 return -1;
894
895         case LWS_RXPS_PULLING_76_LENGTH:
896                 break;
897
898         case LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED:
899                 wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING +
900                                  (wsi->rx_user_buffer_head++)] = c;
901                 if (--wsi->rx_packet_length == 0) {
902                         wsi->lws_rx_parse_state = LWS_RXPS_NEW;
903                         goto spill;
904                 }
905                 if (wsi->rx_user_buffer_head != MAX_USER_RX_BUFFER)
906                         break;
907 spill:
908                 /*
909                  * is this frame a control packet we should take care of at this
910                  * layer?  If so service it and hide it from the user callback
911                  */
912
913                 switch (wsi->opcode) {
914                 case LWS_WS_OPCODE_04__CLOSE:
915                         /* parrot the close packet payload back */
916                         n = libwebsocket_write(wsi, (unsigned char *)
917                            &wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING],
918                                      wsi->rx_user_buffer_head, LWS_WRITE_CLOSE);
919                         wsi->state = WSI_STATE_RETURNED_CLOSE_ALREADY;
920                         /* close the connection */
921                         return -1;
922
923                 case LWS_WS_OPCODE_04__PING:
924                         /* parrot the ping packet payload back as a pong*/
925                         n = libwebsocket_write(wsi, (unsigned char *)
926                             &wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING],
927                                     wsi->rx_user_buffer_head, LWS_WRITE_PONG);
928                         break;
929
930                 case LWS_WS_OPCODE_04__PONG:
931                         /* keep the statistics... */
932                         wsi->pings_vs_pongs--;
933
934                         /* issue it */
935                         callback_action = LWS_CALLBACK_CLIENT_RECEIVE_PONG;
936                         break;
937
938                 default:
939                         break;
940                 }
941
942                 /*
943                  * No it's real payload, pass it up to the user callback.
944                  * It's nicely buffered with the pre-padding taken care of
945                  * so it can be sent straight out again using libwebsocket_write
946                  */
947
948                 if (wsi->protocol->callback)
949                         wsi->protocol->callback(wsi, callback_action,
950                                                 wsi->user_space,
951                           &wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING],
952                                                       wsi->rx_user_buffer_head);
953                 wsi->rx_user_buffer_head = 0;
954                 break;
955         default:
956                 fprintf(stderr, "client rx illegal state\n");
957                 return 1;
958         }
959
960         return 0;
961 }
962
963
964
965 int libwebsocket_interpret_incoming_packet(struct libwebsocket *wsi,
966                                                  unsigned char *buf, size_t len)
967 {
968         int n;
969
970 #ifdef DEBUG
971         fprintf(stderr, "received %d byte packet\n", (int)len);
972         for (n = 0; n < len; n++)
973                 fprintf(stderr, "%02X ", buf[n]);
974         fprintf(stderr, "\n");
975 #endif
976
977         /* let the rx protocol state machine have as much as it needs */
978
979         n = 0;
980         while (n < len)
981                 if (libwebsocket_rx_sm(wsi, buf[n++]) < 0)
982                         return -1;
983
984         return 0;
985 }
986
987
988 static int
989 libwebsocket_0405_frame_mask_generate(struct libwebsocket *wsi)
990 {
991         char buf[4 + 20];
992         int n;
993
994         /* fetch the per-frame nonce */
995
996         n = read(wsi->protocol->owning_server->fd_random,
997                                                 wsi->frame_masking_nonce_04, 4);
998         if (n != 4) {
999                 fprintf(stderr, "Unable to read from random device %s %d\n",
1000                                                      SYSTEM_RANDOM_FILEPATH, n);
1001                 return 1;
1002         }
1003
1004         /* start masking from first byte of masking key buffer */
1005         wsi->frame_mask_index = 0;
1006
1007         if (wsi->ietf_spec_revision != 4)
1008                 return 0;
1009
1010         /* 04 only does SHA-1 more complex key */
1011
1012         /*
1013          * the frame key is the frame nonce (4 bytes) followed by the
1014          * connection masking key, hashed by SHA1
1015          */
1016
1017         memcpy(buf, wsi->frame_masking_nonce_04, 4);
1018         
1019         memcpy(buf + 4, wsi->masking_key_04, 20);
1020
1021         /* concatenate the nonce with the connection key then hash it */
1022
1023         SHA1((unsigned char *)buf, 4 + 20, wsi->frame_mask_04);
1024
1025         return 0;
1026 }
1027
1028
1029 /**
1030  * libwebsocket_write() - Apply protocol then write data to client
1031  * @wsi:        Websocket instance (available from user callback)
1032  * @buf:        The data to send.  For data being sent on a websocket
1033  *              connection (ie, not default http), this buffer MUST have
1034  *              LWS_SEND_BUFFER_PRE_PADDING bytes valid BEFORE the pointer
1035  *              and an additional LWS_SEND_BUFFER_POST_PADDING bytes valid
1036  *              in the buffer after (buf + len).  This is so the protocol
1037  *              header and trailer data can be added in-situ.
1038  * @len:        Count of the data bytes in the payload starting from buf
1039  * @protocol:   Use LWS_WRITE_HTTP to reply to an http connection, and one
1040  *              of LWS_WRITE_BINARY or LWS_WRITE_TEXT to send appropriate
1041  *              data on a websockets connection.  Remember to allow the extra
1042  *              bytes before and after buf if LWS_WRITE_BINARY or LWS_WRITE_TEXT
1043  *              are used.
1044  *
1045  *      This function provides the way to issue data back to the client
1046  *      for both http and websocket protocols.
1047  *
1048  *      In the case of sending using websocket protocol, be sure to allocate
1049  *      valid storage before and after buf as explained above.  This scheme
1050  *      allows maximum efficiency of sending data and protocol in a single
1051  *      packet while not burdening the user code with any protocol knowledge.
1052  */
1053
1054 int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf,
1055                           size_t len, enum libwebsocket_write_protocol protocol)
1056 {
1057         int n;
1058         int pre = 0;
1059         int post = 0;
1060         unsigned int shift = 7;
1061
1062         if (len == 0 && protocol != LWS_WRITE_CLOSE) {
1063                 fprintf(stderr, "zero length libwebsocket_write attempt\n");
1064                 return 0;
1065         }
1066
1067         if (protocol == LWS_WRITE_HTTP)
1068                 goto send_raw;
1069
1070         /* websocket protocol, either binary or text */
1071
1072         if (wsi->state != WSI_STATE_ESTABLISHED)
1073                 return -1;
1074
1075         switch (wsi->ietf_spec_revision) {
1076         /* chrome likes this as of 30 Oct */
1077         /* Firefox 4.0b6 likes this as of 30 Oct */
1078         case 0:
1079                 if ((protocol & 0xf) == LWS_WRITE_BINARY) {
1080                         /* in binary mode we send 7-bit used length blocks */
1081                         pre = 1;
1082                         while (len & (127 << shift)) {
1083                                 pre++;
1084                                 shift += 7;
1085                         }
1086                         n = 0;
1087                         shift -= 7;
1088                         while (shift >= 0) {
1089                                 if (shift)
1090                                         buf[0 - pre + n] =
1091                                                   ((len >> shift) & 127) | 0x80;
1092                                 else
1093                                         buf[0 - pre + n] =
1094                                                   ((len >> shift) & 127);
1095                                 n++;
1096                                 shift -= 7;
1097                         }
1098                         break;
1099                 }
1100
1101                 /* frame type = text, length-free spam mode */
1102
1103                 buf[-1] = 0;
1104                 buf[len] = 0xff; /* EOT marker */
1105                 pre = 1;
1106                 post = 1;
1107                 break;
1108
1109         case 4:
1110         case 5:
1111                 switch (protocol & 0xf) {
1112                 case LWS_WRITE_TEXT:
1113                         n = LWS_WS_OPCODE_04__TEXT_FRAME;
1114                         break;
1115                 case LWS_WRITE_BINARY:
1116                         n = LWS_WS_OPCODE_04__BINARY_FRAME;
1117                         break;
1118                 case LWS_WRITE_CLOSE:
1119                         n = LWS_WS_OPCODE_04__CLOSE;
1120
1121                         /*
1122                          * v5 mandates the first byte of close packet
1123                          * in both client and server directions
1124                          */
1125                         
1126                         if (wsi->ietf_spec_revision >= 5) {
1127
1128                                 /* we can do this because we demand post-buf */
1129
1130                                 if (len < 1)
1131                                         len = 1;
1132                                 
1133                                 switch (wsi->mode) {
1134                                 case LWS_CONNMODE_WS_SERVING:
1135                                         /*
1136                                         fprintf(stderr, "LWS_WRITE_CLOSE S\n");
1137                                         */
1138                                         buf[0] = 'S';
1139                                         break;
1140                                 case LWS_CONNMODE_WS_CLIENT:
1141                                         /*
1142                                         fprintf(stderr, "LWS_WRITE_CLOSE C\n");
1143                                         */
1144                                         buf[0] = 'C';
1145                                         break;
1146                                 }
1147                         }
1148                         break;
1149                 case LWS_WRITE_PING:
1150                         n = LWS_WS_OPCODE_04__PING;
1151                         wsi->pings_vs_pongs++;
1152                         break;
1153                 case LWS_WRITE_PONG:
1154                         n = LWS_WS_OPCODE_04__PONG;
1155                         break;
1156                 default:
1157                         fprintf(stderr, "libwebsocket_write: unknown write "
1158                                                          "opcode / protocol\n");
1159                         return -1;
1160                 }
1161
1162                 if (!(protocol & LWS_WRITE_NO_FIN))
1163                         n |= 1 << 7;
1164
1165                 if (len < 126) {
1166                         buf[-2] = n;
1167                         buf[-1] = len;
1168                         pre = 2;
1169                 } else {
1170                         if (len < 65536) {
1171                                 buf[-4] = n;
1172                                 buf[-3] = 126;
1173                                 buf[-2] = len >> 8;
1174                                 buf[-1] = len;
1175                                 pre = 4;
1176                         } else {
1177                                 buf[-10] = n;
1178                                 buf[-9] = 127;
1179 #if defined __LP64__
1180                                         buf[-8] = (len >> 56) & 0x7f;
1181                                         buf[-7] = len >> 48;
1182                                         buf[-6] = len >> 40;
1183                                         buf[-5] = len >> 32;
1184 #else
1185                                         buf[-8] = 0;
1186                                         buf[-7] = 0;
1187                                         buf[-6] = 0;
1188                                         buf[-5] = 0;
1189 #endif
1190                                 buf[-4] = len >> 24;
1191                                 buf[-3] = len >> 16;
1192                                 buf[-2] = len >> 8;
1193                                 buf[-1] = len;
1194                                 pre = 10;
1195                         }
1196                 }
1197                 break;
1198         }
1199
1200 #if 0
1201         for (n = 0; n < (len + pre + post); n++)
1202                 fprintf(stderr, "%02X ", buf[n - pre]);
1203
1204         fprintf(stderr, "\n");
1205 #endif
1206
1207         /*
1208          * Deal with masking if we are in client -> server direction and
1209          * the protocol demands it
1210          */
1211
1212         if (wsi->mode == LWS_CONNMODE_WS_CLIENT &&
1213                                                  wsi->ietf_spec_revision >= 4) {
1214
1215                 /*
1216                  * this is only useful for security tests where it's required
1217                  * to control the raw packet payload content
1218                  */
1219
1220                 if (!(protocol & LWS_WRITE_CLIENT_IGNORE_XOR_MASK)) {
1221
1222                         if (libwebsocket_0405_frame_mask_generate(wsi)) {
1223                                 fprintf(stderr, "libwebsocket_write: "
1224                                               "frame mask generation failed\n");
1225                                 return 1;
1226                         }
1227
1228                         /*
1229                          * use the XOR masking against everything we send
1230                          * past the frame nonce
1231                          */
1232
1233                         for (n = 0; n < (len + pre + post); n++)
1234                                 buf[n - pre] = wsi->xor_mask(wsi, buf[n - pre]);
1235
1236
1237                         /* make space for the frame nonce in clear */
1238                         pre += 4;
1239
1240                         /* copy the frame nonce into place */
1241                         memcpy(&buf[0 - pre], wsi->frame_masking_nonce_04, 4);
1242                 } else {
1243                         /* make space for the frame nonce in clear */
1244                         pre += 4;
1245
1246                         buf[0 - pre] = 0;
1247                         buf[1 - pre] = 0;
1248                         buf[2 - pre] = 0;
1249                         buf[3 - pre] = 0;
1250                 }
1251
1252         }
1253
1254 send_raw:
1255 #ifdef LWS_OPENSSL_SUPPORT
1256         if (wsi->ssl) {
1257                 n = SSL_write(wsi->ssl, buf - pre, len + pre + post);
1258                 if (n < 0) {
1259                         fprintf(stderr, "ERROR writing to socket\n");
1260                         return -1;
1261                 }
1262         } else {
1263 #endif
1264                 n = send(wsi->sock, buf - pre, len + pre + post, MSG_NOSIGNAL);
1265                 if (n < 0) {
1266                         fprintf(stderr, "ERROR writing to socket\n");
1267                         return -1;
1268                 }
1269 #ifdef LWS_OPENSSL_SUPPORT
1270         }
1271 #endif
1272
1273         debug("written %d bytes to client\n", (int)len);
1274
1275         return 0;
1276 }
1277
1278
1279 /**
1280  * libwebsockets_serve_http_file() - Send a file back to the client using http
1281  * @wsi:                Websocket instance (available from user callback)
1282  * @file:               The file to issue over http
1283  * @content_type:       The http content type, eg, text/html
1284  *
1285  *      This function is intended to be called from the callback in response
1286  *      to http requests from the client.  It allows the callback to issue
1287  *      local files down the http link in a single step.
1288  */
1289
1290 int libwebsockets_serve_http_file(struct libwebsocket *wsi, const char *file,
1291                                                        const char *content_type)
1292 {
1293         int fd;
1294         struct stat stat;
1295         char buf[512];
1296         char *p = buf;
1297         int n;
1298
1299         fd = open(file, O_RDONLY);
1300         if (fd < 1) {
1301                 p += sprintf(p, "HTTP/1.0 400 Bad\x0d\x0a"
1302                         "Server: libwebsockets\x0d\x0a"
1303                         "\x0d\x0a"
1304                 );
1305                 libwebsocket_write(wsi, (unsigned char *)buf, p - buf,
1306                                                                 LWS_WRITE_HTTP);
1307
1308                 return -1;
1309         }
1310
1311         fstat(fd, &stat);
1312         p += sprintf(p, "HTTP/1.0 200 OK\x0d\x0a"
1313                         "Server: libwebsockets\x0d\x0a"
1314                         "Content-Type: %s\x0d\x0a"
1315                         "Content-Length: %u\x0d\x0a"
1316                         "\x0d\x0a", content_type, (unsigned int)stat.st_size);
1317
1318         libwebsocket_write(wsi, (unsigned char *)buf, p - buf, LWS_WRITE_HTTP);
1319
1320         n = 1;
1321         while (n > 0) {
1322                 n = read(fd, buf, 512);
1323                 if (n <= 0)
1324                         continue;
1325                 libwebsocket_write(wsi, (unsigned char *)buf, n,
1326                                                                 LWS_WRITE_HTTP);
1327         }
1328
1329         close(fd);
1330
1331         return 0;
1332 }
1333
1334
1335 /**
1336  * libwebsockets_remaining_packet_payload() - Bytes to come before "overall"
1337  *                                            rx packet is complete
1338  * @wsi:                Websocket instance (available from user callback)
1339  *
1340  *      This function is intended to be called from the callback if the
1341  *  user code is interested in "complete packets" from the client.
1342  *  libwebsockets just passes through payload as it comes and issues a buffer
1343  *  additionally when it hits a built-in limit.  The LWS_CALLBACK_RECEIVE
1344  *  callback handler can use this API to find out if the buffer it has just
1345  *  been given is the last piece of a "complete packet" from the client --
1346  *  when that is the case libwebsockets_remaining_packet_payload() will return
1347  *  0.
1348  *
1349  *  Many protocols won't care becuse their packets are always small.
1350  */
1351
1352 size_t
1353 libwebsockets_remaining_packet_payload(struct libwebsocket *wsi)
1354 {
1355         return wsi->rx_packet_length;
1356 }