1 /*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 */
24
25 #include "private-lib-core.h"
26
27 void
lws_client_http_body_pending(struct lws * wsi,int something_left_to_send)28 lws_client_http_body_pending(struct lws *wsi, int something_left_to_send)
29 {
30 wsi->client_http_body_pending = !!something_left_to_send;
31 }
32
33 int
lws_http_client_socket_service(struct lws * wsi,struct lws_pollfd * pollfd)34 lws_http_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd)
35 {
36 struct lws_context *context = wsi->a.context;
37 struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
38 char *p = (char *)&pt->serv_buf[0];
39 #if defined(LWS_WITH_TLS)
40 char ebuf[128];
41 #endif
42 const char *cce = NULL;
43 char *sb = p;
44 int n = 0;
45
46 switch (lwsi_state(wsi)) {
47
48 case LRS_WAITING_DNS:
49 /*
50 * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
51 * timeout protection set in client-handshake.c
52 */
53 lwsl_err("%s: %s: WAITING_DNS\n", __func__, lws_wsi_tag(wsi));
54 if (!lws_client_connect_2_dnsreq(wsi)) {
55 /* closed */
56 lwsl_client("closed\n");
57 return -1;
58 }
59
60 /* either still pending connection, or changed mode */
61 return 0;
62
63 case LRS_WAITING_CONNECT:
64
65 /*
66 * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
67 * timeout protection set in client-handshake.c
68 */
69 if (pollfd->revents & LWS_POLLOUT)
70 if (lws_client_connect_3_connect(wsi, NULL, NULL, 0, NULL) == NULL) {
71 lwsl_client("closed\n");
72 return -1;
73 }
74 break;
75
76 #if defined(LWS_WITH_SOCKS5)
77 /* SOCKS Greeting Reply */
78 case LRS_WAITING_SOCKS_GREETING_REPLY:
79 case LRS_WAITING_SOCKS_AUTH_REPLY:
80 case LRS_WAITING_SOCKS_CONNECT_REPLY:
81
82 switch (lws_socks5c_handle_state(wsi, pollfd, &cce)) {
83 case LW5CHS_RET_RET0:
84 return 0;
85 case LW5CHS_RET_BAIL3:
86 goto bail3;
87 case LW5CHS_RET_STARTHS:
88 goto start_ws_handshake;
89 default:
90 break;
91 }
92 break;
93 #endif
94
95 #if defined(LWS_CLIENT_HTTP_PROXYING) && (defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2))
96
97 case LRS_WAITING_PROXY_REPLY:
98
99 /* handle proxy hung up on us */
100
101 if (pollfd->revents & LWS_POLLHUP) {
102
103 lwsl_warn("Proxy conn %s (fd=%d) dead\n",
104 lws_wsi_tag(wsi), pollfd->fd);
105
106 cce = "proxy conn dead";
107 goto bail3;
108 }
109
110 n = (int)recv(wsi->desc.sockfd, sb, context->pt_serv_buf_size, 0);
111 if (n < 0) {
112 if (LWS_ERRNO == LWS_EAGAIN) {
113 lwsl_debug("Proxy read EAGAIN... retrying\n");
114 return 0;
115 }
116 lwsl_err("ERROR reading from proxy socket\n");
117 cce = "proxy read err";
118 goto bail3;
119 }
120
121 /* sanity check what we were sent... */
122
123 pt->serv_buf[13] = '\0';
124 if (n < 13 || strncmp(sb, "HTTP/1.", 7) ||
125 (sb[7] != '0' && sb[7] != '1') || sb[8] != ' ') {
126 /* lwsl_hexdump_notice(sb, n); */
127 cce = "http_proxy fail";
128 goto bail3;
129 }
130
131 /* it's h1 alright... what's his logical response code? */
132 n = atoi(&sb[9]);
133 if (n != 200) {
134 lws_snprintf(sb, 20, "http_proxy -> %u",
135 (unsigned int)n);
136 cce = sb;
137 goto bail3;
138 }
139
140 lwsl_info("%s: proxy connection extablished\n", __func__);
141
142 /* clear his proxy connection timeout */
143
144 lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
145
146 /* fallthru */
147
148 #endif
149
150 /* dummy fallthru to satisfy compiler */
151 /* fallthru */
152 case LRS_H1C_ISSUE_HANDSHAKE:
153
154 lwsl_debug("%s: LRS_H1C_ISSUE_HANDSHAKE\n", __func__);
155
156 /*
157 * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
158 * timeout protection set in client-handshake.c
159 *
160 * take care of our lws_callback_on_writable
161 * happening at a time when there's no real connection yet
162 */
163 #if defined(LWS_WITH_SOCKS5)
164 start_ws_handshake:
165 #endif
166 if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
167 return -1;
168
169 #if defined(LWS_ROLE_H2) || defined(LWS_WITH_TLS)
170 if (
171 #if defined(LWS_WITH_TLS)
172 !(wsi->tls.use_ssl & LCCSCF_USE_SSL)
173 #endif
174 #if defined(LWS_ROLE_H2) && defined(LWS_WITH_TLS)
175 &&
176 #endif
177 #if defined(LWS_ROLE_H2)
178 !(wsi->flags & LCCSCF_H2_PRIOR_KNOWLEDGE)
179 #endif
180 )
181 goto hs2;
182 #endif
183
184 #if defined(LWS_WITH_TLS)
185 n = lws_client_create_tls(wsi, &cce, 1);
186 if (n == CCTLS_RETURN_ERROR)
187 goto bail3;
188 if (n == CCTLS_RETURN_RETRY)
189 return 0;
190
191 /*
192 * lws_client_create_tls() can already have done the
193 * whole tls setup and preface send... if so he set our state
194 * to LRS_H1C_ISSUE_HANDSHAKE2... let's proceed but be prepared
195 * to notice our state and not resend the preface...
196 */
197
198 lwsl_debug("%s: LRS_H1C_ISSUE_HANDSHAKE fallthru\n", __func__);
199
200 /* fallthru */
201
202 case LRS_WAITING_SSL:
203
204 if (wsi->tls.use_ssl & LCCSCF_USE_SSL) {
205 n = lws_ssl_client_connect2(wsi, ebuf, sizeof(ebuf));
206 if (!n)
207 return 0;
208 if (n < 0) {
209 cce = ebuf;
210 goto bail3;
211 }
212 } else {
213 wsi->tls.ssl = NULL;
214 if (wsi->flags & LCCSCF_H2_PRIOR_KNOWLEDGE) {
215 lwsl_info("h2 prior knowledge\n");
216 lws_role_call_alpn_negotiated(wsi, "h2");
217 }
218 }
219 #endif
220
221 #if defined (LWS_WITH_HTTP2)
222 if (wsi->client_h2_alpn //&&
223 //lwsi_state(wsi) != LRS_H1C_ISSUE_HANDSHAKE2
224 ) {
225 /*
226 * We connected to the server and set up tls and
227 * negotiated "h2" or connected as clear text
228 * with http/2 prior knowledge.
229 *
230 * So this is it, we are an h2 nwsi client connection
231 * now, not an h1 client connection.
232 */
233
234 lwsl_info("%s: doing h2 hello path\n", __func__);
235
236 /*
237 * send the H2 preface to legitimize the connection
238 *
239 * transitions us to LRS_H2_WAITING_TO_SEND_HEADERS
240 */
241 if (wsi->client_h2_alpn)
242 if (lws_h2_issue_preface(wsi)) {
243 cce = "error sending h2 preface";
244 goto bail3;
245 }
246
247 // lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE2);
248 lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND,
249 (int)context->timeout_secs);
250
251 break;
252 }
253 #endif
254
255 /* fallthru */
256
257 case LRS_H1C_ISSUE_HANDSHAKE2:
258
259 hs2:
260
261 p = lws_generate_client_handshake(wsi, p);
262 if (p == NULL) {
263 if (wsi->role_ops == &role_ops_raw_skt
264 #if defined(LWS_ROLE_RAW_FILE)
265 || wsi->role_ops == &role_ops_raw_file
266 #endif
267 )
268 return 0;
269
270 lwsl_err("Failed to generate handshake for client\n");
271 lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS,
272 "chs");
273 return 0;
274 }
275
276 /* send our request to the server */
277
278 lwsl_info("%s: HANDSHAKE2: %s: sending headers "
279 "(wsistate 0x%lx), w sock %d\n",
280 __func__, lws_wsi_tag(wsi),
281 (unsigned long)wsi->wsistate, wsi->desc.sockfd);
282
283 n = lws_ssl_capable_write(wsi, (unsigned char *)sb, lws_ptr_diff_size_t(p, sb));
284 switch (n) {
285 case LWS_SSL_CAPABLE_ERROR:
286 lwsl_debug("ERROR writing to client socket\n");
287 lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS,
288 "cws");
289 return 0;
290 case LWS_SSL_CAPABLE_MORE_SERVICE:
291 lws_callback_on_writable(wsi);
292 break;
293 }
294
295 if (wsi->client_http_body_pending || lws_has_buffered_out(wsi)) {
296 lwsl_debug("body pending\n");
297 lwsi_set_state(wsi, LRS_ISSUE_HTTP_BODY);
298 lws_set_timeout(wsi,
299 PENDING_TIMEOUT_CLIENT_ISSUE_PAYLOAD,
300 (int)context->timeout_secs);
301
302 if (wsi->flags & LCCSCF_HTTP_X_WWW_FORM_URLENCODED)
303 lws_callback_on_writable(wsi);
304 #if defined(LWS_WITH_HTTP_PROXY)
305 if (wsi->http.proxy_clientside && wsi->parent &&
306 wsi->parent->http.buflist_post_body)
307 lws_callback_on_writable(wsi);
308 #endif
309 /* user code must ask for writable callback */
310 break;
311 }
312
313 lwsi_set_state(wsi, LRS_WAITING_SERVER_REPLY);
314 wsi->hdr_parsing_completed = 0;
315
316 if (lwsi_state(wsi) == LRS_IDLING) {
317 lwsi_set_state(wsi, LRS_WAITING_SERVER_REPLY);
318 wsi->hdr_parsing_completed = 0;
319 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
320 wsi->http.ah->parser_state = WSI_TOKEN_NAME_PART;
321 wsi->http.ah->lextable_pos = 0;
322 wsi->http.ah->unk_pos = 0;
323 /* If we're (re)starting on hdr, need other implied init */
324 wsi->http.ah->ues = URIES_IDLE;
325 #endif
326 }
327
328 lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE,
329 (int)wsi->a.context->timeout_secs);
330
331 lws_callback_on_writable(wsi);
332
333 goto client_http_body_sent;
334
335 case LRS_ISSUE_HTTP_BODY:
336 #if defined(LWS_WITH_HTTP_PROXY)
337 if (wsi->http.proxy_clientside && wsi->parent &&
338 wsi->parent->http.buflist_post_body)
339 lws_callback_on_writable(wsi);
340 #endif
341 if (wsi->client_http_body_pending || lws_has_buffered_out(wsi)) {
342 //lws_set_timeout(wsi,
343 // PENDING_TIMEOUT_CLIENT_ISSUE_PAYLOAD,
344 // context->timeout_secs);
345 /* user code must ask for writable callback */
346 break;
347 }
348 client_http_body_sent:
349 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
350 /* prepare ourselves to do the parsing */
351 wsi->http.ah->parser_state = WSI_TOKEN_NAME_PART;
352 wsi->http.ah->lextable_pos = 0;
353 wsi->http.ah->unk_pos = 0;
354 #endif
355 lwsi_set_state(wsi, LRS_WAITING_SERVER_REPLY);
356 lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE,
357 (int)context->timeout_secs);
358 break;
359
360 case LRS_WAITING_SERVER_REPLY:
361 /*
362 * handle server hanging up on us...
363 * but if there is POLLIN waiting, handle that first
364 */
365 if ((pollfd->revents & (LWS_POLLIN | LWS_POLLHUP)) ==
366 LWS_POLLHUP) {
367
368 if (lws_buflist_total_len(&wsi->buflist))
369 lws_set_timeout(wsi, PENDING_TIMEOUT_CLOSE_ACK, 3);
370 else {
371 lwsl_debug("Server conn %s (fd=%d) dead\n",
372 lws_wsi_tag(wsi), pollfd->fd);
373 cce = "Peer hung up";
374 goto bail3;
375 }
376 }
377
378 if (pollfd->revents & LWS_POLLOUT)
379 if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
380 return -1;
381
382 if (!(pollfd->revents & LWS_POLLIN))
383 break;
384
385 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
386 /* interpret the server response
387 *
388 * HTTP/1.1 101 Switching Protocols
389 * Upgrade: websocket
390 * Connection: Upgrade
391 * Sec-WebSocket-Accept: me89jWimTRKTWwrS3aRrL53YZSo=
392 * Sec-WebSocket-Nonce: AQIDBAUGBwgJCgsMDQ4PEC==
393 * Sec-WebSocket-Protocol: chat
394 *
395 * we have to take some care here to only take from the
396 * socket bytewise. The browser may (and has been seen to
397 * in the case that onopen() performs websocket traffic)
398 * coalesce both handshake response and websocket traffic
399 * in one packet, since at that point the connection is
400 * definitively ready from browser pov.
401 */
402 while (wsi->http.ah->parser_state != WSI_PARSING_COMPLETE) {
403 struct lws_tokens eb;
404 int n, m, buffered;
405
406 eb.token = NULL;
407 eb.len = 0;
408 buffered = lws_buflist_aware_read(pt, wsi, &eb, 0, __func__);
409 lwsl_debug("%s: buflist-aware-read %d %d\n", __func__,
410 buffered, eb.len);
411 if (eb.len == LWS_SSL_CAPABLE_MORE_SERVICE)
412 return 0;
413 if (buffered < 0 || eb.len < 0) {
414 cce = "read failed";
415 goto bail3;
416 }
417 if (!eb.len)
418 return 0;
419
420 n = eb.len;
421 if (lws_parse(wsi, eb.token, &n)) {
422 lwsl_warn("problems parsing header\n");
423 cce = "problems parsing header";
424 goto bail3;
425 }
426
427 m = eb.len - n;
428 #if defined(LWS_WITH_SECURE_STREAMS_BUFFER_DUMP)
429 do {
430 lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi);
431 if (!h)
432 break;
433
434 if (h->info.dump) {
435 h->info.dump(ss_to_userobj(h),
436 (const uint8_t *)eb.token,
437 (size_t)m,
438 (wsi->http.ah->parser_state ==
439 WSI_PARSING_COMPLETE) ? 1 : 0);
440 }
441 } while (0);
442 #endif
443 if (lws_buflist_aware_finished_consuming(wsi, &eb, m,
444 buffered,
445 __func__))
446 return -1;
447
448 /*
449 * coverity: uncomment if extended
450 *
451 * eb.token += m;
452 * eb.len -= m;
453 */
454
455 if (n) {
456 assert(wsi->http.ah->parser_state ==
457 WSI_PARSING_COMPLETE);
458
459 break;
460 }
461 }
462
463 /*
464 * hs may also be coming in multiple packets, there is a 5-sec
465 * libwebsocket timeout still active here too, so if parsing did
466 * not complete just wait for next packet coming in this state
467 */
468 if (wsi->http.ah->parser_state != WSI_PARSING_COMPLETE)
469 break;
470 #endif
471
472 /*
473 * otherwise deal with the handshake. If there's any
474 * packet traffic already arrived we'll trigger poll() again
475 * right away and deal with it that way
476 */
477 return lws_client_interpret_server_handshake(wsi);
478
479 bail3:
480 lwsl_info("%s: closing conn at LWS_CONNMODE...SERVER_REPLY, %s, state 0x%x\n",
481 __func__, lws_wsi_tag(wsi), lwsi_state(wsi));
482 if (cce)
483 lwsl_info("reason: %s\n", cce);
484 else
485 cce = "unknown";
486 lws_inform_client_conn_fail(wsi, (void *)cce, strlen(cce));
487
488 lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "cbail3");
489 return -1;
490
491 default:
492 break;
493 }
494
495 return 0;
496 }
497
498 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
499
500 int LWS_WARN_UNUSED_RESULT
lws_http_transaction_completed_client(struct lws * wsi)501 lws_http_transaction_completed_client(struct lws *wsi)
502 {
503 struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
504 int n;
505
506 lwsl_info("%s: %s (%s)\n", __func__, lws_wsi_tag(wsi),
507 wsi->a.protocol->name);
508
509 // if (wsi->http.ah && wsi->http.ah->http_response)
510 /* we're only judging if any (200, or 500 etc) http txn completed */
511 lws_metrics_caliper_report(wsi->cal_conn, METRES_GO);
512
513 if (user_callback_handle_rxflow(wsi->a.protocol->callback, wsi,
514 LWS_CALLBACK_COMPLETED_CLIENT_HTTP,
515 wsi->user_space, NULL, 0)) {
516 lwsl_debug("%s: Completed call returned nonzero (role 0x%lx)\n",
517 __func__, (unsigned long)lwsi_role(wsi));
518 return -1;
519 }
520
521 wsi->http.rx_content_length = 0;
522
523 /*
524 * For h1, wsi may pass some assets on to a queued child and be
525 * destroyed during this.
526 */
527 lws_pt_lock(pt, __func__);
528 n = _lws_generic_transaction_completed_active_conn(&wsi, 1);
529 lws_pt_unlock(pt);
530
531 if (wsi->http.ah) {
532 if (wsi->client_mux_substream)
533 /*
534 * As an h2 client, once we did our transaction, that is
535 * it for us. Further transactions will happen as new
536 * SIDs on the connection.
537 */
538 __lws_header_table_detach(wsi, 0);
539 else
540 if (!n)
541 _lws_header_table_reset(wsi->http.ah);
542 }
543
544 if (!n || !wsi->http.ah)
545 return 0;
546
547 /*
548 * H1: we can serialize the queued guys into the same ah
549 * H2: everybody needs their own ah until their own STREAM_END
550 */
551
552 /* otherwise set ourselves up ready to go again */
553 lwsi_set_state(wsi, LRS_WAITING_SERVER_REPLY);
554
555 wsi->http.ah->parser_state = WSI_TOKEN_NAME_PART;
556 wsi->http.ah->lextable_pos = 0;
557 wsi->http.ah->unk_pos = 0;
558
559 lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE,
560 (int)wsi->a.context->timeout_secs);
561
562 /* If we're (re)starting on headers, need other implied init */
563 wsi->http.ah->ues = URIES_IDLE;
564 lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE2);
565
566 lwsl_info("%s: %s: new queued transaction\n", __func__, lws_wsi_tag(wsi));
567 lws_callback_on_writable(wsi);
568
569 return 0;
570 }
571
572 unsigned int
lws_http_client_http_response(struct lws * wsi)573 lws_http_client_http_response(struct lws *wsi)
574 {
575 if (wsi->http.ah && wsi->http.ah->http_response)
576 return wsi->http.ah->http_response;
577
578 return 0;
579 }
580 #endif
581
582 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
583
584 int
lws_http_is_redirected_to_get(struct lws * wsi)585 lws_http_is_redirected_to_get(struct lws *wsi)
586 {
587 return wsi->redirected_to_get;
588 }
589
590 int
lws_client_interpret_server_handshake(struct lws * wsi)591 lws_client_interpret_server_handshake(struct lws *wsi)
592 {
593 int n, port = 0, ssl = 0;
594 int close_reason = LWS_CLOSE_STATUS_PROTOCOL_ERR;
595 const char *prot, *ads = NULL, *path, *cce = NULL;
596 struct allocated_headers *ah, *ah1;
597 struct lws *nwsi = lws_get_network_wsi(wsi);
598 char *p = NULL, *q, *simp;
599 char new_path[300];
600 void *opaque;
601
602 // lws_free_set_NULL(wsi->stash);
603
604 #if defined(LWS_WITH_CONMON)
605 wsi->conmon.ciu_txn_resp = (lws_conmon_interval_us_t)
606 (lws_now_usecs() - wsi->conmon_datum);
607 #endif
608
609 ah = wsi->http.ah;
610 if (!wsi->do_ws) {
611 /* we are being an http client...
612 */
613 #if defined(LWS_ROLE_H2)
614 if (wsi->client_h2_alpn || wsi->client_mux_substream) {
615 lwsl_debug("%s: %s: transitioning to h2 client\n",
616 __func__, lws_wsi_tag(wsi));
617 lws_role_transition(wsi, LWSIFR_CLIENT,
618 LRS_ESTABLISHED, &role_ops_h2);
619 } else
620 #endif
621 {
622 #if defined(LWS_ROLE_H1)
623 {
624 lwsl_debug("%s: %s: transitioning to h1 client\n",
625 __func__, lws_wsi_tag(wsi));
626 lws_role_transition(wsi, LWSIFR_CLIENT,
627 LRS_ESTABLISHED, &role_ops_h1);
628 }
629 #else
630 return -1;
631 #endif
632 }
633
634 wsi->http.ah = ah;
635 ah->http_response = 0;
636 }
637
638 #if defined(LWS_WITH_CACHE_NSCOOKIEJAR) && defined(LWS_WITH_CLIENT)
639
640 if ((wsi->flags & LCCSCF_CACHE_COOKIES) &&
641 lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_SET_COOKIE))
642 lws_parse_set_cookie(wsi);
643
644 #endif
645 /*
646 * well, what the server sent looked reasonable for syntax.
647 * Now let's confirm it sent all the necessary headers
648 *
649 * http (non-ws) client will expect something like this
650 *
651 * HTTP/1.0.200
652 * server:.libwebsockets
653 * content-type:.text/html
654 * content-length:.17703
655 * set-cookie:.test=LWS_1456736240_336776_COOKIE;Max-Age=360000
656 */
657
658 wsi->http.conn_type = HTTP_CONNECTION_KEEP_ALIVE;
659 if (!wsi->client_mux_substream) {
660 p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP);
661 /*
662 if (wsi->do_ws && !p) {
663 lwsl_info("no URI\n");
664 cce = "HS: URI missing";
665 goto bail3;
666 }
667 */
668 if (!p) {
669 p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP1_0);
670 wsi->http.conn_type = HTTP_CONNECTION_CLOSE;
671 }
672 if (!p) {
673 cce = "HS: URI missing";
674 lwsl_info("no URI\n");
675 goto bail3;
676 }
677 #if defined(LWS_ROLE_H2)
678 } else {
679 p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_STATUS);
680 if (!p) {
681 cce = "HS: :status missing";
682 lwsl_info("no status\n");
683 goto bail3;
684 }
685 #endif
686 }
687 #if !defined(LWS_ROLE_H2)
688 if (!p) {
689 cce = "HS: :status missing";
690 lwsl_info("no status\n");
691 goto bail3;
692 }
693 #endif
694 n = atoi(p);
695 if (ah)
696 ah->http_response = (unsigned int)n;
697
698 if (!wsi->client_no_follow_redirect &&
699 #if defined(LWS_WITH_HTTP_PROXY)
700 !wsi->http.proxy_clientside &&
701 #endif
702 (n == 301 || n == 302 || n == 303 || n == 307 || n == 308)) {
703 p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_LOCATION);
704 if (!p) {
705 cce = "HS: Redirect code but no Location";
706 goto bail3;
707 }
708
709 #if defined(LWS_WITH_CONMON)
710 if (wsi->conmon.pcol == LWSCONMON_PCOL_NONE) {
711 wsi->conmon.pcol = LWSCONMON_PCOL_HTTP;
712 wsi->conmon.protocol_specific.http.response = n;
713 }
714
715 #if defined(LWS_WITH_SECURE_STREAMS)
716 if (wsi->for_ss
717 #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)
718 && !wsi->client_bound_sspc
719 #endif
720 ) {
721
722 lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi);
723
724 if (h)
725 lws_conmon_ss_json(h);
726 }
727 #endif
728 #endif
729
730 /* let's let the user code know, if he cares */
731
732 if (wsi->a.protocol->callback(wsi,
733 LWS_CALLBACK_CLIENT_HTTP_REDIRECT,
734 wsi->user_space, p, (unsigned int)n)) {
735 cce = "HS: user code rejected redirect";
736 goto bail3;
737 }
738
739 /*
740 * Some redirect codes imply we have to change the method
741 * used for the subsequent transaction, commonly POST ->
742 * 303 -> GET.
743 */
744
745 if (n == 303) {
746 char *mp = lws_hdr_simple_ptr(wsi,_WSI_TOKEN_CLIENT_METHOD);
747 int ml = lws_hdr_total_length(wsi, _WSI_TOKEN_CLIENT_METHOD);
748
749 if (ml >= 3 && mp) {
750 lwsl_info("%s: 303 switching to GET\n", __func__);
751 memcpy(mp, "GET", 4);
752 wsi->redirected_to_get = 1;
753 wsi->http.ah->frags[wsi->http.ah->frag_index[
754 _WSI_TOKEN_CLIENT_METHOD]].len = 3;
755 }
756 }
757
758 /* Relative reference absolute path */
759 if (p[0] == '/' || !strchr(p, ':')) {
760 #if defined(LWS_WITH_TLS)
761 ssl = nwsi->tls.use_ssl & LCCSCF_USE_SSL;
762 #endif
763 ads = lws_hdr_simple_ptr(wsi,
764 _WSI_TOKEN_CLIENT_PEER_ADDRESS);
765 port = nwsi->c_port;
766 path = p;
767 /* lws_client_reset expects leading / omitted */
768 if (*path == '/')
769 path++;
770 }
771 /* Absolute (Full) URI */
772 else if (strchr(p, ':')) {
773 if (lws_parse_uri(p, &prot, &ads, &port, &path)) {
774 cce = "HS: URI did not parse";
775 goto bail3;
776 }
777
778 if (!strcmp(prot, "wss") || !strcmp(prot, "https"))
779 ssl = LCCSCF_USE_SSL;
780 }
781 /* Relative reference relative path */
782 else {
783 /* This doesn't try to calculate an absolute path,
784 * that will be left to the server */
785 #if defined(LWS_WITH_TLS)
786 ssl = nwsi->tls.use_ssl & LCCSCF_USE_SSL;
787 #endif
788 ads = lws_hdr_simple_ptr(wsi,
789 _WSI_TOKEN_CLIENT_PEER_ADDRESS);
790 port = wsi->c_port;
791 /* +1 as lws_client_reset expects leading / omitted */
792 path = new_path + 1;
793 if (lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_URI))
794 lws_strncpy(new_path, lws_hdr_simple_ptr(wsi,
795 _WSI_TOKEN_CLIENT_URI), sizeof(new_path));
796 else {
797 new_path[0] = '/';
798 new_path[1] = '\0';
799 }
800 q = strrchr(new_path, '/');
801 if (q)
802 lws_strncpy(q + 1, p, sizeof(new_path) -
803 (unsigned int)(q - new_path) - 1);
804 else
805 path = p;
806 }
807
808 #if defined(LWS_WITH_TLS)
809 if ((wsi->tls.use_ssl & LCCSCF_USE_SSL) && !ssl &&
810 !(wsi->flags & LCCSCF_ACCEPT_TLS_DOWNGRADE_REDIRECTS)) {
811 cce = "HS: Redirect attempted SSL downgrade";
812 goto bail3;
813 }
814 #endif
815
816 if (!ads) /* make coverity happy */ {
817 cce = "no ads";
818 goto bail3;
819 }
820
821 if (!lws_client_reset(&wsi, ssl, ads, port, path, ads, 1)) {
822 lwsl_err("Redirect failed\n");
823 cce = "HS: Redirect failed";
824 goto bail3;
825 }
826
827 /*
828 * We are redirecting, let's close in order to extricate
829 * ourselves from the current wsi usage, eg, h2 mux cleanly.
830 *
831 * We will notice close_is_redirect and switch to redirect
832 * flow late in the close action.
833 */
834
835 opaque = wsi->a.opaque_user_data;
836 lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "redir");
837 wsi->a.opaque_user_data = opaque;
838
839 return -1;
840 }
841
842 /* if h1 KA is allowed, enable the queued pipeline guys */
843
844 if (!wsi->client_h2_alpn && !wsi->client_mux_substream) {
845 /* ie, coming to this for the first time */
846 if (wsi->http.conn_type == HTTP_CONNECTION_KEEP_ALIVE)
847 wsi->keepalive_active = 1;
848 else {
849 /*
850 * Ugh... now the main http connection has seen
851 * both sides, we learn the server doesn't
852 * support keepalive.
853 *
854 * That means any guys queued on us are going
855 * to have to be restarted from connect2 with
856 * their own connections.
857 */
858
859 /*
860 * stick around telling any new guys they can't
861 * pipeline to this server
862 */
863 wsi->keepalive_rejected = 1;
864
865 lws_vhost_lock(wsi->a.vhost);
866 lws_start_foreach_dll_safe(struct lws_dll2 *,
867 d, d1,
868 wsi->dll2_cli_txn_queue_owner.head) {
869 struct lws *ww = lws_container_of(d,
870 struct lws,
871 dll2_cli_txn_queue);
872
873 /* remove him from our queue */
874 lws_dll2_remove(&ww->dll2_cli_txn_queue);
875 /* give up on pipelining */
876 ww->client_pipeline = 0;
877
878 /* go back to "trying to connect" state */
879 lws_role_transition(ww, LWSIFR_CLIENT,
880 LRS_UNCONNECTED,
881 #if defined(LWS_ROLE_H1)
882 &role_ops_h1);
883 #else
884 #if defined (LWS_ROLE_H2)
885 &role_ops_h2);
886 #else
887 &role_ops_raw);
888 #endif
889 #endif
890 ww->user_space = NULL;
891 } lws_end_foreach_dll_safe(d, d1);
892 lws_vhost_unlock(wsi->a.vhost);
893 }
894 }
895
896 #ifdef LWS_WITH_HTTP_PROXY
897 wsi->http.perform_rewrite = 0;
898 if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE)) {
899 if (!strncmp(lws_hdr_simple_ptr(wsi,
900 WSI_TOKEN_HTTP_CONTENT_TYPE),
901 "text/html", 9))
902 wsi->http.perform_rewrite = 0;
903 }
904 #endif
905
906 /* he may choose to send us stuff in chunked transfer-coding */
907 wsi->chunked = 0;
908 wsi->chunk_remaining = 0; /* ie, next thing is chunk size */
909 if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_TRANSFER_ENCODING)) {
910 simp = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_TRANSFER_ENCODING);
911
912 /* cannot be NULL, since it has nonzero length... coverity */
913 if (!simp)
914 goto bail2;
915 wsi->chunked = !strcmp(simp, "chunked");
916 /* first thing is hex, after payload there is crlf */
917 wsi->chunk_parser = ELCP_HEX;
918 }
919
920 wsi->http.content_length_given = 0;
921 if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH)) {
922 simp = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH);
923
924 /* cannot be NULL, since it has nonzero length... coverity */
925 if (!simp)
926 goto bail2;
927
928 wsi->http.rx_content_length = (lws_filepos_t)atoll(simp);
929 lwsl_info("%s: incoming content length %llu\n",
930 __func__, (unsigned long long)
931 wsi->http.rx_content_length);
932 wsi->http.rx_content_remain =
933 wsi->http.rx_content_length;
934 wsi->http.content_length_given = 1;
935 } else { /* can't do 1.1 without a content length or chunked */
936 if (!wsi->chunked)
937 wsi->http.conn_type = HTTP_CONNECTION_CLOSE;
938 lwsl_debug("%s: no content length\n", __func__);
939 }
940
941 if (wsi->do_ws) {
942 /*
943 * Give one last opportunity to ws protocols to inspect server reply
944 * before the ws upgrade code discard it. ie: download reply body in case
945 * of any other response code than 101.
946 */
947 if (wsi->a.protocol->callback(wsi,
948 LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP,
949 wsi->user_space, NULL, 0)) {
950
951 cce = "HS: disallowed by client filter";
952 goto bail2;
953 }
954 } else {
955 /* allocate the per-connection user memory (if any) */
956 if (lws_ensure_user_space(wsi)) {
957 lwsl_err("Problem allocating wsi user mem\n");
958 cce = "HS: OOM";
959 goto bail2;
960 }
961
962
963 /*
964 * we seem to be good to go, give client last chance to check
965 * headers and OK it
966 */
967 ah1 = wsi->http.ah;
968 wsi->http.ah = ah;
969 if (wsi->a.protocol->callback(wsi,
970 LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH,
971 wsi->user_space, NULL, 0)) {
972 wsi->http.ah = ah1;
973 cce = "HS: disallowed by client filter";
974 goto bail2;
975 }
976
977 /* clear his proxy connection timeout */
978 lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
979
980 wsi->rxflow_change_to = LWS_RXFLOW_ALLOW;
981
982 /* call him back to inform him he is up */
983 if (wsi->a.protocol->callback(wsi,
984 LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP,
985 wsi->user_space, NULL, 0)) {
986 wsi->http.ah = ah1;
987 cce = "HS: disallowed at ESTABLISHED";
988 goto bail3;
989 }
990
991 wsi->http.ah = ah1;
992
993 lwsl_info("%s: %s: client conn up\n", __func__, lws_wsi_tag(wsi));
994
995 /*
996 * Did we get a response from the server with an explicit
997 * content-length of zero? If so, and it's not H2 which will
998 * notice it via END_STREAM, this transaction is already
999 * completed at the end of the header processing...
1000 */
1001 if (!wsi->mux_substream && !wsi->client_mux_substream &&
1002 lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH) &&
1003 !wsi->http.rx_content_length)
1004 return !!lws_http_transaction_completed_client(wsi);
1005
1006 /*
1007 * We can also get a case where it's http/1 and there's no
1008 * content-length at all, so anything that comes is the body
1009 * until it hangs up on us. With that situation, hanging up
1010 * on us past this point should generate a valid
1011 * LWS_CALLBACK_COMPLETED_CLIENT_HTTP.
1012 *
1013 * In that situation, he can't pipeline because in h1 there's
1014 * no post-header in-band way to signal the end of the
1015 * transaction except hangup.
1016 *
1017 * lws_http_transaction_completed_client() is the right guy to
1018 * issue it when we see the peer has hung up on us.
1019 */
1020
1021 return 0;
1022 }
1023
1024 #if defined(LWS_ROLE_WS)
1025 switch (lws_client_ws_upgrade(wsi, &cce)) {
1026 case 2:
1027 goto bail2;
1028 case 3:
1029 goto bail3;
1030 }
1031
1032 return 0;
1033 #endif
1034
1035 bail3:
1036 close_reason = LWS_CLOSE_STATUS_NOSTATUS;
1037
1038 bail2:
1039 if (wsi->a.protocol) {
1040 n = 0;
1041 if (cce)
1042 n = (int)strlen(cce);
1043
1044 lws_inform_client_conn_fail(wsi, (void *)cce, (unsigned int)n);
1045 }
1046
1047 lwsl_info("closing connection (prot %s) "
1048 "due to bail2 connection error: %s\n", wsi->a.protocol ?
1049 wsi->a.protocol->name : "unknown", cce);
1050
1051 /* closing will free up his parsing allocations */
1052 lws_close_free_wsi(wsi, (enum lws_close_status)close_reason, "c hs interp");
1053
1054 return 1;
1055 }
1056 #endif
1057
1058 /*
1059 * set the boundary string and the content-type for client multipart mime
1060 */
1061
1062 uint8_t *
lws_http_multipart_headers(struct lws * wsi,uint8_t * p)1063 lws_http_multipart_headers(struct lws *wsi, uint8_t *p)
1064 {
1065 char buf[10], arg[48];
1066 int n;
1067
1068 if (lws_get_random(wsi->a.context, (uint8_t *)buf, sizeof(buf)) !=
1069 sizeof(buf))
1070 return NULL;
1071
1072 lws_b64_encode_string(buf, sizeof(buf),
1073 wsi->http.multipart_boundary,
1074 sizeof(wsi->http.multipart_boundary));
1075
1076 n = lws_snprintf(arg, sizeof(arg), "multipart/form-data; boundary=\"%s\"",
1077 wsi->http.multipart_boundary);
1078
1079 if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
1080 (uint8_t *)arg, n, &p, p + 100))
1081 return NULL;
1082
1083 wsi->http.multipart = wsi->http.multipart_issue_boundary = 1;
1084 lws_client_http_body_pending(wsi, 1);
1085
1086 return p;
1087 }
1088
1089 int
lws_client_http_multipart(struct lws * wsi,const char * name,const char * filename,const char * content_type,char ** p,char * end)1090 lws_client_http_multipart(struct lws *wsi, const char *name,
1091 const char *filename, const char *content_type,
1092 char **p, char *end)
1093 {
1094 /*
1095 * Client conn must have been created with LCCSCF_HTTP_MULTIPART_MIME
1096 * flag to use this api
1097 */
1098 assert(wsi->http.multipart);
1099
1100 if (!name) {
1101 *p += lws_snprintf((char *)(*p), lws_ptr_diff_size_t(end, *p),
1102 "\xd\xa--%s--\xd\xa",
1103 wsi->http.multipart_boundary);
1104
1105 return 0;
1106 }
1107
1108 if (wsi->client_subsequent_mime_part)
1109 *p += lws_snprintf((char *)(*p), lws_ptr_diff_size_t(end, *p), "\xd\xa");
1110 wsi->client_subsequent_mime_part = 1;
1111
1112 *p += lws_snprintf((char *)(*p), lws_ptr_diff_size_t(end, *p), "--%s\xd\xa"
1113 "Content-Disposition: form-data; "
1114 "name=\"%s\"",
1115 wsi->http.multipart_boundary, name);
1116 if (filename)
1117 *p += lws_snprintf((char *)(*p), lws_ptr_diff_size_t(end, *p),
1118 "; filename=\"%s\"", filename);
1119
1120 if (content_type)
1121 *p += lws_snprintf((char *)(*p), lws_ptr_diff_size_t(end, *p), "\xd\xa"
1122 "Content-Type: %s", content_type);
1123
1124 *p += lws_snprintf((char *)(*p), lws_ptr_diff_size_t(end, *p), "\xd\xa\xd\xa");
1125
1126 return *p == end;
1127 }
1128
1129 char *
lws_generate_client_handshake(struct lws * wsi,char * pkt)1130 lws_generate_client_handshake(struct lws *wsi, char *pkt)
1131 {
1132 const char *meth, *pp = lws_hdr_simple_ptr(wsi,
1133 _WSI_TOKEN_CLIENT_SENT_PROTOCOLS), *path;
1134 char *p = pkt, *p1, *end = p + wsi->a.context->pt_serv_buf_size;
1135
1136 meth = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_METHOD);
1137 if (!meth) {
1138 meth = "GET";
1139 wsi->do_ws = 1;
1140 } else {
1141 wsi->do_ws = 0;
1142 }
1143
1144 if (!strcmp(meth, "RAW")) {
1145 lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
1146 lwsl_notice("client transition to raw\n");
1147
1148 if (pp) {
1149 const struct lws_protocols *pr;
1150
1151 pr = lws_vhost_name_to_protocol(wsi->a.vhost, pp);
1152
1153 if (!pr) {
1154 lwsl_err("protocol %s not enabled on vhost\n",
1155 pp);
1156 return NULL;
1157 }
1158
1159 lws_bind_protocol(wsi, pr, __func__);
1160 }
1161
1162 if ((wsi->a.protocol->callback)(wsi, LWS_CALLBACK_RAW_ADOPT,
1163 wsi->user_space, NULL, 0))
1164 return NULL;
1165
1166 lws_role_transition(wsi, LWSIFR_CLIENT, LRS_ESTABLISHED,
1167 &role_ops_raw_skt);
1168 lws_header_table_detach(wsi, 1);
1169
1170 return NULL;
1171 }
1172
1173 /*
1174 * 04 example client handshake
1175 *
1176 * GET /chat HTTP/1.1
1177 * Host: server.example.com
1178 * Upgrade: websocket
1179 * Connection: Upgrade
1180 * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
1181 * Sec-WebSocket-Origin: http://example.com
1182 * Sec-WebSocket-Protocol: chat, superchat
1183 * Sec-WebSocket-Version: 4
1184 */
1185
1186 path = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_URI);
1187 if (!path) {
1188 if (wsi->stash && wsi->stash->cis[CIS_PATH] &&
1189 wsi->stash->cis[CIS_PATH][0])
1190 path = wsi->stash->cis[CIS_PATH];
1191 else
1192 path = "/";
1193 }
1194
1195 p += lws_snprintf(p, lws_ptr_diff_size_t(end, p),
1196 "%s %s HTTP/1.1\x0d\x0a", meth, path);
1197
1198 p += lws_snprintf(p, lws_ptr_diff_size_t(end, p),
1199 "Pragma: no-cache\x0d\x0a"
1200 "Cache-Control: no-cache\x0d\x0a");
1201
1202 p += lws_snprintf(p, lws_ptr_diff_size_t(end, p),
1203 "Host: %s\x0d\x0a",
1204 lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_HOST));
1205
1206 if (lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN)) {
1207 if (lws_check_opt(wsi->a.context->options,
1208 LWS_SERVER_OPTION_JUST_USE_RAW_ORIGIN))
1209 p += lws_snprintf(p, lws_ptr_diff_size_t(end, p),
1210 "Origin: %s\x0d\x0a",
1211 lws_hdr_simple_ptr(wsi,
1212 _WSI_TOKEN_CLIENT_ORIGIN));
1213 else
1214 p += lws_snprintf(p, lws_ptr_diff_size_t(end, p),
1215 "Origin: %s://%s\x0d\x0a",
1216 wsi->flags & LCCSCF_USE_SSL ?
1217 "https" : "http",
1218 lws_hdr_simple_ptr(wsi,
1219 _WSI_TOKEN_CLIENT_ORIGIN));
1220 }
1221
1222 if (wsi->flags & LCCSCF_HTTP_MULTIPART_MIME) {
1223 p1 = (char *)lws_http_multipart_headers(wsi, (uint8_t *)p);
1224 if (!p1)
1225 return NULL;
1226 p = p1;
1227 }
1228
1229 #if defined(LWS_WITH_HTTP_PROXY)
1230 if (wsi->parent &&
1231 lws_hdr_total_length(wsi->parent, WSI_TOKEN_HTTP_CONTENT_LENGTH)) {
1232 p += lws_snprintf(p, lws_ptr_diff_size_t(end, p),
1233 "Content-Length: %s\x0d\x0a",
1234 lws_hdr_simple_ptr(wsi->parent, WSI_TOKEN_HTTP_CONTENT_LENGTH));
1235 if (atoi(lws_hdr_simple_ptr(wsi->parent, WSI_TOKEN_HTTP_CONTENT_LENGTH)))
1236 wsi->client_http_body_pending = 1;
1237 }
1238 if (wsi->parent &&
1239 lws_hdr_total_length(wsi->parent, WSI_TOKEN_HTTP_AUTHORIZATION)) {
1240 p += lws_snprintf(p, lws_ptr_diff_size_t(end, p),
1241 "Authorization: %s\x0d\x0a",
1242 lws_hdr_simple_ptr(wsi->parent, WSI_TOKEN_HTTP_AUTHORIZATION));
1243 }
1244 if (wsi->parent &&
1245 lws_hdr_total_length(wsi->parent, WSI_TOKEN_HTTP_CONTENT_TYPE)) {
1246 p += lws_snprintf(p, lws_ptr_diff_size_t(end, p),
1247 "Content-Type: %s\x0d\x0a",
1248 lws_hdr_simple_ptr(wsi->parent, WSI_TOKEN_HTTP_CONTENT_TYPE));
1249 }
1250 #endif
1251
1252 #if defined(LWS_ROLE_WS)
1253 if (wsi->do_ws) {
1254 const char *conn1 = "";
1255 // if (!wsi->client_pipeline)
1256 // conn1 = "close, ";
1257 p = lws_generate_client_ws_handshake(wsi, p, conn1);
1258 } else
1259 #endif
1260 {
1261 if (!wsi->client_pipeline)
1262 p += lws_snprintf(p, 64, "connection: close\x0d\x0a");
1263 }
1264
1265 /* give userland a chance to append, eg, cookies */
1266
1267 #if defined(LWS_WITH_CACHE_NSCOOKIEJAR) && defined(LWS_WITH_CLIENT)
1268 if (wsi->flags & LCCSCF_CACHE_COOKIES)
1269 lws_cookie_send_cookies(wsi, &p, end);
1270 #endif
1271
1272 if (wsi->a.protocol->callback(wsi,
1273 LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER,
1274 wsi->user_space, &p,
1275 (unsigned int)((pkt + wsi->a.context->pt_serv_buf_size) - p - 12)))
1276 return NULL;
1277
1278 if (wsi->flags & LCCSCF_HTTP_X_WWW_FORM_URLENCODED) {
1279 p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "Content-Type: application/x-www-form-urlencoded\x0d\x0a");
1280 p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "Content-Length: %lu\x0d\x0a", wsi->http.writeable_len);
1281 lws_client_http_body_pending(wsi, 1);
1282 }
1283
1284 p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "\x0d\x0a");
1285
1286 if (wsi->client_http_body_pending || lws_has_buffered_out(wsi))
1287 lws_callback_on_writable(wsi);
1288
1289 lws_metrics_caliper_bind(wsi->cal_conn, wsi->a.context->mt_http_txn);
1290 #if defined(LWS_WITH_CONMON)
1291 wsi->conmon_datum = lws_now_usecs();
1292 #endif
1293
1294 // puts(pkt);
1295
1296 return p;
1297 }
1298
1299 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
1300 #if defined(LWS_WITH_HTTP_BASIC_AUTH)
1301
1302 int
lws_http_basic_auth_gen(const char * user,const char * pw,char * buf,size_t len)1303 lws_http_basic_auth_gen(const char *user, const char *pw, char *buf, size_t len)
1304 {
1305 size_t n = strlen(user), m = strlen(pw);
1306 char b[128];
1307
1308 if (len < 6 + ((4 * (n + m + 1)) / 3) + 1)
1309 return 1;
1310
1311 memcpy(buf, "Basic ", 6);
1312
1313 n = (unsigned int)lws_snprintf(b, sizeof(b), "%s:%s", user, pw);
1314 if (n >= sizeof(b) - 2)
1315 return 2;
1316
1317 lws_b64_encode_string(b, (int)n, buf + 6, (int)len - 6);
1318 buf[len - 1] = '\0';
1319
1320 return 0;
1321 }
1322
1323 #endif
1324
1325 int
lws_http_client_read(struct lws * wsi,char ** buf,int * len)1326 lws_http_client_read(struct lws *wsi, char **buf, int *len)
1327 {
1328 struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
1329 struct lws_tokens eb;
1330 int buffered, n, consumed = 0;
1331
1332 /*
1333 * If the caller provided a non-NULL *buf and nonzero *len, we should
1334 * use that as the buffer for the read action, limititing it to *len
1335 * (actual payload will be less if chunked headers inside).
1336 *
1337 * If it's NULL / 0 length, buflist_aware_read will use the pt_serv_buf
1338 */
1339
1340 eb.token = (unsigned char *)*buf;
1341 eb.len = *len;
1342
1343 buffered = lws_buflist_aware_read(pt, wsi, &eb, 0, __func__);
1344 *buf = (char *)eb.token; /* may be pointing to buflist or pt_serv_buf */
1345 *len = 0;
1346
1347 /*
1348 * we're taking on responsibility for handling used / unused eb
1349 * when we leave, via lws_buflist_aware_finished_consuming()
1350 */
1351
1352 // lwsl_notice("%s: eb.len %d ENTRY chunk remaining %d\n", __func__, eb.len,
1353 // wsi->chunk_remaining);
1354
1355 /* allow the source to signal he has data again next time */
1356 if (lws_change_pollfd(wsi, 0, LWS_POLLIN))
1357 return -1;
1358
1359 if (buffered < 0) {
1360 lwsl_debug("%s: SSL capable error\n", __func__);
1361
1362 if (wsi->http.ah &&
1363 wsi->http.ah->parser_state == WSI_PARSING_COMPLETE &&
1364 !lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH))
1365 /*
1366 * We had the headers from this stream, but as there
1367 * was no content-length: we had to wait until the
1368 * stream ended to inform the user code the transaction
1369 * has completed to the best of our knowledge
1370 */
1371 if (lws_http_transaction_completed_client(wsi))
1372 /*
1373 * We're going to close anyway, but that api has
1374 * warn_unused_result
1375 */
1376 return -1;
1377
1378 return -1;
1379 }
1380
1381 if (eb.len <= 0)
1382 return 0;
1383
1384 *len = eb.len;
1385 wsi->client_rx_avail = 0;
1386
1387 /*
1388 * server may insist on transfer-encoding: chunked,
1389 * so http client must deal with it
1390 */
1391 spin_chunks:
1392 //lwsl_notice("%s: len %d SPIN chunk remaining %d\n", __func__, *len,
1393 // wsi->chunk_remaining);
1394 while (wsi->chunked && (wsi->chunk_parser != ELCP_CONTENT) && *len) {
1395 switch (wsi->chunk_parser) {
1396 case ELCP_HEX:
1397 if ((*buf)[0] == '\x0d') {
1398 wsi->chunk_parser = ELCP_CR;
1399 break;
1400 }
1401 n = char_to_hex((*buf)[0]);
1402 if (n < 0) {
1403 lwsl_err("%s: chunking failure A\n", __func__);
1404 return -1;
1405 }
1406 wsi->chunk_remaining <<= 4;
1407 wsi->chunk_remaining |= n;
1408 break;
1409 case ELCP_CR:
1410 if ((*buf)[0] != '\x0a') {
1411 lwsl_err("%s: chunking failure B\n", __func__);
1412 return -1;
1413 }
1414 if (wsi->chunk_remaining) {
1415 wsi->chunk_parser = ELCP_CONTENT;
1416 //lwsl_notice("starting chunk size %d (block rem %d)\n",
1417 // wsi->chunk_remaining, *len);
1418 break;
1419 }
1420
1421 wsi->chunk_parser = ELCP_TRAILER_CR;
1422 break;
1423
1424 case ELCP_CONTENT:
1425 break;
1426
1427 case ELCP_POST_CR:
1428 if ((*buf)[0] != '\x0d') {
1429 lwsl_err("%s: chunking failure C\n", __func__);
1430 lwsl_hexdump_err(*buf, (unsigned int)*len);
1431
1432 return -1;
1433 }
1434
1435 wsi->chunk_parser = ELCP_POST_LF;
1436 break;
1437
1438 case ELCP_POST_LF:
1439 if ((*buf)[0] != '\x0a') {
1440 lwsl_err("%s: chunking failure D\n", __func__);
1441
1442 return -1;
1443 }
1444
1445 wsi->chunk_parser = ELCP_HEX;
1446 wsi->chunk_remaining = 0;
1447 break;
1448
1449 case ELCP_TRAILER_CR:
1450 if ((*buf)[0] != '\x0d') {
1451 lwsl_err("%s: chunking failure F\n", __func__);
1452 lwsl_hexdump_err(*buf, (unsigned int)*len);
1453
1454 return -1;
1455 }
1456
1457 wsi->chunk_parser = ELCP_TRAILER_LF;
1458 break;
1459
1460 case ELCP_TRAILER_LF:
1461 if ((*buf)[0] != '\x0a') {
1462 lwsl_err("%s: chunking failure F\n", __func__);
1463 lwsl_hexdump_err(*buf, (unsigned int)*len);
1464
1465 return -1;
1466 }
1467
1468 (*buf)++;
1469 (*len)--;
1470 consumed++;
1471
1472 lwsl_info("final chunk\n");
1473 goto completed;
1474 }
1475 (*buf)++;
1476 (*len)--;
1477 consumed++;
1478 }
1479
1480 if (wsi->chunked && !wsi->chunk_remaining)
1481 goto account_and_ret;
1482
1483 if (wsi->http.rx_content_remain &&
1484 wsi->http.rx_content_remain < (unsigned int)*len)
1485 n = (int)wsi->http.rx_content_remain;
1486 else
1487 n = *len;
1488
1489 if (wsi->chunked && wsi->chunk_remaining &&
1490 wsi->chunk_remaining < n)
1491 n = wsi->chunk_remaining;
1492
1493 #if defined(LWS_WITH_HTTP_PROXY) && defined(LWS_WITH_HUBBUB)
1494 /* hubbub */
1495 if (wsi->http.perform_rewrite)
1496 lws_rewrite_parse(wsi->http.rw, (unsigned char *)*buf, n);
1497 else
1498 #endif
1499 {
1500 if (
1501 #if defined(LWS_WITH_HTTP_PROXY)
1502 !wsi->protocol_bind_balance ==
1503 !!wsi->http.proxy_clientside
1504 #else
1505 !!wsi->protocol_bind_balance
1506 #endif
1507 ) {
1508 int q;
1509
1510 q = user_callback_handle_rxflow(wsi->a.protocol->callback,
1511 wsi, LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ,
1512 wsi->user_space, *buf, (unsigned int)n);
1513 if (q) {
1514 lwsl_info("%s: RECEIVE_CLIENT_HTTP_READ returned %d\n",
1515 __func__, q);
1516
1517 return q;
1518 }
1519 } else
1520 lwsl_notice("%s: swallowed read (%d)\n", __func__, n);
1521 }
1522
1523 (*buf) += n;
1524 *len -= n;
1525 if (wsi->chunked && wsi->chunk_remaining)
1526 wsi->chunk_remaining -= n;
1527
1528 //lwsl_notice("chunk_remaining <- %d, block remaining %d\n",
1529 // wsi->chunk_remaining, *len);
1530
1531 consumed += n;
1532 //eb.token += n;
1533 //eb.len -= n;
1534
1535 if (wsi->chunked && !wsi->chunk_remaining)
1536 wsi->chunk_parser = ELCP_POST_CR;
1537
1538 if (wsi->chunked && *len)
1539 goto spin_chunks;
1540
1541 if (wsi->chunked)
1542 goto account_and_ret;
1543
1544 /* if we know the content length, decrement the content remaining */
1545 if (wsi->http.rx_content_length > 0)
1546 wsi->http.rx_content_remain -= (unsigned int)n;
1547
1548 // lwsl_notice("rx_content_remain %lld, rx_content_length %lld, giv %d\n",
1549 // wsi->http.rx_content_remain, wsi->http.rx_content_length,
1550 // wsi->http.content_length_given);
1551
1552 if (wsi->http.rx_content_remain || !wsi->http.content_length_given)
1553 goto account_and_ret;
1554
1555 completed:
1556
1557 if (lws_http_transaction_completed_client(wsi)) {
1558 lwsl_info("%s: transaction completed says -1\n", __func__);
1559 return -1;
1560 }
1561
1562 account_and_ret:
1563 // lwsl_warn("%s: on way out, consuming %d / %d\n", __func__, consumed, eb.len);
1564 if (lws_buflist_aware_finished_consuming(wsi, &eb, consumed, buffered,
1565 __func__))
1566 return -1;
1567
1568 return 0;
1569 }
1570
1571 #endif
1572
1573 static uint8_t hnames2[] = {
1574 _WSI_TOKEN_CLIENT_ORIGIN,
1575 _WSI_TOKEN_CLIENT_SENT_PROTOCOLS,
1576 _WSI_TOKEN_CLIENT_METHOD,
1577 _WSI_TOKEN_CLIENT_IFACE
1578 };
1579
1580 /**
1581 * lws_client_reset() - retarget a connected wsi to start over with a new
1582 * connection (ie, redirect)
1583 * this only works if still in HTTP, ie, not upgraded yet
1584 * wsi: connection to reset
1585 * address: network address of the new server
1586 * port: port to connect to
1587 * path: uri path to connect to on the new server
1588 * host: host header to send to the new server
1589 */
1590 struct lws *
lws_client_reset(struct lws ** pwsi,int ssl,const char * address,int port,const char * path,const char * host,char weak)1591 lws_client_reset(struct lws **pwsi, int ssl, const char *address, int port,
1592 const char *path, const char *host, char weak)
1593 {
1594 struct lws_context_per_thread *pt;
1595 #if defined(LWS_ROLE_WS)
1596 struct _lws_websocket_related *ws;
1597 #endif
1598 const char *cisin[CIS_COUNT];
1599 struct lws *wsi;
1600 size_t o;
1601 int n;
1602
1603 if (!pwsi)
1604 return NULL;
1605
1606 wsi = *pwsi;
1607 pt = &wsi->a.context->pt[(int)wsi->tsi];
1608
1609 lwsl_debug("%s: %s: redir %d: %s\n", __func__, lws_wsi_tag(wsi),
1610 wsi->redirects, address);
1611
1612 if (wsi->redirects == 4) {
1613 lwsl_err("%s: Too many redirects\n", __func__);
1614 return NULL;
1615 }
1616 wsi->redirects++;
1617
1618 /*
1619 * goal is to close our role part, close the sockfd, detach the ah
1620 * but leave our wsi extant and still bound to whatever vhost it was
1621 */
1622
1623 o = path[0] == '/' && path[1] == '/';
1624
1625 memset((char *)cisin, 0, sizeof(cisin));
1626
1627 cisin[CIS_ADDRESS] = address;
1628 cisin[CIS_PATH] = path + o;
1629 cisin[CIS_HOST] = host;
1630
1631 for (n = 0; n < (int)LWS_ARRAY_SIZE(hnames2); n++)
1632 cisin[n + 3] = lws_hdr_simple_ptr(wsi, hnames2[n]);
1633
1634 #if defined(LWS_WITH_TLS)
1635 cisin[CIS_ALPN] = wsi->alpn;
1636 #endif
1637
1638 if (lws_client_stash_create(wsi, cisin))
1639 return NULL;
1640
1641 if (!port) {
1642 lwsl_info("%s: forcing port 443\n", __func__);
1643
1644 port = 443;
1645 ssl = 1;
1646 }
1647
1648 wsi->c_port = (uint16_t)port;
1649
1650 wsi->flags = (wsi->flags & (~LCCSCF_USE_SSL)) |
1651 (ssl ? LCCSCF_USE_SSL : 0);
1652
1653 if (!cisin[CIS_ALPN] || !cisin[CIS_ALPN][0])
1654 #if defined(LWS_ROLE_H2)
1655 cisin[CIS_ALPN] = "h2,http/1.1";
1656 #else
1657 cisin[CIS_ALPN] = "http/1.1";
1658 #endif
1659
1660 lwsl_notice("%s: REDIRECT %s:%d, path='%s', ssl = %d, alpn='%s'\n",
1661 __func__, address, port, path, ssl, cisin[CIS_ALPN]);
1662
1663 lws_pt_lock(pt, __func__);
1664 __remove_wsi_socket_from_fds(wsi);
1665 lws_pt_unlock(pt);
1666
1667 #if defined(LWS_ROLE_WS)
1668 if (weak) {
1669 ws = wsi->ws;
1670 wsi->ws = NULL;
1671 }
1672 #endif
1673
1674 /*
1675 * After this point we can't trust the incoming strings like address,
1676 * path any more, since they may have been pointing into the old ah.
1677 *
1678 * We must use the copies in the wsi->stash instead if we want them.
1679 */
1680
1681 __lws_reset_wsi(wsi); /* detaches ah here */
1682 #if defined(LWS_ROLE_WS)
1683 if (weak)
1684 wsi->ws = ws;
1685 #endif
1686 wsi->client_pipeline = 1;
1687
1688 /*
1689 * Will complete at close flow
1690 */
1691
1692 wsi->close_is_redirect = 1;
1693
1694 return *pwsi;
1695 }
1696