blob: 05be1531fae6196103c2648fe47b2119e8f9525f [file] [log] [blame]
Andy Greenff95d7a2010-10-28 22:36:01 +01001#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <ctype.h>
5#include <unistd.h>
Andy Green775c0dd2010-10-29 14:15:22 +01006#include <errno.h>
Andy Green5fd8a5e2010-10-31 11:57:17 +00007#include <sys/types.h>
8#include <sys/stat.h>
9#include <fcntl.h>
Andy Greenff95d7a2010-10-28 22:36:01 +010010
11#include <sys/types.h>
12#include <sys/socket.h>
13#include <netinet/in.h>
14
15#include <poll.h>
16#include <sys/mman.h>
17
18#include "libwebsockets.h"
19
20void md5(const unsigned char *input, int ilen, unsigned char output[16]);
Andy Green775c0dd2010-10-29 14:15:22 +010021static void libwebsocket_service(struct libwebsocket *wsi, int sock);
Andy Greenff95d7a2010-10-28 22:36:01 +010022
Andy Green775c0dd2010-10-29 14:15:22 +010023#define LWS_MAX_HEADER_NAME_LENGTH 64
24#define LWS_MAX_HEADER_LEN 4096
25#define LWS_INITIAL_HDR_ALLOC 256
26#define LWS_ADDITIONAL_HDR_ALLOC 64
27
28
Andy Green4ea60062010-10-30 12:15:07 +010029/*
30 * Chrome (v0)
31 *
32 * GET / HTTP/1.1
33 * Upgrade: WebSocket
34 * Connection: Upgrade
35 * Host: 127.0.0.1:7681
36 * Origin: null
37 * Sec-WebSocket-Key1: +46 3 1 75 7Y 60
38 * Sec-WebSocket-Key2: m^+J358s0 6N 6e0 Q1 0 ~4~
39 *
40 * Firefox (v76)
41 *
42 * GET / HTTP/1.1
43 * Upgrade: WebSocket
44 * Host: 127.0.0.1:7681
45 * Connection: Upgrade
46 * Sec-WebSocket-Key1: EC."/$14 7 687YG+gZ 44d 16
47 * Origin: file://
48 * Sec-WebSocket-Key2: 2 / 9 0. 4 B8 77|ov968
49 *
50 */
51
52
Andy Green775c0dd2010-10-29 14:15:22 +010053enum lws_connection_states {
Andy Green5fd8a5e2010-10-31 11:57:17 +000054 WSI_STATE_HTTP,
55 WSI_STATE_HTTP_HEADERS,
Andy Green775c0dd2010-10-29 14:15:22 +010056 WSI_STATE_DEAD_SOCKET,
57 WSI_STATE_ESTABLISHED
58};
59
60enum lws_token_indexes {
61 WSI_TOKEN_GET_URI,
62 WSI_TOKEN_HOST,
63 WSI_TOKEN_CONNECTION,
64 WSI_TOKEN_KEY1,
65 WSI_TOKEN_KEY2,
66 WSI_TOKEN_PROTOCOL,
67 WSI_TOKEN_UPGRADE,
68 WSI_TOKEN_ORIGIN,
69 WSI_TOKEN_CHALLENGE,
70
71 /* always last real token index*/
72 WSI_TOKEN_COUNT,
73 /* parser state additions */
74 WSI_TOKEN_NAME_PART,
75 WSI_TOKEN_SKIPPING,
76 WSI_TOKEN_SKIPPING_SAW_CR,
77 WSI_PARSING_COMPLETE
78};
79
Andy Green4ea60062010-10-30 12:15:07 +010080enum lws_rx_parse_state {
81 LWS_RXPS_NEW,
82
83 LWS_RXPS_SEEN_76_FF,
84 LWS_RXPS_PULLING_76_LENGTH,
85
86 LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED
87};
88
Andy Green775c0dd2010-10-29 14:15:22 +010089
90struct lws_tokens {
91 char * token;
92 int token_len;
93};
94
95
96/*
97 * This is totally opaque to code using the library. It's exported as a
Andy Greenab990e42010-10-31 12:42:52 +000098 * forward-reference pointer-only declaration; the user can use the pointer with
99 * other APIs to get information out of it.
Andy Green775c0dd2010-10-29 14:15:22 +0100100 */
101
102struct libwebsocket {
103 int (*callback)(struct libwebsocket *,
Andy Green4ea60062010-10-30 12:15:07 +0100104 enum libwebsocket_callback_reasons reason, void *, size_t);
Andy Green775c0dd2010-10-29 14:15:22 +0100105
106 enum lws_connection_states state;
107
108 char name_buffer[LWS_MAX_HEADER_NAME_LENGTH];
109 int name_buffer_pos;
110 int current_alloc_len;
111 enum lws_token_indexes parser_state;
112 struct lws_tokens utf8_token[WSI_TOKEN_COUNT];
113 int ietf_spec_revision;
114
115 int sock;
Andy Green4ea60062010-10-30 12:15:07 +0100116
117 enum lws_rx_parse_state lws_rx_parse_state;
118 size_t rx_packet_length;
Andy Green775c0dd2010-10-29 14:15:22 +0100119};
120
Andy Greenff95d7a2010-10-28 22:36:01 +0100121
122const struct lws_tokens lws_tokens[WSI_TOKEN_COUNT] = {
123 { "GET ", 4 },
124 { "Host:", 5 },
125 { "Connection:", 11 },
126 { "Sec-WebSocket-Key1:", 19 },
127 { "Sec-WebSocket-Key2:", 19 },
128 { "Sec-WebSocket-Protocol:", 23 },
129 { "Upgrade:", 8 },
130 { "Origin:", 7 },
131 { "\x0d\x0a", 2 },
132};
133
Andy Greenab990e42010-10-31 12:42:52 +0000134/**
135 * libwebsocket_create_server() - Create the listening websockets server
136 * @port: Port to listen on
137 * @callback: The callback in user code to perform actual serving
138 * @protocol: Which version of the websockets protocol (currently 76)
139 *
140 * This function forks to create the listening socket and takes care
141 * of all initialization in one step.
142 *
143 * The callback function is called for a handful of events including
144 * http requests coming in, websocket connections becoming
145 * established, and data arriving; it's also called periodically to allow
146 * async transmission.
147 *
148 * The server created is a simple http server by default; part of the
149 * websocket standard is upgrading this http connection to a websocket one.
150 *
151 * This allows the same server to provide files like scripts and favicon /
152 * images or whatever over http and dynamic data over websockets all in
153 * one place; they're all handled in the user callback.
154 */
Andy Green4ea60062010-10-30 12:15:07 +0100155
Andy Greenea71ed12010-10-31 07:40:33 +0000156int libwebsocket_create_server(int port,
157 int (*callback)(struct libwebsocket *,
158 enum libwebsocket_callback_reasons, void *, size_t),
159 int protocol)
Andy Greenff95d7a2010-10-28 22:36:01 +0100160{
161 int n;
162 int sockfd, newsockfd;
163 unsigned int clilen;
164 struct sockaddr_in serv_addr, cli_addr;
165 int pid;
Andy Green775c0dd2010-10-29 14:15:22 +0100166 struct libwebsocket *wsi = malloc(sizeof(struct libwebsocket));
167
168 if (!wsi)
169 return -1;
Andy Greenff95d7a2010-10-28 22:36:01 +0100170
Andy Green5fd8a5e2010-10-31 11:57:17 +0000171 wsi->state = WSI_STATE_HTTP;
Andy Greenff95d7a2010-10-28 22:36:01 +0100172 wsi->name_buffer_pos = 0;
Andy Greenff95d7a2010-10-28 22:36:01 +0100173
174 for (n = 0; n < WSI_TOKEN_COUNT; n++) {
175 wsi->utf8_token[n].token = NULL;
176 wsi->utf8_token[n].token_len = 0;
177 }
Andy Green775c0dd2010-10-29 14:15:22 +0100178
179 wsi->callback = callback;
Andy Greenea71ed12010-10-31 07:40:33 +0000180 switch (protocol) {
181 case 0:
182 case 2:
183 case 76:
Andy Green5fd8a5e2010-10-31 11:57:17 +0000184 fprintf(stderr, " Using protocol v%d\n", protocol);
Andy Greenea71ed12010-10-31 07:40:33 +0000185 wsi->ietf_spec_revision = protocol;
186 break;
187 default:
188 fprintf(stderr, "protocol %d not supported (try 0 2 or 76)\n",
189 protocol);
190 return -1;
191 }
Andy Greenff95d7a2010-10-28 22:36:01 +0100192
Andy Green775c0dd2010-10-29 14:15:22 +0100193 /* sit there listening for connects, accept and spawn session servers */
194
195 sockfd = socket(AF_INET, SOCK_STREAM, 0);
196 if (sockfd < 0) {
197 fprintf(stderr, "ERROR opening socket");
198 }
199 bzero((char *) &serv_addr, sizeof(serv_addr));
200
201 serv_addr.sin_family = AF_INET;
202 serv_addr.sin_addr.s_addr = INADDR_ANY;
203 serv_addr.sin_port = htons(port);
204 n = bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
205 if (n < 0) {
Andy Greenea71ed12010-10-31 07:40:33 +0000206 fprintf(stderr, "ERROR on binding to port %d (%d %d)\n", port, n,
207 errno);
Andy Green775c0dd2010-10-29 14:15:22 +0100208 return -1;
209 }
210
211 /* fork off a master server for this websocket server */
Andy Greenff95d7a2010-10-28 22:36:01 +0100212
213 n = fork();
214 if (n < 0) {
215 fprintf(stderr, "Failed on forking server thread: %d\n", n);
216 exit(1);
217 }
218
219 /* we are done as far as the caller is concerned */
220
221 if (n)
222 return 0;
223
Andy Green5fd8a5e2010-10-31 11:57:17 +0000224 fprintf(stderr, " Listening on port %d\n", port);
Andy Greenea71ed12010-10-31 07:40:33 +0000225
Andy Greenff95d7a2010-10-28 22:36:01 +0100226 listen(sockfd, 5);
227
228 while (1) {
229 clilen = sizeof(cli_addr);
230
231 newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
Andy Green775c0dd2010-10-29 14:15:22 +0100232 if (newsockfd < 0) {
Andy Greenff95d7a2010-10-28 22:36:01 +0100233 fprintf(stderr, "ERROR on accept");
Andy Green775c0dd2010-10-29 14:15:22 +0100234 continue;
235 }
Andy Green5fd8a5e2010-10-31 11:57:17 +0000236
237// fcntl(newsockfd, F_SETFL, O_NONBLOCK);
Andy Greenff95d7a2010-10-28 22:36:01 +0100238
239 /* fork off a new server instance */
240
241 pid = fork();
Andy Green775c0dd2010-10-29 14:15:22 +0100242 if (pid < 0) {
Andy Greenff95d7a2010-10-28 22:36:01 +0100243 fprintf(stderr, "ERROR on fork");
Andy Green775c0dd2010-10-29 14:15:22 +0100244 continue;
245 }
246
247 if (pid) {
Andy Greenff95d7a2010-10-28 22:36:01 +0100248 close(newsockfd);
Andy Green775c0dd2010-10-29 14:15:22 +0100249 continue;
250 }
251
252 /* we are the session process */
253
254 close(sockfd);
255
256 /* sit in libwebsocket_service() until session socket closed */
257
258 libwebsocket_service(wsi, newsockfd);
259 exit(0);
Andy Greenff95d7a2010-10-28 22:36:01 +0100260 }
261}
262
Andy Greenab990e42010-10-31 12:42:52 +0000263static void libwebsocket_close(struct libwebsocket *wsi)
Andy Greenff95d7a2010-10-28 22:36:01 +0100264{
265 int n;
266
267 wsi->state = WSI_STATE_DEAD_SOCKET;
268
Andy Green775c0dd2010-10-29 14:15:22 +0100269 if (wsi->callback)
Andy Green4ea60062010-10-30 12:15:07 +0100270 wsi->callback(wsi, LWS_CALLBACK_CLOSED, NULL, 0);
Andy Greenff95d7a2010-10-28 22:36:01 +0100271
272 for (n = 0; n < WSI_TOKEN_COUNT; n++)
273 if (wsi->utf8_token[n].token)
274 free(wsi->utf8_token[n].token);
Andy Greenff95d7a2010-10-28 22:36:01 +0100275}
276
Andy Greenab990e42010-10-31 12:42:52 +0000277/**
278 * libwebsocket_get_uri() - Return the URI path being requested
279 * @wsi: Websocket instance
280 *
281 * The user code can find out the local path being opened from this
282 * call, it's valid on HTTP or established websocket connections.
283 * If the client opened the connection with "http://127.0.0.1/xyz/abc.d"
284 * then this call will return a pointer to "/xyz/abc.d"
285 */
286
Andy Green5fd8a5e2010-10-31 11:57:17 +0000287const char * libwebsocket_get_uri(struct libwebsocket *wsi)
288{
289 if (wsi->utf8_token[WSI_TOKEN_GET_URI].token)
290 return wsi->utf8_token[WSI_TOKEN_GET_URI].token;
291
292 return NULL;
293}
Andy Greenff95d7a2010-10-28 22:36:01 +0100294
295static int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c)
296{
297 int n;
298
299 switch (wsi->parser_state) {
300 case WSI_TOKEN_GET_URI:
301 case WSI_TOKEN_HOST:
302 case WSI_TOKEN_CONNECTION:
303 case WSI_TOKEN_KEY1:
304 case WSI_TOKEN_KEY2:
305 case WSI_TOKEN_PROTOCOL:
306 case WSI_TOKEN_UPGRADE:
307 case WSI_TOKEN_ORIGIN:
308 case WSI_TOKEN_CHALLENGE:
309
310// fprintf(stderr, "WSI_TOKEN_(body %d) '%c'\n", wsi->parser_state, c);
311
312 /* collect into malloc'd buffers */
313 /* optional space swallow */
314 if (!wsi->utf8_token[wsi->parser_state].token_len && c == ' ')
315 break;
316
317 /* special case space terminator for get-uri */
318 if (wsi->parser_state == WSI_TOKEN_GET_URI && c == ' ') {
319 wsi->utf8_token[wsi->parser_state].token[
320 wsi->utf8_token[wsi->parser_state].token_len] = '\0';
321 wsi->parser_state = WSI_TOKEN_SKIPPING;
322 break;
323 }
324
325 /* allocate appropriate memory */
Andy Green4ea60062010-10-30 12:15:07 +0100326 if (wsi->utf8_token[wsi->parser_state].token_len ==
327 wsi->current_alloc_len - 1) {
Andy Greenff95d7a2010-10-28 22:36:01 +0100328 /* need to extend */
329 wsi->current_alloc_len += LWS_ADDITIONAL_HDR_ALLOC;
330 if (wsi->current_alloc_len >= LWS_MAX_HEADER_LEN) {
331 /* it's waaay to much payload, fail it */
332 strcpy(wsi->utf8_token[wsi->parser_state].token,
Andy Green4ea60062010-10-30 12:15:07 +0100333 "!!! Length exceeded maximum supported !!!");
Andy Greenff95d7a2010-10-28 22:36:01 +0100334 wsi->parser_state = WSI_TOKEN_SKIPPING;
335 break;
336 }
337 wsi->utf8_token[wsi->parser_state].token =
338 realloc(wsi->utf8_token[wsi->parser_state].token,
339 wsi->current_alloc_len);
340 }
341
342 /* bail at EOL */
343 if (wsi->parser_state != WSI_TOKEN_CHALLENGE && c == '\x0d') {
344 wsi->utf8_token[wsi->parser_state].token[
345 wsi->utf8_token[wsi->parser_state].token_len] = '\0';
346 wsi->parser_state = WSI_TOKEN_SKIPPING_SAW_CR;
347 break;
348 }
349
350 wsi->utf8_token[wsi->parser_state].token[
351 wsi->utf8_token[wsi->parser_state].token_len++] = c;
352
353 /* special payload limiting */
Andy Green775c0dd2010-10-29 14:15:22 +0100354 if (wsi->parser_state == WSI_TOKEN_CHALLENGE &&
355 wsi->utf8_token[wsi->parser_state].token_len == 8) {
356// fprintf(stderr, "Setting WSI_PARSING_COMPLETE\n");
357 wsi->parser_state = WSI_PARSING_COMPLETE;
358 break;
359 }
Andy Greenff95d7a2010-10-28 22:36:01 +0100360
361 break;
362
363 /* collecting and checking a name part */
364 case WSI_TOKEN_NAME_PART:
365// fprintf(stderr, "WSI_TOKEN_NAME_PART '%c'\n", c);
366
367 if (wsi->name_buffer_pos == sizeof(wsi->name_buffer) - 1) {
368 /* name bigger than we can handle, skip until next */
369 wsi->parser_state = WSI_TOKEN_SKIPPING;
370 break;
371 }
372 wsi->name_buffer[wsi->name_buffer_pos++] = c;
373 wsi->name_buffer[wsi->name_buffer_pos] = '\0';
374
375 for (n = 0; n < WSI_TOKEN_COUNT; n++) {
376 if (wsi->name_buffer_pos != lws_tokens[n].token_len)
377 continue;
378 if (strcmp(lws_tokens[n].token, wsi->name_buffer))
379 continue;
Andy Green5fd8a5e2010-10-31 11:57:17 +0000380 fprintf(stderr, "known header '%s'\n", wsi->name_buffer);
Andy Greenff95d7a2010-10-28 22:36:01 +0100381 wsi->parser_state = WSI_TOKEN_GET_URI + n;
382 wsi->current_alloc_len = LWS_INITIAL_HDR_ALLOC;
383 wsi->utf8_token[wsi->parser_state].token =
384 malloc(wsi->current_alloc_len);
385 wsi->utf8_token[wsi->parser_state].token_len = 0;
386 n = WSI_TOKEN_COUNT;
387 }
Andy Green5fd8a5e2010-10-31 11:57:17 +0000388
389 /* colon delimiter means we just don't know this name */
390
391 if (wsi->parser_state == WSI_TOKEN_NAME_PART && c == ':') {
392 fprintf(stderr, "skipping unknown header '%s'\n", wsi->name_buffer);
393 wsi->parser_state = WSI_TOKEN_SKIPPING;
Andy Greenff95d7a2010-10-28 22:36:01 +0100394 break;
Andy Green5fd8a5e2010-10-31 11:57:17 +0000395 }
396
397 /* don't look for payload when it can just be http headers */
398
399 if (wsi->parser_state == WSI_TOKEN_CHALLENGE &&
400 !wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len) {
401 /* they're HTTP headers, not websocket upgrade! */
402 fprintf(stderr, "Setting WSI_PARSING_COMPLETE from http headers\n");
403 wsi->parser_state = WSI_PARSING_COMPLETE;
404 }
Andy Greenff95d7a2010-10-28 22:36:01 +0100405 break;
406
407 /* skipping arg part of a name we didn't recognize */
408 case WSI_TOKEN_SKIPPING:
409// fprintf(stderr, "WSI_TOKEN_SKIPPING '%c'\n", c);
410 if (c == '\x0d')
411 wsi->parser_state = WSI_TOKEN_SKIPPING_SAW_CR;
412 break;
413 case WSI_TOKEN_SKIPPING_SAW_CR:
414// fprintf(stderr, "WSI_TOKEN_SKIPPING_SAW_CR '%c'\n", c);
415 if (c == '\x0a')
416 wsi->parser_state = WSI_TOKEN_NAME_PART;
417 else
418 wsi->parser_state = WSI_TOKEN_SKIPPING;
419 wsi->name_buffer_pos = 0;
420 break;
421 /* we're done, ignore anything else */
422 case WSI_PARSING_COMPLETE:
423// fprintf(stderr, "WSI_PARSING_COMPLETE '%c'\n", c);
424 break;
425
426 default: /* keep gcc happy */
427 break;
428 }
429
430 return 0;
431}
432
433static int interpret_key(const char *key, unsigned int *result)
434{
435 char digits[20];
436 int digit_pos = 0;
437 const char *p = key;
438 int spaces = 0;
439
440 while (*p) {
441 if (isdigit(*p)) {
442 if (digit_pos == sizeof(digits) - 1)
443 return -1;
444 digits[digit_pos++] = *p;
445 }
446 p++;
447 }
448 digits[digit_pos] = '\0';
449 if (!digit_pos)
450 return -2;
451
452 while (*key) {
453 if (*key == ' ')
454 spaces++;
455 key++;
456 }
457
458 if (!spaces)
459 return -3;
460
461 *result = atol(digits) / spaces;
462
463 return 0;
464}
465
Andy Green4ea60062010-10-30 12:15:07 +0100466static int libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c)
467{
468 int n;
469 unsigned char buf[2];
470
471 switch (wsi->lws_rx_parse_state) {
472 case LWS_RXPS_NEW:
473
474 switch (wsi->ietf_spec_revision) {
475 /* Firefox 4.0b6 likes this as of 30 Oct */
476 case 76:
477 if (c == 0xff)
478 wsi->lws_rx_parse_state = LWS_RXPS_SEEN_76_FF;
479 break;
480 case 0:
481 break;
482 }
483 break;
484 case LWS_RXPS_SEEN_76_FF:
485 if (c != 0) {
486 break;
487 }
488
489 fprintf(stderr, "Seen that client is requesting a v76 close, sending ack\n");
490 buf[0] = 0xff;
491 buf[1] = 0;
492 n = write(wsi->sock, buf, 2);
493 if (n < 0) {
494 fprintf(stderr, "ERROR writing to socket");
495 return -1;
496 }
497 fprintf(stderr, " v76 close ack sent, server closing socket\n");
498 /* returning < 0 will get it closed in parent */
499 return -1;
500
501 case LWS_RXPS_PULLING_76_LENGTH:
502 break;
503 case LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED:
504 break;
505 }
506
507 return 0;
508}
509
510static int libwebsocket_interpret_incoming_packet(struct libwebsocket *wsi,
511 unsigned char *buf, size_t len)
512{
513 int n;
514
515 fprintf(stderr, "received %d byte packet\n", (int)len);
516 for (n = 0; n < len; n++)
517 fprintf(stderr, "%02X ", buf[n]);
518 fprintf(stderr, "\n");
519
520 /* let the rx protocol state machine have as much as it needs */
521
522 n = 0;
523 while (wsi->lws_rx_parse_state !=
524 LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED && n < len)
525 if (libwebsocket_rx_sm(wsi, buf[n++]) < 0)
526 return -1;
527
528 if (n != len) {
529 if (wsi->callback)
530 wsi->callback(wsi, LWS_CALLBACK_RECEIVE, &buf[n], len - n);
531 }
532
533 return -0;
534}
535
Andy Greenff95d7a2010-10-28 22:36:01 +0100536
537/*
538 * We have to take care about parsing because the headers may be split
539 * into multiple fragments. They may contain unknown headers with arbitrary
Andy Green775c0dd2010-10-29 14:15:22 +0100540 * argument lengths. So, we parse using a single-character at a time state
541 * machine that is completely independent of packet size.
Andy Greenff95d7a2010-10-28 22:36:01 +0100542 */
543
Andy Greenab990e42010-10-31 12:42:52 +0000544static int
545libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len)
Andy Greenff95d7a2010-10-28 22:36:01 +0100546{
547 size_t n;
548 char *p;
549 unsigned int key1, key2;
550 unsigned char sum[16];
Andy Green775c0dd2010-10-29 14:15:22 +0100551 char *response;
Andy Greenff95d7a2010-10-28 22:36:01 +0100552
553 switch (wsi->state) {
Andy Green5fd8a5e2010-10-31 11:57:17 +0000554 case WSI_STATE_HTTP:
555 wsi->state = WSI_STATE_HTTP_HEADERS;
Andy Greenff95d7a2010-10-28 22:36:01 +0100556 wsi->parser_state = WSI_TOKEN_NAME_PART;
Andy Green775c0dd2010-10-29 14:15:22 +0100557 /* fallthru */
Andy Green5fd8a5e2010-10-31 11:57:17 +0000558 case WSI_STATE_HTTP_HEADERS:
Andy Greenff95d7a2010-10-28 22:36:01 +0100559
Andy Green4ea60062010-10-30 12:15:07 +0100560 fprintf(stderr, "issuing %d bytes to parser\n", (int)len);
Andy Greenff95d7a2010-10-28 22:36:01 +0100561
562 fwrite(buf, 1, len, stderr);
563 for (n = 0; n< len; n++)
564 libwebsocket_parse(wsi, *buf++);
565
566 if (wsi->parser_state != WSI_PARSING_COMPLETE)
567 break;
Andy Green5fd8a5e2010-10-31 11:57:17 +0000568
569 /* is this websocket protocol or normal http 1.0? */
570
571 if (!wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len ||
572 !wsi->utf8_token[WSI_TOKEN_CONNECTION].token_len) {
573 if (wsi->callback)
574 (wsi->callback)(wsi, LWS_CALLBACK_HTTP, NULL, 0);
575 wsi->state = WSI_STATE_HTTP;
576 return 0;
577 }
578
Andy Greenff95d7a2010-10-28 22:36:01 +0100579
580 fprintf(stderr, "Preparing return packet\n");
581
Andy Green5fd8a5e2010-10-31 11:57:17 +0000582 /* Websocket - confirm we have all the necessary pieces */
Andy Greenff95d7a2010-10-28 22:36:01 +0100583
Andy Green5fd8a5e2010-10-31 11:57:17 +0000584 if (!wsi->utf8_token[WSI_TOKEN_ORIGIN].token_len ||
Andy Greenff95d7a2010-10-28 22:36:01 +0100585 !wsi->utf8_token[WSI_TOKEN_HOST].token_len ||
586 !wsi->utf8_token[WSI_TOKEN_CHALLENGE].token_len ||
587 !wsi->utf8_token[WSI_TOKEN_KEY1].token_len ||
Andy Green5fd8a5e2010-10-31 11:57:17 +0000588 !wsi->utf8_token[WSI_TOKEN_KEY2].token_len)
Andy Greenff95d7a2010-10-28 22:36:01 +0100589 /* completed header processing, but missing some bits */
590 goto bail;
Andy Greenff95d7a2010-10-28 22:36:01 +0100591
592 /* create the response packet */
593
Andy Green4ea60062010-10-30 12:15:07 +0100594 /* make a buffer big enough for everything */
595
Andy Green775c0dd2010-10-29 14:15:22 +0100596 response = malloc(256 +
Andy Greenff95d7a2010-10-28 22:36:01 +0100597 wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len +
598 wsi->utf8_token[WSI_TOKEN_CONNECTION].token_len +
599 wsi->utf8_token[WSI_TOKEN_HOST].token_len +
600 wsi->utf8_token[WSI_TOKEN_ORIGIN].token_len +
601 wsi->utf8_token[WSI_TOKEN_GET_URI].token_len +
602 wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len);
Andy Green4ea60062010-10-30 12:15:07 +0100603 if (!response) {
604 fprintf(stderr, "Out of memory for response buffer\n");
605 goto bail;
606 }
Andy Greenff95d7a2010-10-28 22:36:01 +0100607
Andy Green775c0dd2010-10-29 14:15:22 +0100608 p = response;
Andy Green4ea60062010-10-30 12:15:07 +0100609 strcpy(p, "HTTP/1.1 101 WebSocket Protocol Handshake\x0d\x0a"
610 "Upgrade: WebSocket\x0d\x0a");
611 p += strlen("HTTP/1.1 101 WebSocket Protocol Handshake\x0d\x0a"
612 "Upgrade: WebSocket\x0d\x0a");
Andy Greenff95d7a2010-10-28 22:36:01 +0100613 strcpy(p, "Connection: Upgrade\x0d\x0aSec-WebSocket-Origin: ");
614 p += strlen("Connection: Upgrade\x0d\x0aSec-WebSocket-Origin: ");
615 strcpy(p, wsi->utf8_token[WSI_TOKEN_ORIGIN].token);
616 p += wsi->utf8_token[WSI_TOKEN_ORIGIN].token_len;
617 strcpy(p, "\x0d\x0aSec-WebSocket-Location: ws://");
618 p += strlen("\x0d\x0aSec-WebSocket-Location: ws://");
619 strcpy(p, wsi->utf8_token[WSI_TOKEN_HOST].token);
620 p += wsi->utf8_token[WSI_TOKEN_HOST].token_len;
621 strcpy(p, wsi->utf8_token[WSI_TOKEN_GET_URI].token);
622 p += wsi->utf8_token[WSI_TOKEN_GET_URI].token_len;
Andy Greenea71ed12010-10-31 07:40:33 +0000623
Andy Greenff95d7a2010-10-28 22:36:01 +0100624 if (wsi->utf8_token[WSI_TOKEN_PROTOCOL].token) {
Andy Greenea71ed12010-10-31 07:40:33 +0000625 strcpy(p, "\x0d\x0aSec-WebSocket-Protocol: ");
626 p += strlen("\x0d\x0aSec-WebSocket-Protocol: ");
Andy Greenff95d7a2010-10-28 22:36:01 +0100627 strcpy(p, wsi->utf8_token[WSI_TOKEN_PROTOCOL].token);
628 p += wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len;
629 }
Andy Greenea71ed12010-10-31 07:40:33 +0000630
Andy Greenff95d7a2010-10-28 22:36:01 +0100631 strcpy(p, "\x0d\x0a\x0d\x0a");
632 p += strlen("\x0d\x0a\x0d\x0a");
633
Andy Green775c0dd2010-10-29 14:15:22 +0100634 /* convert the two keys into 32-bit integers */
635
Andy Greenff95d7a2010-10-28 22:36:01 +0100636 if (interpret_key(wsi->utf8_token[WSI_TOKEN_KEY1].token, &key1))
637 goto bail;
Andy Greenff95d7a2010-10-28 22:36:01 +0100638 if (interpret_key(wsi->utf8_token[WSI_TOKEN_KEY2].token, &key2))
639 goto bail;
Andy Green775c0dd2010-10-29 14:15:22 +0100640
641 /* lay them out in network byte order (MSB first */
Andy Greenff95d7a2010-10-28 22:36:01 +0100642
643 sum[0] = key1 >> 24;
644 sum[1] = key1 >> 16;
645 sum[2] = key1 >> 8;
646 sum[3] = key1;
647 sum[4] = key2 >> 24;
648 sum[5] = key2 >> 16;
649 sum[6] = key2 >> 8;
650 sum[7] = key2;
Andy Green775c0dd2010-10-29 14:15:22 +0100651
652 /* follow them with the challenge token we were sent */
653
Andy Greenff95d7a2010-10-28 22:36:01 +0100654 memcpy(&sum[8], wsi->utf8_token[WSI_TOKEN_CHALLENGE].token, 8);
655
Andy Green775c0dd2010-10-29 14:15:22 +0100656 /*
657 * compute the md5sum of that 16-byte series and use as our
658 * payload after our headers
659 */
660
Andy Greenff95d7a2010-10-28 22:36:01 +0100661 md5(sum, 16, (unsigned char *)p);
662 p += 16;
663
Andy Green4ea60062010-10-30 12:15:07 +0100664 /* it's complete: go ahead and send it */
Andy Greenff95d7a2010-10-28 22:36:01 +0100665
Andy Green775c0dd2010-10-29 14:15:22 +0100666 fprintf(stderr, "issuing response packet %d len\n",
Andy Green4ea60062010-10-30 12:15:07 +0100667 (int)(p - response));
Andy Green775c0dd2010-10-29 14:15:22 +0100668 fwrite(response, 1, p - response, stderr);
669
670 n = write(wsi->sock, response, p - response);
671 if (n < 0) {
672 fprintf(stderr, "ERROR writing to socket");
673 goto bail;
674 }
Andy Green4ea60062010-10-30 12:15:07 +0100675
676 /* alright clean up and set ourselves into established state */
Andy Green775c0dd2010-10-29 14:15:22 +0100677
678 free(response);
679 wsi->state = WSI_STATE_ESTABLISHED;
Andy Green4ea60062010-10-30 12:15:07 +0100680 wsi->lws_rx_parse_state = LWS_RXPS_NEW;
Andy Green775c0dd2010-10-29 14:15:22 +0100681
682 /* notify user code that we're ready to roll */
683
684 if (wsi->callback)
Andy Green4ea60062010-10-30 12:15:07 +0100685 wsi->callback(wsi, LWS_CALLBACK_ESTABLISHED, NULL, 0);
Andy Greenff95d7a2010-10-28 22:36:01 +0100686 break;
687
688 case WSI_STATE_ESTABLISHED:
Andy Green4ea60062010-10-30 12:15:07 +0100689 if (libwebsocket_interpret_incoming_packet(wsi, buf, len) < 0)
690 goto bail;
Andy Greenff95d7a2010-10-28 22:36:01 +0100691 break;
692 default:
693 break;
694 }
695
696 return 0;
697
698bail:
699 libwebsocket_close(wsi);
700 return -1;
701}
702
Andy Greenab990e42010-10-31 12:42:52 +0000703/**
704 * libwebsocket_write() - Apply protocol then write data to client
705 * @wsi: Websocket instance (available from user callback)
706 * @buf: The data to send. For data being sent on a websocket
707 * connection (ie, not default http), this buffer MUST have
708 * LWS_SEND_BUFFER_PRE_PADDING bytes valid BEFORE the pointer
709 * and an additional LWS_SEND_BUFFER_POST_PADDING bytes valid
710 * in the buffer after (buf + len). This is so the protocol
711 * header and trailer data can be added in-situ.
712 * @len: Count of the data bytes in the payload starting from buf
713 * @protocol: Use LWS_WRITE_HTTP to reply to an http connection, and one
714 * of LWS_WRITE_BINARY or LWS_WRITE_TEXT to send appropriate
715 * data on a websockets connection. Remember to allow the extra
716 * bytes before and after buf if LWS_WRITE_BINARY or LWS_WRITE_TEXT
717 * are used.
718 *
719 * This function provides the way to issue data back to the client
720 * for both http and websocket protocols.
Andy Green4ea60062010-10-30 12:15:07 +0100721 *
Andy Greenab990e42010-10-31 12:42:52 +0000722 * In the case of sending using websocket protocol, be sure to allocate
723 * valid storage before and after buf as explained above. This scheme
724 * allows maximum efficiency of sending data and protocol in a single
725 * packet while not burdening the user code with any protocol knowledge.
Andy Green4ea60062010-10-30 12:15:07 +0100726 */
727
728int libwebsocket_write(struct libwebsocket * wsi, unsigned char *buf,
Andy Green5fd8a5e2010-10-31 11:57:17 +0000729 size_t len, enum libwebsocket_write_protocol protocol)
Andy Green775c0dd2010-10-29 14:15:22 +0100730{
731 int n;
Andy Green4ea60062010-10-30 12:15:07 +0100732 int pre = 0;
733 int post = 0;
734 unsigned int shift = 7;
Andy Green775c0dd2010-10-29 14:15:22 +0100735
Andy Green5fd8a5e2010-10-31 11:57:17 +0000736 if (protocol == LWS_WRITE_HTTP)
737 goto send_raw;
738
739 /* websocket protocol, either binary or text */
740
Andy Green775c0dd2010-10-29 14:15:22 +0100741 if (wsi->state != WSI_STATE_ESTABLISHED)
742 return -1;
Andy Greenff95d7a2010-10-28 22:36:01 +0100743
Andy Green775c0dd2010-10-29 14:15:22 +0100744 switch (wsi->ietf_spec_revision) {
Andy Green4ea60062010-10-30 12:15:07 +0100745 /* Firefox 4.0b6 likes this as of 30 Oct */
746 case 76:
Andy Green5fd8a5e2010-10-31 11:57:17 +0000747 if (protocol == LWS_WRITE_BINARY) {
Andy Green4ea60062010-10-30 12:15:07 +0100748 /* in binary mode we send 7-bit used length blocks */
749 pre = 1;
750 while (len & (127 << shift)) {
751 pre++;
752 shift += 7;
753 }
754 n = 0;
755 shift -= 7;
756 while (shift >= 0) {
757 if (shift)
758 buf[0 - pre + n] =
759 ((len >> shift) & 127) | 0x80;
760 else
761 buf[0 - pre + n] =
762 ((len >> shift) & 127);
763 n++;
764 shift -= 7;
765 }
766 break;
Andy Green775c0dd2010-10-29 14:15:22 +0100767 }
Andy Green4ea60062010-10-30 12:15:07 +0100768
769 /* frame type = text, length-free spam mode */
770
771 buf[-1] = 0;
772 buf[len] = 0xff; /* EOT marker */
773 pre = 1;
774 post = 1;
Andy Green775c0dd2010-10-29 14:15:22 +0100775 break;
Andy Green4ea60062010-10-30 12:15:07 +0100776
777 /* chrome likes this as of 30 Oct */
778 case 0:
779 buf[-9] = 0xff;
780#if defined __LP64__
781 buf[-8] = len >> 56;
782 buf[-7] = len >> 48;
783 buf[-6] = len >> 40;
784 buf[-5] = len >> 32;
785#else
786 buf[-8] = 0;
787 buf[-7] = 0;
788 buf[-6] = 0;
789 buf[-5] = 0;
790#endif
791 buf[-4] = len >> 24;
792 buf[-3] = len >> 16;
793 buf[-2] = len >> 8;
794 buf[-1] = len;
795 pre = 9;
796 break;
797
Andy Green775c0dd2010-10-29 14:15:22 +0100798 /* just an unimplemented spec right now apparently */
799 case 2:
Andy Green4ea60062010-10-30 12:15:07 +0100800 n = 4; /* text */
Andy Green5fd8a5e2010-10-31 11:57:17 +0000801 if (protocol == LWS_WRITE_BINARY)
Andy Green4ea60062010-10-30 12:15:07 +0100802 n = 5; /* binary */
Andy Green775c0dd2010-10-29 14:15:22 +0100803 if (len < 126) {
Andy Green4ea60062010-10-30 12:15:07 +0100804 buf[-2] = n;
805 buf[-1] = len;
806 pre = 2;
Andy Green775c0dd2010-10-29 14:15:22 +0100807 } else {
808 if (len < 65536) {
Andy Green4ea60062010-10-30 12:15:07 +0100809 buf[-4] = n;
810 buf[-3] = 126;
811 buf[-2] = len >> 8;
812 buf[-1] = len;
813 pre = 4;
Andy Green775c0dd2010-10-29 14:15:22 +0100814 } else {
Andy Green4ea60062010-10-30 12:15:07 +0100815 buf[-10] = n;
816 buf[-9] = 127;
817#if defined __LP64__
818 buf[-8] = (len >> 56) & 0x7f;
819 buf[-7] = len >> 48;
820 buf[-6] = len >> 40;
821 buf[-5] = len >> 32;
822#else
823 buf[-8] = 0;
824 buf[-7] = 0;
825 buf[-6] = 0;
826 buf[-5] = 0;
827#endif
828 buf[-4] = len >> 24;
829 buf[-3] = len >> 16;
830 buf[-2] = len >> 8;
831 buf[-1] = len;
832 pre = 10;
Andy Green775c0dd2010-10-29 14:15:22 +0100833 }
834 }
Andy Green775c0dd2010-10-29 14:15:22 +0100835 break;
836 }
Andy Greenea71ed12010-10-31 07:40:33 +0000837
Andy Green5fd8a5e2010-10-31 11:57:17 +0000838// for (n = 0; n < (len + pre + post); n++)
839// fprintf(stderr, "%02X ", buf[n - pre]);
840//
841// fprintf(stderr, "\n");
Andy Green775c0dd2010-10-29 14:15:22 +0100842
Andy Green5fd8a5e2010-10-31 11:57:17 +0000843send_raw:
844
845 n = send(wsi->sock, buf - pre, len + pre + post, 0);
Andy Green775c0dd2010-10-29 14:15:22 +0100846 if (n < 0) {
847 fprintf(stderr, "ERROR writing to socket");
848 return -1;
849 }
Andy Green4ea60062010-10-30 12:15:07 +0100850
Andy Green5fd8a5e2010-10-31 11:57:17 +0000851// fprintf(stderr, "written %d bytes to client\n", (int)len);
Andy Green775c0dd2010-10-29 14:15:22 +0100852
853 return 0;
854}
855
856static void libwebsocket_service(struct libwebsocket *wsi, int sock)
Andy Greenff95d7a2010-10-28 22:36:01 +0100857{
858 int n;
859 unsigned char buf[256];
860 struct pollfd fds;
861
862 wsi->sock = sock;
Andy Green5fd8a5e2010-10-31 11:57:17 +0000863
Andy Greenff95d7a2010-10-28 22:36:01 +0100864 while (1) {
Andy Green5fd8a5e2010-10-31 11:57:17 +0000865 fds.fd = sock;
866 fds.events = POLLIN;
867 fds.revents = 0;
868 n = poll(&fds, 1, 50);
869
870 /*
871 * we seem to get a ton of POLLINs coming when there's nothing
872 * to read (at least, 0 bytes read)... don't understand why yet
873 * but I stuck a usleep() in the 0 byte read case to regulate
874 * CPU
875 */
876
877
Andy Greenff95d7a2010-10-28 22:36:01 +0100878 if (n < 0) {
879 fprintf(stderr, "Socket dead (poll = %d)\n", n);
880 return;
881 }
Andy Green5fd8a5e2010-10-31 11:57:17 +0000882 if (n == 0)
883 goto pout;
Andy Greenff95d7a2010-10-28 22:36:01 +0100884
885 if (fds.revents & (POLLERR | POLLHUP)) {
886 fprintf(stderr, "Socket dead\n");
887 return;
888 }
889
Andy Green5fd8a5e2010-10-31 11:57:17 +0000890 if (wsi->state == WSI_STATE_DEAD_SOCKET) {
891 fprintf(stderr, "Seen socket dead, returning from service\n");
Andy Greenff95d7a2010-10-28 22:36:01 +0100892 return;
Andy Green5fd8a5e2010-10-31 11:57:17 +0000893 }
Andy Greenff95d7a2010-10-28 22:36:01 +0100894
895 if (fds.revents & POLLIN) {
896
897// fprintf(stderr, "POLLIN\n");
898
Andy Green5fd8a5e2010-10-31 11:57:17 +0000899 n = recv(sock, buf, sizeof(buf), 0);
Andy Greenff95d7a2010-10-28 22:36:01 +0100900 if (n < 0) {
901 fprintf(stderr, "Socket read returned %d\n", n);
902 continue;
903 }
904 if (n)
905 libwebsocket_read(wsi, buf, n);
Andy Green5fd8a5e2010-10-31 11:57:17 +0000906 else {
907// fprintf(stderr, "POLLIN with zero length waiting\n");
908 usleep(50000);
909 }
Andy Greenff95d7a2010-10-28 22:36:01 +0100910 }
Andy Green5fd8a5e2010-10-31 11:57:17 +0000911pout:
Andy Green775c0dd2010-10-29 14:15:22 +0100912 if (wsi->state != WSI_STATE_ESTABLISHED)
Andy Greenff95d7a2010-10-28 22:36:01 +0100913 continue;
Andy Green5fd8a5e2010-10-31 11:57:17 +0000914
915// fprintf(stderr, "POLLOUT\n");
916
Andy Green775c0dd2010-10-29 14:15:22 +0100917 if (wsi->callback)
Andy Green4ea60062010-10-30 12:15:07 +0100918 wsi->callback(wsi, LWS_CALLBACK_SEND, NULL, 0);
Andy Greenff95d7a2010-10-28 22:36:01 +0100919 }
920}
921
Andy Greenab990e42010-10-31 12:42:52 +0000922/**
923 * libwebsockets_serve_http_file() - Send a file back to the client using http
924 * @wsi: Websocket instance (available from user callback)
925 * @file: The file to issue over http
926 * @content_type: The http content type, eg, text/html
927 *
928 * This function is intended to be called from the callback in response
929 * to http requests from the client. It allows the callback to issue
930 * local files down the http link in a single step.
931 */
932
Andy Green5fd8a5e2010-10-31 11:57:17 +0000933int libwebsockets_serve_http_file(struct libwebsocket *wsi, const char * file,
934 const char * content_type)
935{
936 int fd;
937 struct stat stat;
938 char buf[512];
939 char *p = buf;
940 int n;
941
942 fd = open(file, O_RDONLY);
943 if (fd < 1) {
944 p += sprintf(p, "HTTP/1.0 400 Bad\x0d\x0a"
945 "Server: libwebsockets\x0d\x0a"
946 "\x0d\x0a"
947 );
948 libwebsocket_write(wsi, (unsigned char *)buf, p - buf, LWS_WRITE_HTTP);
949
950 return -1;
951 }
952
953 fstat(fd, &stat);
954 p += sprintf(p, "HTTP/1.0 200 OK\x0d\x0a"
955 "Server: libwebsockets\x0d\x0a"
956 "Content-Type: %s\x0d\x0a"
957 "Content-Length: %u\x0d\x0a"
958 "\x0d\x0a", content_type, (unsigned int)stat.st_size
959 );
960
961 libwebsocket_write(wsi, (unsigned char *)buf, p - buf, LWS_WRITE_HTTP);
962
963 n = 1;
964 while (n > 0) {
965 n = read(fd, buf, 512);
966 libwebsocket_write(wsi, (unsigned char *)buf, n, LWS_WRITE_HTTP);
967 }
968
969 close(fd);
970
971 return 0;
972}