client redirect: make sure there is a leading / on path
[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
25 lws_handshake_client(struct lws *wsi, unsigned char **buf, size_t len)
26 {
27         int m;
28
29         switch (wsi->mode) {
30         case LWSCM_WSCL_WAITING_PROXY_REPLY:
31         case LWSCM_WSCL_ISSUE_HANDSHAKE:
32         case LWSCM_WSCL_WAITING_SERVER_REPLY:
33         case LWSCM_WSCL_WAITING_EXTENSION_CONNECT:
34         case LWSCM_WS_CLIENT:
35                 while (len) {
36                         /*
37                          * we were accepting input but now we stopped doing so
38                          */
39                         if (!(wsi->rxflow_change_to & LWS_RXFLOW_ALLOW)) {
40                                 lwsl_debug("%s: caching %ld\n", __func__, (long)len);
41                                 lws_rxflow_cache(wsi, *buf, 0, len);
42                                 return 0;
43                         }
44                         if (wsi->u.ws.rx_draining_ext) {
45                                 m = lws_rx_sm(wsi, 0);
46                                 if (m < 0)
47                                         return -1;
48                                 continue;
49                         }
50                         /* account for what we're using in rxflow buffer */
51                         if (wsi->rxflow_buffer)
52                                 wsi->rxflow_pos++;
53
54                         if (lws_client_rx_sm(wsi, *(*buf)++)) {
55                                 lwsl_debug("client_rx_sm exited\n");
56                                 return -1;
57                         }
58                         len--;
59                 }
60                 lwsl_debug("%s: finished with %ld\n", __func__, (long)len);
61                 return 0;
62         default:
63                 break;
64         }
65
66         return 0;
67 }
68
69 LWS_VISIBLE LWS_EXTERN void
70 lws_client_http_body_pending(struct lws *wsi, int something_left_to_send)
71 {
72         wsi->client_http_body_pending = !!something_left_to_send;
73 }
74
75 int
76 lws_client_socket_service(struct lws_context *context, struct lws *wsi,
77                           struct lws_pollfd *pollfd)
78 {
79         struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
80         char *p = (char *)&pt->serv_buf[0];
81         const char *cce = NULL;
82         unsigned char c;
83         char *sb = p;
84         int n, len;
85
86         switch (wsi->mode) {
87
88         case LWSCM_WSCL_WAITING_CONNECT:
89
90                 /*
91                  * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
92                  * timeout protection set in client-handshake.c
93                  */
94
95                 if (!lws_client_connect_2(wsi)) {
96                         /* closed */
97                         lwsl_client("closed\n");
98                         return -1;
99                 }
100
101                 /* either still pending connection, or changed mode */
102                 return 0;
103
104         case LWSCM_WSCL_WAITING_PROXY_REPLY:
105
106                 /* handle proxy hung up on us */
107
108                 if (pollfd->revents & LWS_POLLHUP) {
109
110                         lwsl_warn("Proxy connection %p (fd=%d) dead\n",
111                                   (void *)wsi, pollfd->fd);
112
113                         lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
114                         return 0;
115                 }
116
117                 n = recv(wsi->sock, sb, context->pt_serv_buf_size, 0);
118                 if (n < 0) {
119                         if (LWS_ERRNO == LWS_EAGAIN) {
120                                 lwsl_debug("Proxy read returned EAGAIN... retrying\n");
121                                 return 0;
122                         }
123
124                         lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
125                         lwsl_err("ERROR reading from proxy socket\n");
126                         return 0;
127                 }
128
129                 pt->serv_buf[13] = '\0';
130                 if (strcmp(sb, "HTTP/1.0 200 ") &&
131                     strcmp(sb, "HTTP/1.1 200 ")) {
132                         lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
133                         lwsl_err("ERROR proxy: %s\n", sb);
134                         return 0;
135                 }
136
137                 /* clear his proxy connection timeout */
138
139                 lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
140
141                 /* fallthru */
142
143         case LWSCM_WSCL_ISSUE_HANDSHAKE:
144
145                 /*
146                  * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
147                  * timeout protection set in client-handshake.c
148                  *
149                  * take care of our lws_callback_on_writable
150                  * happening at a time when there's no real connection yet
151                  */
152                 if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
153                         return -1;
154
155 #ifdef LWS_OPENSSL_SUPPORT
156                 /* we can retry this... just cook the SSL BIO the first time */
157
158                 if (wsi->use_ssl && !wsi->ssl) {
159                         if (lws_ssl_client_bio_create(wsi))
160                                 return -1;
161                 }
162
163                 if (wsi->use_ssl) {
164                         n = lws_ssl_client_connect1(wsi);
165                         if (!n)
166                                 return 0;
167                         if (n < 0) {
168                                 cce = "lws_ssl_client_connect1 failed";
169                                 goto bail3;
170                         }
171                 } else
172                         wsi->ssl = NULL;
173
174                 /* fallthru */
175
176         case LWSCM_WSCL_WAITING_SSL:
177
178                 if (wsi->use_ssl) {
179                         n = lws_ssl_client_connect2(wsi);
180                         if (!n)
181                                 return 0;
182                         if (n < 0) {
183                                 cce = "lws_ssl_client_connect2 failed";
184                                 goto bail3;
185                         }
186                 } else
187                         wsi->ssl = NULL;
188 #endif
189
190                 wsi->mode = LWSCM_WSCL_ISSUE_HANDSHAKE2;
191                 lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND,
192                                 context->timeout_secs);
193
194                 /* fallthru */
195
196         case LWSCM_WSCL_ISSUE_HANDSHAKE2:
197                 p = lws_generate_client_handshake(wsi, p);
198                 if (p == NULL) {
199                         lwsl_err("Failed to generate handshake for client\n");
200                         lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
201                         return 0;
202                 }
203
204                 /* send our request to the server */
205
206                 lws_latency_pre(context, wsi);
207
208                 n = lws_ssl_capable_write(wsi, (unsigned char *)sb, p - sb);
209                 lws_latency(context, wsi, "send lws_issue_raw", n,
210                             n == p - sb);
211                 switch (n) {
212                 case LWS_SSL_CAPABLE_ERROR:
213                         lwsl_debug("ERROR writing to client socket\n");
214                         lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
215                         return 0;
216                 case LWS_SSL_CAPABLE_MORE_SERVICE:
217                         lws_callback_on_writable(wsi);
218                         break;
219                 }
220
221                 if (wsi->client_http_body_pending) {
222                         wsi->mode = LWSCM_WSCL_ISSUE_HTTP_BODY;
223                         lws_set_timeout(wsi, PENDING_TIMEOUT_CLIENT_ISSUE_PAYLOAD,
224                                         context->timeout_secs);
225                         /* user code must ask for writable callback */
226                         break;
227                 }
228
229                 goto client_http_body_sent;
230
231         case LWSCM_WSCL_ISSUE_HTTP_BODY:
232                 if (wsi->client_http_body_pending) {
233                         lws_set_timeout(wsi, PENDING_TIMEOUT_CLIENT_ISSUE_PAYLOAD,
234                                         context->timeout_secs);
235                         /* user code must ask for writable callback */
236                         break;
237                 }
238 client_http_body_sent:
239                 wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART;
240                 wsi->u.hdr.lextable_pos = 0;
241                 wsi->mode = LWSCM_WSCL_WAITING_SERVER_REPLY;
242                 lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE,
243                                 context->timeout_secs);
244                 break;
245
246         case LWSCM_WSCL_WAITING_SERVER_REPLY:
247
248                 /* handle server hung up on us */
249
250                 if (pollfd->revents & LWS_POLLHUP) {
251
252                         lwsl_debug("Server connection %p (fd=%d) dead\n",
253                                 (void *)wsi, pollfd->fd);
254                         cce = "Peer hung up";
255                         goto bail3;
256                 }
257
258                 if (!(pollfd->revents & LWS_POLLIN))
259                         break;
260
261                 /* interpret the server response */
262
263                 /*
264                  *  HTTP/1.1 101 Switching Protocols
265                  *  Upgrade: websocket
266                  *  Connection: Upgrade
267                  *  Sec-WebSocket-Accept: me89jWimTRKTWwrS3aRrL53YZSo=
268                  *  Sec-WebSocket-Nonce: AQIDBAUGBwgJCgsMDQ4PEC==
269                  *  Sec-WebSocket-Protocol: chat
270                  */
271
272                 /*
273                  * we have to take some care here to only take from the
274                  * socket bytewise.  The browser may (and has been seen to
275                  * in the case that onopen() performs websocket traffic)
276                  * coalesce both handshake response and websocket traffic
277                  * in one packet, since at that point the connection is
278                  * definitively ready from browser pov.
279                  */
280                 len = 1;
281                 while (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE &&
282                        len > 0) {
283                         n = lws_ssl_capable_read(wsi, &c, 1);
284                         lws_latency(context, wsi, "send lws_issue_raw", n,
285                                     n == 1);
286                         switch (n) {
287                         case 0:
288                         case LWS_SSL_CAPABLE_ERROR:
289                                 cce = "read failed";
290                                 goto bail3;
291                         case LWS_SSL_CAPABLE_MORE_SERVICE:
292                                 return 0;
293                         }
294
295                         if (lws_parse(wsi, c)) {
296                                 lwsl_warn("problems parsing header\n");
297                                 goto bail3;
298                         }
299                 }
300
301                 /*
302                  * hs may also be coming in multiple packets, there is a 5-sec
303                  * libwebsocket timeout still active here too, so if parsing did
304                  * not complete just wait for next packet coming in this state
305                  */
306
307                 if (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE)
308                         break;
309
310                 /*
311                  * otherwise deal with the handshake.  If there's any
312                  * packet traffic already arrived we'll trigger poll() again
313                  * right away and deal with it that way
314                  */
315
316                 return lws_client_interpret_server_handshake(wsi);
317
318 bail3:
319                 lwsl_info("closing conn at LWS_CONNMODE...SERVER_REPLY\n");
320                 wsi->vhost->protocols[0].callback(wsi,
321                         LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
322                         wsi->user_space, (void *)cce, cce ? strlen(cce) : 0);
323                 wsi->already_did_cce = 1;
324                 lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
325                 return -1;
326
327         case LWSCM_WSCL_WAITING_EXTENSION_CONNECT:
328                 lwsl_ext("LWSCM_WSCL_WAITING_EXTENSION_CONNECT\n");
329                 break;
330
331         case LWSCM_WSCL_PENDING_CANDIDATE_CHILD:
332                 lwsl_ext("LWSCM_WSCL_PENDING_CANDIDATE_CHILD\n");
333                 break;
334         default:
335                 break;
336         }
337
338         return 0;
339 }
340
341 /*
342  * In-place str to lower case
343  */
344
345 static void
346 strtolower(char *s)
347 {
348         while (*s) {
349 #ifdef LWS_PLAT_OPTEE
350                 int tolower_optee(int c);
351                 *s = tolower_optee((int)*s);
352 #else
353                 *s = tolower((int)*s);
354 #endif
355                 s++;
356         }
357 }
358
359 int LWS_WARN_UNUSED_RESULT
360 lws_http_transaction_completed_client(struct lws *wsi)
361 {
362         lwsl_debug("%s: wsi %p\n", __func__, wsi);
363         /* if we can't go back to accept new headers, drop the connection */
364         if (wsi->u.http.connection_type != HTTP_CONNECTION_KEEP_ALIVE) {
365                 lwsl_info("%s: %p: close connection\n", __func__, wsi);
366                 return 1;
367         }
368
369         /* otherwise set ourselves up ready to go again */
370         wsi->state = LWSS_CLIENT_HTTP_ESTABLISHED;
371         wsi->mode = LWSCM_HTTP_CLIENT_ACCEPTED;
372         wsi->u.http.content_length = 0;
373         wsi->hdr_parsing_completed = 0;
374
375         /* He asked for it to stay alive indefinitely */
376         lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
377
378         /*
379          * As client, nothing new is going to come until we ask for it
380          * we can drop the ah, if any
381          */
382         if (wsi->u.hdr.ah) {
383                 wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen;
384                 lws_header_table_detach(wsi, 0);
385         }
386
387         /* If we're (re)starting on headers, need other implied init */
388         wsi->u.hdr.ues = URIES_IDLE;
389
390         lwsl_info("%s: %p: keep-alive await new transaction\n", __func__, wsi);
391
392         return 0;
393 }
394
395 LWS_VISIBLE LWS_EXTERN unsigned int
396 lws_http_client_http_response(struct lws *wsi)
397 {
398         if (!wsi->u.http.ah)
399                 return 0;
400
401         return wsi->u.http.ah->http_response;
402 }
403
404 int
405 lws_client_interpret_server_handshake(struct lws *wsi)
406 {
407         int n, len, okay = 0, port = 0, ssl = 0;
408         int close_reason = LWS_CLOSE_STATUS_PROTOCOL_ERR;
409         struct lws_context *context = wsi->context;
410         const char *pc, *prot, *ads = NULL, *path, *cce = NULL;
411         struct allocated_headers *ah = NULL;
412         char *p;
413 #ifndef LWS_NO_EXTENSIONS
414         struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
415         char *sb = (char *)&pt->serv_buf[0];
416         const struct lws_ext_options *opts;
417         const struct lws_extension *ext;
418         char ext_name[128];
419         const char *c, *a;
420         char ignore;
421         int more = 1;
422         void *v;
423 #endif
424
425         if (!wsi->do_ws) {
426                 /* we are being an http client...
427                  */
428                 ah = wsi->u.hdr.ah;
429                 lws_union_transition(wsi, LWSCM_HTTP_CLIENT_ACCEPTED);
430                 wsi->state = LWSS_CLIENT_HTTP_ESTABLISHED;
431                 wsi->u.http.ah = ah;
432                 ah->http_response = 0;
433         }
434
435         /*
436          * well, what the server sent looked reasonable for syntax.
437          * Now let's confirm it sent all the necessary headers
438          *
439          * http (non-ws) client will expect something like this
440          *
441          * HTTP/1.0.200
442          * server:.libwebsockets
443          * content-type:.text/html
444          * content-length:.17703
445          * set-cookie:.test=LWS_1456736240_336776_COOKIE;Max-Age=360000
446          *
447          *
448          *
449          */
450
451         wsi->u.http.connection_type = HTTP_CONNECTION_KEEP_ALIVE;
452         p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP);
453         if (wsi->do_ws && !p) {
454                 lwsl_info("no URI\n");
455                 cce = "HS: URI missing";
456                 goto bail3;
457         }
458         if (!p) {
459                 p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP1_0);
460                 wsi->u.http.connection_type = HTTP_CONNECTION_CLOSE;
461         }
462         if (!p) {
463                 cce = "HS: URI missing";
464                 lwsl_info("no URI\n");
465                 goto bail3;
466         }
467         n = atoi(p);
468         if (ah)
469                 ah->http_response = n;
470
471         if (n == 301 || n == 302 || n == 303 || n == 307 || n == 308) {
472                 p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_LOCATION);
473                 if (!p) {
474                         cce = "HS: Redirect code but no Location";
475                         goto bail3;
476                 }
477
478                 if (lws_parse_uri(p, &prot, &ads, &port, &path)) {
479                         cce = "HS: URI did not parse";
480                         goto bail3;
481                 }
482
483                 if (!strcmp(prot, "wss") || !strcmp(prot, "https"))
484                         ssl = 1;
485
486                 if (!lws_client_reset(wsi, ssl, ads, port, path, ads)) {
487                         lwsl_err("Redirect failed\n");
488                         cce = "HS: Redirect failed";
489                         goto bail3;
490                 }
491                 return 0;
492         }
493
494         if (!wsi->do_ws) {
495                 if (n != 200 && n != 304) {
496                         lwsl_notice("Connection failed with code %d\n", n);
497                         cce = "HS: Server did not return 200 or 304";
498                         goto bail2;
499                 }
500
501 #ifdef LWS_WITH_HTTP_PROXY
502                 wsi->perform_rewrite = 0;
503                 if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE)) {
504                         if (!strncmp(lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE),
505                                      "text/html", 9))
506                                 wsi->perform_rewrite = 1;
507                 }
508 #endif
509
510                 /* allocate the per-connection user memory (if any) */
511                 if (lws_ensure_user_space(wsi)) {
512                         lwsl_err("Problem allocating wsi user mem\n");
513                         cce = "HS: OOM";
514                         goto bail2;
515                 }
516
517                 /* he may choose to send us stuff in chunked transfer-coding */
518                 wsi->chunked = 0;
519                 wsi->chunk_remaining = 0; /* ie, next thing is chunk size */
520                 if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_TRANSFER_ENCODING)) {
521                         wsi->chunked = !strcmp(lws_hdr_simple_ptr(wsi,
522                                                WSI_TOKEN_HTTP_TRANSFER_ENCODING),
523                                         "chunked");
524                         /* first thing is hex, after payload there is crlf */
525                         wsi->chunk_parser = ELCP_HEX;
526                 }
527
528                 if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH)) {
529                         wsi->u.http.content_length =
530                                         atoi(lws_hdr_simple_ptr(wsi,
531                                                 WSI_TOKEN_HTTP_CONTENT_LENGTH));
532                         lwsl_notice("%s: incoming content length %d\n", __func__,
533                                         wsi->u.http.content_length);
534                         wsi->u.http.content_remain = wsi->u.http.content_length;
535                 } else /* can't do 1.1 without a content length or chunked */
536                         if (!wsi->chunked)
537                                 wsi->u.http.connection_type = HTTP_CONNECTION_CLOSE;
538
539                 /*
540                  * we seem to be good to go, give client last chance to check
541                  * headers and OK it
542                  */
543                 if (wsi->protocol->callback(wsi, LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH,
544                                             wsi->user_space, NULL, 0)) {
545
546                         cce = "HS: disallowed by client filter";
547                         goto bail2;
548                 }
549
550                 /* clear his proxy connection timeout */
551                 lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
552
553                 wsi->rxflow_change_to = LWS_RXFLOW_ALLOW;
554
555                 /* call him back to inform him he is up */
556                 if (wsi->protocol->callback(wsi,
557                                             LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP,
558                                             wsi->user_space, NULL, 0)) {
559                         cce = "HS: disallowed at ESTABLISHED";
560                         goto bail3;
561                 }
562
563                 /* free up his parsing allocations */
564                 lws_header_table_detach(wsi, 0);
565
566                 lwsl_notice("%s: client connection up\n", __func__);
567
568                 return 0;
569         }
570
571         if (lws_hdr_total_length(wsi, WSI_TOKEN_ACCEPT) == 0) {
572                 lwsl_info("no ACCEPT\n");
573                 cce = "HS: ACCEPT missing";
574                 goto bail3;
575         }
576
577         if (p && strncmp(p, "101", 3)) {
578                 lwsl_warn(
579                        "lws_client_handshake: got bad HTTP response '%s'\n", p);
580                 cce = "HS: ws upgrade response not 101";
581                 goto bail3;
582         }
583
584         p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_UPGRADE);
585         if (!p) {
586                 lwsl_info("no UPGRADE\n");
587                 cce = "HS: UPGRADE missing";
588                 goto bail3;
589         }
590         strtolower(p);
591         if (strcmp(p, "websocket")) {
592                 lwsl_warn(
593                       "lws_client_handshake: got bad Upgrade header '%s'\n", p);
594                 cce = "HS: Upgrade to something other than websocket";
595                 goto bail3;
596         }
597
598         p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_CONNECTION);
599         if (!p) {
600                 lwsl_info("no Connection hdr\n");
601                 cce = "HS: CONNECTION missing";
602                 goto bail3;
603         }
604         strtolower(p);
605         if (strcmp(p, "upgrade")) {
606                 lwsl_warn("lws_client_int_s_hs: bad header %s\n", p);
607                 cce = "HS: UPGRADE malformed";
608                 goto bail3;
609         }
610
611         pc = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS);
612         if (!pc) {
613                 lwsl_parser("lws_client_int_s_hs: no protocol list\n");
614         } else
615                 lwsl_parser("lws_client_int_s_hs: protocol list '%s'\n", pc);
616
617         /*
618          * confirm the protocol the server wants to talk was in the list
619          * of protocols we offered
620          */
621
622         len = lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL);
623         if (!len) {
624                 lwsl_info("lws_client_int_s_hs: WSI_TOKEN_PROTOCOL is null\n");
625                 /*
626                  * no protocol name to work from,
627                  * default to first protocol
628                  */
629                 n = 0;
630                 wsi->protocol = &wsi->vhost->protocols[0];
631                 goto check_extensions;
632         }
633
634         p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL);
635         len = strlen(p);
636
637         while (pc && *pc && !okay) {
638                 if (!strncmp(pc, p, len) &&
639                     (pc[len] == ',' || pc[len] == '\0')) {
640                         okay = 1;
641                         continue;
642                 }
643                 while (*pc && *pc++ != ',')
644                         ;
645                 while (*pc && *pc == ' ')
646                         pc++;
647         }
648
649         if (!okay) {
650                 lwsl_err("lws_client_int_s_hs: got bad protocol %s\n", p);
651                 cce = "HS: PROTOCOL malformed";
652                 goto bail2;
653         }
654
655         /*
656          * identify the selected protocol struct and set it
657          */
658         n = 0;
659         wsi->protocol = NULL;
660         while (wsi->vhost->protocols[n].callback && !wsi->protocol) {
661                 if (strcmp(p, wsi->vhost->protocols[n].name) == 0) {
662                         wsi->protocol = &wsi->vhost->protocols[n];
663                         break;
664                 }
665                 n++;
666         }
667
668         if (wsi->protocol == NULL) {
669                 lwsl_err("lws_client_int_s_hs: fail protocol %s\n", p);
670                 cce = "HS: Cannot match protocol";
671                 goto bail2;
672         }
673
674 check_extensions:
675         /*
676          * stitch protocol choice into the vh protocol linked list
677          * We always insert ourselves at the start of the list
678          *
679          * X <-> B
680          * X <-> pAn <-> pB
681          */
682         //lwsl_err("%s: pre insert vhost start wsi %p, that wsi prev == %p\n",
683         //              __func__,
684         //              wsi->vhost->same_vh_protocol_list[n],
685         //              wsi->same_vh_protocol_prev);
686         wsi->same_vh_protocol_prev = /* guy who points to us */
687                 &wsi->vhost->same_vh_protocol_list[n];
688         wsi->same_vh_protocol_next = /* old first guy is our next */
689                         wsi->vhost->same_vh_protocol_list[n];
690         /* we become the new first guy */
691         wsi->vhost->same_vh_protocol_list[n] = wsi;
692
693         if (wsi->same_vh_protocol_next)
694                 /* old first guy points back to us now */
695                 wsi->same_vh_protocol_next->same_vh_protocol_prev =
696                                 &wsi->same_vh_protocol_next;
697
698 #ifndef LWS_NO_EXTENSIONS
699         /* instantiate the accepted extensions */
700
701         if (!lws_hdr_total_length(wsi, WSI_TOKEN_EXTENSIONS)) {
702                 lwsl_ext("no client extensions allowed by server\n");
703                 goto check_accept;
704         }
705
706         /*
707          * break down the list of server accepted extensions
708          * and go through matching them or identifying bogons
709          */
710
711         if (lws_hdr_copy(wsi, sb, context->pt_serv_buf_size, WSI_TOKEN_EXTENSIONS) < 0) {
712                 lwsl_warn("ext list from server failed to copy\n");
713                 cce = "HS: EXT: list too big";
714                 goto bail2;
715         }
716
717         c = sb;
718         n = 0;
719         ignore = 0;
720         a = NULL;
721         while (more) {
722
723                 if (*c && (*c != ',' && *c != '\t')) {
724                         if (*c == ';') {
725                                 ignore = 1;
726                                 if (!a)
727                                         a = c + 1;
728                         }
729                         if (ignore || *c == ' ') {
730                                 c++;
731                                 continue;
732                         }
733
734                         ext_name[n] = *c++;
735                         if (n < sizeof(ext_name) - 1)
736                                 n++;
737                         continue;
738                 }
739                 ext_name[n] = '\0';
740                 ignore = 0;
741                 if (!*c)
742                         more = 0;
743                 else {
744                         c++;
745                         if (!n)
746                                 continue;
747                 }
748
749                 /* check we actually support it */
750
751                 lwsl_notice("checking client ext %s\n", ext_name);
752
753                 n = 0;
754                 ext = wsi->vhost->extensions;
755                 while (ext && ext->callback) {
756                         if (strcmp(ext_name, ext->name)) {
757                                 ext++;
758                                 continue;
759                         }
760
761                         n = 1;
762                         lwsl_notice("instantiating client ext %s\n", ext_name);
763
764                         /* instantiate the extension on this conn */
765
766                         wsi->active_extensions[wsi->count_act_ext] = ext;
767
768                         /* allow him to construct his ext instance */
769
770                         if (ext->callback(lws_get_context(wsi), ext, wsi,
771                                       LWS_EXT_CB_CLIENT_CONSTRUCT,
772                                       (void *)&wsi->act_ext_user[wsi->count_act_ext],
773                                       (void *)&opts, 0)) {
774                                 lwsl_notice(" ext %s failed construction\n", ext_name);
775                                 ext++;
776                                 continue;
777                         }
778
779                         /*
780                          * allow the user code to override ext defaults if it
781                          * wants to
782                          */
783                         ext_name[0] = '\0';
784                         if (user_callback_handle_rxflow(wsi->protocol->callback,
785                                         wsi, LWS_CALLBACK_WS_EXT_DEFAULTS,
786                                         (char *)ext->name, ext_name,
787                                         sizeof(ext_name))) {
788                                 cce = "HS: EXT: failed setting defaults";
789                                 goto bail2;
790                         }
791
792                         if (ext_name[0] &&
793                             lws_ext_parse_options(ext, wsi, wsi->act_ext_user[
794                                                   wsi->count_act_ext], opts, ext_name,
795                                                   strlen(ext_name))) {
796                                 lwsl_err("%s: unable to parse user defaults '%s'",
797                                          __func__, ext_name);
798                                 cce = "HS: EXT: failed parsing defaults";
799                                 goto bail2;
800                         }
801
802                         /*
803                          * give the extension the server options
804                          */
805                         if (a && lws_ext_parse_options(ext, wsi,
806                                         wsi->act_ext_user[wsi->count_act_ext],
807                                         opts, a, c - a)) {
808                                 lwsl_err("%s: unable to parse remote def '%s'",
809                                          __func__, a);
810                                 cce = "HS: EXT: failed parsing options";
811                                 goto bail2;
812                         }
813
814                         if (ext->callback(lws_get_context(wsi), ext, wsi,
815                                         LWS_EXT_CB_OPTION_CONFIRM,
816                                       wsi->act_ext_user[wsi->count_act_ext],
817                                       NULL, 0)) {
818                                 lwsl_err("%s: ext %s rejects server options %s",
819                                          __func__, ext->name, a);
820                                 cce = "HS: EXT: Rejects server options";
821                                 goto bail2;
822                         }
823
824                         wsi->count_act_ext++;
825
826                         ext++;
827                 }
828
829                 if (n == 0) {
830                         lwsl_warn("Unknown ext '%s'!\n", ext_name);
831                         cce = "HS: EXT: unknown ext";
832                         goto bail2;
833                 }
834
835                 a = NULL;
836                 n = 0;
837         }
838
839 check_accept:
840 #endif
841
842         /*
843          * Confirm his accept token is the one we precomputed
844          */
845
846         p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_ACCEPT);
847         if (strcmp(p, wsi->u.hdr.ah->initial_handshake_hash_base64)) {
848                 lwsl_warn("lws_client_int_s_hs: accept '%s' wrong vs '%s'\n", p,
849                                   wsi->u.hdr.ah->initial_handshake_hash_base64);
850                 cce = "HS: Accept hash wrong";
851                 goto bail2;
852         }
853
854         /* allocate the per-connection user memory (if any) */
855         if (lws_ensure_user_space(wsi)) {
856                 lwsl_err("Problem allocating wsi user mem\n");
857                 cce = "HS: OOM";
858                 goto bail2;
859         }
860
861         /*
862          * we seem to be good to go, give client last chance to check
863          * headers and OK it
864          */
865         if (wsi->protocol->callback(wsi, LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH,
866                                     wsi->user_space, NULL, 0)) {
867                 cce = "HS: Rejected by filter cb";
868                 goto bail2;
869         }
870
871         /* clear his proxy connection timeout */
872         lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
873
874         /* free up his parsing allocations */
875         lws_header_table_detach(wsi, 0);
876
877         lws_union_transition(wsi, LWSCM_WS_CLIENT);
878         wsi->state = LWSS_ESTABLISHED;
879         lws_restart_ws_ping_pong_timer(wsi);
880
881         wsi->rxflow_change_to = LWS_RXFLOW_ALLOW;
882
883         /*
884          * create the frame buffer for this connection according to the
885          * size mentioned in the protocol definition.  If 0 there, then
886          * use a big default for compatibility
887          */
888         n = wsi->protocol->rx_buffer_size;
889         if (!n)
890                 n = context->pt_serv_buf_size;
891         n += LWS_PRE;
892         wsi->u.ws.rx_ubuf = lws_malloc(n + 4 /* 0x0000ffff zlib */);
893         if (!wsi->u.ws.rx_ubuf) {
894                 lwsl_err("Out of Mem allocating rx buffer %d\n", n);
895                 cce = "HS: OOM";
896                 goto bail2;
897         }
898        wsi->u.ws.rx_ubuf_alloc = n;
899         lwsl_info("Allocating client RX buffer %d\n", n);
900
901         if (setsockopt(wsi->sock, SOL_SOCKET, SO_SNDBUF, (const char *)&n,
902                        sizeof n)) {
903                 lwsl_warn("Failed to set SNDBUF to %d", n);
904                 cce = "HS: SO_SNDBUF failed";
905                 goto bail3;
906         }
907
908         lwsl_debug("handshake OK for protocol %s\n", wsi->protocol->name);
909
910         /* call him back to inform him he is up */
911
912         if (wsi->protocol->callback(wsi, LWS_CALLBACK_CLIENT_ESTABLISHED,
913                                     wsi->user_space, NULL, 0)) {
914                 cce = "HS: Rejected at CLIENT_ESTABLISHED";
915                 goto bail3;
916         }
917 #ifndef LWS_NO_EXTENSIONS
918         /*
919          * inform all extensions, not just active ones since they
920          * already know
921          */
922         ext = wsi->vhost->extensions;
923
924         while (ext && ext->callback) {
925                 v = NULL;
926                 for (n = 0; n < wsi->count_act_ext; n++)
927                         if (wsi->active_extensions[n] == ext)
928                                 v = wsi->act_ext_user[n];
929
930                 ext->callback(context, ext, wsi,
931                           LWS_EXT_CB_ANY_WSI_ESTABLISHED, v, NULL, 0);
932                 ext++;
933         }
934 #endif
935
936         return 0;
937
938 bail3:
939         close_reason = LWS_CLOSE_STATUS_NOSTATUS;
940
941 bail2:
942         if (wsi->protocol)
943                 wsi->protocol->callback(wsi, LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
944                                 wsi->user_space, (void *)cce,
945                                 (unsigned int)strlen(cce));
946         wsi->already_did_cce = 1;
947
948         lwsl_info("closing connection due to bail2 connection error\n");
949
950         /* closing will free up his parsing allocations */
951         lws_close_free_wsi(wsi, close_reason);
952
953         return 1;
954 }
955
956
957 char *
958 lws_generate_client_handshake(struct lws *wsi, char *pkt)
959 {
960         char buf[128], hash[20], key_b64[40], *p = pkt;
961         struct lws_context *context = wsi->context;
962         const char *meth;
963         int n;
964 #ifndef LWS_NO_EXTENSIONS
965         const struct lws_extension *ext;
966         int ext_count = 0;
967 #endif
968
969         meth = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_METHOD);
970         if (!meth) {
971                 meth = "GET";
972                 wsi->do_ws = 1;
973         } else
974                 wsi->do_ws = 0;
975
976         if (wsi->do_ws) {
977                 /*
978                  * create the random key
979                  */
980                 n = lws_get_random(context, hash, 16);
981                 if (n != 16) {
982                         lwsl_err("Unable to read from random dev %s\n",
983                                  SYSTEM_RANDOM_FILEPATH);
984                         lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
985                         return NULL;
986                 }
987
988                 lws_b64_encode_string(hash, 16, key_b64, sizeof(key_b64));
989         }
990
991         /*
992          * 04 example client handshake
993          *
994          * GET /chat HTTP/1.1
995          * Host: server.example.com
996          * Upgrade: websocket
997          * Connection: Upgrade
998          * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
999          * Sec-WebSocket-Origin: http://example.com
1000          * Sec-WebSocket-Protocol: chat, superchat
1001          * Sec-WebSocket-Version: 4
1002          */
1003
1004         p += sprintf(p, "%s %s HTTP/1.1\x0d\x0a", meth,
1005                      lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_URI));
1006
1007         p += sprintf(p, "Pragma: no-cache\x0d\x0a"
1008                         "Cache-Control: no-cache\x0d\x0a");
1009
1010         p += sprintf(p, "Host: %s\x0d\x0a",
1011                      lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_HOST));
1012
1013         if (lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN)) {
1014                 if (lws_check_opt(context->options, LWS_SERVER_OPTION_JUST_USE_RAW_ORIGIN))
1015                         p += sprintf(p, "Origin: %s\x0d\x0a",
1016                                      lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN));
1017                 else
1018                         p += sprintf(p, "Origin: http://%s\x0d\x0a",
1019                                      lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN));
1020         }
1021
1022         if (wsi->do_ws) {
1023                 p += sprintf(p, "Upgrade: websocket\x0d\x0a"
1024                                 "Connection: Upgrade\x0d\x0a"
1025                                 "Sec-WebSocket-Key: ");
1026                 strcpy(p, key_b64);
1027                 p += strlen(key_b64);
1028                 p += sprintf(p, "\x0d\x0a");
1029                 if (lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS))
1030                         p += sprintf(p, "Sec-WebSocket-Protocol: %s\x0d\x0a",
1031                              lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS));
1032
1033                 /* tell the server what extensions we could support */
1034
1035 #ifndef LWS_NO_EXTENSIONS
1036                 ext = wsi->vhost->extensions;
1037                 while (ext && ext->callback) {
1038                         n = lws_ext_cb_all_exts(context, wsi,
1039                                    LWS_EXT_CB_CHECK_OK_TO_PROPOSE_EXTENSION,
1040                                    (char *)ext->name, 0);
1041                         if (n) { /* an extension vetos us */
1042                                 lwsl_ext("ext %s vetoed\n", (char *)ext->name);
1043                                 ext++;
1044                                 continue;
1045                         }
1046                         n = wsi->vhost->protocols[0].callback(wsi,
1047                                 LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED,
1048                                         wsi->user_space, (char *)ext->name, 0);
1049
1050                         /*
1051                          * zero return from callback means
1052                          * go ahead and allow the extension,
1053                          * it's what we get if the callback is
1054                          * unhandled
1055                          */
1056
1057                         if (n) {
1058                                 ext++;
1059                                 continue;
1060                         }
1061
1062                         /* apply it */
1063
1064                         if (ext_count)
1065                                 *p++ = ',';
1066                         else
1067                                 p += sprintf(p, "Sec-WebSocket-Extensions: ");
1068                         p += sprintf(p, "%s", ext->client_offer);
1069                         ext_count++;
1070
1071                         ext++;
1072                 }
1073                 if (ext_count)
1074                         p += sprintf(p, "\x0d\x0a");
1075 #endif
1076
1077                 if (wsi->ietf_spec_revision)
1078                         p += sprintf(p, "Sec-WebSocket-Version: %d\x0d\x0a",
1079                                      wsi->ietf_spec_revision);
1080
1081                 /* prepare the expected server accept response */
1082
1083                 key_b64[39] = '\0'; /* enforce composed length below buf sizeof */
1084                 n = sprintf(buf, "%s258EAFA5-E914-47DA-95CA-C5AB0DC85B11", key_b64);
1085
1086                 lws_SHA1((unsigned char *)buf, n, (unsigned char *)hash);
1087
1088                 lws_b64_encode_string(hash, 20,
1089                                       wsi->u.hdr.ah->initial_handshake_hash_base64,
1090                                       sizeof(wsi->u.hdr.ah->initial_handshake_hash_base64));
1091         }
1092
1093         /* give userland a chance to append, eg, cookies */
1094
1095         wsi->vhost->protocols[0].callback(wsi, LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER,
1096                                 wsi->user_space, &p, (pkt + context->pt_serv_buf_size) - p - 12);
1097
1098         p += sprintf(p, "\x0d\x0a");
1099
1100         return p;
1101 }
1102