3da932692fdad2d491409a64a84ccbaab5467c6a
[profile/ivi/libwebsockets.git] / lib / client.c
1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010-2013 Andy Green <andy@warmcat.com>
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public
8  *  License as published by the Free Software Foundation:
9  *  version 2.1 of the License.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19  *  MA  02110-1301  USA
20  */
21
22 #include "private-libwebsockets.h"
23
24 #ifdef WIN32
25 #include <tchar.h>
26 #include <io.h>
27 #else
28 #ifdef LWS_BUILTIN_GETIFADDRS
29 #include <getifaddrs.h>
30 #else
31 #include <ifaddrs.h>
32 #endif
33 #include <sys/un.h>
34 #include <sys/socket.h>
35 #include <netdb.h>
36 #endif
37
38 int lws_client_socket_service(struct libwebsocket_context *context,
39                                 struct libwebsocket *wsi, struct pollfd *pollfd)
40 {
41         int n;
42         char *p = (char *)&context->service_buffer[0];
43         int len;
44         char c;
45
46         switch (wsi->mode) {
47
48         case LWS_CONNMODE_WS_CLIENT_WAITING_PROXY_REPLY:
49
50                 /* handle proxy hung up on us */
51
52                 if (pollfd->revents & (POLLERR | POLLHUP)) {
53
54                         lwsl_warn("Proxy connection %p (fd=%d) dead\n",
55                                 (void *)wsi, pollfd->fd);
56
57                         libwebsocket_close_and_free_session(context, wsi,
58                                                      LWS_CLOSE_STATUS_NOSTATUS);
59                         return 0;
60                 }
61
62                 n = recv(wsi->sock, context->service_buffer,
63                                         sizeof(context->service_buffer), 0);
64                 if (n < 0) {
65                         libwebsocket_close_and_free_session(context, wsi,
66                                                      LWS_CLOSE_STATUS_NOSTATUS);
67                         lwsl_err("ERROR reading from proxy socket\n");
68                         return 0;
69                 }
70
71                 context->service_buffer[13] = '\0';
72                 if (strcmp((char *)context->service_buffer, "HTTP/1.0 200 ")) {
73                         libwebsocket_close_and_free_session(context, wsi,
74                                                      LWS_CLOSE_STATUS_NOSTATUS);
75                         lwsl_err("ERROR proxy: %s\n", context->service_buffer);
76                         return 0;
77                 }
78
79                 /* clear his proxy connection timeout */
80
81                 libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
82
83                 /* fallthru */
84
85         case LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE:
86
87                 /*
88                  * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
89                  * timeout protection set in client-handshake.c
90                  */
91
92         #ifdef LWS_OPENSSL_SUPPORT
93
94                 /*
95                  * take care of our libwebsocket_callback_on_writable
96                  * happening at a time when there's no real connection yet
97                  */
98
99                 pollfd->events &= ~POLLOUT;
100
101                 /* external POLL support via protocol 0 */
102                 context->protocols[0].callback(context, wsi,
103                         LWS_CALLBACK_CLEAR_MODE_POLL_FD,
104                         wsi->user_space, (void *)(long)wsi->sock, POLLOUT);
105
106                 /* we can retry this... just cook the SSL BIO the first time */
107
108                 if (wsi->use_ssl && !wsi->ssl) {
109
110                         wsi->ssl = SSL_new(context->ssl_client_ctx);
111
112 #ifdef USE_CYASSL
113                         /*
114                          * CyaSSL does certificate verification differently
115                          * from OpenSSL.
116                          * If we should ignore the certificate, we need to set
117                          * this before SSL_new and SSL_connect is called.
118                          * Otherwise the connect will simply fail with error
119                          * code -155
120                          */
121                         if (wsi->use_ssl == 2)
122                                 CyaSSL_set_verify(wsi->ssl,
123                                                         SSL_VERIFY_NONE, NULL);
124 #endif /* USE_CYASSL */
125
126                         wsi->client_bio =
127                                 BIO_new_socket(wsi->sock, BIO_NOCLOSE);
128                         SSL_set_bio(wsi->ssl, wsi->client_bio, wsi->client_bio);
129
130 #ifdef USE_CYASSL
131                         CyaSSL_set_using_nonblock(wsi->ssl, 1);
132 #else
133                         BIO_set_nbio(wsi->client_bio, 1); /* nonblocking */
134 #endif
135
136                         SSL_set_ex_data(wsi->ssl,
137                                         openssl_websocket_private_data_index,
138                                                                        context);
139                 }
140
141                 if (wsi->use_ssl) {
142                         lws_latency_pre(context, wsi);
143                         n = SSL_connect(wsi->ssl);
144                         lws_latency(context, wsi,
145                           "SSL_connect LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE",
146                                                                       n, n > 0);
147
148                         if (n < 0) {
149                                 n = SSL_get_error(wsi->ssl, n);
150
151                                 if (n == SSL_ERROR_WANT_READ ||
152                                         n == SSL_ERROR_WANT_WRITE) {
153                                         /*
154                                          * wants us to retry connect due to
155                                          * state of the underlying ssl layer...
156                                          * but since it may be stalled on
157                                          * blocked write, no incoming data may
158                                          * arrive to trigger the retry.
159                                          * Force (possibly many times if the SSL
160                                          * state persists in returning the
161                                          * condition code, but other sockets
162                                          * are getting serviced inbetweentimes)
163                                          * us to get called back when writable.
164                                          */
165
166                                         lwsl_info(
167                                              "SSL_connect WANT_... retrying\n");
168                                         libwebsocket_callback_on_writable(
169                                                                   context, wsi);
170
171                                         return 0; /* no error */
172                                 }
173                                 n = -1;
174                         }
175
176                         if (n <= 0) {
177                                 /*
178                                  * retry if new data comes until we
179                                  * run into the connection timeout or win
180                                  */
181
182                                 lwsl_err("SSL connect error %lu: %s\n", 
183                                         ERR_get_error(),
184                                         ERR_error_string(ERR_get_error(),
185                                               (char *)context->service_buffer));
186                                 return 0;
187                         }
188
189                         #ifndef USE_CYASSL
190                         /*
191                          * See comment above about CyaSSL certificate
192                          * verification
193                          */
194                         lws_latency_pre(context, wsi);
195                         n = SSL_get_verify_result(wsi->ssl);
196                         lws_latency(context, wsi,
197                                 "SSL_get_verify_result LWS_CONNMODE..HANDSHAKE",
198                                                                       n, n > 0);
199                         if ((n != X509_V_OK) && (
200                                 n != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
201                                                            wsi->use_ssl != 2)) {
202
203                                 lwsl_err(
204                                       "server's cert didn't look good %d\n", n);
205                                 libwebsocket_close_and_free_session(context,
206                                                 wsi, LWS_CLOSE_STATUS_NOSTATUS);
207                                 return 0;
208                         }
209 #endif /* USE_CYASSL */
210                 } else
211                         wsi->ssl = NULL;
212 #endif
213
214                 p = libwebsockets_generate_client_handshake(context, wsi, p);
215                 if (p == NULL) {
216                         lwsl_err("Failed to generate handshake for client\n");
217                         libwebsocket_close_and_free_session(context, wsi,
218                                                      LWS_CLOSE_STATUS_NOSTATUS);
219                         return 0;
220                 }
221
222                 /* send our request to the server */
223
224                 lws_latency_pre(context, wsi);
225 #ifdef LWS_OPENSSL_SUPPORT
226                 if (wsi->use_ssl)
227                         n = SSL_write(wsi->ssl, context->service_buffer,
228                                            p - (char *)context->service_buffer);
229                 else
230 #endif
231                         n = send(wsi->sock, context->service_buffer,
232                                         p - (char *)context->service_buffer, 0);
233                 lws_latency(context, wsi,
234                         "send or SSL_write LWS_CONNMODE...HANDSHAKE",
235                                                                      n, n >= 0);
236
237                 if (n < 0) {
238                         lwsl_debug("ERROR writing to client socket\n");
239                         libwebsocket_close_and_free_session(context, wsi,
240                                                      LWS_CLOSE_STATUS_NOSTATUS);
241                         return 0;
242                 }
243
244                 wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART;
245                 wsi->u.hdr.lextable_pos = 0;
246                 wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY;
247                 libwebsocket_set_timeout(wsi,
248                                 PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE,
249                                                               AWAITING_TIMEOUT);
250                 break;
251
252         case LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY:
253
254                 /* handle server hung up on us */
255
256                 if (pollfd->revents & (POLLERR | POLLHUP)) {
257
258                         lwsl_debug("Server connection %p (fd=%d) dead\n",
259                                 (void *)wsi, pollfd->fd);
260
261                         goto bail3;
262                 }
263
264                 if (!(pollfd->revents & POLLIN)) {
265                         lwsl_warn("server reply no POLLIN\n");
266                         goto bail3;
267                 }
268
269                 /* interpret the server response */
270
271                 /*
272                  *  HTTP/1.1 101 Switching Protocols
273                  *  Upgrade: websocket
274                  *  Connection: Upgrade
275                  *  Sec-WebSocket-Accept: me89jWimTRKTWwrS3aRrL53YZSo=
276                  *  Sec-WebSocket-Nonce: AQIDBAUGBwgJCgsMDQ4PEC==
277                  *  Sec-WebSocket-Protocol: chat
278                  */
279
280                 /*
281                  * we have to take some care here to only take from the
282                  * socket bytewise.  The browser may (and has been seen to
283                  * in the case that onopen() performs websocket traffic)
284                  * coalesce both handshake response and websocket traffic
285                  * in one packet, since at that point the connection is
286                  * definitively ready from browser pov.
287                  */
288
289                 len = 1;
290                 while (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE &&
291                                                                       len > 0) {
292 #ifdef LWS_OPENSSL_SUPPORT
293                         if (wsi->use_ssl) {
294                                 len = SSL_read(wsi->ssl, &c, 1);
295                                 if (len < 0) {
296                                         n = SSL_get_error(wsi->ssl, len);
297                                         if (n ==  SSL_ERROR_WANT_READ ||
298                                                      n ==  SSL_ERROR_WANT_WRITE)
299                                                 return 0;
300                                 }
301                         } else
302 #endif
303                                 len = recv(wsi->sock, &c, 1, 0);
304
305                         if (len < 0) {
306                                 lwsl_warn("error on parsing recv\n");
307                                 goto bail3;
308                         }
309
310                         if (libwebsocket_parse(wsi, c)) {
311                                 lwsl_warn("problems parsing header\n");
312                                 goto bail3;
313                         }
314                 }
315
316                 /*
317                  * hs may also be coming in multiple packets, there is a 5-sec
318                  * libwebsocket timeout still active here too, so if parsing did
319                  * not complete just wait for next packet coming in this state
320                  */
321
322                 if (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE)
323                         break;
324
325                 /*
326                  * otherwise deal with the handshake.  If there's any
327                  * packet traffic already arrived we'll trigger poll() again
328                  * right away and deal with it that way
329                  */
330
331                 return lws_client_interpret_server_handshake(context, wsi);
332
333 bail3:
334                 lwsl_info(
335                         "closing connection at LWS_CONNMODE...SERVER_REPLY\n");
336                 libwebsocket_close_and_free_session(context, wsi,
337                                                     LWS_CLOSE_STATUS_NOSTATUS);
338                 return 0;
339
340         case LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT:
341                 lwsl_ext("LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT\n");
342                 break;
343
344         case LWS_CONNMODE_WS_CLIENT_PENDING_CANDIDATE_CHILD:
345                 lwsl_ext("LWS_CONNMODE_WS_CLIENT_PENDING_CANDIDATE_CHILD\n");
346                 break;
347         default:
348                 break;
349         }
350
351         return 0;
352 }
353
354
355 /*
356  * In-place str to lower case
357  */
358
359 static void
360 strtolower(char *s)
361 {
362         while (*s) {
363                 *s = tolower(*s);
364                 s++;
365         }
366 }
367
368 int
369 lws_client_interpret_server_handshake(struct libwebsocket_context *context,
370                 struct libwebsocket *wsi)
371 {
372         const char *pc;
373         int okay = 0;
374         char *p;
375         int len;
376 #ifndef LWS_NO_EXTENSIONS
377         char ext_name[128];
378         struct libwebsocket_extension *ext;
379         void *v;
380         int more = 1;
381         const char *c;
382 #endif
383         int n;
384
385         /*
386          * well, what the server sent looked reasonable for syntax.
387          * Now let's confirm it sent all the necessary headers
388          */
389
390         if (lws_hdr_total_length(wsi, WSI_TOKEN_ACCEPT) == 0) {
391                 lwsl_info("no ACCEPT\n");
392                 goto bail3;
393         }
394
395         p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP);
396         if (!p) {
397                 lwsl_info("no URI\n");
398                 goto bail3;
399         }
400         if (p && strncmp(p, "101", 3)) {
401                 lwsl_warn(
402                        "lws_client_handshake: got bad HTTP response '%s'\n", p);
403                 goto bail3;
404         }
405
406         p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_UPGRADE);
407         if (!p) {
408                 lwsl_info("no UPGRADE\n");
409                 goto bail3;
410         }
411         strtolower(p);
412         if (strcmp(p, "websocket")) {
413                 lwsl_warn(
414                       "lws_client_handshake: got bad Upgrade header '%s'\n", p);
415                 goto bail3;
416         }
417
418         p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_CONNECTION);
419         if (!p) {
420                 lwsl_info("no Connection hdr\n");
421                 goto bail3;
422         }
423         strtolower(p);
424         if (strcmp(p, "upgrade")) {
425                 lwsl_warn("lws_client_int_s_hs: bad header %s\n", p);
426                 goto bail3;
427         }
428
429         pc = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS);
430         if (pc == NULL)
431                 lwsl_parser("lws_client_int_s_hs: no protocol list\n");
432         else
433                 lwsl_parser("lws_client_int_s_hs: protocol list '%s'\n", pc);
434
435         /*
436          * confirm the protocol the server wants to talk was in the list
437          * of protocols we offered
438          */
439
440         len = lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL);
441         if (!len) {
442
443                 lwsl_info("lws_client_int_s_hs: WSI_TOKEN_PROTOCOL is null\n");
444                 /*
445                  * no protocol name to work from,
446                  * default to first protocol
447                  */
448                 wsi->protocol = &context->protocols[0];
449                 goto check_extensions;
450         }
451
452         p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL);
453         len = strlen(p);
454
455         while (*pc && !okay) {
456                 if (!strncmp(pc, p, len) &&
457                                           (pc[len] == ',' || pc[len] == '\0')) {
458                         okay = 1;
459                         continue;
460                 }
461                 while (*pc && *pc != ',')
462                         pc++;
463                 while (*pc && *pc != ' ')
464                         pc++;
465         }
466
467         if (!okay) {
468                 lwsl_err("lws_client_int_s_hs: got bad protocol %s\n", p);
469                 goto bail2;
470         }
471
472         /*
473          * identify the selected protocol struct and set it
474          */
475         n = 0;
476         wsi->protocol = NULL;
477         while (context->protocols[n].callback && !wsi->protocol) {
478                 if (strcmp(p, context->protocols[n].name) == 0) {
479                         wsi->protocol = &context->protocols[n];
480                         break;
481                 }
482                 n++;
483         }
484
485         if (wsi->protocol == NULL) {
486                 lwsl_err("lws_client_int_s_hs: fail protocol %s\n", p);
487                 goto bail2;
488         }
489
490
491 check_extensions:
492 #ifndef LWS_NO_EXTENSIONS
493         /* instantiate the accepted extensions */
494
495         if (!lws_hdr_total_length(wsi, WSI_TOKEN_EXTENSIONS)) {
496                 lwsl_ext("no client extenstions allowed by server\n");
497                 goto check_accept;
498         }
499
500         /*
501          * break down the list of server accepted extensions
502          * and go through matching them or identifying bogons
503          */
504
505         if (lws_hdr_copy(wsi, (char *)context->service_buffer,
506                    sizeof(context->service_buffer), WSI_TOKEN_EXTENSIONS) < 0) {
507                 lwsl_warn("ext list from server failed to copy\n");
508                 goto bail2;
509         }
510
511         c = (char *)context->service_buffer;
512         n = 0;
513         while (more) {
514
515                 if (*c && (*c != ',' && *c != ' ' && *c != '\t')) {
516                         ext_name[n] = *c++;
517                         if (n < sizeof(ext_name) - 1)
518                                 n++;
519                         continue;
520                 }
521                 ext_name[n] = '\0';
522                 if (!*c)
523                         more = 0;
524                 else {
525                         c++;
526                         if (!n)
527                                 continue;
528                 }
529
530                 /* check we actually support it */
531
532                 lwsl_ext("checking client ext %s\n", ext_name);
533
534                 n = 0;
535                 ext = wsi->protocol->owning_server->extensions;
536                 while (ext && ext->callback) {
537
538                         if (strcmp(ext_name, ext->name)) {
539                                 ext++;
540                                 continue;
541                         }
542
543                         n = 1;
544
545                         lwsl_ext("instantiating client ext %s\n", ext_name);
546
547                         /* instantiate the extension on this conn */
548
549                         wsi->active_extensions_user[
550                                 wsi->count_active_extensions] =
551                                          malloc(ext->per_session_data_size);
552                         if (wsi->active_extensions_user[
553                                 wsi->count_active_extensions] == NULL) {
554                                 lwsl_err("Out of mem\n");
555                                 goto bail2;
556                         }
557                         memset(wsi->active_extensions_user[
558                                 wsi->count_active_extensions], 0,
559                                                     ext->per_session_data_size);
560                         wsi->active_extensions[
561                                   wsi->count_active_extensions] = ext;
562
563                         /* allow him to construct his context */
564
565                         ext->callback(wsi->protocol->owning_server,
566                                 ext, wsi,
567                                    LWS_EXT_CALLBACK_CLIENT_CONSTRUCT,
568                                         wsi->active_extensions_user[
569                                          wsi->count_active_extensions],
570                                                                    NULL, 0);
571
572                         wsi->count_active_extensions++;
573
574                         ext++;
575                 }
576
577                 if (n == 0) {
578                         lwsl_warn("Unknown ext '%s'!\n", ext_name);
579                         goto bail2;
580                 }
581
582                 n = 0;
583         }
584
585 check_accept:
586 #endif
587
588         /*
589          * Confirm his accept token is the one we precomputed
590          */
591
592         p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_ACCEPT);
593         if (strcmp(p, wsi->u.hdr.ah->initial_handshake_hash_base64)) {
594                 lwsl_warn("lws_client_int_s_hs: accept %s wrong vs %s\n", p,
595                                   wsi->u.hdr.ah->initial_handshake_hash_base64);
596                 goto bail2;
597         }
598
599         /* allocate the per-connection user memory (if any) */
600         if (libwebsocket_ensure_user_space(wsi)) {
601                 lwsl_err("Problem allocating wsi user mem\n");
602                 goto bail2;
603         }
604
605         /*
606          * we seem to be good to go, give client last chance to check
607          * headers and OK it
608          */
609
610         wsi->protocol->callback(context, wsi,
611                                 LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH,
612                                                      wsi->user_space, NULL, 0);
613
614         /* clear his proxy connection timeout */
615
616         libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
617
618         /* free up his parsing allocations */
619         if (wsi->u.hdr.ah)
620                 free(wsi->u.hdr.ah);
621
622         /* mark him as being alive */
623
624         wsi->state = WSI_STATE_ESTABLISHED;
625         wsi->mode = LWS_CONNMODE_WS_CLIENT;
626
627         /* union transition */
628
629         memset(&wsi->u, 0, sizeof(wsi->u));
630
631         /*
632          * create the frame buffer for this connection according to the
633          * size mentioned in the protocol definition.  If 0 there, then
634          * use a big default for compatibility
635          */
636
637         n = wsi->protocol->rx_buffer_size;
638         if (!n)
639                 n = LWS_MAX_SOCKET_IO_BUF;
640         n += LWS_SEND_BUFFER_PRE_PADDING + LWS_SEND_BUFFER_POST_PADDING;
641         wsi->u.ws.rx_user_buffer = malloc(n);
642         if (!wsi->u.ws.rx_user_buffer) {
643                 lwsl_err("Out of Mem allocating rx buffer %d\n", n);
644                 goto bail3;
645         }
646         lwsl_info("Allocating client RX buffer %d\n", n);
647
648         lwsl_debug("handshake OK for protocol %s\n", wsi->protocol->name);
649
650         /* call him back to inform him he is up */
651
652         wsi->protocol->callback(context, wsi,
653                                 LWS_CALLBACK_CLIENT_ESTABLISHED,
654                                                      wsi->user_space, NULL, 0);
655 #ifndef LWS_NO_EXTENSIONS
656         /*
657          * inform all extensions, not just active ones since they
658          * already know
659          */
660
661         ext = context->extensions;
662
663         while (ext && ext->callback) {
664                 v = NULL;
665                 for (n = 0; n < wsi->count_active_extensions; n++)
666                         if (wsi->active_extensions[n] == ext)
667                                 v = wsi->active_extensions_user[n];
668
669                 ext->callback(context, ext, wsi,
670                           LWS_EXT_CALLBACK_ANY_WSI_ESTABLISHED, v, NULL, 0);
671                 ext++;
672         }
673 #endif
674
675         return 0;
676
677 bail3:
678
679 bail2:
680         if (wsi->protocol)
681                 wsi->protocol->callback(context, wsi,
682                         LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
683                                                       wsi->user_space, NULL, 0);
684
685         lwsl_info("closing connection due to bail2 connection error\n");
686
687         /* free up his parsing allocations */
688
689         if (wsi->u.hdr.ah)
690                 free(wsi->u.hdr.ah);
691
692         libwebsocket_close_and_free_session(context, wsi,
693                                                  LWS_CLOSE_STATUS_PROTOCOL_ERR);
694
695         return 1;
696 }
697
698
699 char *
700 libwebsockets_generate_client_handshake(struct libwebsocket_context *context,
701                 struct libwebsocket *wsi, char *pkt)
702 {
703         char buf[128];
704         char hash[20];
705         char key_b64[40];
706         char *p = pkt;
707         int n;
708 #ifndef LWS_NO_EXTENSIONS
709         struct libwebsocket_extension *ext;
710         struct libwebsocket_extension *ext1;
711         int ext_count = 0;
712 #endif
713
714         /*
715          * create the random key
716          */
717
718         n = libwebsockets_get_random(context, hash, 16);
719         if (n != 16) {
720                 lwsl_err("Unable to read from random dev %s\n",
721                                                 SYSTEM_RANDOM_FILEPATH);
722                 libwebsocket_close_and_free_session(context, wsi,
723                                              LWS_CLOSE_STATUS_NOSTATUS);
724                 return NULL;
725         }
726
727         lws_b64_encode_string(hash, 16, key_b64, sizeof(key_b64));
728
729         /*
730          * 00 example client handshake
731          *
732          * GET /socket.io/websocket HTTP/1.1
733          * Upgrade: WebSocket
734          * Connection: Upgrade
735          * Host: 127.0.0.1:9999
736          * Origin: http://127.0.0.1
737          * Sec-WebSocket-Key1: 1 0 2#0W 9 89 7  92 ^
738          * Sec-WebSocket-Key2: 7 7Y 4328 B2v[8(z1
739          * Cookie: socketio=websocket
740          *
741          * (Á®Ä0¶†≥
742          *
743          * 04 example client handshake
744          *
745          * GET /chat HTTP/1.1
746          * Host: server.example.com
747          * Upgrade: websocket
748          * Connection: Upgrade
749          * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
750          * Sec-WebSocket-Origin: http://example.com
751          * Sec-WebSocket-Protocol: chat, superchat
752          * Sec-WebSocket-Version: 4
753          */
754
755         p += sprintf(p, "GET %s HTTP/1.1\x0d\x0a",
756                                 lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_URI));
757
758         p += sprintf(p,
759                 "Pragma: no-cache\x0d\x0a""Cache-Control: no-cache\x0d\x0a");
760
761         p += sprintf(p, "Host: %s\x0d\x0a",
762                                lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_HOST));
763         p += sprintf(p,
764 "Upgrade: websocket\x0d\x0a""Connection: Upgrade\x0d\x0a""Sec-WebSocket-Key: ");
765         strcpy(p, key_b64);
766         p += strlen(key_b64);
767         p += sprintf(p, "\x0d\x0a");
768         if (lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN))
769                 p += sprintf(p, "Origin: %s\x0d\x0a",
770                              lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN));
771
772         if (lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS))
773                 p += sprintf(p, "Sec-WebSocket-Protocol: %s\x0d\x0a",
774                      lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS));
775
776         /* tell the server what extensions we could support */
777
778         p += sprintf(p, "Sec-WebSocket-Extensions: ");
779 #ifndef LWS_NO_EXTENSIONS
780         ext = context->extensions;
781         while (ext && ext->callback) {
782
783                 n = 0;
784                 ext1 = context->extensions;
785
786                 while (ext1 && ext1->callback) {
787                         n |= ext1->callback(context, ext1, wsi,
788                                 LWS_EXT_CALLBACK_CHECK_OK_TO_PROPOSE_EXTENSION,
789                                         NULL, (char *)ext->name, 0);
790
791                         ext1++;
792                 }
793
794                 if (n) { /* an extension vetos us */
795                         lwsl_ext("ext %s vetoed\n", (char *)ext->name);
796                         ext++;
797                         continue;
798                 }
799
800                 n = context->protocols[0].callback(context, wsi,
801                         LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED,
802                                 wsi->user_space, (char *)ext->name, 0);
803
804                 /*
805                  * zero return from callback means
806                  * go ahead and allow the extension,
807                  * it's what we get if the callback is
808                  * unhandled
809                  */
810
811                 if (n) {
812                         ext++;
813                         continue;
814                 }
815
816                 /* apply it */
817
818                 if (ext_count)
819                         *p++ = ',';
820                 p += sprintf(p, "%s", ext->name);
821                 ext_count++;
822
823                 ext++;
824         }
825 #endif
826         p += sprintf(p, "\x0d\x0a");
827
828         if (wsi->ietf_spec_revision)
829                 p += sprintf(p, "Sec-WebSocket-Version: %d\x0d\x0a",
830                                                wsi->ietf_spec_revision);
831
832         /* give userland a chance to append, eg, cookies */
833
834         context->protocols[0].callback(context, wsi,
835                 LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER,
836                 NULL, &p, (pkt + sizeof(context->service_buffer)) - p - 12);
837
838         p += sprintf(p, "\x0d\x0a");
839
840         /* prepare the expected server accept response */
841
842         key_b64[39] = '\0'; /* enforce composed length below buf sizeof */
843         n = sprintf(buf, "%s258EAFA5-E914-47DA-95CA-C5AB0DC85B11", key_b64);
844
845         SHA1((unsigned char *)buf, n, (unsigned char *)hash);
846
847         lws_b64_encode_string(hash, 20,
848                         wsi->u.hdr.ah->initial_handshake_hash_base64,
849                           sizeof(wsi->u.hdr.ah->initial_handshake_hash_base64));
850
851         return p;
852 }
853