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