2 * libwebsockets - small server side websockets and web server implementation
4 * Copyright (C) 2010 Andy Green <andy@warmcat.com>
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.
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.
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,
28 #include <sys/types.h>
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
40 #ifdef LWS_OPENSSL_SUPPORT
41 #include <openssl/ssl.h>
42 #include <openssl/evp.h>
43 #include <openssl/err.h>
51 #include "libwebsockets.h"
54 #define debug(format, args...) \
55 fprintf(stderr, format , ## args)
57 #define debug(format, args...)
60 void md5(const unsigned char *input, int ilen, unsigned char output[16]);
62 libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len);
64 #define MAX_CLIENTS 100
65 #define LWS_MAX_HEADER_NAME_LENGTH 64
66 #define LWS_MAX_HEADER_LEN 4096
67 #define LWS_INITIAL_HDR_ALLOC 256
68 #define LWS_ADDITIONAL_HDR_ALLOC 64
72 enum lws_connection_states {
74 WSI_STATE_HTTP_HEADERS,
75 WSI_STATE_DEAD_SOCKET,
79 enum lws_token_indexes {
90 /* always last real token index*/
92 /* parser state additions */
95 WSI_TOKEN_SKIPPING_SAW_CR,
99 enum lws_rx_parse_state {
103 LWS_RXPS_PULLING_76_LENGTH,
105 LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED
116 * This is totally opaque to code using the library. It's exported as a
117 * forward-reference pointer-only declaration; the user can use the pointer with
118 * other APIs to get information out of it.
121 struct libwebsocket {
122 int (*callback)(struct libwebsocket *,
123 enum libwebsocket_callback_reasons reason, void *, void *, size_t);
125 enum lws_connection_states state;
127 char name_buffer[LWS_MAX_HEADER_NAME_LENGTH];
129 int current_alloc_len;
130 enum lws_token_indexes parser_state;
131 struct lws_tokens utf8_token[WSI_TOKEN_COUNT];
132 int ietf_spec_revision;
136 enum lws_rx_parse_state lws_rx_parse_state;
137 size_t rx_packet_length;
139 #ifdef LWS_OPENSSL_SUPPORT
141 struct sockaddr_in m_addr;
146 // these are valid if it is a POST
151 time_t m_timeStarted;
152 long long m_llTransferred;
153 long long m_llSizeIfKnown;
155 char m_szTitle[PATH_MAX];
156 char m_szStatus[PATH_MAX];
164 const struct lws_tokens lws_tokens[WSI_TOKEN_COUNT] = {
167 { "Connection:", 11 },
168 { "Sec-WebSocket-Key1:", 19 },
169 { "Sec-WebSocket-Key2:", 19 },
170 { "Sec-WebSocket-Protocol:", 23 },
177 libwebsocket_close_and_free_session(struct libwebsocket *wsi)
181 wsi->state = WSI_STATE_DEAD_SOCKET;
183 if (wsi->callback && n == WSI_STATE_ESTABLISHED)
184 wsi->callback(wsi, LWS_CALLBACK_CLOSED, &wsi->user_space[0],
187 for (n = 0; n < WSI_TOKEN_COUNT; n++)
188 if (wsi->utf8_token[n].token)
189 free(wsi->utf8_token[n].token);
191 // fprintf(stderr, "closing fd=%d\n", wsi->sock);
193 #ifdef LWS_OPENSSL_SUPPORT
195 n = SSL_get_fd(wsi->ssl);
196 SSL_shutdown(wsi->ssl);
201 shutdown(wsi->sock, SHUT_RDWR);
203 #ifdef LWS_OPENSSL_SUPPORT
210 * libwebsocket_create_server() - Create the listening websockets server
211 * @port: Port to listen on
212 * @callback: The callback in user code to perform actual serving
213 * @protocol: Which version of the websockets protocol (currently 76)
214 * @user_area_size: How much memory to allocate per connection session
215 * which will be used by the user application to store
216 * per-session data. A pointer to this space is given
217 * when the user callback is called.
218 * @ssl_cert_filepath: If libwebsockets was compiled to use ssl, and you want
219 * to listen using SSL, set to the filepath to fetch the
220 * server cert from, otherwise NULL for unencrypted
221 * @ssl_private_key_filepath: filepath to private key if wanting SSL mode,
223 * @gid: group id to change to after setting listen socket, or -1.
224 * @uid: user id to change to after setting listen socket, or -1.
226 * This function forks to create the listening socket and takes care
227 * of all initialization in one step.
229 * The callback function is called for a handful of events including
230 * http requests coming in, websocket connections becoming
231 * established, and data arriving; it's also called periodically to allow
232 * async transmission.
234 * The server created is a simple http server by default; part of the
235 * websocket standard is upgrading this http connection to a websocket one.
237 * This allows the same server to provide files like scripts and favicon /
238 * images or whatever over http and dynamic data over websockets all in
239 * one place; they're all handled in the user callback.
242 int libwebsocket_create_server(int port,
243 int (*callback)(struct libwebsocket *,
244 enum libwebsocket_callback_reasons,
245 void *, void *, size_t),
246 int protocol, size_t user_area_size,
247 const char * ssl_cert_filepath,
248 const char * ssl_private_key_filepath,
256 struct sockaddr_in serv_addr, cli_addr;
257 struct libwebsocket *wsi[MAX_CLIENTS + 1];
258 struct pollfd fds[MAX_CLIENTS + 1];
260 unsigned char buf[1024];
263 #ifdef LWS_OPENSSL_SUPPORT
264 const SSL_METHOD *method;
265 char ssl_err_buf[512];
267 use_ssl = ssl_cert_filepath != NULL && ssl_private_key_filepath != NULL;
269 fprintf(stderr, " Compiled with SSL support, using it\n");
271 fprintf(stderr, " Compiled with SSL support, but not using it\n");
274 if (ssl_cert_filepath != NULL && ssl_private_key_filepath != NULL) {
275 fprintf(stderr, " Not compiled for OpenSSl support!\n");
278 fprintf(stderr, " Compiled without SSL support, listening unencrypted\n");
281 #ifdef LWS_OPENSSL_SUPPORT
285 OpenSSL_add_all_algorithms();
286 SSL_load_error_strings();
288 // Firefox insists on SSLv23 not SSLv3
289 // Konq disables SSLv2 by default now, SSLv23 works
291 method = SSLv23_server_method(); // create server instance
293 fprintf(stderr, "problem creating ssl method: %s\n",
294 ERR_error_string(ERR_get_error(), ssl_err_buf));
297 ssl_ctx = SSL_CTX_new(method); /* create context */
299 printf("problem creating ssl context: %s\n",
300 ERR_error_string(ERR_get_error(), ssl_err_buf));
303 /* set the local certificate from CertFile */
304 n = SSL_CTX_use_certificate_file(ssl_ctx,
305 ssl_cert_filepath, SSL_FILETYPE_PEM);
307 fprintf(stderr, "problem getting cert '%s': %s\n",
309 ERR_error_string(ERR_get_error(), ssl_err_buf));
312 /* set the private key from KeyFile */
313 if (SSL_CTX_use_PrivateKey_file(ssl_ctx, ssl_private_key_filepath,
314 SSL_FILETYPE_PEM) != 1) {
315 fprintf(stderr, "ssl problem getting key '%s': %s\n", ssl_private_key_filepath, ERR_error_string(ERR_get_error(), ssl_err_buf));
318 /* verify private key */
319 if (!SSL_CTX_check_private_key(ssl_ctx)) {
320 fprintf(stderr, "Private SSL key does not match cert\n");
324 /* SSL is happy and has a cert it's content with */
334 fprintf(stderr, " Using protocol v%d\n", protocol);
337 fprintf(stderr, "protocol %d not supported (try 0 2 or 76)\n",
343 fprintf(stderr, "callback is not optional!\n");
347 /* sit there listening for connects, accept and spawn session servers */
349 sockfd = socket(AF_INET, SOCK_STREAM, 0);
351 fprintf(stderr, "ERROR opening socket");
355 /* allow us to restart even if old sockets in TIME_WAIT */
356 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
358 bzero((char *) &serv_addr, sizeof(serv_addr));
359 serv_addr.sin_family = AF_INET;
360 serv_addr.sin_addr.s_addr = INADDR_ANY;
361 serv_addr.sin_port = htons(port);
362 n = bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
364 fprintf(stderr, "ERROR on binding to port %d (%d %d)\n", port, n,
369 /* fork off a master server for this websocket server */
373 fprintf(stderr, "Failed on forking server thread: %d\n", n);
377 /* we are done as far as the caller is concerned */
382 // drop any root privs for this thread
386 fprintf(stderr, "setgid: %s\n", strerror(errno));
389 fprintf(stderr, "setuid: %s\n", strerror(errno));
391 /* we are running in a forked subprocess now */
394 fprintf(stderr, " Listening on port %d\n", port);
398 fds[0].events = POLLIN;
402 n = poll(fds, fds_count, 50);
403 if (n < 0 || fds[0].revents & (POLLERR | POLLHUP)) {
404 // fprintf(stderr, "Listen Socket dead\n");
407 if (n == 0) /* poll timeout */
410 if (fds[0].revents & POLLIN) {
412 /* listen socket got an unencrypted connection... */
414 clilen = sizeof(cli_addr);
416 (struct sockaddr *)&cli_addr,
419 fprintf(stderr, "ERROR on accept");
423 if (fds_count >= MAX_CLIENTS) {
424 fprintf(stderr, "too busy");
429 wsi[fds_count] = malloc(sizeof(struct libwebsocket) +
435 #ifdef LWS_OPENSSL_SUPPORT
438 wsi[fds_count]->ssl = SSL_new(ssl_ctx); // get new SSL state with context
439 if (wsi[fds_count]->ssl == NULL) {
440 fprintf(stderr, "SSL_new failed: %s\n",
441 ERR_error_string(SSL_get_error(wsi[fds_count]->ssl, 0), NULL));
442 free(wsi[fds_count]);
446 SSL_set_fd(wsi[fds_count]->ssl, fd); // set SSL socket
448 n = SSL_accept(wsi[fds_count]->ssl);
450 /* browsers seem to probe with various ssl params which fail then retry */
451 debug("SSL_accept failed for socket %u: %s\n",
453 ERR_error_string(SSL_get_error(wsi[fds_count]->ssl, n),
455 SSL_free(wsi[fds_count]->ssl);
456 free(wsi[fds_count]);
459 debug("accepted new SSL conn port %u on fd=%d SSL ver %s\n",
460 ntohs(cli_addr.sin_port), fd, SSL_get_version(wsi[fds_count]->ssl));
463 // fprintf(stderr, "accepted new conn port %u on fd=%d\n",
464 // ntohs(cli_addr.sin_port), fd);
468 /* intialize the instance struct */
470 wsi[fds_count]->sock = fd;
471 wsi[fds_count]->state = WSI_STATE_HTTP;
472 wsi[fds_count]->name_buffer_pos = 0;
474 for (n = 0; n < WSI_TOKEN_COUNT; n++) {
475 wsi[fds_count]->utf8_token[n].token = NULL;
476 wsi[fds_count]->utf8_token[n].token_len = 0;
479 wsi[fds_count]->callback = callback;
480 wsi[fds_count]->ietf_spec_revision = protocol;
482 fds[fds_count].events = POLLIN;
483 fds[fds_count++].fd = fd;
486 /* check for activity on client sockets */
488 for (client = 1; client < fds_count; client++) {
490 /* handle session socket closed */
492 if (fds[client].revents & (POLLERR | POLLHUP)) {
494 fprintf(stderr, "Session Socket dead\n");
496 libwebsocket_close_and_free_session(wsi[client]);
500 /* any incoming data ready? */
502 if (!(fds[client].revents & POLLIN))
505 // fprintf(stderr, "POLLIN\n");
507 #ifdef LWS_OPENSSL_SUPPORT
509 n = SSL_read(wsi[client]->ssl, buf, sizeof buf);
512 n = recv(fds[client].fd, buf, sizeof(buf), 0);
514 // fprintf(stderr, "read returned %d\n", n);
517 fprintf(stderr, "Socket read returned %d\n", n);
521 // fprintf(stderr, "POLLIN with 0 len waiting\n");
522 libwebsocket_close_and_free_session(wsi[client]);
526 /* service incoming data */
528 if (libwebsocket_read(wsi[client], buf, n) >= 0)
531 /* it closed and nuked wsi[client] */
533 for (n = client; n < fds_count - 1; n++) {
542 for (client = 1; client < fds_count; client++) {
544 if (wsi[client]->state != WSI_STATE_ESTABLISHED)
547 if (!wsi[client]->callback)
550 wsi[client]->callback(wsi[client], LWS_CALLBACK_SEND,
551 &wsi[client]->user_space[0], NULL, 0);
558 /* listening socket */
560 for (client = 1; client < fds_count; client++)
561 libwebsocket_close_and_free_session(wsi[client]);
563 #ifdef LWS_OPENSSL_SUPPORT
564 SSL_CTX_free(ssl_ctx);
572 * libwebsocket_get_uri() - Return the URI path being requested
573 * @wsi: Websocket instance
575 * The user code can find out the local path being opened from this
576 * call, it's valid on HTTP or established websocket connections.
577 * If the client opened the connection with "http://127.0.0.1/xyz/abc.d"
578 * then this call will return a pointer to "/xyz/abc.d"
581 const char * libwebsocket_get_uri(struct libwebsocket *wsi)
583 if (wsi->utf8_token[WSI_TOKEN_GET_URI].token)
584 return wsi->utf8_token[WSI_TOKEN_GET_URI].token;
589 static int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c)
593 switch (wsi->parser_state) {
594 case WSI_TOKEN_GET_URI:
596 case WSI_TOKEN_CONNECTION:
599 case WSI_TOKEN_PROTOCOL:
600 case WSI_TOKEN_UPGRADE:
601 case WSI_TOKEN_ORIGIN:
602 case WSI_TOKEN_CHALLENGE:
604 debug("WSI_TOKEN_(%d) '%c'\n", wsi->parser_state, c);
606 /* collect into malloc'd buffers */
607 /* optional space swallow */
608 if (!wsi->utf8_token[wsi->parser_state].token_len && c == ' ')
611 /* special case space terminator for get-uri */
612 if (wsi->parser_state == WSI_TOKEN_GET_URI && c == ' ') {
613 wsi->utf8_token[wsi->parser_state].token[
614 wsi->utf8_token[wsi->parser_state].token_len] = '\0';
615 wsi->parser_state = WSI_TOKEN_SKIPPING;
619 /* allocate appropriate memory */
620 if (wsi->utf8_token[wsi->parser_state].token_len ==
621 wsi->current_alloc_len - 1) {
623 wsi->current_alloc_len += LWS_ADDITIONAL_HDR_ALLOC;
624 if (wsi->current_alloc_len >= LWS_MAX_HEADER_LEN) {
625 /* it's waaay to much payload, fail it */
626 strcpy(wsi->utf8_token[wsi->parser_state].token,
627 "!!! Length exceeded maximum supported !!!");
628 wsi->parser_state = WSI_TOKEN_SKIPPING;
631 wsi->utf8_token[wsi->parser_state].token =
632 realloc(wsi->utf8_token[wsi->parser_state].token,
633 wsi->current_alloc_len);
637 if (wsi->parser_state != WSI_TOKEN_CHALLENGE && c == '\x0d') {
638 wsi->utf8_token[wsi->parser_state].token[
639 wsi->utf8_token[wsi->parser_state].token_len] = '\0';
640 wsi->parser_state = WSI_TOKEN_SKIPPING_SAW_CR;
644 wsi->utf8_token[wsi->parser_state].token[
645 wsi->utf8_token[wsi->parser_state].token_len++] = c;
647 /* special payload limiting */
648 if (wsi->parser_state == WSI_TOKEN_CHALLENGE &&
649 wsi->utf8_token[wsi->parser_state].token_len == 8) {
650 debug("Setting WSI_PARSING_COMPLETE\n");
651 wsi->parser_state = WSI_PARSING_COMPLETE;
657 /* collecting and checking a name part */
658 case WSI_TOKEN_NAME_PART:
659 debug("WSI_TOKEN_NAME_PART '%c'\n", c);
661 if (wsi->name_buffer_pos == sizeof(wsi->name_buffer) - 1) {
662 /* name bigger than we can handle, skip until next */
663 wsi->parser_state = WSI_TOKEN_SKIPPING;
666 wsi->name_buffer[wsi->name_buffer_pos++] = c;
667 wsi->name_buffer[wsi->name_buffer_pos] = '\0';
669 for (n = 0; n < WSI_TOKEN_COUNT; n++) {
670 if (wsi->name_buffer_pos != lws_tokens[n].token_len)
672 if (strcmp(lws_tokens[n].token, wsi->name_buffer))
674 debug("known hdr '%s'\n", wsi->name_buffer);
675 wsi->parser_state = WSI_TOKEN_GET_URI + n;
676 wsi->current_alloc_len = LWS_INITIAL_HDR_ALLOC;
677 wsi->utf8_token[wsi->parser_state].token =
678 malloc(wsi->current_alloc_len);
679 wsi->utf8_token[wsi->parser_state].token_len = 0;
683 /* colon delimiter means we just don't know this name */
685 if (wsi->parser_state == WSI_TOKEN_NAME_PART && c == ':') {
686 debug("skipping unknown header '%s'\n",
688 wsi->parser_state = WSI_TOKEN_SKIPPING;
692 /* don't look for payload when it can just be http headers */
694 if (wsi->parser_state == WSI_TOKEN_CHALLENGE &&
695 !wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len) {
696 /* they're HTTP headers, not websocket upgrade! */
697 debug("Setting WSI_PARSING_COMPLETE "
698 "from http headers\n");
699 wsi->parser_state = WSI_PARSING_COMPLETE;
703 /* skipping arg part of a name we didn't recognize */
704 case WSI_TOKEN_SKIPPING:
705 debug("WSI_TOKEN_SKIPPING '%c'\n", c);
707 wsi->parser_state = WSI_TOKEN_SKIPPING_SAW_CR;
709 case WSI_TOKEN_SKIPPING_SAW_CR:
710 debug("WSI_TOKEN_SKIPPING_SAW_CR '%c'\n", c);
712 wsi->parser_state = WSI_TOKEN_NAME_PART;
714 wsi->parser_state = WSI_TOKEN_SKIPPING;
715 wsi->name_buffer_pos = 0;
717 /* we're done, ignore anything else */
718 case WSI_PARSING_COMPLETE:
719 debug("WSI_PARSING_COMPLETE '%c'\n", c);
722 default: /* keep gcc happy */
729 static int interpret_key(const char *key, unsigned int *result)
738 if (digit_pos == sizeof(digits) - 1)
740 digits[digit_pos++] = *p;
744 digits[digit_pos] = '\0';
757 *result = atol(digits) / spaces;
762 static int libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c)
765 unsigned char buf[2];
767 switch (wsi->lws_rx_parse_state) {
770 switch (wsi->ietf_spec_revision) {
771 /* Firefox 4.0b6 likes this as of 30 Oct */
774 wsi->lws_rx_parse_state = LWS_RXPS_SEEN_76_FF;
780 case LWS_RXPS_SEEN_76_FF:
784 debug("Seen that client is requesting "
785 "a v76 close, sending ack\n");
788 n = libwebsocket_write(wsi, buf, 2, LWS_WRITE_HTTP);
790 fprintf(stderr, "ERROR writing to socket");
793 debug(" v76 close ack sent, server closing skt\n");
794 /* returning < 0 will get it closed in parent */
797 case LWS_RXPS_PULLING_76_LENGTH:
799 case LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED:
806 static int libwebsocket_interpret_incoming_packet(struct libwebsocket *wsi,
807 unsigned char *buf, size_t len)
811 fprintf(stderr, "received %d byte packet\n", (int)len);
812 for (n = 0; n < len; n++)
813 fprintf(stderr, "%02X ", buf[n]);
814 fprintf(stderr, "\n");
816 /* let the rx protocol state machine have as much as it needs */
819 while (wsi->lws_rx_parse_state !=
820 LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED && n < len)
821 if (libwebsocket_rx_sm(wsi, buf[n++]) < 0)
824 if (n != len && wsi->callback)
825 wsi->callback(wsi, LWS_CALLBACK_RECEIVE, &wsi->user_space[0],
833 * We have to take care about parsing because the headers may be split
834 * into multiple fragments. They may contain unknown headers with arbitrary
835 * argument lengths. So, we parse using a single-character at a time state
836 * machine that is completely independent of packet size.
840 libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len)
844 unsigned int key1, key2;
845 unsigned char sum[16];
848 switch (wsi->state) {
850 wsi->state = WSI_STATE_HTTP_HEADERS;
851 wsi->parser_state = WSI_TOKEN_NAME_PART;
853 case WSI_STATE_HTTP_HEADERS:
855 debug("issuing %d bytes to parser\n", (int)len);
857 fwrite(buf, 1, len, stderr);
859 for (n = 0; n< len; n++)
860 libwebsocket_parse(wsi, *buf++);
862 if (wsi->parser_state != WSI_PARSING_COMPLETE)
865 /* is this websocket protocol or normal http 1.0? */
867 if (!wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len ||
868 !wsi->utf8_token[WSI_TOKEN_CONNECTION].token_len) {
870 (wsi->callback)(wsi, LWS_CALLBACK_HTTP,
873 wsi->state = WSI_STATE_HTTP;
877 /* Websocket - confirm we have all the necessary pieces */
879 if (!wsi->utf8_token[WSI_TOKEN_ORIGIN].token_len ||
880 !wsi->utf8_token[WSI_TOKEN_HOST].token_len ||
881 !wsi->utf8_token[WSI_TOKEN_CHALLENGE].token_len ||
882 !wsi->utf8_token[WSI_TOKEN_KEY1].token_len ||
883 !wsi->utf8_token[WSI_TOKEN_KEY2].token_len)
884 /* completed header processing, but missing some bits */
887 /* create the response packet */
889 /* make a buffer big enough for everything */
891 response = malloc(256 +
892 wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len +
893 wsi->utf8_token[WSI_TOKEN_CONNECTION].token_len +
894 wsi->utf8_token[WSI_TOKEN_HOST].token_len +
895 wsi->utf8_token[WSI_TOKEN_ORIGIN].token_len +
896 wsi->utf8_token[WSI_TOKEN_GET_URI].token_len +
897 wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len);
899 fprintf(stderr, "Out of memory for response buffer\n");
904 strcpy(p, "HTTP/1.1 101 WebSocket Protocol Handshake\x0d\x0a"
905 "Upgrade: WebSocket\x0d\x0a");
906 p += strlen("HTTP/1.1 101 WebSocket Protocol Handshake\x0d\x0a"
907 "Upgrade: WebSocket\x0d\x0a");
908 strcpy(p, "Connection: Upgrade\x0d\x0a"
909 "Sec-WebSocket-Origin: ");
910 p += strlen("Connection: Upgrade\x0d\x0a"
911 "Sec-WebSocket-Origin: ");
912 strcpy(p, wsi->utf8_token[WSI_TOKEN_ORIGIN].token);
913 p += wsi->utf8_token[WSI_TOKEN_ORIGIN].token_len;
914 #ifdef LWS_OPENSSL_SUPPORT
916 strcpy(p, "\x0d\x0aSec-WebSocket-Location: wss://");
917 p += strlen("\x0d\x0aSec-WebSocket-Location: wss://");
920 strcpy(p, "\x0d\x0aSec-WebSocket-Location: ws://");
921 p += strlen("\x0d\x0aSec-WebSocket-Location: ws://");
922 #ifdef LWS_OPENSSL_SUPPORT
925 strcpy(p, wsi->utf8_token[WSI_TOKEN_HOST].token);
926 p += wsi->utf8_token[WSI_TOKEN_HOST].token_len;
927 strcpy(p, wsi->utf8_token[WSI_TOKEN_GET_URI].token);
928 p += wsi->utf8_token[WSI_TOKEN_GET_URI].token_len;
930 if (wsi->utf8_token[WSI_TOKEN_PROTOCOL].token) {
931 strcpy(p, "\x0d\x0aSec-WebSocket-Protocol: ");
932 p += strlen("\x0d\x0aSec-WebSocket-Protocol: ");
933 strcpy(p, wsi->utf8_token[WSI_TOKEN_PROTOCOL].token);
934 p += wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len;
937 strcpy(p, "\x0d\x0a\x0d\x0a");
938 p += strlen("\x0d\x0a\x0d\x0a");
940 /* convert the two keys into 32-bit integers */
942 if (interpret_key(wsi->utf8_token[WSI_TOKEN_KEY1].token, &key1))
944 if (interpret_key(wsi->utf8_token[WSI_TOKEN_KEY2].token, &key2))
947 /* lay them out in network byte order (MSB first */
958 /* follow them with the challenge token we were sent */
960 memcpy(&sum[8], wsi->utf8_token[WSI_TOKEN_CHALLENGE].token, 8);
963 * compute the md5sum of that 16-byte series and use as our
964 * payload after our headers
967 md5(sum, 16, (unsigned char *)p);
970 /* it's complete: go ahead and send it */
972 debug("issuing response packet %d len\n",
973 (int)(p - response));
975 fwrite(response, 1, p - response, stderr);
977 n = libwebsocket_write(wsi, (unsigned char *)response, p - response,
980 fprintf(stderr, "ERROR writing to socket");
984 /* alright clean up and set ourselves into established state */
987 wsi->state = WSI_STATE_ESTABLISHED;
988 wsi->lws_rx_parse_state = LWS_RXPS_NEW;
990 /* notify user code that we're ready to roll */
993 wsi->callback(wsi, LWS_CALLBACK_ESTABLISHED,
994 &wsi->user_space[0], NULL, 0);
997 case WSI_STATE_ESTABLISHED:
998 if (libwebsocket_interpret_incoming_packet(wsi, buf, len) < 0)
1008 libwebsocket_close_and_free_session(wsi);
1013 * libwebsocket_write() - Apply protocol then write data to client
1014 * @wsi: Websocket instance (available from user callback)
1015 * @buf: The data to send. For data being sent on a websocket
1016 * connection (ie, not default http), this buffer MUST have
1017 * LWS_SEND_BUFFER_PRE_PADDING bytes valid BEFORE the pointer
1018 * and an additional LWS_SEND_BUFFER_POST_PADDING bytes valid
1019 * in the buffer after (buf + len). This is so the protocol
1020 * header and trailer data can be added in-situ.
1021 * @len: Count of the data bytes in the payload starting from buf
1022 * @protocol: Use LWS_WRITE_HTTP to reply to an http connection, and one
1023 * of LWS_WRITE_BINARY or LWS_WRITE_TEXT to send appropriate
1024 * data on a websockets connection. Remember to allow the extra
1025 * bytes before and after buf if LWS_WRITE_BINARY or LWS_WRITE_TEXT
1028 * This function provides the way to issue data back to the client
1029 * for both http and websocket protocols.
1031 * In the case of sending using websocket protocol, be sure to allocate
1032 * valid storage before and after buf as explained above. This scheme
1033 * allows maximum efficiency of sending data and protocol in a single
1034 * packet while not burdening the user code with any protocol knowledge.
1037 int libwebsocket_write(struct libwebsocket * wsi, unsigned char *buf,
1038 size_t len, enum libwebsocket_write_protocol protocol)
1043 unsigned int shift = 7;
1045 if (protocol == LWS_WRITE_HTTP)
1048 /* websocket protocol, either binary or text */
1050 if (wsi->state != WSI_STATE_ESTABLISHED)
1053 switch (wsi->ietf_spec_revision) {
1054 /* chrome likes this as of 30 Oct */
1055 /* Firefox 4.0b6 likes this as of 30 Oct */
1057 if (protocol == LWS_WRITE_BINARY) {
1058 /* in binary mode we send 7-bit used length blocks */
1060 while (len & (127 << shift)) {
1066 while (shift >= 0) {
1069 ((len >> shift) & 127) | 0x80;
1072 ((len >> shift) & 127);
1079 /* frame type = text, length-free spam mode */
1082 buf[len] = 0xff; /* EOT marker */
1089 #if defined __LP64__
1090 buf[-8] = len >> 56;
1091 buf[-7] = len >> 48;
1092 buf[-6] = len >> 40;
1093 buf[-5] = len >> 32;
1100 buf[-4] = len >> 24;
1101 buf[-3] = len >> 16;
1107 /* just an unimplemented spec right now apparently */
1110 if (protocol == LWS_WRITE_BINARY)
1126 #if defined __LP64__
1127 buf[-8] = (len >> 56) & 0x7f;
1128 buf[-7] = len >> 48;
1129 buf[-6] = len >> 40;
1130 buf[-5] = len >> 32;
1137 buf[-4] = len >> 24;
1138 buf[-3] = len >> 16;
1148 for (n = 0; n < (len + pre + post); n++)
1149 fprintf(stderr, "%02X ", buf[n - pre]);
1151 fprintf(stderr, "\n");
1155 #ifdef LWS_OPENSSL_SUPPORT
1157 n = SSL_write(wsi->ssl, buf - pre, len + pre + post);
1159 fprintf(stderr, "ERROR writing to socket");
1164 n = send(wsi->sock, buf - pre, len + pre + post, 0);
1166 fprintf(stderr, "ERROR writing to socket");
1169 #ifdef LWS_OPENSSL_SUPPORT
1172 // fprintf(stderr, "written %d bytes to client\n", (int)len);
1179 * libwebsockets_serve_http_file() - Send a file back to the client using http
1180 * @wsi: Websocket instance (available from user callback)
1181 * @file: The file to issue over http
1182 * @content_type: The http content type, eg, text/html
1184 * This function is intended to be called from the callback in response
1185 * to http requests from the client. It allows the callback to issue
1186 * local files down the http link in a single step.
1189 int libwebsockets_serve_http_file(struct libwebsocket *wsi, const char * file,
1190 const char * content_type)
1198 fd = open(file, O_RDONLY);
1200 p += sprintf(p, "HTTP/1.0 400 Bad\x0d\x0a"
1201 "Server: libwebsockets\x0d\x0a"
1204 libwebsocket_write(wsi, (unsigned char *)buf, p - buf,
1211 p += sprintf(p, "HTTP/1.0 200 OK\x0d\x0a"
1212 "Server: libwebsockets\x0d\x0a"
1213 "Content-Type: %s\x0d\x0a"
1214 "Content-Length: %u\x0d\x0a"
1215 "\x0d\x0a", content_type, (unsigned int)stat.st_size);
1217 libwebsocket_write(wsi, (unsigned char *)buf, p - buf, LWS_WRITE_HTTP);
1221 n = read(fd, buf, 512);
1222 libwebsocket_write(wsi, (unsigned char *)buf, n,