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