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 #if defined(LWS_WITH_TLS)
28 int
lws_client_create_tls(struct lws * wsi,const char ** pcce,int do_c1)29 lws_client_create_tls(struct lws *wsi, const char **pcce, int do_c1)
30 {
31 int n;
32
33 /* we can retry this... just cook the SSL BIO the first time */
34
35 if (wsi->tls.use_ssl & LCCSCF_USE_SSL) {
36
37 if (!wsi->tls.ssl) {
38 if (lws_ssl_client_bio_create(wsi) < 0) {
39 *pcce = "bio_create failed";
40 return -1;
41 }
42
43 if (!wsi->transaction_from_pipeline_queue &&
44 lws_tls_restrict_borrow(wsi->context)) {
45 *pcce = "tls restriction limit";
46 return -1;
47 }
48 }
49
50 if (!do_c1)
51 return 0;
52
53 n = lws_ssl_client_connect1(wsi);
54 if (!n)
55 return 1; /* caller should return 0 */
56 if (n < 0) {
57 *pcce = "lws_ssl_client_connect1 failed";
58 return -1;
59 }
60 } else
61 wsi->tls.ssl = NULL;
62
63 #if defined (LWS_WITH_HTTP2)
64 if (wsi->client_h2_alpn) {
65 /*
66 * We connected to the server and set up tls, and
67 * negotiated "h2".
68 *
69 * So this is it, we are an h2 master client connection
70 * now, not an h1 client connection.
71 */
72 #if defined(LWS_WITH_TLS)
73 lws_tls_server_conn_alpn(wsi);
74 #endif
75
76 /* send the H2 preface to legitimize the connection */
77 if (lws_h2_issue_preface(wsi)) {
78 *pcce = "error sending h2 preface";
79 return -1;
80 }
81 }
82 #endif
83
84 return 0; /* OK */
85 }
86
87 #endif
88
89 void
lws_client_http_body_pending(struct lws * wsi,int something_left_to_send)90 lws_client_http_body_pending(struct lws *wsi, int something_left_to_send)
91 {
92 wsi->client_http_body_pending = !!something_left_to_send;
93 }
94
95 int
lws_client_socket_service(struct lws * wsi,struct lws_pollfd * pollfd)96 lws_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd)
97 {
98 struct lws_context *context = wsi->context;
99 struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
100 char *p = (char *)&pt->serv_buf[0];
101 #if defined(LWS_WITH_TLS)
102 char ebuf[128];
103 #endif
104 const char *cce = NULL;
105 char *sb = p;
106 int n = 0;
107
108 switch (lwsi_state(wsi)) {
109
110 case LRS_WAITING_DNS:
111 /*
112 * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
113 * timeout protection set in client-handshake.c
114 */
115 lwsl_err("%s: wsi %p: WAITING_DNS\n", __func__, wsi);
116 if (!lws_client_connect_2_dnsreq(wsi)) {
117 /* closed */
118 lwsl_client("closed\n");
119 return -1;
120 }
121
122 /* either still pending connection, or changed mode */
123 return 0;
124
125 case LRS_WAITING_CONNECT:
126
127 /*
128 * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
129 * timeout protection set in client-handshake.c
130 */
131 if (pollfd->revents & LWS_POLLOUT)
132 lws_client_connect_3_connect(wsi, NULL, NULL, 0, NULL);
133 break;
134
135 #if defined(LWS_WITH_SOCKS5)
136 /* SOCKS Greeting Reply */
137 case LRS_WAITING_SOCKS_GREETING_REPLY:
138 case LRS_WAITING_SOCKS_AUTH_REPLY:
139 case LRS_WAITING_SOCKS_CONNECT_REPLY:
140
141 switch (lws_socks5c_handle_state(wsi, pollfd, &cce)) {
142 case LW5CHS_RET_RET0:
143 return 0;
144 case LW5CHS_RET_BAIL3:
145 goto bail3;
146 case LW5CHS_RET_STARTHS:
147 goto start_ws_handshake;
148 default:
149 break;
150 }
151 break;
152 #endif
153
154 #if defined(LWS_CLIENT_HTTP_PROXYING) && (defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2))
155
156 case LRS_WAITING_PROXY_REPLY:
157
158 /* handle proxy hung up on us */
159
160 if (pollfd->revents & LWS_POLLHUP) {
161
162 lwsl_warn("Proxy connection %p (fd=%d) dead\n",
163 (void *)wsi, pollfd->fd);
164
165 cce = "proxy conn dead";
166 goto bail3;
167 }
168
169 n = recv(wsi->desc.sockfd, sb, context->pt_serv_buf_size, 0);
170 if (n < 0) {
171 if (LWS_ERRNO == LWS_EAGAIN) {
172 lwsl_debug("Proxy read EAGAIN... retrying\n");
173 return 0;
174 }
175 lwsl_err("ERROR reading from proxy socket\n");
176 cce = "proxy read err";
177 goto bail3;
178 }
179
180 pt->serv_buf[13] = '\0';
181 if (n < 13 || (strncmp(sb, "HTTP/1.0 200 ", 13) &&
182 strncmp(sb, "HTTP/1.1 200 ", 13))) {
183 lwsl_err("%s: ERROR proxy did not reply with h1\n",
184 __func__);
185 /* lwsl_hexdump_notice(sb, n); */
186 cce = "proxy not h1";
187 goto bail3;
188 }
189
190 lwsl_info("%s: proxy connection extablished\n", __func__);
191
192 /* clear his proxy connection timeout */
193
194 lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
195
196 /* fallthru */
197
198 #endif
199
200 case LRS_H1C_ISSUE_HANDSHAKE:
201
202 /*
203 * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
204 * timeout protection set in client-handshake.c
205 *
206 * take care of our lws_callback_on_writable
207 * happening at a time when there's no real connection yet
208 */
209 #if defined(LWS_WITH_SOCKS5)
210 start_ws_handshake:
211 #endif
212 if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
213 return -1;
214
215 #if defined(LWS_WITH_TLS)
216 n = lws_client_create_tls(wsi, &cce, 1);
217 if (n < 0)
218 goto bail3;
219 if (n == 1)
220 return 0;
221
222 /* fallthru */
223
224 case LRS_WAITING_SSL:
225
226 if (wsi->tls.use_ssl & LCCSCF_USE_SSL) {
227 n = lws_ssl_client_connect2(wsi, ebuf, sizeof(ebuf));
228 if (!n)
229 return 0;
230 if (n < 0) {
231 cce = ebuf;
232 goto bail3;
233 }
234 } else
235 wsi->tls.ssl = NULL;
236 #endif
237 #if defined(LWS_WITH_DETAILED_LATENCY)
238 if (context->detailed_latency_cb) {
239 wsi->detlat.type = LDLT_TLS_NEG_CLIENT;
240 wsi->detlat.latencies[LAT_DUR_PROXY_CLIENT_REQ_TO_WRITE] =
241 lws_now_usecs() -
242 wsi->detlat.earliest_write_req_pre_write;
243 wsi->detlat.latencies[LAT_DUR_USERCB] = 0;
244 lws_det_lat_cb(wsi->context, &wsi->detlat);
245 }
246 #endif
247 #if defined (LWS_WITH_HTTP2)
248 if (wsi->client_h2_alpn) {
249 /*
250 * We connected to the server and set up tls, and
251 * negotiated "h2".
252 *
253 * So this is it, we are an h2 master client connection
254 * now, not an h1 client connection.
255 */
256 #if defined(LWS_WITH_TLS)
257 lws_tls_server_conn_alpn(wsi);
258 #endif
259
260 /* send the H2 preface to legitimize the connection */
261 if (lws_h2_issue_preface(wsi)) {
262 cce = "error sending h2 preface";
263 goto bail3;
264 }
265
266 // lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE2);
267 lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND,
268 context->timeout_secs);
269
270 break;
271 }
272 #endif
273
274 /* fallthru */
275
276 case LRS_H1C_ISSUE_HANDSHAKE2:
277 p = lws_generate_client_handshake(wsi, p);
278 if (p == NULL) {
279 if (wsi->role_ops == &role_ops_raw_skt
280 #if defined(LWS_ROLE_RAW_FILE)
281 || wsi->role_ops == &role_ops_raw_file
282 #endif
283 )
284 return 0;
285
286 lwsl_err("Failed to generate handshake for client\n");
287 lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS,
288 "chs");
289 return 0;
290 }
291
292 /* send our request to the server */
293
294 lwsl_info("%s: HANDSHAKE2: %p: sending headers "
295 "(wsistate 0x%lx), w sock %d\n",
296 __func__, wsi, (unsigned long)wsi->wsistate,
297 wsi->desc.sockfd);
298 #if defined(LWS_WITH_DETAILED_LATENCY)
299 wsi->detlat.earliest_write_req_pre_write = lws_now_usecs();
300 #endif
301 n = lws_ssl_capable_write(wsi, (unsigned char *)sb, (int)(p - sb));
302 switch (n) {
303 case LWS_SSL_CAPABLE_ERROR:
304 lwsl_debug("ERROR writing to client socket\n");
305 lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS,
306 "cws");
307 return 0;
308 case LWS_SSL_CAPABLE_MORE_SERVICE:
309 lws_callback_on_writable(wsi);
310 break;
311 }
312
313 if (wsi->client_http_body_pending) {
314 lwsl_debug("body pending\n");
315 lwsi_set_state(wsi, LRS_ISSUE_HTTP_BODY);
316 lws_set_timeout(wsi,
317 PENDING_TIMEOUT_CLIENT_ISSUE_PAYLOAD,
318 context->timeout_secs);
319
320 if (wsi->flags & LCCSCF_HTTP_X_WWW_FORM_URLENCODED)
321 lws_callback_on_writable(wsi);
322 #if defined(LWS_WITH_HTTP_PROXY)
323 if (wsi->http.proxy_clientside)
324 lws_callback_on_writable(wsi);
325 #endif
326 /* user code must ask for writable callback */
327 break;
328 }
329
330 lwsi_set_state(wsi, LRS_WAITING_SERVER_REPLY);
331 wsi->hdr_parsing_completed = 0;
332
333 if (lwsi_state(wsi) == LRS_IDLING) {
334 lwsi_set_state(wsi, LRS_WAITING_SERVER_REPLY);
335 wsi->hdr_parsing_completed = 0;
336 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
337 wsi->http.ah->parser_state = WSI_TOKEN_NAME_PART;
338 wsi->http.ah->lextable_pos = 0;
339 #if defined(LWS_WITH_CUSTOM_HEADERS)
340 wsi->http.ah->unk_pos = 0;
341 #endif
342 /* If we're (re)starting on hdr, need other implied init */
343 wsi->http.ah->ues = URIES_IDLE;
344 #endif
345 }
346
347 lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE,
348 wsi->context->timeout_secs);
349
350 lws_callback_on_writable(wsi);
351
352 goto client_http_body_sent;
353
354 case LRS_ISSUE_HTTP_BODY:
355 #if defined(LWS_WITH_HTTP_PROXY)
356 if (wsi->http.proxy_clientside) {
357 lws_callback_on_writable(wsi);
358 break;
359 }
360 #endif
361 if (wsi->client_http_body_pending) {
362 //lws_set_timeout(wsi,
363 // PENDING_TIMEOUT_CLIENT_ISSUE_PAYLOAD,
364 // context->timeout_secs);
365 /* user code must ask for writable callback */
366 break;
367 }
368 client_http_body_sent:
369 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
370 /* prepare ourselves to do the parsing */
371 wsi->http.ah->parser_state = WSI_TOKEN_NAME_PART;
372 wsi->http.ah->lextable_pos = 0;
373 #if defined(LWS_WITH_CUSTOM_HEADERS)
374 wsi->http.ah->unk_pos = 0;
375 #endif
376 #endif
377 lwsi_set_state(wsi, LRS_WAITING_SERVER_REPLY);
378 lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE,
379 context->timeout_secs);
380 break;
381
382 case LRS_WAITING_SERVER_REPLY:
383 /*
384 * handle server hanging up on us...
385 * but if there is POLLIN waiting, handle that first
386 */
387 if ((pollfd->revents & (LWS_POLLIN | LWS_POLLHUP)) ==
388 LWS_POLLHUP) {
389
390 lwsl_debug("Server connection %p (fd=%d) dead\n",
391 (void *)wsi, pollfd->fd);
392 cce = "Peer hung up";
393 goto bail3;
394 }
395
396 if (!(pollfd->revents & LWS_POLLIN))
397 break;
398
399 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
400 /* interpret the server response
401 *
402 * HTTP/1.1 101 Switching Protocols
403 * Upgrade: websocket
404 * Connection: Upgrade
405 * Sec-WebSocket-Accept: me89jWimTRKTWwrS3aRrL53YZSo=
406 * Sec-WebSocket-Nonce: AQIDBAUGBwgJCgsMDQ4PEC==
407 * Sec-WebSocket-Protocol: chat
408 *
409 * we have to take some care here to only take from the
410 * socket bytewise. The browser may (and has been seen to
411 * in the case that onopen() performs websocket traffic)
412 * coalesce both handshake response and websocket traffic
413 * in one packet, since at that point the connection is
414 * definitively ready from browser pov.
415 */
416 while (wsi->http.ah->parser_state != WSI_PARSING_COMPLETE) {
417 struct lws_tokens eb;
418 int n, m, buffered;
419
420 eb.token = NULL;
421 eb.len = 0;
422 buffered = lws_buflist_aware_read(pt, wsi, &eb, 0, __func__);
423 lwsl_debug("%s: buflist-aware-read %d %d\n", __func__,
424 buffered, eb.len);
425 if (eb.len == LWS_SSL_CAPABLE_MORE_SERVICE)
426 return 0;
427 if (buffered < 0 || eb.len < 0) {
428 cce = "read failed";
429 goto bail3;
430 }
431 if (!eb.len)
432 return 0;
433
434 n = eb.len;
435 if (lws_parse(wsi, eb.token, &n)) {
436 lwsl_warn("problems parsing header\n");
437 cce = "problems parsing header";
438 goto bail3;
439 }
440
441 m = eb.len - n;
442 if (lws_buflist_aware_finished_consuming(wsi, &eb, m,
443 buffered,
444 __func__))
445 return -1;
446 eb.token += m;
447 eb.len -= m;
448
449 if (n) {
450 assert(wsi->http.ah->parser_state ==
451 WSI_PARSING_COMPLETE);
452
453 break;
454 }
455 }
456
457 /*
458 * hs may also be coming in multiple packets, there is a 5-sec
459 * libwebsocket timeout still active here too, so if parsing did
460 * not complete just wait for next packet coming in this state
461 */
462 if (wsi->http.ah->parser_state != WSI_PARSING_COMPLETE)
463 break;
464 #endif
465
466 /*
467 * otherwise deal with the handshake. If there's any
468 * packet traffic already arrived we'll trigger poll() again
469 * right away and deal with it that way
470 */
471 return lws_client_interpret_server_handshake(wsi);
472
473 bail3:
474 lwsl_info("closing conn at LWS_CONNMODE...SERVER_REPLY\n");
475 if (cce)
476 lwsl_info("reason: %s\n", cce);
477 lws_inform_client_conn_fail(wsi, (void *)cce, strlen(cce));
478
479 lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "cbail3");
480 return -1;
481
482 default:
483 break;
484 }
485
486 return 0;
487 }
488
489 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
490
491 int LWS_WARN_UNUSED_RESULT
lws_http_transaction_completed_client(struct lws * wsi)492 lws_http_transaction_completed_client(struct lws *wsi)
493 {
494 int n;
495
496 lwsl_info("%s: wsi: %p (%s)\n", __func__, wsi, wsi->protocol->name);
497
498 if (user_callback_handle_rxflow(wsi->protocol->callback, wsi,
499 LWS_CALLBACK_COMPLETED_CLIENT_HTTP,
500 wsi->user_space, NULL, 0)) {
501 lwsl_debug("%s: Completed call returned nonzero (role 0x%lx)\n",
502 __func__, (unsigned long)lwsi_role(wsi));
503 return -1;
504 }
505
506 wsi->http.rx_content_length = 0;
507
508 /*
509 * For h1, wsi may pass some assets on to a queued child and be
510 * destroyed during this.
511 */
512 n = _lws_generic_transaction_completed_active_conn(&wsi);
513
514 if (wsi->http.ah) {
515 if (wsi->client_mux_substream)
516 /*
517 * As an h2 client, once we did our transaction, that is
518 * it for us. Further transactions will happen as new
519 * SIDs on the connection.
520 */
521 __lws_header_table_detach(wsi, 0);
522 else
523 if (!n)
524 _lws_header_table_reset(wsi->http.ah);
525 }
526
527 if (!n || !wsi->http.ah)
528 return 0;
529
530 /*
531 * H1: we can serialize the queued guys into the same ah
532 * H2: everybody needs their own ah until their own STREAM_END
533 */
534
535 /* otherwise set ourselves up ready to go again */
536 lwsi_set_state(wsi, LRS_WAITING_SERVER_REPLY);
537
538 wsi->http.ah->parser_state = WSI_TOKEN_NAME_PART;
539 wsi->http.ah->lextable_pos = 0;
540 #if defined(LWS_WITH_CUSTOM_HEADERS)
541 wsi->http.ah->unk_pos = 0;
542 #endif
543
544 lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE,
545 wsi->context->timeout_secs);
546
547 /* If we're (re)starting on headers, need other implied init */
548 wsi->http.ah->ues = URIES_IDLE;
549 lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE2);
550
551 lwsl_info("%s: %p: new queued transaction\n", __func__, wsi);
552 lws_callback_on_writable(wsi);
553
554 return 0;
555 }
556
557 unsigned int
lws_http_client_http_response(struct lws * wsi)558 lws_http_client_http_response(struct lws *wsi)
559 {
560 if (wsi->http.ah && wsi->http.ah->http_response)
561 return wsi->http.ah->http_response;
562
563 return 0;
564 }
565 #endif
566
567 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
568
569 int
lws_http_is_redirected_to_get(struct lws * wsi)570 lws_http_is_redirected_to_get(struct lws *wsi)
571 {
572 return wsi->redirected_to_get;
573 }
574
575 int
lws_client_interpret_server_handshake(struct lws * wsi)576 lws_client_interpret_server_handshake(struct lws *wsi)
577 {
578 int n, port = 0, ssl = 0;
579 int close_reason = LWS_CLOSE_STATUS_PROTOCOL_ERR;
580 const char *prot, *ads = NULL, *path, *cce = NULL;
581 struct allocated_headers *ah, *ah1;
582 struct lws *nwsi = lws_get_network_wsi(wsi);
583 char *p = NULL, *q;
584 char new_path[300];
585
586 lws_free_set_NULL(wsi->stash);
587
588 ah = wsi->http.ah;
589 if (!wsi->do_ws) {
590 /* we are being an http client...
591 */
592 #if defined(LWS_ROLE_H2)
593 if (wsi->client_h2_alpn || wsi->client_mux_substream) {
594 lwsl_debug("%s: %p: transitioning to h2 client\n",
595 __func__, wsi);
596 lws_role_transition(wsi, LWSIFR_CLIENT,
597 LRS_ESTABLISHED, &role_ops_h2);
598 } else
599 #endif
600 {
601 #if defined(LWS_ROLE_H1)
602 {
603 lwsl_debug("%s: %p: transitioning to h1 client\n",
604 __func__, wsi);
605 lws_role_transition(wsi, LWSIFR_CLIENT,
606 LRS_ESTABLISHED, &role_ops_h1);
607 }
608 #else
609 return -1;
610 #endif
611 }
612
613 wsi->http.ah = ah;
614 ah->http_response = 0;
615 }
616
617 /*
618 * well, what the server sent looked reasonable for syntax.
619 * Now let's confirm it sent all the necessary headers
620 *
621 * http (non-ws) client will expect something like this
622 *
623 * HTTP/1.0.200
624 * server:.libwebsockets
625 * content-type:.text/html
626 * content-length:.17703
627 * set-cookie:.test=LWS_1456736240_336776_COOKIE;Max-Age=360000
628 */
629
630 wsi->http.conn_type = HTTP_CONNECTION_KEEP_ALIVE;
631 if (!wsi->client_mux_substream) {
632 p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP);
633 /*
634 if (wsi->do_ws && !p) {
635 lwsl_info("no URI\n");
636 cce = "HS: URI missing";
637 goto bail3;
638 }
639 */
640 if (!p) {
641 p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP1_0);
642 wsi->http.conn_type = HTTP_CONNECTION_CLOSE;
643 }
644 if (!p) {
645 cce = "HS: URI missing";
646 lwsl_info("no URI\n");
647 goto bail3;
648 }
649 #if defined(LWS_ROLE_H2)
650 } else {
651 p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_STATUS);
652 if (!p) {
653 cce = "HS: :status missing";
654 lwsl_info("no status\n");
655 goto bail3;
656 }
657 #endif
658 }
659 #if !defined(LWS_ROLE_H2)
660 if (!p) {
661 cce = "HS: :status missing";
662 lwsl_info("no status\n");
663 goto bail3;
664 }
665 #endif
666 n = atoi(p);
667 if (ah)
668 ah->http_response = n;
669
670 if (!wsi->client_no_follow_redirect &&
671 #if defined(LWS_WITH_HTTP_PROXY)
672 !wsi->http.proxy_clientside &&
673 #endif
674 (n == 301 || n == 302 || n == 303 || n == 307 || n == 308)) {
675 p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_LOCATION);
676 if (!p) {
677 cce = "HS: Redirect code but no Location";
678 goto bail3;
679 }
680
681 /*
682 * Some redirect codes imply we have to change the method
683 * used for the subsequent transaction, commonly POST ->
684 * 303 -> GET.
685 */
686
687 if (n == 303) {
688 char *mp = lws_hdr_simple_ptr(wsi,_WSI_TOKEN_CLIENT_METHOD);
689 int ml = lws_hdr_total_length(wsi, _WSI_TOKEN_CLIENT_METHOD);
690
691 if (ml >= 3 && mp) {
692 lwsl_info("%s: 303 switching to GET\n", __func__);
693 memcpy(mp, "GET", 4);
694 wsi->redirected_to_get = 1;
695 wsi->http.ah->frags[wsi->http.ah->frag_index[
696 _WSI_TOKEN_CLIENT_METHOD]].len = 3;
697 }
698 }
699
700 /* Relative reference absolute path */
701 if (p[0] == '/' || !strchr(p, ':')) {
702 #if defined(LWS_WITH_TLS)
703 ssl = nwsi->tls.use_ssl & LCCSCF_USE_SSL;
704 #endif
705 ads = lws_hdr_simple_ptr(wsi,
706 _WSI_TOKEN_CLIENT_PEER_ADDRESS);
707 port = nwsi->c_port;
708 path = p;
709 /* lws_client_reset expects leading / omitted */
710 if (*path == '/')
711 path++;
712 }
713 /* Absolute (Full) URI */
714 else if (strchr(p, ':')) {
715 if (lws_parse_uri(p, &prot, &ads, &port, &path)) {
716 cce = "HS: URI did not parse";
717 goto bail3;
718 }
719
720 if (!strcmp(prot, "wss") || !strcmp(prot, "https"))
721 ssl = LCCSCF_USE_SSL;
722 }
723 /* Relative reference relative path */
724 else {
725 /* This doesn't try to calculate an absolute path,
726 * that will be left to the server */
727 #if defined(LWS_WITH_TLS)
728 ssl = nwsi->tls.use_ssl & LCCSCF_USE_SSL;
729 #endif
730 ads = lws_hdr_simple_ptr(wsi,
731 _WSI_TOKEN_CLIENT_PEER_ADDRESS);
732 port = wsi->c_port;
733 /* +1 as lws_client_reset expects leading / omitted */
734 path = new_path + 1;
735 if (lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_URI))
736 lws_strncpy(new_path, lws_hdr_simple_ptr(wsi,
737 _WSI_TOKEN_CLIENT_URI), sizeof(new_path));
738 else {
739 new_path[0] = '/';
740 new_path[1] = '\0';
741 }
742 q = strrchr(new_path, '/');
743 if (q)
744 lws_strncpy(q + 1, p, sizeof(new_path) -
745 (q - new_path) - 1);
746 else
747 path = p;
748 }
749
750 #if defined(LWS_WITH_TLS)
751 if ((wsi->tls.use_ssl & LCCSCF_USE_SSL) && !ssl) {
752 cce = "HS: Redirect attempted SSL downgrade";
753 goto bail3;
754 }
755 #endif
756
757 if (!ads) /* make coverity happy */ {
758 cce = "no ads";
759 goto bail3;
760 }
761
762 if (!lws_client_reset(&wsi, ssl, ads, port, path, ads, 1)) {
763 /*
764 * There are two ways to fail out with NULL return...
765 * simple, early problem where the wsi is intact, or
766 * we went through with the reconnect attempt and the
767 * wsi is already closed. In the latter case, the wsi
768 * has been set to NULL additionally.
769 */
770 lwsl_err("Redirect failed\n");
771 cce = "HS: Redirect failed";
772 /* coverity[reverse_inull] */
773 if (wsi)
774 goto bail3;
775
776 /* wsi has closed */
777 return 1;
778 }
779 return 0;
780 }
781
782 if (!wsi->do_ws) {
783
784 /* if h1 KA is allowed, enable the queued pipeline guys */
785
786 if (!wsi->client_h2_alpn && !wsi->client_mux_substream) {
787 /* ie, coming to this for the first time */
788 if (wsi->http.conn_type == HTTP_CONNECTION_KEEP_ALIVE)
789 wsi->keepalive_active = 1;
790 else {
791 /*
792 * Ugh... now the main http connection has seen
793 * both sides, we learn the server doesn't
794 * support keepalive.
795 *
796 * That means any guys queued on us are going
797 * to have to be restarted from connect2 with
798 * their own connections.
799 */
800
801 /*
802 * stick around telling any new guys they can't
803 * pipeline to this server
804 */
805 wsi->keepalive_rejected = 1;
806
807 lws_vhost_lock(wsi->vhost);
808 lws_start_foreach_dll_safe(struct lws_dll2 *,
809 d, d1,
810 wsi->dll2_cli_txn_queue_owner.head) {
811 struct lws *ww = lws_container_of(d,
812 struct lws,
813 dll2_cli_txn_queue);
814
815 /* remove him from our queue */
816 lws_dll2_remove(&ww->dll2_cli_txn_queue);
817 /* give up on pipelining */
818 ww->client_pipeline = 0;
819
820 /* go back to "trying to connect" state */
821 lws_role_transition(ww, LWSIFR_CLIENT,
822 LRS_UNCONNECTED,
823 #if defined(LWS_ROLE_H1)
824 &role_ops_h1);
825 #else
826 #if defined (LWS_ROLE_H2)
827 &role_ops_h2);
828 #else
829 &role_ops_raw);
830 #endif
831 #endif
832 ww->user_space = NULL;
833 } lws_end_foreach_dll_safe(d, d1);
834 lws_vhost_unlock(wsi->vhost);
835 }
836 }
837
838 #ifdef LWS_WITH_HTTP_PROXY
839 wsi->http.perform_rewrite = 0;
840 if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE)) {
841 if (!strncmp(lws_hdr_simple_ptr(wsi,
842 WSI_TOKEN_HTTP_CONTENT_TYPE),
843 "text/html", 9))
844 wsi->http.perform_rewrite = 0;
845 }
846 #endif
847
848 /* allocate the per-connection user memory (if any) */
849 if (lws_ensure_user_space(wsi)) {
850 lwsl_err("Problem allocating wsi user mem\n");
851 cce = "HS: OOM";
852 goto bail2;
853 }
854
855 /* he may choose to send us stuff in chunked transfer-coding */
856 wsi->chunked = 0;
857 wsi->chunk_remaining = 0; /* ie, next thing is chunk size */
858 if (lws_hdr_total_length(wsi,
859 WSI_TOKEN_HTTP_TRANSFER_ENCODING)) {
860 wsi->chunked = !strcmp(lws_hdr_simple_ptr(wsi,
861 WSI_TOKEN_HTTP_TRANSFER_ENCODING),
862 "chunked");
863 /* first thing is hex, after payload there is crlf */
864 wsi->chunk_parser = ELCP_HEX;
865 }
866
867 wsi->http.content_length_given = 0;
868 if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH)) {
869 wsi->http.rx_content_length =
870 atoll(lws_hdr_simple_ptr(wsi,
871 WSI_TOKEN_HTTP_CONTENT_LENGTH));
872 lwsl_info("%s: incoming content length %llu\n",
873 __func__, (unsigned long long)
874 wsi->http.rx_content_length);
875 wsi->http.rx_content_remain =
876 wsi->http.rx_content_length;
877 wsi->http.content_length_given = 1;
878 } else { /* can't do 1.1 without a content length or chunked */
879 if (!wsi->chunked)
880 wsi->http.conn_type = HTTP_CONNECTION_CLOSE;
881 lwsl_debug("%s: no content length\n", __func__);
882 }
883
884 /*
885 * we seem to be good to go, give client last chance to check
886 * headers and OK it
887 */
888 ah1 = wsi->http.ah;
889 wsi->http.ah = ah;
890 if (wsi->protocol->callback(wsi,
891 LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH,
892 wsi->user_space, NULL, 0)) {
893 wsi->http.ah = ah1;
894 cce = "HS: disallowed by client filter";
895 goto bail2;
896 }
897
898 /* clear his proxy connection timeout */
899 lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
900
901 wsi->rxflow_change_to = LWS_RXFLOW_ALLOW;
902
903 /* call him back to inform him he is up */
904 if (wsi->protocol->callback(wsi,
905 LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP,
906 wsi->user_space, NULL, 0)) {
907 wsi->http.ah = ah1;
908 cce = "HS: disallowed at ESTABLISHED";
909 goto bail3;
910 }
911
912 wsi->http.ah = ah1;
913
914 lwsl_info("%s: client connection up\n", __func__);
915
916 /*
917 * Did we get a response from the server with an explicit
918 * content-length of zero? If so, this transaction is already
919 * completed at the end of the header processing...
920 */
921 if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH) &&
922 !wsi->http.rx_content_length)
923 return !!lws_http_transaction_completed_client(wsi);
924
925 return 0;
926 }
927
928 #if defined(LWS_ROLE_WS)
929 switch (lws_client_ws_upgrade(wsi, &cce)) {
930 case 2:
931 goto bail2;
932 case 3:
933 goto bail3;
934 }
935
936 return 0;
937 #endif
938
939 bail3:
940 close_reason = LWS_CLOSE_STATUS_NOSTATUS;
941
942 bail2:
943 if (wsi->protocol) {
944 n = 0;
945 if (cce)
946 n = (int)strlen(cce);
947
948 lws_inform_client_conn_fail(wsi, (void *)cce, (unsigned int)n);
949 }
950
951 lwsl_info("closing connection (prot %s) "
952 "due to bail2 connection error: %s\n", wsi->protocol ?
953 wsi->protocol->name : "unknown", cce);
954
955 /* closing will free up his parsing allocations */
956 lws_close_free_wsi(wsi, close_reason, "c hs interp");
957
958 return 1;
959 }
960 #endif
961
962 /*
963 * set the boundary string and the content-type for client multipart mime
964 */
965
966 uint8_t *
lws_http_multipart_headers(struct lws * wsi,uint8_t * p)967 lws_http_multipart_headers(struct lws *wsi, uint8_t *p)
968 {
969 char buf[10], arg[48];
970 int n;
971
972 lws_get_random(wsi->context, (uint8_t *)buf, sizeof(buf));
973 lws_b64_encode_string(buf, sizeof(buf),
974 wsi->http.multipart_boundary,
975 sizeof(wsi->http.multipart_boundary));
976
977 n = lws_snprintf(arg, sizeof(arg), "multipart/form-data; boundary=%s",
978 wsi->http.multipart_boundary);
979
980 if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
981 (uint8_t *)arg, n, &p, p + 100))
982 return NULL;
983
984 wsi->http.multipart = wsi->http.multipart_issue_boundary = 1;
985 lws_client_http_body_pending(wsi, 1);
986
987 return p;
988 }
989
990 int
lws_client_http_multipart(struct lws * wsi,const char * name,const char * filename,const char * content_type,char ** p,char * end)991 lws_client_http_multipart(struct lws *wsi, const char *name,
992 const char *filename, const char *content_type,
993 char **p, char *end)
994 {
995 /*
996 * Client conn must have been created with LCCSCF_HTTP_MULTIPART_MIME
997 * flag to use this api
998 */
999 assert(wsi->http.multipart);
1000
1001 if (!name) {
1002 *p += lws_snprintf((char *)(*p), lws_ptr_diff(end, p),
1003 "\xd\xa--%s--\xd\xa",
1004 wsi->http.multipart_boundary);
1005
1006 return 0;
1007 }
1008
1009 if (wsi->client_subsequent_mime_part)
1010 *p += lws_snprintf((char *)(*p), lws_ptr_diff(end, p), "\xd\xa");
1011 wsi->client_subsequent_mime_part = 1;
1012
1013 *p += lws_snprintf((char *)(*p), lws_ptr_diff(end, p), "--%s\xd\xa"
1014 "Content-Disposition: form-data; "
1015 "name=\"%s\"",
1016 wsi->http.multipart_boundary, name);
1017 if (filename)
1018 *p += lws_snprintf((char *)(*p), lws_ptr_diff(end, p),
1019 "; filename=\"%s\"", filename);
1020
1021 if (content_type)
1022 *p += lws_snprintf((char *)(*p), lws_ptr_diff(end, p), "\xd\xa"
1023 "Content-Type: %s", content_type);
1024
1025 *p += lws_snprintf((char *)(*p), lws_ptr_diff(end, p), "\xd\xa\xd\xa");
1026
1027 return *p == end;
1028 }
1029
1030 char *
lws_generate_client_handshake(struct lws * wsi,char * pkt)1031 lws_generate_client_handshake(struct lws *wsi, char *pkt)
1032 {
1033 const char *meth, *pp = lws_hdr_simple_ptr(wsi,
1034 _WSI_TOKEN_CLIENT_SENT_PROTOCOLS);
1035 char *p = pkt, *p1;
1036
1037 meth = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_METHOD);
1038 if (!meth) {
1039 meth = "GET";
1040 wsi->do_ws = 1;
1041 } else {
1042 wsi->do_ws = 0;
1043 }
1044
1045 if (!strcmp(meth, "RAW")) {
1046 lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
1047 lwsl_notice("client transition to raw\n");
1048
1049 if (pp) {
1050 const struct lws_protocols *pr;
1051
1052 pr = lws_vhost_name_to_protocol(wsi->vhost, pp);
1053
1054 if (!pr) {
1055 lwsl_err("protocol %s not enabled on vhost\n",
1056 pp);
1057 return NULL;
1058 }
1059
1060 lws_bind_protocol(wsi, pr, __func__);
1061 }
1062
1063 if ((wsi->protocol->callback)(wsi, LWS_CALLBACK_RAW_ADOPT,
1064 wsi->user_space, NULL, 0))
1065 return NULL;
1066
1067 lws_role_transition(wsi, LWSIFR_CLIENT, LRS_ESTABLISHED,
1068 &role_ops_raw_skt);
1069 lws_header_table_detach(wsi, 1);
1070
1071 return NULL;
1072 }
1073
1074 /*
1075 * 04 example client handshake
1076 *
1077 * GET /chat HTTP/1.1
1078 * Host: server.example.com
1079 * Upgrade: websocket
1080 * Connection: Upgrade
1081 * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
1082 * Sec-WebSocket-Origin: http://example.com
1083 * Sec-WebSocket-Protocol: chat, superchat
1084 * Sec-WebSocket-Version: 4
1085 */
1086
1087 p += lws_snprintf(p, 2048, "%s %s HTTP/1.1\x0d\x0a", meth,
1088 lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_URI));
1089
1090 p += lws_snprintf(p, 64, "Pragma: no-cache\x0d\x0a"
1091 "Cache-Control: no-cache\x0d\x0a");
1092
1093 p += lws_snprintf(p, 128, "Host: %s\x0d\x0a",
1094 lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_HOST));
1095
1096 if (lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN)) {
1097 if (lws_check_opt(wsi->context->options,
1098 LWS_SERVER_OPTION_JUST_USE_RAW_ORIGIN))
1099 p += lws_snprintf(p, 128, "Origin: %s\x0d\x0a",
1100 lws_hdr_simple_ptr(wsi,
1101 _WSI_TOKEN_CLIENT_ORIGIN));
1102 else
1103 p += lws_snprintf(p, 128, "Origin: http://%s\x0d\x0a",
1104 lws_hdr_simple_ptr(wsi,
1105 _WSI_TOKEN_CLIENT_ORIGIN));
1106 }
1107
1108 if (wsi->flags & LCCSCF_HTTP_MULTIPART_MIME) {
1109 p1 = (char *)lws_http_multipart_headers(wsi, (uint8_t *)p);
1110 if (!p1)
1111 return NULL;
1112 p = p1;
1113 }
1114
1115 #if defined(LWS_WITH_HTTP_PROXY)
1116 if (wsi->parent &&
1117 lws_hdr_total_length(wsi->parent, WSI_TOKEN_HTTP_CONTENT_LENGTH)) {
1118 p += lws_snprintf(p, 128, "Content-Length: %s\x0d\x0a",
1119 lws_hdr_simple_ptr(wsi->parent, WSI_TOKEN_HTTP_CONTENT_LENGTH));
1120 if (atoi(lws_hdr_simple_ptr(wsi->parent, WSI_TOKEN_HTTP_CONTENT_LENGTH)))
1121 wsi->client_http_body_pending = 1;
1122 }
1123 if (wsi->parent &&
1124 lws_hdr_total_length(wsi->parent, WSI_TOKEN_HTTP_AUTHORIZATION)) {
1125 p += lws_snprintf(p, 128, "Authorization: %s\x0d\x0a",
1126 lws_hdr_simple_ptr(wsi->parent, WSI_TOKEN_HTTP_AUTHORIZATION));
1127 }
1128 if (wsi->parent &&
1129 lws_hdr_total_length(wsi->parent, WSI_TOKEN_HTTP_CONTENT_TYPE)) {
1130 p += lws_snprintf(p, 128, "Content-Type: %s\x0d\x0a",
1131 lws_hdr_simple_ptr(wsi->parent, WSI_TOKEN_HTTP_CONTENT_TYPE));
1132 }
1133 #endif
1134
1135 #if defined(LWS_ROLE_WS)
1136 if (wsi->do_ws) {
1137 const char *conn1 = "";
1138 // if (!wsi->client_pipeline)
1139 // conn1 = "close, ";
1140 p = lws_generate_client_ws_handshake(wsi, p, conn1);
1141 } else
1142 #endif
1143 {
1144 if (!wsi->client_pipeline)
1145 p += lws_snprintf(p, 64, "connection: close\x0d\x0a");
1146 }
1147
1148 /* give userland a chance to append, eg, cookies */
1149
1150 if (wsi->protocol->callback(wsi,
1151 LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER,
1152 wsi->user_space, &p,
1153 (pkt + wsi->context->pt_serv_buf_size) - p - 12))
1154 return NULL;
1155
1156 if (wsi->flags & LCCSCF_HTTP_X_WWW_FORM_URLENCODED) {
1157 p += lws_snprintf(p, 128, "Content-Type: application/x-www-form-urlencoded\x0d\x0a");
1158 p += lws_snprintf(p, 128, "Content-Length: %lu\x0d\x0a", wsi->http.writeable_len);
1159 lws_client_http_body_pending(wsi, 1);
1160 }
1161
1162 p += lws_snprintf(p, 4, "\x0d\x0a");
1163
1164 if (wsi->client_http_body_pending)
1165 lws_callback_on_writable(wsi);
1166
1167 // puts(pkt);
1168
1169 return p;
1170 }
1171
1172 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
1173 #if defined(LWS_WITH_HTTP_BASIC_AUTH)
1174
1175 int
lws_http_basic_auth_gen(const char * user,const char * pw,char * buf,size_t len)1176 lws_http_basic_auth_gen(const char *user, const char *pw, char *buf, size_t len)
1177 {
1178 size_t n = strlen(user), m = strlen(pw);
1179 char b[128];
1180
1181 if (len < 6 + ((4 * (n + m + 1)) / 3) + 1)
1182 return 1;
1183
1184 memcpy(buf, "Basic ", 6);
1185
1186 n = lws_snprintf(b, sizeof(b), "%s:%s", user, pw);
1187 if (n >= sizeof(b) - 2)
1188 return 2;
1189
1190 lws_b64_encode_string(b, (int)n, buf + 6, (int)len - 6);
1191 buf[len - 1] = '\0';
1192
1193 return 0;
1194 }
1195
1196 #endif
1197
1198 int
lws_http_client_read(struct lws * wsi,char ** buf,int * len)1199 lws_http_client_read(struct lws *wsi, char **buf, int *len)
1200 {
1201 struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
1202 struct lws_tokens eb;
1203 int buffered, n, consumed = 0;
1204
1205 /*
1206 * If the caller provided a non-NULL *buf and nonzero *len, we should
1207 * use that as the buffer for the read action, limititing it to *len
1208 * (actual payload will be less if chunked headers inside).
1209 *
1210 * If it's NULL / 0 length, buflist_aware_read will use the pt_serv_buf
1211 */
1212
1213 eb.token = (unsigned char *)*buf;
1214 eb.len = *len;
1215
1216 buffered = lws_buflist_aware_read(pt, wsi, &eb, 0, __func__);
1217 *buf = (char *)eb.token; /* may be pointing to buflist or pt_serv_buf */
1218 *len = 0;
1219
1220 /*
1221 * we're taking on responsibility for handling used / unused eb
1222 * when we leave, via lws_buflist_aware_finished_consuming()
1223 */
1224
1225 // lwsl_notice("%s: eb.len %d ENTRY chunk remaining %d\n", __func__, eb.len,
1226 // wsi->chunk_remaining);
1227
1228 /* allow the source to signal he has data again next time */
1229 if (lws_change_pollfd(wsi, 0, LWS_POLLIN))
1230 return -1;
1231
1232 if (buffered < 0) {
1233 lwsl_debug("%s: SSL capable error\n", __func__);
1234 return -1;
1235 }
1236
1237 if (eb.len <= 0)
1238 return 0;
1239
1240 *len = eb.len;
1241 wsi->client_rx_avail = 0;
1242
1243 /*
1244 * server may insist on transfer-encoding: chunked,
1245 * so http client must deal with it
1246 */
1247 spin_chunks:
1248 //lwsl_notice("%s: len %d SPIN chunk remaining %d\n", __func__, *len,
1249 // wsi->chunk_remaining);
1250 while (wsi->chunked && (wsi->chunk_parser != ELCP_CONTENT) && *len) {
1251 switch (wsi->chunk_parser) {
1252 case ELCP_HEX:
1253 if ((*buf)[0] == '\x0d') {
1254 wsi->chunk_parser = ELCP_CR;
1255 break;
1256 }
1257 n = char_to_hex((*buf)[0]);
1258 if (n < 0) {
1259 lwsl_err("%s: chunking failure A\n", __func__);
1260 return -1;
1261 }
1262 wsi->chunk_remaining <<= 4;
1263 wsi->chunk_remaining |= n;
1264 break;
1265 case ELCP_CR:
1266 if ((*buf)[0] != '\x0a') {
1267 lwsl_err("%s: chunking failure B\n", __func__);
1268 return -1;
1269 }
1270 if (wsi->chunk_remaining) {
1271 wsi->chunk_parser = ELCP_CONTENT;
1272 //lwsl_notice("starting chunk size %d (block rem %d)\n",
1273 // wsi->chunk_remaining, *len);
1274 break;
1275 }
1276
1277 wsi->chunk_parser = ELCP_TRAILER_CR;
1278 break;
1279
1280 case ELCP_CONTENT:
1281 break;
1282
1283 case ELCP_POST_CR:
1284 if ((*buf)[0] != '\x0d') {
1285 lwsl_err("%s: chunking failure C\n", __func__);
1286 lwsl_hexdump_err(*buf, *len);
1287
1288 return -1;
1289 }
1290
1291 wsi->chunk_parser = ELCP_POST_LF;
1292 break;
1293
1294 case ELCP_POST_LF:
1295 if ((*buf)[0] != '\x0a') {
1296 lwsl_err("%s: chunking failure D\n", __func__);
1297
1298 return -1;
1299 }
1300
1301 wsi->chunk_parser = ELCP_HEX;
1302 wsi->chunk_remaining = 0;
1303 break;
1304
1305 case ELCP_TRAILER_CR:
1306 if ((*buf)[0] != '\x0d') {
1307 lwsl_err("%s: chunking failure F\n", __func__);
1308 lwsl_hexdump_err(*buf, *len);
1309
1310 return -1;
1311 }
1312
1313 wsi->chunk_parser = ELCP_TRAILER_LF;
1314 break;
1315
1316 case ELCP_TRAILER_LF:
1317 if ((*buf)[0] != '\x0a') {
1318 lwsl_err("%s: chunking failure F\n", __func__);
1319 lwsl_hexdump_err(*buf, *len);
1320
1321 return -1;
1322 }
1323
1324 (*buf)++;
1325 (*len)--;
1326 consumed++;
1327
1328 lwsl_info("final chunk\n");
1329 goto completed;
1330 }
1331 (*buf)++;
1332 (*len)--;
1333 consumed++;
1334 }
1335
1336 if (wsi->chunked && !wsi->chunk_remaining)
1337 goto account_and_ret;
1338
1339 if (wsi->http.rx_content_remain &&
1340 wsi->http.rx_content_remain < (unsigned int)*len)
1341 n = (int)wsi->http.rx_content_remain;
1342 else
1343 n = *len;
1344
1345 if (wsi->chunked && wsi->chunk_remaining &&
1346 wsi->chunk_remaining < n)
1347 n = wsi->chunk_remaining;
1348
1349 #if defined(LWS_WITH_HTTP_PROXY) && defined(LWS_WITH_HUBBUB)
1350 /* hubbub */
1351 if (wsi->http.perform_rewrite)
1352 lws_rewrite_parse(wsi->http.rw, (unsigned char *)*buf, n);
1353 else
1354 #endif
1355 {
1356 if (
1357 #if defined(LWS_WITH_HTTP_PROXY)
1358 !wsi->protocol_bind_balance ==
1359 !!wsi->http.proxy_clientside
1360 #else
1361 !!wsi->protocol_bind_balance
1362 #endif
1363 ) {
1364 if (user_callback_handle_rxflow(wsi->protocol->callback,
1365 wsi, LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ,
1366 wsi->user_space, *buf, n)) {
1367 lwsl_info("%s: RECEIVE_CLIENT_HTTP_READ returned -1\n",
1368 __func__);
1369
1370 return -1;
1371 }
1372 } else
1373 lwsl_notice("%s: swallowed read (%d)\n", __func__, n);
1374 }
1375
1376 (*buf) += n;
1377 *len -= n;
1378 if (wsi->chunked && wsi->chunk_remaining)
1379 wsi->chunk_remaining -= n;
1380
1381 //lwsl_notice("chunk_remaining <- %d, block remaining %d\n",
1382 // wsi->chunk_remaining, *len);
1383
1384 consumed += n;
1385 //eb.token += n;
1386 //eb.len -= n;
1387
1388 if (wsi->chunked && !wsi->chunk_remaining)
1389 wsi->chunk_parser = ELCP_POST_CR;
1390
1391 if (wsi->chunked && *len)
1392 goto spin_chunks;
1393
1394 if (wsi->chunked)
1395 goto account_and_ret;
1396
1397 /* if we know the content length, decrement the content remaining */
1398 if (wsi->http.rx_content_length > 0)
1399 wsi->http.rx_content_remain -= n;
1400
1401 // lwsl_notice("rx_content_remain %lld, rx_content_length %lld, giv %d\n",
1402 // wsi->http.rx_content_remain, wsi->http.rx_content_length,
1403 // wsi->http.content_length_given);
1404
1405 if (wsi->http.rx_content_remain || !wsi->http.content_length_given)
1406 goto account_and_ret;
1407
1408 completed:
1409
1410 if (lws_http_transaction_completed_client(wsi)) {
1411 lwsl_notice("%s: transaction completed says -1\n", __func__);
1412 return -1;
1413 }
1414
1415 account_and_ret:
1416 // lwsl_warn("%s: on way out, consuming %d / %d\n", __func__, consumed, eb.len);
1417 if (lws_buflist_aware_finished_consuming(wsi, &eb, consumed, buffered,
1418 __func__))
1419 return -1;
1420
1421 return 0;
1422 }
1423
1424 #endif
1425