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