style cleanup
[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                         (void *)(long)wsi->sock, NULL, 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 %s\n",
183                                         ERR_error_string(ERR_get_error(),
184                                               (char *)context->service_buffer));
185                                 return 0;
186                         }
187
188                         #ifndef USE_CYASSL
189                         /*
190                          * See comment above about CyaSSL certificate
191                          * verification
192                          */
193                         lws_latency_pre(context, wsi);
194                         n = SSL_get_verify_result(wsi->ssl);
195                         lws_latency(context, wsi,
196                                 "SSL_get_verify_result LWS_CONNMODE..HANDSHAKE",
197                                                                       n, n > 0);
198                         if ((n != X509_V_OK) && (
199                                 n != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
200                                                            wsi->use_ssl != 2)) {
201
202                                 lwsl_err(
203                                       "server's cert didn't look good %d\n", n);
204                                 libwebsocket_close_and_free_session(context,
205                                                 wsi, LWS_CLOSE_STATUS_NOSTATUS);
206                                 return 0;
207                         }
208 #endif /* USE_CYASSL */
209                 } else
210                         wsi->ssl = NULL;
211 #endif
212
213                 p = libwebsockets_generate_client_handshake(context, wsi, p);
214                 if (p == NULL) {
215                         lwsl_err("Failed to generate handshake for client\n");
216                         libwebsocket_close_and_free_session(context, wsi,
217                                                      LWS_CLOSE_STATUS_NOSTATUS);
218                         return 0;
219                 }
220
221                 /* send our request to the server */
222
223                 lws_latency_pre(context, wsi);
224 #ifdef LWS_OPENSSL_SUPPORT
225                 if (wsi->use_ssl)
226                         n = SSL_write(wsi->ssl, context->service_buffer,
227                                            p - (char *)context->service_buffer);
228                 else
229 #endif
230                         n = send(wsi->sock, context->service_buffer,
231                                         p - (char *)context->service_buffer, 0);
232                 lws_latency(context, wsi,
233                         "send or SSL_write LWS_CONNMODE...HANDSHAKE",
234                                                                      n, n >= 0);
235
236                 if (n < 0) {
237                         lwsl_debug("ERROR writing to client socket\n");
238                         libwebsocket_close_and_free_session(context, wsi,
239                                                      LWS_CLOSE_STATUS_NOSTATUS);
240                         return 0;
241                 }
242
243                 wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART;
244                 wsi->u.hdr.lextable_pos = 0;
245                 wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY;
246                 libwebsocket_set_timeout(wsi,
247                                 PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE,
248                                                               AWAITING_TIMEOUT);
249                 break;
250
251         case LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY:
252
253                 /* handle server hung up on us */
254
255                 if (pollfd->revents & (POLLERR | POLLHUP)) {
256
257                         lwsl_debug("Server connection %p (fd=%d) dead\n",
258                                 (void *)wsi, pollfd->fd);
259
260                         goto bail3;
261                 }
262
263                 if (!(pollfd->revents & POLLIN))
264                         goto bail3;
265
266                 /* interpret the server response */
267
268                 /*
269                  *  HTTP/1.1 101 Switching Protocols
270                  *  Upgrade: websocket
271                  *  Connection: Upgrade
272                  *  Sec-WebSocket-Accept: me89jWimTRKTWwrS3aRrL53YZSo=
273                  *  Sec-WebSocket-Nonce: AQIDBAUGBwgJCgsMDQ4PEC==
274                  *  Sec-WebSocket-Protocol: chat
275                  */
276
277                 /*
278                  * we have to take some care here to only take from the
279                  * socket bytewise.  The browser may (and has been seen to
280                  * in the case that onopen() performs websocket traffic)
281                  * coalesce both handshake response and websocket traffic
282                  * in one packet, since at that point the connection is
283                  * definitively ready from browser pov.
284                  */
285
286                 len = 1;
287                 while (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE &&
288                                                                       len > 0) {
289 #ifdef LWS_OPENSSL_SUPPORT
290                         if (wsi->use_ssl) {
291                                 len = SSL_read(wsi->ssl, &c, 1);
292                                 if (len < 0) {
293                                         n = SSL_get_error(wsi->ssl, len);
294                                         if (n ==  SSL_ERROR_WANT_READ ||
295                                                      n ==  SSL_ERROR_WANT_WRITE)
296                                                 return 0;
297                                 }
298                         } else
299 #endif
300                                 len = recv(wsi->sock, &c, 1, 0);
301
302                         if (len < 0)
303                                 goto bail3;
304
305                         if (libwebsocket_parse(wsi, c)) {
306                                 /* problems */
307                                 goto bail3;
308                         }
309                 }
310
311                 /*
312                  * hs may also be coming in multiple packets, there is a 5-sec
313                  * libwebsocket timeout still active here too, so if parsing did
314                  * not complete just wait for next packet coming in this state
315                  */
316
317                 if (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE)
318                         break;
319
320                 /*
321                  * otherwise deal with the handshake.  If there's any
322                  * packet traffic already arrived we'll trigger poll() again
323                  * right away and deal with it that way
324                  */
325
326                 return lws_client_interpret_server_handshake(context, wsi);
327
328 bail3:
329                 lwsl_info(
330                         "closing connection at LWS_CONNMODE...SERVER_REPLY\n");
331                 libwebsocket_close_and_free_session(context, wsi,
332                                                     LWS_CLOSE_STATUS_NOSTATUS);
333                 return 0;
334
335         case LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT:
336                 lwsl_ext("LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT\n");
337                 break;
338
339         case LWS_CONNMODE_WS_CLIENT_PENDING_CANDIDATE_CHILD:
340                 lwsl_ext("LWS_CONNMODE_WS_CLIENT_PENDING_CANDIDATE_CHILD\n");
341                 break;
342         default:
343                 break;
344         }
345
346         return 0;
347 }
348
349
350 /*
351  * In-place str to lower case
352  */
353
354 static void
355 strtolower(char *s)
356 {
357         while (*s) {
358                 *s = tolower(*s);
359                 s++;
360         }
361 }
362
363 int
364 lws_client_interpret_server_handshake(struct libwebsocket_context *context,
365                 struct libwebsocket *wsi)
366 {
367         const char *pc;
368         int okay = 0;
369         char *p;
370         int len;
371 #ifndef LWS_NO_EXTENSIONS
372         char ext_name[128];
373         struct libwebsocket_extension *ext;
374         void *v;
375         int more = 1;
376         const char *c;
377 #endif
378         int n;
379
380         /*
381          * well, what the server sent looked reasonable for syntax.
382          * Now let's confirm it sent all the necessary headers
383          */
384
385         if (lws_hdr_total_length(wsi, WSI_TOKEN_ACCEPT) == 0)
386                 goto bail3;
387
388         p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP);
389         if (!p)
390                 goto bail3;
391         if (p && strncmp(p, "101", 3)) {
392                 lwsl_warn(
393                        "lws_client_handshake: got bad HTTP response '%s'\n", p);
394                 goto bail3;
395         }
396
397         p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_UPGRADE);
398         if (!p)
399                 goto bail3;
400         strtolower(p);
401         if (strcmp(p, "websocket")) {
402                 lwsl_warn(
403                       "lws_client_handshake: got bad Upgrade header '%s'\n", p);
404                 goto bail3;
405         }
406
407         p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_CONNECTION);
408         if (!p)
409                 goto bail3;
410         strtolower(p);
411         if (strcmp(p, "upgrade")) {
412                 lwsl_warn("lws_client_int_s_hs: bad header %s\n", p);
413                 goto bail3;
414         }
415
416         pc = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS);
417         if (pc == NULL)
418                 lwsl_parser("lws_client_int_s_hs: no protocol list\n");
419         else
420                 lwsl_parser("lws_client_int_s_hs: protocol list '%s'\n", pc);
421
422         /*
423          * confirm the protocol the server wants to talk was in the list
424          * of protocols we offered
425          */
426
427         len = lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL);
428         if (!len) {
429
430                 lwsl_info("lws_client_int_s_hs: WSI_TOKEN_PROTOCOL is null\n");
431                 /*
432                  * no protocol name to work from,
433                  * default to first protocol
434                  */
435                 wsi->protocol = &context->protocols[0];
436                 goto check_extensions;
437         }
438
439         p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL);
440         len = strlen(p);
441
442         while (*pc && !okay) {
443                 if (!strncmp(pc, p, len) &&
444                                           (pc[len] == ',' || pc[len] == '\0')) {
445                         okay = 1;
446                         continue;
447                 }
448                 while (*pc && *pc != ',')
449                         pc++;
450                 while (*pc && *pc != ' ')
451                         pc++;
452         }
453
454         if (!okay) {
455                 lwsl_err("lws_client_int_s_hs: got bad protocol %s\n", p);
456                 goto bail2;
457         }
458
459         /*
460          * identify the selected protocol struct and set it
461          */
462         n = 0;
463         wsi->protocol = NULL;
464         while (context->protocols[n].callback && !wsi->protocol) {
465                 if (strcmp(p, context->protocols[n].name) == 0) {
466                         wsi->protocol = &context->protocols[n];
467                         break;
468                 }
469                 n++;
470         }
471
472         if (wsi->protocol == NULL) {
473                 lwsl_err("lws_client_int_s_hs: fail protocol %s\n", p);
474                 goto bail2;
475         }
476
477
478 check_extensions:
479 #ifndef LWS_NO_EXTENSIONS
480         /* instantiate the accepted extensions */
481
482         if (!lws_hdr_total_length(wsi, WSI_TOKEN_EXTENSIONS)) {
483                 lwsl_ext("no client extenstions allowed by server\n");
484                 goto check_accept;
485         }
486
487         /*
488          * break down the list of server accepted extensions
489          * and go through matching them or identifying bogons
490          */
491
492         if (lws_hdr_copy(wsi, (char *)context->service_buffer,
493                      sizeof(context->service_buffer), WSI_TOKEN_EXTENSIONS) < 0)
494                 goto bail2;
495
496         c = (char *)context->service_buffer;
497         n = 0;
498         while (more) {
499
500                 if (*c && (*c != ',' && *c != ' ' && *c != '\t')) {
501                         ext_name[n] = *c++;
502                         if (n < sizeof(ext_name) - 1)
503                                 n++;
504                         continue;
505                 }
506                 ext_name[n] = '\0';
507                 if (!*c)
508                         more = 0;
509                 else {
510                         c++;
511                         if (!n)
512                                 continue;
513                 }
514
515                 /* check we actually support it */
516
517                 lwsl_ext("checking client ext %s\n", ext_name);
518
519                 n = 0;
520                 ext = wsi->protocol->owning_server->extensions;
521                 while (ext && ext->callback) {
522
523                         if (strcmp(ext_name, ext->name)) {
524                                 ext++;
525                                 continue;
526                         }
527
528                         n = 1;
529
530                         lwsl_ext("instantiating client ext %s\n", ext_name);
531
532                         /* instantiate the extension on this conn */
533
534                         wsi->active_extensions_user[
535                                 wsi->count_active_extensions] =
536                                          malloc(ext->per_session_data_size);
537                         if (wsi->active_extensions_user[
538                                 wsi->count_active_extensions] == NULL) {
539                                 lwsl_err("Out of mem\n");
540                                 goto bail2;
541                         }
542                         memset(wsi->active_extensions_user[
543                                 wsi->count_active_extensions], 0,
544                                                     ext->per_session_data_size);
545                         wsi->active_extensions[
546                                   wsi->count_active_extensions] = ext;
547
548                         /* allow him to construct his context */
549
550                         ext->callback(wsi->protocol->owning_server,
551                                 ext, wsi,
552                                    LWS_EXT_CALLBACK_CLIENT_CONSTRUCT,
553                                         wsi->active_extensions_user[
554                                          wsi->count_active_extensions],
555                                                                    NULL, 0);
556
557                         wsi->count_active_extensions++;
558
559                         ext++;
560                 }
561
562                 if (n == 0) {
563                         lwsl_warn("Unknown ext '%s'!\n", ext_name);
564                         goto bail2;
565                 }
566
567                 n = 0;
568         }
569
570 check_accept:
571 #endif
572
573         /*
574          * Confirm his accept token is the one we precomputed
575          */
576
577         p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_ACCEPT);
578         if (strcmp(p, wsi->u.hdr.initial_handshake_hash_base64)) {
579                 lwsl_warn("lws_client_int_s_hs: accept %s wrong vs %s\n", p,
580                                       wsi->u.hdr.initial_handshake_hash_base64);
581                 goto bail2;
582         }
583
584         /* allocate the per-connection user memory (if any) */
585         if (wsi->protocol->per_session_data_size &&
586                                           !libwebsocket_ensure_user_space(wsi))
587                 goto bail2;
588
589         /*
590          * we seem to be good to go, give client last chance to check
591          * headers and OK it
592          */
593
594         wsi->protocol->callback(context, wsi,
595                                 LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH,
596                                                      wsi->user_space, NULL, 0);
597
598         /* clear his proxy connection timeout */
599
600         libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
601
602         /* free up his parsing allocations */
603         if (wsi->u.hdr.ah)
604                 free(wsi->u.hdr.ah);
605
606         /* mark him as being alive */
607
608         wsi->state = WSI_STATE_ESTABLISHED;
609         wsi->mode = LWS_CONNMODE_WS_CLIENT;
610
611         /* union transition */
612
613         memset(&wsi->u, 0, sizeof(wsi->u));
614
615         /*
616          * create the frame buffer for this connection according to the
617          * size mentioned in the protocol definition.  If 0 there, then
618          * use a big default for compatibility
619          */
620
621         n = wsi->protocol->rx_buffer_size;
622         if (!n)
623                 n = LWS_MAX_SOCKET_IO_BUF;
624         n += LWS_SEND_BUFFER_PRE_PADDING + LWS_SEND_BUFFER_POST_PADDING;
625         wsi->u.ws.rx_user_buffer = malloc(n);
626         if (!wsi->u.ws.rx_user_buffer) {
627                 lwsl_err("Out of Mem allocating rx buffer %d\n", n);
628                 goto bail3;
629         }
630         lwsl_info("Allocating client RX buffer %d\n", n);
631
632         lwsl_debug("handshake OK for protocol %s\n", wsi->protocol->name);
633
634         /* call him back to inform him he is up */
635
636         wsi->protocol->callback(context, wsi,
637                                 LWS_CALLBACK_CLIENT_ESTABLISHED,
638                                                      wsi->user_space, NULL, 0);
639 #ifndef LWS_NO_EXTENSIONS
640         /*
641          * inform all extensions, not just active ones since they
642          * already know
643          */
644
645         ext = context->extensions;
646
647         while (ext && ext->callback) {
648                 v = NULL;
649                 for (n = 0; n < wsi->count_active_extensions; n++)
650                         if (wsi->active_extensions[n] == ext)
651                                 v = wsi->active_extensions_user[n];
652
653                 ext->callback(context, ext, wsi,
654                           LWS_EXT_CALLBACK_ANY_WSI_ESTABLISHED, v, NULL, 0);
655                 ext++;
656         }
657 #endif
658
659         return 0;
660
661 bail3:
662
663 bail2:
664         if (wsi->protocol)
665                 wsi->protocol->callback(context, wsi,
666                         LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
667                                                       wsi->user_space, NULL, 0);
668
669         lwsl_info("closing connection due to bail2 connection error\n");
670
671         /* free up his parsing allocations */
672
673         if (wsi->u.hdr.ah)
674                 free(wsi->u.hdr.ah);
675
676         libwebsocket_close_and_free_session(context, wsi,
677                                                  LWS_CLOSE_STATUS_PROTOCOL_ERR);
678
679         return 1;
680 }
681
682
683 char *
684 libwebsockets_generate_client_handshake(struct libwebsocket_context *context,
685                 struct libwebsocket *wsi, char *pkt)
686 {
687         char buf[128];
688         char hash[20];
689         char key_b64[40];
690         char *p = pkt;
691         int n;
692 #ifndef LWS_NO_EXTENSIONS
693         struct libwebsocket_extension *ext;
694         struct libwebsocket_extension *ext1;
695         int ext_count = 0;
696 #endif
697         static const char magic_websocket_guid[] =
698                                          "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
699
700         /*
701          * create the random key
702          */
703
704         n = libwebsockets_get_random(context, hash, 16);
705         if (n != 16) {
706                 lwsl_err("Unable to read from random dev %s\n",
707                                                 SYSTEM_RANDOM_FILEPATH);
708                 libwebsocket_close_and_free_session(context, wsi,
709                                              LWS_CLOSE_STATUS_NOSTATUS);
710                 return NULL;
711         }
712
713         lws_b64_encode_string(hash, 16, key_b64, sizeof(key_b64));
714
715         /*
716          * 00 example client handshake
717          *
718          * GET /socket.io/websocket HTTP/1.1
719          * Upgrade: WebSocket
720          * Connection: Upgrade
721          * Host: 127.0.0.1:9999
722          * Origin: http://127.0.0.1
723          * Sec-WebSocket-Key1: 1 0 2#0W 9 89 7  92 ^
724          * Sec-WebSocket-Key2: 7 7Y 4328 B2v[8(z1
725          * Cookie: socketio=websocket
726          *
727          * (Á®Ä0¶†≥
728          *
729          * 04 example client handshake
730          *
731          * GET /chat HTTP/1.1
732          * Host: server.example.com
733          * Upgrade: websocket
734          * Connection: Upgrade
735          * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
736          * Sec-WebSocket-Origin: http://example.com
737          * Sec-WebSocket-Protocol: chat, superchat
738          * Sec-WebSocket-Version: 4
739          */
740
741         p += sprintf(p, "GET %s HTTP/1.1\x0d\x0a",
742                                 lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_URI));
743
744         p += sprintf(p,
745                 "Pragma: no-cache\x0d\x0a""Cache-Control: no-cache\x0d\x0a");
746
747         p += sprintf(p, "Host: %s\x0d\x0a",
748                                lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_HOST));
749         p += sprintf(p,
750 "Upgrade: websocket\x0d\x0aConnection: Upgrade\x0d\x0aSec-WebSocket-Key: ");
751         strcpy(p, key_b64);
752         p += strlen(key_b64);
753         p += sprintf(p, "\x0d\x0a");
754         if (lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN))
755                 p += sprintf(p, "Origin: %s\x0d\x0a",
756                              lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN));
757
758         if (lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS))
759                 p += sprintf(p, "Sec-WebSocket-Protocol: %s\x0d\x0a",
760                      lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS));
761
762         /* tell the server what extensions we could support */
763
764         p += sprintf(p, "Sec-WebSocket-Extensions: ");
765 #ifndef LWS_NO_EXTENSIONS
766         ext = context->extensions;
767         while (ext && ext->callback) {
768
769                 n = 0;
770                 ext1 = context->extensions;
771
772                 while (ext1 && ext1->callback) {
773                         n |= ext1->callback(context, ext1, wsi,
774                                 LWS_EXT_CALLBACK_CHECK_OK_TO_PROPOSE_EXTENSION,
775                                         NULL, (char *)ext->name, 0);
776
777                         ext1++;
778                 }
779
780                 if (n) { /* an extension vetos us */
781                         lwsl_ext("ext %s vetoed\n", (char *)ext->name);
782                         ext++;
783                         continue;
784                 }
785
786                 n = context->protocols[0].callback(context, wsi,
787                         LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED,
788                                 wsi->user_space, (char *)ext->name, 0);
789
790                 /*
791                  * zero return from callback means
792                  * go ahead and allow the extension,
793                  * it's what we get if the callback is
794                  * unhandled
795                  */
796
797                 if (n) {
798                         ext++;
799                         continue;
800                 }
801
802                 /* apply it */
803
804                 if (ext_count)
805                         *p++ = ',';
806                 p += sprintf(p, "%s", ext->name);
807                 ext_count++;
808
809                 ext++;
810         }
811 #endif
812         p += sprintf(p, "\x0d\x0a");
813
814         if (wsi->ietf_spec_revision)
815                 p += sprintf(p, "Sec-WebSocket-Version: %d\x0d\x0a",
816                                                wsi->ietf_spec_revision);
817
818         /* give userland a chance to append, eg, cookies */
819
820         context->protocols[0].callback(context, wsi,
821                 LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER,
822                 NULL, &p, (pkt + sizeof(context->service_buffer)) - p - 12);
823
824         p += sprintf(p, "\x0d\x0a");
825
826         /* prepare the expected server accept response */
827
828         n = snprintf(buf, sizeof(buf), "%s%s", key_b64, magic_websocket_guid);
829         buf[sizeof(buf) - 1] = '\0';
830         SHA1((unsigned char *)buf, n, (unsigned char *)hash);
831
832         lws_b64_encode_string(hash, 20,
833                         wsi->u.hdr.initial_handshake_hash_base64,
834                              sizeof(wsi->u.hdr.initial_handshake_hash_base64));
835
836         return p;
837 }
838