1d4afb5ceSopenharmony_ci/* 2d4afb5ceSopenharmony_ci * libwebsockets - small server side websockets and web server implementation 3d4afb5ceSopenharmony_ci * 4d4afb5ceSopenharmony_ci * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com> 5d4afb5ceSopenharmony_ci * 6d4afb5ceSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 7d4afb5ceSopenharmony_ci * of this software and associated documentation files (the "Software"), to 8d4afb5ceSopenharmony_ci * deal in the Software without restriction, including without limitation the 9d4afb5ceSopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10d4afb5ceSopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is 11d4afb5ceSopenharmony_ci * furnished to do so, subject to the following conditions: 12d4afb5ceSopenharmony_ci * 13d4afb5ceSopenharmony_ci * The above copyright notice and this permission notice shall be included in 14d4afb5ceSopenharmony_ci * all copies or substantial portions of the Software. 15d4afb5ceSopenharmony_ci * 16d4afb5ceSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17d4afb5ceSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18d4afb5ceSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19d4afb5ceSopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20d4afb5ceSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21d4afb5ceSopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22d4afb5ceSopenharmony_ci * IN THE SOFTWARE. 23d4afb5ceSopenharmony_ci */ 24d4afb5ceSopenharmony_ci 25d4afb5ceSopenharmony_ci#include <private-lib-core.h> 26d4afb5ceSopenharmony_ci 27d4afb5ceSopenharmony_ci#ifndef min 28d4afb5ceSopenharmony_ci#define min(a, b) ((a) < (b) ? (a) : (b)) 29d4afb5ceSopenharmony_ci#endif 30d4afb5ceSopenharmony_ci 31d4afb5ceSopenharmony_ci 32d4afb5ceSopenharmony_ci/* 33d4afb5ceSopenharmony_ci * We have to take care about parsing because the headers may be split 34d4afb5ceSopenharmony_ci * into multiple fragments. They may contain unknown headers with arbitrary 35d4afb5ceSopenharmony_ci * argument lengths. So, we parse using a single-character at a time state 36d4afb5ceSopenharmony_ci * machine that is completely independent of packet size. 37d4afb5ceSopenharmony_ci * 38d4afb5ceSopenharmony_ci * Returns <0 for error or length of chars consumed from buf (up to len) 39d4afb5ceSopenharmony_ci */ 40d4afb5ceSopenharmony_ci 41d4afb5ceSopenharmony_ciint 42d4afb5ceSopenharmony_cilws_read_h1(struct lws *wsi, unsigned char *buf, lws_filepos_t len) 43d4afb5ceSopenharmony_ci{ 44d4afb5ceSopenharmony_ci unsigned char *last_char, *oldbuf = buf; 45d4afb5ceSopenharmony_ci lws_filepos_t body_chunk_len; 46d4afb5ceSopenharmony_ci size_t n; 47d4afb5ceSopenharmony_ci 48d4afb5ceSopenharmony_ci lwsl_debug("%s: h1 path: wsi state 0x%x\n", __func__, lwsi_state(wsi)); 49d4afb5ceSopenharmony_ci 50d4afb5ceSopenharmony_ci switch (lwsi_state(wsi)) { 51d4afb5ceSopenharmony_ci 52d4afb5ceSopenharmony_ci case LRS_ISSUING_FILE: 53d4afb5ceSopenharmony_ci return 0; 54d4afb5ceSopenharmony_ci 55d4afb5ceSopenharmony_ci case LRS_ESTABLISHED: 56d4afb5ceSopenharmony_ci 57d4afb5ceSopenharmony_ci if (lwsi_role_ws(wsi)) 58d4afb5ceSopenharmony_ci goto ws_mode; 59d4afb5ceSopenharmony_ci 60d4afb5ceSopenharmony_ci if (lwsi_role_client(wsi)) 61d4afb5ceSopenharmony_ci break; 62d4afb5ceSopenharmony_ci 63d4afb5ceSopenharmony_ci wsi->hdr_parsing_completed = 0; 64d4afb5ceSopenharmony_ci 65d4afb5ceSopenharmony_ci /* fallthru */ 66d4afb5ceSopenharmony_ci 67d4afb5ceSopenharmony_ci case LRS_HEADERS: 68d4afb5ceSopenharmony_ci if (!wsi->http.ah) { 69d4afb5ceSopenharmony_ci lwsl_err("%s: LRS_HEADERS: NULL ah\n", __func__); 70d4afb5ceSopenharmony_ci assert(0); 71d4afb5ceSopenharmony_ci } 72d4afb5ceSopenharmony_ci lwsl_parser("issuing %d bytes to parser\n", (int)len); 73d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_WS) && defined(LWS_WITH_CLIENT) 74d4afb5ceSopenharmony_ci if (lws_ws_handshake_client(wsi, &buf, (size_t)len)) 75d4afb5ceSopenharmony_ci goto bail; 76d4afb5ceSopenharmony_ci#endif 77d4afb5ceSopenharmony_ci last_char = buf; 78d4afb5ceSopenharmony_ci if (lws_handshake_server(wsi, &buf, (size_t)len)) 79d4afb5ceSopenharmony_ci /* Handshake indicates this session is done. */ 80d4afb5ceSopenharmony_ci goto bail; 81d4afb5ceSopenharmony_ci 82d4afb5ceSopenharmony_ci /* we might have transitioned to RAW */ 83d4afb5ceSopenharmony_ci if (wsi->role_ops == &role_ops_raw_skt 84d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_RAW_FILE) 85d4afb5ceSopenharmony_ci || 86d4afb5ceSopenharmony_ci wsi->role_ops == &role_ops_raw_file 87d4afb5ceSopenharmony_ci#endif 88d4afb5ceSopenharmony_ci ) 89d4afb5ceSopenharmony_ci /* we gave the read buffer to RAW handler already */ 90d4afb5ceSopenharmony_ci goto read_ok; 91d4afb5ceSopenharmony_ci 92d4afb5ceSopenharmony_ci /* 93d4afb5ceSopenharmony_ci * It's possible that we've exhausted our data already, or 94d4afb5ceSopenharmony_ci * rx flow control has stopped us dealing with this early, 95d4afb5ceSopenharmony_ci * but lws_handshake_server doesn't update len for us. 96d4afb5ceSopenharmony_ci * Figure out how much was read, so that we can proceed 97d4afb5ceSopenharmony_ci * appropriately: 98d4afb5ceSopenharmony_ci */ 99d4afb5ceSopenharmony_ci len -= (unsigned int)lws_ptr_diff(buf, last_char); 100d4afb5ceSopenharmony_ci 101d4afb5ceSopenharmony_ci if (!wsi->hdr_parsing_completed) 102d4afb5ceSopenharmony_ci /* More header content on the way */ 103d4afb5ceSopenharmony_ci goto read_ok; 104d4afb5ceSopenharmony_ci 105d4afb5ceSopenharmony_ci switch (lwsi_state(wsi)) { 106d4afb5ceSopenharmony_ci case LRS_ESTABLISHED: 107d4afb5ceSopenharmony_ci case LRS_HEADERS: 108d4afb5ceSopenharmony_ci goto read_ok; 109d4afb5ceSopenharmony_ci case LRS_ISSUING_FILE: 110d4afb5ceSopenharmony_ci goto read_ok; 111d4afb5ceSopenharmony_ci case LRS_DISCARD_BODY: 112d4afb5ceSopenharmony_ci case LRS_BODY: 113d4afb5ceSopenharmony_ci wsi->http.rx_content_remain = 114d4afb5ceSopenharmony_ci wsi->http.rx_content_length; 115d4afb5ceSopenharmony_ci if (wsi->http.rx_content_remain) 116d4afb5ceSopenharmony_ci goto http_postbody; 117d4afb5ceSopenharmony_ci 118d4afb5ceSopenharmony_ci /* there is no POST content */ 119d4afb5ceSopenharmony_ci goto postbody_completion; 120d4afb5ceSopenharmony_ci default: 121d4afb5ceSopenharmony_ci break; 122d4afb5ceSopenharmony_ci } 123d4afb5ceSopenharmony_ci break; 124d4afb5ceSopenharmony_ci 125d4afb5ceSopenharmony_ci case LRS_DISCARD_BODY: 126d4afb5ceSopenharmony_ci case LRS_BODY: 127d4afb5ceSopenharmony_cihttp_postbody: 128d4afb5ceSopenharmony_ci lwsl_info("%s: http post body: cl set %d, remain %d, len %d\n", __func__, 129d4afb5ceSopenharmony_ci (int)wsi->http.content_length_given, 130d4afb5ceSopenharmony_ci (int)wsi->http.rx_content_remain, (int)len); 131d4afb5ceSopenharmony_ci 132d4afb5ceSopenharmony_ci if (wsi->http.content_length_given && !wsi->http.rx_content_remain) 133d4afb5ceSopenharmony_ci goto postbody_completion; 134d4afb5ceSopenharmony_ci 135d4afb5ceSopenharmony_ci while (len && (!wsi->http.content_length_given || wsi->http.rx_content_remain)) { 136d4afb5ceSopenharmony_ci /* Copy as much as possible, up to the limit of: 137d4afb5ceSopenharmony_ci * what we have in the read buffer (len) 138d4afb5ceSopenharmony_ci * remaining portion of the POST body (content_remain) 139d4afb5ceSopenharmony_ci */ 140d4afb5ceSopenharmony_ci if (wsi->http.content_length_given) 141d4afb5ceSopenharmony_ci body_chunk_len = min(wsi->http.rx_content_remain, len); 142d4afb5ceSopenharmony_ci else 143d4afb5ceSopenharmony_ci body_chunk_len = len; 144d4afb5ceSopenharmony_ci wsi->http.rx_content_remain -= body_chunk_len; 145d4afb5ceSopenharmony_ci // len -= body_chunk_len; 146d4afb5ceSopenharmony_ci#ifdef LWS_WITH_CGI 147d4afb5ceSopenharmony_ci if (wsi->http.cgi) { 148d4afb5ceSopenharmony_ci struct lws_cgi_args args; 149d4afb5ceSopenharmony_ci 150d4afb5ceSopenharmony_ci args.ch = LWS_STDIN; 151d4afb5ceSopenharmony_ci args.stdwsi = &wsi->http.cgi->lsp->stdwsi[0]; 152d4afb5ceSopenharmony_ci args.data = buf; 153d4afb5ceSopenharmony_ci args.len = (int)(unsigned int)body_chunk_len; 154d4afb5ceSopenharmony_ci 155d4afb5ceSopenharmony_ci /* returns how much used */ 156d4afb5ceSopenharmony_ci n = (unsigned int)user_callback_handle_rxflow( 157d4afb5ceSopenharmony_ci wsi->a.protocol->callback, 158d4afb5ceSopenharmony_ci wsi, LWS_CALLBACK_CGI_STDIN_DATA, 159d4afb5ceSopenharmony_ci wsi->user_space, 160d4afb5ceSopenharmony_ci (void *)&args, 0); 161d4afb5ceSopenharmony_ci if ((int)n < 0) 162d4afb5ceSopenharmony_ci goto bail; 163d4afb5ceSopenharmony_ci } else { 164d4afb5ceSopenharmony_ci#endif 165d4afb5ceSopenharmony_ci if (lwsi_state(wsi) != LRS_DISCARD_BODY) { 166d4afb5ceSopenharmony_ci lwsl_info("%s: HTTP_BODY %d\n", __func__, (int)body_chunk_len); 167d4afb5ceSopenharmony_ci n = (unsigned int)wsi->a.protocol->callback(wsi, 168d4afb5ceSopenharmony_ci LWS_CALLBACK_HTTP_BODY, wsi->user_space, 169d4afb5ceSopenharmony_ci buf, (size_t)body_chunk_len); 170d4afb5ceSopenharmony_ci if (n) 171d4afb5ceSopenharmony_ci goto bail; 172d4afb5ceSopenharmony_ci } 173d4afb5ceSopenharmony_ci n = (size_t)body_chunk_len; 174d4afb5ceSopenharmony_ci#ifdef LWS_WITH_CGI 175d4afb5ceSopenharmony_ci } 176d4afb5ceSopenharmony_ci#endif 177d4afb5ceSopenharmony_ci lwsl_info("%s: advancing buf by %d\n", __func__, (int)n); 178d4afb5ceSopenharmony_ci buf += n; 179d4afb5ceSopenharmony_ci 180d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_H2) 181d4afb5ceSopenharmony_ci if (lwsi_role_h2(wsi) && !wsi->http.content_length_given) { 182d4afb5ceSopenharmony_ci struct lws *w = lws_get_network_wsi(wsi); 183d4afb5ceSopenharmony_ci 184d4afb5ceSopenharmony_ci if (w) 185d4afb5ceSopenharmony_ci lwsl_info("%s: h2: nwsi h2 flags %d\n", __func__, 186d4afb5ceSopenharmony_ci w->h2.h2n ? w->h2.h2n->flags: -1); 187d4afb5ceSopenharmony_ci 188d4afb5ceSopenharmony_ci if (w && w->h2.h2n && !(w->h2.h2n->flags & 1)) { 189d4afb5ceSopenharmony_ci lwsl_info("%s: h2, no cl, not END_STREAM, continuing\n", __func__); 190d4afb5ceSopenharmony_ci lws_set_timeout(wsi, 191d4afb5ceSopenharmony_ci PENDING_TIMEOUT_HTTP_CONTENT, 192d4afb5ceSopenharmony_ci (int)wsi->a.context->timeout_secs); 193d4afb5ceSopenharmony_ci break; 194d4afb5ceSopenharmony_ci } 195d4afb5ceSopenharmony_ci goto postbody_completion; 196d4afb5ceSopenharmony_ci } 197d4afb5ceSopenharmony_ci#endif 198d4afb5ceSopenharmony_ci 199d4afb5ceSopenharmony_ci if (wsi->http.rx_content_remain) { 200d4afb5ceSopenharmony_ci lws_set_timeout(wsi, 201d4afb5ceSopenharmony_ci PENDING_TIMEOUT_HTTP_CONTENT, 202d4afb5ceSopenharmony_ci (int)wsi->a.context->timeout_secs); 203d4afb5ceSopenharmony_ci break; 204d4afb5ceSopenharmony_ci } 205d4afb5ceSopenharmony_ci /* he sent all the content in time */ 206d4afb5ceSopenharmony_cipostbody_completion: 207d4afb5ceSopenharmony_ci#ifdef LWS_WITH_CGI 208d4afb5ceSopenharmony_ci /* 209d4afb5ceSopenharmony_ci * If we're running a cgi, we can't let him off the 210d4afb5ceSopenharmony_ci * hook just because he sent his POST data 211d4afb5ceSopenharmony_ci */ 212d4afb5ceSopenharmony_ci if (wsi->http.cgi) 213d4afb5ceSopenharmony_ci lws_set_timeout(wsi, PENDING_TIMEOUT_CGI, 214d4afb5ceSopenharmony_ci (int)wsi->a.context->timeout_secs); 215d4afb5ceSopenharmony_ci else 216d4afb5ceSopenharmony_ci#endif 217d4afb5ceSopenharmony_ci lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0); 218d4afb5ceSopenharmony_ci#ifdef LWS_WITH_CGI 219d4afb5ceSopenharmony_ci if (!wsi->http.cgi) 220d4afb5ceSopenharmony_ci#endif 221d4afb5ceSopenharmony_ci { 222d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER) 223d4afb5ceSopenharmony_ci if (lwsi_state(wsi) == LRS_DISCARD_BODY) { 224d4afb5ceSopenharmony_ci /* 225d4afb5ceSopenharmony_ci * repeat the transaction completed 226d4afb5ceSopenharmony_ci * that got us into this state, having 227d4afb5ceSopenharmony_ci * consumed the pending body now 228d4afb5ceSopenharmony_ci */ 229d4afb5ceSopenharmony_ci 230d4afb5ceSopenharmony_ci if (lws_http_transaction_completed(wsi)) 231d4afb5ceSopenharmony_ci goto bail; 232d4afb5ceSopenharmony_ci break; 233d4afb5ceSopenharmony_ci } 234d4afb5ceSopenharmony_ci#endif 235d4afb5ceSopenharmony_ci lwsl_info("HTTP_BODY_COMPLETION: %s (%s)\n", 236d4afb5ceSopenharmony_ci lws_wsi_tag(wsi), wsi->a.protocol->name); 237d4afb5ceSopenharmony_ci 238d4afb5ceSopenharmony_ci n = (unsigned int)wsi->a.protocol->callback(wsi, 239d4afb5ceSopenharmony_ci LWS_CALLBACK_HTTP_BODY_COMPLETION, 240d4afb5ceSopenharmony_ci wsi->user_space, NULL, 0); 241d4afb5ceSopenharmony_ci if (n) { 242d4afb5ceSopenharmony_ci lwsl_info("%s: bailing after BODY_COMPLETION\n", __func__); 243d4afb5ceSopenharmony_ci goto bail; 244d4afb5ceSopenharmony_ci } 245d4afb5ceSopenharmony_ci 246d4afb5ceSopenharmony_ci if (wsi->mux_substream) 247d4afb5ceSopenharmony_ci lwsi_set_state(wsi, LRS_ESTABLISHED); 248d4afb5ceSopenharmony_ci } 249d4afb5ceSopenharmony_ci 250d4afb5ceSopenharmony_ci break; 251d4afb5ceSopenharmony_ci } 252d4afb5ceSopenharmony_ci break; 253d4afb5ceSopenharmony_ci 254d4afb5ceSopenharmony_ci case LRS_RETURNED_CLOSE: 255d4afb5ceSopenharmony_ci case LRS_AWAITING_CLOSE_ACK: 256d4afb5ceSopenharmony_ci case LRS_WAITING_TO_SEND_CLOSE: 257d4afb5ceSopenharmony_ci case LRS_SHUTDOWN: 258d4afb5ceSopenharmony_ci 259d4afb5ceSopenharmony_ciws_mode: 260d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CLIENT) && defined(LWS_ROLE_WS) 261d4afb5ceSopenharmony_ci // lwsl_notice("%s: ws_mode\n", __func__); 262d4afb5ceSopenharmony_ci if (lws_ws_handshake_client(wsi, &buf, (size_t)len)) 263d4afb5ceSopenharmony_ci goto bail; 264d4afb5ceSopenharmony_ci#endif 265d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_WS) 266d4afb5ceSopenharmony_ci if (lwsi_role_ws(wsi) && lwsi_role_server(wsi) && 267d4afb5ceSopenharmony_ci /* 268d4afb5ceSopenharmony_ci * for h2 we are on the swsi 269d4afb5ceSopenharmony_ci */ 270d4afb5ceSopenharmony_ci lws_parse_ws(wsi, &buf, (size_t)len) < 0) { 271d4afb5ceSopenharmony_ci lwsl_info("%s: lws_parse_ws bailed\n", __func__); 272d4afb5ceSopenharmony_ci goto bail; 273d4afb5ceSopenharmony_ci } 274d4afb5ceSopenharmony_ci#endif 275d4afb5ceSopenharmony_ci // lwsl_notice("%s: ws_mode: buf moved on by %d\n", __func__, 276d4afb5ceSopenharmony_ci // lws_ptr_diff(buf, oldbuf)); 277d4afb5ceSopenharmony_ci break; 278d4afb5ceSopenharmony_ci 279d4afb5ceSopenharmony_ci case LRS_DEFERRING_ACTION: 280d4afb5ceSopenharmony_ci lwsl_notice("%s: LRS_DEFERRING_ACTION\n", __func__); 281d4afb5ceSopenharmony_ci break; 282d4afb5ceSopenharmony_ci 283d4afb5ceSopenharmony_ci case LRS_SSL_ACK_PENDING: 284d4afb5ceSopenharmony_ci break; 285d4afb5ceSopenharmony_ci 286d4afb5ceSopenharmony_ci case LRS_FLUSHING_BEFORE_CLOSE: 287d4afb5ceSopenharmony_ci break; 288d4afb5ceSopenharmony_ci 289d4afb5ceSopenharmony_ci case LRS_DEAD_SOCKET: 290d4afb5ceSopenharmony_ci lwsl_err("%s: Unhandled state LRS_DEAD_SOCKET\n", __func__); 291d4afb5ceSopenharmony_ci goto bail; 292d4afb5ceSopenharmony_ci // assert(0); 293d4afb5ceSopenharmony_ci /* fallthru */ 294d4afb5ceSopenharmony_ci 295d4afb5ceSopenharmony_ci case LRS_WAITING_CONNECT: /* observed on warmcat.com */ 296d4afb5ceSopenharmony_ci break; 297d4afb5ceSopenharmony_ci 298d4afb5ceSopenharmony_ci default: 299d4afb5ceSopenharmony_ci lwsl_err("%s: Unhandled state %d\n", __func__, lwsi_state(wsi)); 300d4afb5ceSopenharmony_ci goto bail; 301d4afb5ceSopenharmony_ci } 302d4afb5ceSopenharmony_ci 303d4afb5ceSopenharmony_ciread_ok: 304d4afb5ceSopenharmony_ci /* Nothing more to do for now */ 305d4afb5ceSopenharmony_ci// lwsl_info("%s: %p: read_ok, used %ld (len %d, state %d)\n", __func__, 306d4afb5ceSopenharmony_ci// wsi, (long)(buf - oldbuf), (int)len, wsi->state); 307d4afb5ceSopenharmony_ci 308d4afb5ceSopenharmony_ci return lws_ptr_diff(buf, oldbuf); 309d4afb5ceSopenharmony_ci 310d4afb5ceSopenharmony_cibail: 311d4afb5ceSopenharmony_ci /* 312d4afb5ceSopenharmony_ci * h2 / h2-ws calls us recursively in 313d4afb5ceSopenharmony_ci * 314d4afb5ceSopenharmony_ci * lws_read_h1()-> 315d4afb5ceSopenharmony_ci * lws_h2_parser()-> 316d4afb5ceSopenharmony_ci * lws_read_h1() 317d4afb5ceSopenharmony_ci * 318d4afb5ceSopenharmony_ci * pattern, having stripped the h2 framing in the middle. 319d4afb5ceSopenharmony_ci * 320d4afb5ceSopenharmony_ci * When taking down the whole connection, make sure that only the 321d4afb5ceSopenharmony_ci * outer lws_read() does the wsi close. 322d4afb5ceSopenharmony_ci */ 323d4afb5ceSopenharmony_ci if (!wsi->outer_will_close) 324d4afb5ceSopenharmony_ci lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, 325d4afb5ceSopenharmony_ci "lws_read_h1 bail"); 326d4afb5ceSopenharmony_ci 327d4afb5ceSopenharmony_ci return -1; 328d4afb5ceSopenharmony_ci} 329d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER) 330d4afb5ceSopenharmony_cistatic int 331d4afb5ceSopenharmony_cilws_h1_server_socket_service(struct lws *wsi, struct lws_pollfd *pollfd) 332d4afb5ceSopenharmony_ci{ 333d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; 334d4afb5ceSopenharmony_ci struct lws_tokens ebuf; 335d4afb5ceSopenharmony_ci int n, buffered; 336d4afb5ceSopenharmony_ci 337d4afb5ceSopenharmony_ci if (lwsi_state(wsi) == LRS_DEFERRING_ACTION) 338d4afb5ceSopenharmony_ci goto try_pollout; 339d4afb5ceSopenharmony_ci 340d4afb5ceSopenharmony_ci /* any incoming data ready? */ 341d4afb5ceSopenharmony_ci 342d4afb5ceSopenharmony_ci if (!(pollfd->revents & pollfd->events & LWS_POLLIN)) 343d4afb5ceSopenharmony_ci goto try_pollout; 344d4afb5ceSopenharmony_ci 345d4afb5ceSopenharmony_ci /* 346d4afb5ceSopenharmony_ci * If we previously just did POLLIN when IN and OUT were signaled 347d4afb5ceSopenharmony_ci * (because POLLIN processing may have used up the POLLOUT), don't let 348d4afb5ceSopenharmony_ci * that happen twice in a row... next time we see the situation favour 349d4afb5ceSopenharmony_ci * POLLOUT 350d4afb5ceSopenharmony_ci */ 351d4afb5ceSopenharmony_ci 352d4afb5ceSopenharmony_ci if (wsi->favoured_pollin && 353d4afb5ceSopenharmony_ci (pollfd->revents & pollfd->events & LWS_POLLOUT)) { 354d4afb5ceSopenharmony_ci // lwsl_notice("favouring pollout\n"); 355d4afb5ceSopenharmony_ci wsi->favoured_pollin = 0; 356d4afb5ceSopenharmony_ci goto try_pollout; 357d4afb5ceSopenharmony_ci } 358d4afb5ceSopenharmony_ci 359d4afb5ceSopenharmony_ci /* 360d4afb5ceSopenharmony_ci * We haven't processed that the tunnel is set up yet, so 361d4afb5ceSopenharmony_ci * defer reading 362d4afb5ceSopenharmony_ci */ 363d4afb5ceSopenharmony_ci 364d4afb5ceSopenharmony_ci if (lwsi_state(wsi) == LRS_SSL_ACK_PENDING) 365d4afb5ceSopenharmony_ci return LWS_HPI_RET_HANDLED; 366d4afb5ceSopenharmony_ci 367d4afb5ceSopenharmony_ci /* these states imply we MUST have an ah attached */ 368d4afb5ceSopenharmony_ci 369d4afb5ceSopenharmony_ci if ((lwsi_state(wsi) == LRS_ESTABLISHED || 370d4afb5ceSopenharmony_ci lwsi_state(wsi) == LRS_ISSUING_FILE || 371d4afb5ceSopenharmony_ci lwsi_state(wsi) == LRS_HEADERS || 372d4afb5ceSopenharmony_ci lwsi_state(wsi) == LRS_DOING_TRANSACTION || /* at least, SSE */ 373d4afb5ceSopenharmony_ci lwsi_state(wsi) == LRS_DISCARD_BODY || 374d4afb5ceSopenharmony_ci lwsi_state(wsi) == LRS_BODY)) { 375d4afb5ceSopenharmony_ci 376d4afb5ceSopenharmony_ci if (!wsi->http.ah && lws_header_table_attach(wsi, 0)) { 377d4afb5ceSopenharmony_ci lwsl_info("%s: %s: ah not available\n", __func__, 378d4afb5ceSopenharmony_ci lws_wsi_tag(wsi)); 379d4afb5ceSopenharmony_ci goto try_pollout; 380d4afb5ceSopenharmony_ci } 381d4afb5ceSopenharmony_ci 382d4afb5ceSopenharmony_ci /* 383d4afb5ceSopenharmony_ci * We got here because there was specifically POLLIN... 384d4afb5ceSopenharmony_ci * regardless of our buflist state, we need to get it, 385d4afb5ceSopenharmony_ci * and either use it, or append to the buflist and use 386d4afb5ceSopenharmony_ci * buflist head material. 387d4afb5ceSopenharmony_ci * 388d4afb5ceSopenharmony_ci * We will not notice a connection close until the buflist is 389d4afb5ceSopenharmony_ci * exhausted and we tried to do a read of some kind. 390d4afb5ceSopenharmony_ci */ 391d4afb5ceSopenharmony_ci 392d4afb5ceSopenharmony_ci ebuf.token = NULL; 393d4afb5ceSopenharmony_ci ebuf.len = 0; 394d4afb5ceSopenharmony_ci buffered = lws_buflist_aware_read(pt, wsi, &ebuf, 0, __func__); 395d4afb5ceSopenharmony_ci switch (ebuf.len) { 396d4afb5ceSopenharmony_ci case 0: 397d4afb5ceSopenharmony_ci lwsl_info("%s: read 0 len a\n", __func__); 398d4afb5ceSopenharmony_ci wsi->seen_zero_length_recv = 1; 399d4afb5ceSopenharmony_ci if (lws_change_pollfd(wsi, LWS_POLLIN, 0)) 400d4afb5ceSopenharmony_ci goto fail; 401d4afb5ceSopenharmony_ci#if !defined(LWS_WITHOUT_EXTENSIONS) 402d4afb5ceSopenharmony_ci /* 403d4afb5ceSopenharmony_ci * autobahn requires us to win the race between close 404d4afb5ceSopenharmony_ci * and draining the extensions 405d4afb5ceSopenharmony_ci */ 406d4afb5ceSopenharmony_ci if (wsi->ws && 407d4afb5ceSopenharmony_ci (wsi->ws->rx_draining_ext || 408d4afb5ceSopenharmony_ci wsi->ws->tx_draining_ext)) 409d4afb5ceSopenharmony_ci goto try_pollout; 410d4afb5ceSopenharmony_ci#endif 411d4afb5ceSopenharmony_ci /* 412d4afb5ceSopenharmony_ci * normally, we respond to close with logically closing 413d4afb5ceSopenharmony_ci * our side immediately 414d4afb5ceSopenharmony_ci */ 415d4afb5ceSopenharmony_ci goto fail; 416d4afb5ceSopenharmony_ci 417d4afb5ceSopenharmony_ci case LWS_SSL_CAPABLE_ERROR: 418d4afb5ceSopenharmony_ci goto fail; 419d4afb5ceSopenharmony_ci case LWS_SSL_CAPABLE_MORE_SERVICE: 420d4afb5ceSopenharmony_ci goto try_pollout; 421d4afb5ceSopenharmony_ci } 422d4afb5ceSopenharmony_ci 423d4afb5ceSopenharmony_ci /* just ignore incoming if waiting for close */ 424d4afb5ceSopenharmony_ci if (lwsi_state(wsi) == LRS_FLUSHING_BEFORE_CLOSE) { 425d4afb5ceSopenharmony_ci lwsl_notice("%s: just ignoring\n", __func__); 426d4afb5ceSopenharmony_ci goto try_pollout; 427d4afb5ceSopenharmony_ci } 428d4afb5ceSopenharmony_ci 429d4afb5ceSopenharmony_ci if (lwsi_state(wsi) == LRS_ISSUING_FILE) { 430d4afb5ceSopenharmony_ci // lwsl_notice("stashing: wsi %p: bd %d\n", wsi, buffered); 431d4afb5ceSopenharmony_ci if (lws_buflist_aware_finished_consuming(wsi, &ebuf, 0, 432d4afb5ceSopenharmony_ci buffered, __func__)) 433d4afb5ceSopenharmony_ci return LWS_HPI_RET_PLEASE_CLOSE_ME; 434d4afb5ceSopenharmony_ci 435d4afb5ceSopenharmony_ci goto try_pollout; 436d4afb5ceSopenharmony_ci } 437d4afb5ceSopenharmony_ci 438d4afb5ceSopenharmony_ci /* 439d4afb5ceSopenharmony_ci * Otherwise give it to whoever wants it according to the 440d4afb5ceSopenharmony_ci * connection state 441d4afb5ceSopenharmony_ci */ 442d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_H2) 443d4afb5ceSopenharmony_ci if (lwsi_role_h2(wsi) && lwsi_state(wsi) != LRS_BODY) 444d4afb5ceSopenharmony_ci n = lws_read_h2(wsi, ebuf.token, (unsigned int)ebuf.len); 445d4afb5ceSopenharmony_ci else 446d4afb5ceSopenharmony_ci#endif 447d4afb5ceSopenharmony_ci n = lws_read_h1(wsi, ebuf.token, (unsigned int)ebuf.len); 448d4afb5ceSopenharmony_ci if (n < 0) /* we closed wsi */ 449d4afb5ceSopenharmony_ci return LWS_HPI_RET_WSI_ALREADY_DIED; 450d4afb5ceSopenharmony_ci 451d4afb5ceSopenharmony_ci // lwsl_notice("%s: consumed %d\n", __func__, n); 452d4afb5ceSopenharmony_ci 453d4afb5ceSopenharmony_ci if (lws_buflist_aware_finished_consuming(wsi, &ebuf, n, 454d4afb5ceSopenharmony_ci buffered, __func__)) 455d4afb5ceSopenharmony_ci return LWS_HPI_RET_PLEASE_CLOSE_ME; 456d4afb5ceSopenharmony_ci 457d4afb5ceSopenharmony_ci /* 458d4afb5ceSopenharmony_ci * during the parsing our role changed to something non-http, 459d4afb5ceSopenharmony_ci * so the ah has no further meaning 460d4afb5ceSopenharmony_ci */ 461d4afb5ceSopenharmony_ci 462d4afb5ceSopenharmony_ci if (wsi->http.ah && 463d4afb5ceSopenharmony_ci !lwsi_role_h1(wsi) && 464d4afb5ceSopenharmony_ci !lwsi_role_h2(wsi) && 465d4afb5ceSopenharmony_ci !lwsi_role_cgi(wsi)) 466d4afb5ceSopenharmony_ci lws_header_table_detach(wsi, 0); 467d4afb5ceSopenharmony_ci 468d4afb5ceSopenharmony_ci /* 469d4afb5ceSopenharmony_ci * He may have used up the writability above, if we will defer 470d4afb5ceSopenharmony_ci * POLLOUT processing in favour of POLLIN, note it 471d4afb5ceSopenharmony_ci */ 472d4afb5ceSopenharmony_ci 473d4afb5ceSopenharmony_ci if (pollfd->revents & LWS_POLLOUT) 474d4afb5ceSopenharmony_ci wsi->favoured_pollin = 1; 475d4afb5ceSopenharmony_ci 476d4afb5ceSopenharmony_ci return LWS_HPI_RET_HANDLED; 477d4afb5ceSopenharmony_ci } 478d4afb5ceSopenharmony_ci 479d4afb5ceSopenharmony_ci /* 480d4afb5ceSopenharmony_ci * He may have used up the writability above, if we will defer POLLOUT 481d4afb5ceSopenharmony_ci * processing in favour of POLLIN, note it 482d4afb5ceSopenharmony_ci */ 483d4afb5ceSopenharmony_ci 484d4afb5ceSopenharmony_ci if (pollfd->revents & LWS_POLLOUT) 485d4afb5ceSopenharmony_ci wsi->favoured_pollin = 1; 486d4afb5ceSopenharmony_ci 487d4afb5ceSopenharmony_citry_pollout: 488d4afb5ceSopenharmony_ci 489d4afb5ceSopenharmony_ci /* this handles POLLOUT for http serving fragments */ 490d4afb5ceSopenharmony_ci 491d4afb5ceSopenharmony_ci if (!(pollfd->revents & LWS_POLLOUT)) 492d4afb5ceSopenharmony_ci return LWS_HPI_RET_HANDLED; 493d4afb5ceSopenharmony_ci 494d4afb5ceSopenharmony_ci /* one shot */ 495d4afb5ceSopenharmony_ci if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) { 496d4afb5ceSopenharmony_ci lwsl_notice("%s a\n", __func__); 497d4afb5ceSopenharmony_ci goto fail; 498d4afb5ceSopenharmony_ci } 499d4afb5ceSopenharmony_ci 500d4afb5ceSopenharmony_ci /* clear back-to-back write detection */ 501d4afb5ceSopenharmony_ci wsi->could_have_pending = 0; 502d4afb5ceSopenharmony_ci 503d4afb5ceSopenharmony_ci if (lwsi_state(wsi) == LRS_DEFERRING_ACTION) { 504d4afb5ceSopenharmony_ci lwsl_debug("%s: LRS_DEFERRING_ACTION now writable\n", __func__); 505d4afb5ceSopenharmony_ci 506d4afb5ceSopenharmony_ci lwsi_set_state(wsi, LRS_ESTABLISHED); 507d4afb5ceSopenharmony_ci if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) { 508d4afb5ceSopenharmony_ci lwsl_info("failed at set pollfd\n"); 509d4afb5ceSopenharmony_ci goto fail; 510d4afb5ceSopenharmony_ci } 511d4afb5ceSopenharmony_ci } 512d4afb5ceSopenharmony_ci 513d4afb5ceSopenharmony_ci if (!wsi->hdr_parsing_completed) 514d4afb5ceSopenharmony_ci return LWS_HPI_RET_HANDLED; 515d4afb5ceSopenharmony_ci 516d4afb5ceSopenharmony_ci if (lwsi_state(wsi) != LRS_ISSUING_FILE) { 517d4afb5ceSopenharmony_ci 518d4afb5ceSopenharmony_ci if (lws_has_buffered_out(wsi)) { 519d4afb5ceSopenharmony_ci //lwsl_notice("%s: completing partial\n", __func__); 520d4afb5ceSopenharmony_ci if (lws_issue_raw(wsi, NULL, 0) < 0) { 521d4afb5ceSopenharmony_ci lwsl_info("%s signalling to close\n", __func__); 522d4afb5ceSopenharmony_ci goto fail; 523d4afb5ceSopenharmony_ci } 524d4afb5ceSopenharmony_ci return LWS_HPI_RET_HANDLED; 525d4afb5ceSopenharmony_ci } 526d4afb5ceSopenharmony_ci 527d4afb5ceSopenharmony_ci n = user_callback_handle_rxflow(wsi->a.protocol->callback, wsi, 528d4afb5ceSopenharmony_ci LWS_CALLBACK_HTTP_WRITEABLE, 529d4afb5ceSopenharmony_ci wsi->user_space, NULL, 0); 530d4afb5ceSopenharmony_ci if (n < 0) { 531d4afb5ceSopenharmony_ci lwsl_info("writeable_fail\n"); 532d4afb5ceSopenharmony_ci goto fail; 533d4afb5ceSopenharmony_ci } 534d4afb5ceSopenharmony_ci 535d4afb5ceSopenharmony_ci return LWS_HPI_RET_HANDLED; 536d4afb5ceSopenharmony_ci } 537d4afb5ceSopenharmony_ci 538d4afb5ceSopenharmony_ci#if defined(LWS_WITH_FILE_OPS) 539d4afb5ceSopenharmony_ci 540d4afb5ceSopenharmony_ci /* >0 == completion, <0 == error 541d4afb5ceSopenharmony_ci * 542d4afb5ceSopenharmony_ci * We'll get a LWS_CALLBACK_HTTP_FILE_COMPLETION callback when 543d4afb5ceSopenharmony_ci * it's done. That's the case even if we just completed the 544d4afb5ceSopenharmony_ci * send, so wait for that. 545d4afb5ceSopenharmony_ci */ 546d4afb5ceSopenharmony_ci n = lws_serve_http_file_fragment(wsi); 547d4afb5ceSopenharmony_ci if (n < 0) 548d4afb5ceSopenharmony_ci goto fail; 549d4afb5ceSopenharmony_ci#endif 550d4afb5ceSopenharmony_ci 551d4afb5ceSopenharmony_ci return LWS_HPI_RET_HANDLED; 552d4afb5ceSopenharmony_ci 553d4afb5ceSopenharmony_ci 554d4afb5ceSopenharmony_cifail: 555d4afb5ceSopenharmony_ci lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, 556d4afb5ceSopenharmony_ci "server socket svc fail"); 557d4afb5ceSopenharmony_ci 558d4afb5ceSopenharmony_ci return LWS_HPI_RET_WSI_ALREADY_DIED; 559d4afb5ceSopenharmony_ci} 560d4afb5ceSopenharmony_ci#endif 561d4afb5ceSopenharmony_ci 562d4afb5ceSopenharmony_cistatic int 563d4afb5ceSopenharmony_cirops_handle_POLLIN_h1(struct lws_context_per_thread *pt, struct lws *wsi, 564d4afb5ceSopenharmony_ci struct lws_pollfd *pollfd) 565d4afb5ceSopenharmony_ci{ 566d4afb5ceSopenharmony_ci if (lwsi_state(wsi) == LRS_IDLING) { 567d4afb5ceSopenharmony_ci uint8_t buf[1]; 568d4afb5ceSopenharmony_ci int rlen; 569d4afb5ceSopenharmony_ci 570d4afb5ceSopenharmony_ci /* 571d4afb5ceSopenharmony_ci * h1 staggered spins here in IDLING if we don't close it. 572d4afb5ceSopenharmony_ci * It shows POLLIN but the tls connection returns ERROR if 573d4afb5ceSopenharmony_ci * you try to read it. 574d4afb5ceSopenharmony_ci */ 575d4afb5ceSopenharmony_ci 576d4afb5ceSopenharmony_ci // lwsl_notice("%s: %p: wsistate 0x%x %s, revents 0x%x\n", 577d4afb5ceSopenharmony_ci // __func__, wsi, wsi->wsistate, wsi->role_ops->name, 578d4afb5ceSopenharmony_ci // pollfd->revents); 579d4afb5ceSopenharmony_ci 580d4afb5ceSopenharmony_ci rlen = lws_ssl_capable_read(wsi, buf, sizeof(buf)); 581d4afb5ceSopenharmony_ci if (rlen == LWS_SSL_CAPABLE_ERROR) 582d4afb5ceSopenharmony_ci return LWS_HPI_RET_PLEASE_CLOSE_ME; 583d4afb5ceSopenharmony_ci } 584d4afb5ceSopenharmony_ci 585d4afb5ceSopenharmony_ci#ifdef LWS_WITH_CGI 586d4afb5ceSopenharmony_ci if (wsi->http.cgi && (pollfd->revents & LWS_POLLOUT)) { 587d4afb5ceSopenharmony_ci if (lws_handle_POLLOUT_event(wsi, pollfd)) 588d4afb5ceSopenharmony_ci return LWS_HPI_RET_PLEASE_CLOSE_ME; 589d4afb5ceSopenharmony_ci 590d4afb5ceSopenharmony_ci return LWS_HPI_RET_HANDLED; 591d4afb5ceSopenharmony_ci } 592d4afb5ceSopenharmony_ci#endif 593d4afb5ceSopenharmony_ci 594d4afb5ceSopenharmony_ci /* Priority 2: pre- compression transform */ 595d4afb5ceSopenharmony_ci 596d4afb5ceSopenharmony_ci#if defined(LWS_WITH_HTTP_STREAM_COMPRESSION) 597d4afb5ceSopenharmony_ci if (wsi->http.comp_ctx.buflist_comp || 598d4afb5ceSopenharmony_ci wsi->http.comp_ctx.may_have_more) { 599d4afb5ceSopenharmony_ci enum lws_write_protocol wp = LWS_WRITE_HTTP; 600d4afb5ceSopenharmony_ci 601d4afb5ceSopenharmony_ci lwsl_info("%s: completing comp partial (buflist_comp %p, may %d)\n", 602d4afb5ceSopenharmony_ci __func__, wsi->http.comp_ctx.buflist_comp, 603d4afb5ceSopenharmony_ci wsi->http.comp_ctx.may_have_more 604d4afb5ceSopenharmony_ci ); 605d4afb5ceSopenharmony_ci 606d4afb5ceSopenharmony_ci if (lws_rops_fidx(wsi->role_ops, LWS_ROPS_write_role_protocol) && 607d4afb5ceSopenharmony_ci lws_rops_func_fidx(wsi->role_ops, LWS_ROPS_write_role_protocol). 608d4afb5ceSopenharmony_ci write_role_protocol(wsi, NULL, 0, &wp) < 0) { 609d4afb5ceSopenharmony_ci lwsl_info("%s signalling to close\n", __func__); 610d4afb5ceSopenharmony_ci return LWS_HPI_RET_PLEASE_CLOSE_ME; 611d4afb5ceSopenharmony_ci } 612d4afb5ceSopenharmony_ci lws_callback_on_writable(wsi); 613d4afb5ceSopenharmony_ci 614d4afb5ceSopenharmony_ci if (!wsi->http.comp_ctx.buflist_comp && 615d4afb5ceSopenharmony_ci !wsi->http.comp_ctx.may_have_more && 616d4afb5ceSopenharmony_ci wsi->http.deferred_transaction_completed) { 617d4afb5ceSopenharmony_ci wsi->http.deferred_transaction_completed = 0; 618d4afb5ceSopenharmony_ci if (lws_http_transaction_completed(wsi)) 619d4afb5ceSopenharmony_ci return LWS_HPI_RET_PLEASE_CLOSE_ME; 620d4afb5ceSopenharmony_ci } 621d4afb5ceSopenharmony_ci 622d4afb5ceSopenharmony_ci return LWS_HPI_RET_HANDLED; 623d4afb5ceSopenharmony_ci } 624d4afb5ceSopenharmony_ci#endif 625d4afb5ceSopenharmony_ci 626d4afb5ceSopenharmony_ci if (lws_is_flowcontrolled(wsi)) 627d4afb5ceSopenharmony_ci /* We cannot deal with any kind of new RX because we are 628d4afb5ceSopenharmony_ci * RX-flowcontrolled. 629d4afb5ceSopenharmony_ci */ 630d4afb5ceSopenharmony_ci return LWS_HPI_RET_HANDLED; 631d4afb5ceSopenharmony_ci 632d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER) 633d4afb5ceSopenharmony_ci if (!lwsi_role_client(wsi)) { 634d4afb5ceSopenharmony_ci int n; 635d4afb5ceSopenharmony_ci 636d4afb5ceSopenharmony_ci lwsl_debug("%s: %s: wsistate 0x%x\n", __func__, lws_wsi_tag(wsi), 637d4afb5ceSopenharmony_ci (unsigned int)wsi->wsistate); 638d4afb5ceSopenharmony_ci 639d4afb5ceSopenharmony_ci if (pollfd->revents & LWS_POLLHUP && 640d4afb5ceSopenharmony_ci !lws_buflist_total_len(&wsi->buflist)) 641d4afb5ceSopenharmony_ci return LWS_HPI_RET_PLEASE_CLOSE_ME; 642d4afb5ceSopenharmony_ci 643d4afb5ceSopenharmony_ci n = lws_h1_server_socket_service(wsi, pollfd); 644d4afb5ceSopenharmony_ci if (n != LWS_HPI_RET_HANDLED) 645d4afb5ceSopenharmony_ci return n; 646d4afb5ceSopenharmony_ci if (lwsi_state(wsi) != LRS_SSL_INIT) 647d4afb5ceSopenharmony_ci if (lws_server_socket_service_ssl(wsi, 648d4afb5ceSopenharmony_ci LWS_SOCK_INVALID, 649d4afb5ceSopenharmony_ci !!(pollfd->revents & LWS_POLLIN))) 650d4afb5ceSopenharmony_ci return LWS_HPI_RET_PLEASE_CLOSE_ME; 651d4afb5ceSopenharmony_ci 652d4afb5ceSopenharmony_ci return LWS_HPI_RET_HANDLED; 653d4afb5ceSopenharmony_ci } 654d4afb5ceSopenharmony_ci#endif 655d4afb5ceSopenharmony_ci 656d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CLIENT) 657d4afb5ceSopenharmony_ci if ((pollfd->revents & LWS_POLLIN) && 658d4afb5ceSopenharmony_ci wsi->hdr_parsing_completed && !wsi->told_user_closed) { 659d4afb5ceSopenharmony_ci 660d4afb5ceSopenharmony_ci /* 661d4afb5ceSopenharmony_ci * In SSL mode we get POLLIN notification about 662d4afb5ceSopenharmony_ci * encrypted data in. 663d4afb5ceSopenharmony_ci * 664d4afb5ceSopenharmony_ci * But that is not necessarily related to decrypted 665d4afb5ceSopenharmony_ci * data out becoming available; in may need to perform 666d4afb5ceSopenharmony_ci * other in or out before that happens. 667d4afb5ceSopenharmony_ci * 668d4afb5ceSopenharmony_ci * simply mark ourselves as having readable data 669d4afb5ceSopenharmony_ci * and turn off our POLLIN 670d4afb5ceSopenharmony_ci */ 671d4afb5ceSopenharmony_ci wsi->client_rx_avail = 1; 672d4afb5ceSopenharmony_ci if (lws_change_pollfd(wsi, LWS_POLLIN, 0)) 673d4afb5ceSopenharmony_ci return LWS_HPI_RET_PLEASE_CLOSE_ME; 674d4afb5ceSopenharmony_ci 675d4afb5ceSopenharmony_ci //lwsl_notice("calling back %s\n", wsi->a.protocol->name); 676d4afb5ceSopenharmony_ci 677d4afb5ceSopenharmony_ci /* let user code know, he'll usually ask for writeable 678d4afb5ceSopenharmony_ci * callback and drain / re-enable it there 679d4afb5ceSopenharmony_ci */ 680d4afb5ceSopenharmony_ci if (user_callback_handle_rxflow(wsi->a.protocol->callback, wsi, 681d4afb5ceSopenharmony_ci LWS_CALLBACK_RECEIVE_CLIENT_HTTP, 682d4afb5ceSopenharmony_ci wsi->user_space, NULL, 0)) { 683d4afb5ceSopenharmony_ci lwsl_info("RECEIVE_CLIENT_HTTP closed it\n"); 684d4afb5ceSopenharmony_ci return LWS_HPI_RET_PLEASE_CLOSE_ME; 685d4afb5ceSopenharmony_ci } 686d4afb5ceSopenharmony_ci 687d4afb5ceSopenharmony_ci return LWS_HPI_RET_HANDLED; 688d4afb5ceSopenharmony_ci } 689d4afb5ceSopenharmony_ci#endif 690d4afb5ceSopenharmony_ci 691d4afb5ceSopenharmony_ci// if (lwsi_state(wsi) == LRS_ESTABLISHED) 692d4afb5ceSopenharmony_ci// return LWS_HPI_RET_HANDLED; 693d4afb5ceSopenharmony_ci 694d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CLIENT) 695d4afb5ceSopenharmony_ci if ((pollfd->revents & LWS_POLLOUT) && 696d4afb5ceSopenharmony_ci lws_handle_POLLOUT_event(wsi, pollfd)) { 697d4afb5ceSopenharmony_ci lwsl_debug("POLLOUT event closed it\n"); 698d4afb5ceSopenharmony_ci return LWS_HPI_RET_PLEASE_CLOSE_ME; 699d4afb5ceSopenharmony_ci } 700d4afb5ceSopenharmony_ci 701d4afb5ceSopenharmony_ci if (lws_http_client_socket_service(wsi, pollfd)) 702d4afb5ceSopenharmony_ci return LWS_HPI_RET_WSI_ALREADY_DIED; 703d4afb5ceSopenharmony_ci#endif 704d4afb5ceSopenharmony_ci 705d4afb5ceSopenharmony_ci if (lwsi_state(wsi) == LRS_WAITING_CONNECT && 706d4afb5ceSopenharmony_ci (pollfd->revents & LWS_POLLHUP)) 707d4afb5ceSopenharmony_ci return LWS_HPI_RET_PLEASE_CLOSE_ME; 708d4afb5ceSopenharmony_ci 709d4afb5ceSopenharmony_ci return LWS_HPI_RET_HANDLED; 710d4afb5ceSopenharmony_ci} 711d4afb5ceSopenharmony_ci 712d4afb5ceSopenharmony_cistatic int 713d4afb5ceSopenharmony_cirops_handle_POLLOUT_h1(struct lws *wsi) 714d4afb5ceSopenharmony_ci{ 715d4afb5ceSopenharmony_ci 716d4afb5ceSopenharmony_ci 717d4afb5ceSopenharmony_ci if (lwsi_state(wsi) == LRS_ISSUE_HTTP_BODY || 718d4afb5ceSopenharmony_ci lwsi_state(wsi) == LRS_WAITING_SERVER_REPLY) { 719d4afb5ceSopenharmony_ci#if defined(LWS_WITH_HTTP_PROXY) 720d4afb5ceSopenharmony_ci if (wsi->http.proxy_clientside) { 721d4afb5ceSopenharmony_ci unsigned char *buf, prebuf[LWS_PRE + 1024]; 722d4afb5ceSopenharmony_ci size_t len = lws_buflist_next_segment_len( 723d4afb5ceSopenharmony_ci &wsi->parent->http.buflist_post_body, &buf); 724d4afb5ceSopenharmony_ci int n; 725d4afb5ceSopenharmony_ci 726d4afb5ceSopenharmony_ci if (len > sizeof(prebuf) - LWS_PRE) 727d4afb5ceSopenharmony_ci len = sizeof(prebuf) - LWS_PRE; 728d4afb5ceSopenharmony_ci 729d4afb5ceSopenharmony_ci if (len) { 730d4afb5ceSopenharmony_ci memcpy(prebuf + LWS_PRE, buf, len); 731d4afb5ceSopenharmony_ci 732d4afb5ceSopenharmony_ci lwsl_debug("%s: %s: proxying body %d %d %d %d %d\n", 733d4afb5ceSopenharmony_ci __func__, lws_wsi_tag(wsi), (int)len, 734d4afb5ceSopenharmony_ci (int)wsi->http.tx_content_length, 735d4afb5ceSopenharmony_ci (int)wsi->http.tx_content_remain, 736d4afb5ceSopenharmony_ci (int)wsi->http.rx_content_length, 737d4afb5ceSopenharmony_ci (int)wsi->http.rx_content_remain 738d4afb5ceSopenharmony_ci ); 739d4afb5ceSopenharmony_ci 740d4afb5ceSopenharmony_ci n = lws_write(wsi, prebuf + LWS_PRE, len, LWS_WRITE_HTTP); 741d4afb5ceSopenharmony_ci if (n < 0) { 742d4afb5ceSopenharmony_ci lwsl_err("%s: PROXY_BODY: write %d failed\n", 743d4afb5ceSopenharmony_ci __func__, (int)len); 744d4afb5ceSopenharmony_ci return LWS_HP_RET_BAIL_DIE; 745d4afb5ceSopenharmony_ci } 746d4afb5ceSopenharmony_ci 747d4afb5ceSopenharmony_ci lws_buflist_use_segment(&wsi->parent->http.buflist_post_body, len); 748d4afb5ceSopenharmony_ci 749d4afb5ceSopenharmony_ci } 750d4afb5ceSopenharmony_ci 751d4afb5ceSopenharmony_ci if (wsi->parent->http.buflist_post_body) { 752d4afb5ceSopenharmony_ci lws_callback_on_writable(wsi); 753d4afb5ceSopenharmony_ci return LWS_HP_RET_DROP_POLLOUT; 754d4afb5ceSopenharmony_ci } 755d4afb5ceSopenharmony_ci 756d4afb5ceSopenharmony_ci lwsl_wsi_err(wsi, "nothing to send"); 757d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) 758d4afb5ceSopenharmony_ci /* prepare ourselves to do the parsing */ 759d4afb5ceSopenharmony_ci wsi->http.ah->parser_state = WSI_TOKEN_NAME_PART; 760d4afb5ceSopenharmony_ci wsi->http.ah->lextable_pos = 0; 761d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CUSTOM_HEADERS) 762d4afb5ceSopenharmony_ci wsi->http.ah->unk_pos = 0; 763d4afb5ceSopenharmony_ci#endif 764d4afb5ceSopenharmony_ci#endif 765d4afb5ceSopenharmony_ci lwsi_set_state(wsi, LRS_WAITING_SERVER_REPLY); 766d4afb5ceSopenharmony_ci lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE, 767d4afb5ceSopenharmony_ci (int)wsi->a.context->timeout_secs); 768d4afb5ceSopenharmony_ci 769d4afb5ceSopenharmony_ci return LWS_HP_RET_DROP_POLLOUT; 770d4afb5ceSopenharmony_ci } 771d4afb5ceSopenharmony_ci#endif 772d4afb5ceSopenharmony_ci return LWS_HP_RET_USER_SERVICE; 773d4afb5ceSopenharmony_ci } 774d4afb5ceSopenharmony_ci 775d4afb5ceSopenharmony_ci if (lwsi_role_client(wsi)) 776d4afb5ceSopenharmony_ci return LWS_HP_RET_USER_SERVICE; 777d4afb5ceSopenharmony_ci 778d4afb5ceSopenharmony_ci return LWS_HP_RET_BAIL_OK; 779d4afb5ceSopenharmony_ci} 780d4afb5ceSopenharmony_ci 781d4afb5ceSopenharmony_cistatic int 782d4afb5ceSopenharmony_cirops_write_role_protocol_h1(struct lws *wsi, unsigned char *buf, size_t len, 783d4afb5ceSopenharmony_ci enum lws_write_protocol *wp) 784d4afb5ceSopenharmony_ci{ 785d4afb5ceSopenharmony_ci size_t olen = len; 786d4afb5ceSopenharmony_ci int n; 787d4afb5ceSopenharmony_ci 788d4afb5ceSopenharmony_ci#if defined(LWS_WITH_HTTP_STREAM_COMPRESSION) 789d4afb5ceSopenharmony_ci if (wsi->http.lcs && (((*wp) & 0x1f) == LWS_WRITE_HTTP_FINAL || 790d4afb5ceSopenharmony_ci ((*wp) & 0x1f) == LWS_WRITE_HTTP)) { 791d4afb5ceSopenharmony_ci unsigned char mtubuf[1500 + LWS_PRE + 792d4afb5ceSopenharmony_ci LWS_HTTP_CHUNK_HDR_MAX_SIZE + 793d4afb5ceSopenharmony_ci LWS_HTTP_CHUNK_TRL_MAX_SIZE], 794d4afb5ceSopenharmony_ci *out = mtubuf + LWS_PRE + 795d4afb5ceSopenharmony_ci LWS_HTTP_CHUNK_HDR_MAX_SIZE; 796d4afb5ceSopenharmony_ci size_t o = sizeof(mtubuf) - LWS_PRE - 797d4afb5ceSopenharmony_ci LWS_HTTP_CHUNK_HDR_MAX_SIZE - 798d4afb5ceSopenharmony_ci LWS_HTTP_CHUNK_TRL_MAX_SIZE; 799d4afb5ceSopenharmony_ci 800d4afb5ceSopenharmony_ci n = lws_http_compression_transform(wsi, buf, len, wp, &out, &o); 801d4afb5ceSopenharmony_ci if (n) 802d4afb5ceSopenharmony_ci return n; 803d4afb5ceSopenharmony_ci 804d4afb5ceSopenharmony_ci lwsl_info("%s: %s: transformed %d bytes to %d " 805d4afb5ceSopenharmony_ci "(wp 0x%x, more %d)\n", __func__, 806d4afb5ceSopenharmony_ci lws_wsi_tag(wsi), (int)len, 807d4afb5ceSopenharmony_ci (int)o, (int)*wp, wsi->http.comp_ctx.may_have_more); 808d4afb5ceSopenharmony_ci 809d4afb5ceSopenharmony_ci if (!o) 810d4afb5ceSopenharmony_ci return (int)olen; 811d4afb5ceSopenharmony_ci 812d4afb5ceSopenharmony_ci if (wsi->http.comp_ctx.chunking) { 813d4afb5ceSopenharmony_ci char c[LWS_HTTP_CHUNK_HDR_MAX_SIZE + 2]; 814d4afb5ceSopenharmony_ci /* 815d4afb5ceSopenharmony_ci * this only needs dealing with on http/1.1 to allow 816d4afb5ceSopenharmony_ci * pipelining 817d4afb5ceSopenharmony_ci */ 818d4afb5ceSopenharmony_ci n = lws_snprintf(c, sizeof(c), "%X\x0d\x0a", (int)o); 819d4afb5ceSopenharmony_ci lwsl_info("%s: chunk (%d) %s", __func__, (int)o, c); 820d4afb5ceSopenharmony_ci out -= n; 821d4afb5ceSopenharmony_ci o += (unsigned int)n; 822d4afb5ceSopenharmony_ci memcpy(out, c, (unsigned int)n); 823d4afb5ceSopenharmony_ci out[o++] = '\x0d'; 824d4afb5ceSopenharmony_ci out[o++] = '\x0a'; 825d4afb5ceSopenharmony_ci 826d4afb5ceSopenharmony_ci if (((*wp) & 0x1f) == LWS_WRITE_HTTP_FINAL) { 827d4afb5ceSopenharmony_ci lwsl_info("%s: final chunk\n", __func__); 828d4afb5ceSopenharmony_ci out[o++] = '0'; 829d4afb5ceSopenharmony_ci out[o++] = '\x0d'; 830d4afb5ceSopenharmony_ci out[o++] = '\x0a'; 831d4afb5ceSopenharmony_ci out[o++] = '\x0d'; 832d4afb5ceSopenharmony_ci out[o++] = '\x0a'; 833d4afb5ceSopenharmony_ci } 834d4afb5ceSopenharmony_ci } 835d4afb5ceSopenharmony_ci 836d4afb5ceSopenharmony_ci buf = out; 837d4afb5ceSopenharmony_ci len = o; 838d4afb5ceSopenharmony_ci } 839d4afb5ceSopenharmony_ci#endif 840d4afb5ceSopenharmony_ci 841d4afb5ceSopenharmony_ci n = lws_issue_raw(wsi, (unsigned char *)buf, len); 842d4afb5ceSopenharmony_ci if (n < 0) 843d4afb5ceSopenharmony_ci return n; 844d4afb5ceSopenharmony_ci 845d4afb5ceSopenharmony_ci /* hide there may have been compression */ 846d4afb5ceSopenharmony_ci 847d4afb5ceSopenharmony_ci return (int)olen; 848d4afb5ceSopenharmony_ci} 849d4afb5ceSopenharmony_ci 850d4afb5ceSopenharmony_cistatic int 851d4afb5ceSopenharmony_cirops_alpn_negotiated_h1(struct lws *wsi, const char *alpn) 852d4afb5ceSopenharmony_ci{ 853d4afb5ceSopenharmony_ci lwsl_debug("%s: client %d\n", __func__, lwsi_role_client(wsi)); 854d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CLIENT) 855d4afb5ceSopenharmony_ci if (lwsi_role_client(wsi)) { 856d4afb5ceSopenharmony_ci /* 857d4afb5ceSopenharmony_ci * If alpn asserts it is http/1.1, server support for KA is 858d4afb5ceSopenharmony_ci * mandatory. 859d4afb5ceSopenharmony_ci * 860d4afb5ceSopenharmony_ci * Knowing this lets us proceed with sending pipelined headers 861d4afb5ceSopenharmony_ci * before we received the first response headers. 862d4afb5ceSopenharmony_ci */ 863d4afb5ceSopenharmony_ci wsi->keepalive_active = 1; 864d4afb5ceSopenharmony_ci } 865d4afb5ceSopenharmony_ci#endif 866d4afb5ceSopenharmony_ci 867d4afb5ceSopenharmony_ci return 0; 868d4afb5ceSopenharmony_ci} 869d4afb5ceSopenharmony_ci 870d4afb5ceSopenharmony_cistatic int 871d4afb5ceSopenharmony_cirops_destroy_role_h1(struct lws *wsi) 872d4afb5ceSopenharmony_ci{ 873d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; 874d4afb5ceSopenharmony_ci struct allocated_headers *ah; 875d4afb5ceSopenharmony_ci 876d4afb5ceSopenharmony_ci /* we may not have an ah, but may be on the waiting list... */ 877d4afb5ceSopenharmony_ci lwsl_info("%s: ah det due to close\n", __func__); 878d4afb5ceSopenharmony_ci __lws_header_table_detach(wsi, 0); 879d4afb5ceSopenharmony_ci 880d4afb5ceSopenharmony_ci ah = pt->http.ah_list; 881d4afb5ceSopenharmony_ci 882d4afb5ceSopenharmony_ci while (ah) { 883d4afb5ceSopenharmony_ci if (ah->in_use && ah->wsi == wsi) { 884d4afb5ceSopenharmony_ci lwsl_err("%s: ah leak: wsi %s\n", __func__, 885d4afb5ceSopenharmony_ci lws_wsi_tag(wsi)); 886d4afb5ceSopenharmony_ci ah->in_use = 0; 887d4afb5ceSopenharmony_ci ah->wsi = NULL; 888d4afb5ceSopenharmony_ci pt->http.ah_count_in_use--; 889d4afb5ceSopenharmony_ci break; 890d4afb5ceSopenharmony_ci } 891d4afb5ceSopenharmony_ci ah = ah->next; 892d4afb5ceSopenharmony_ci } 893d4afb5ceSopenharmony_ci 894d4afb5ceSopenharmony_ci#if defined(LWS_WITH_HTTP_STREAM_COMPRESSION) 895d4afb5ceSopenharmony_ci lws_http_compression_destroy(wsi); 896d4afb5ceSopenharmony_ci#endif 897d4afb5ceSopenharmony_ci 898d4afb5ceSopenharmony_ci#ifdef LWS_ROLE_WS 899d4afb5ceSopenharmony_ci lws_free_set_NULL(wsi->ws); 900d4afb5ceSopenharmony_ci#endif 901d4afb5ceSopenharmony_ci return 0; 902d4afb5ceSopenharmony_ci} 903d4afb5ceSopenharmony_ci 904d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER) 905d4afb5ceSopenharmony_ci 906d4afb5ceSopenharmony_cistatic int 907d4afb5ceSopenharmony_cirops_adoption_bind_h1(struct lws *wsi, int type, const char *vh_prot_name) 908d4afb5ceSopenharmony_ci{ 909d4afb5ceSopenharmony_ci if (!(type & LWS_ADOPT_HTTP)) 910d4afb5ceSopenharmony_ci return 0; /* no match */ 911d4afb5ceSopenharmony_ci 912d4afb5ceSopenharmony_ci if (type & _LWS_ADOPT_FINISH && !lwsi_role_http(wsi)) 913d4afb5ceSopenharmony_ci return 0; 914d4afb5ceSopenharmony_ci 915d4afb5ceSopenharmony_ci if (type & _LWS_ADOPT_FINISH) { 916d4afb5ceSopenharmony_ci if (!lws_header_table_attach(wsi, 0)) 917d4afb5ceSopenharmony_ci lwsl_debug("Attached ah immediately\n"); 918d4afb5ceSopenharmony_ci else 919d4afb5ceSopenharmony_ci lwsl_info("%s: waiting for ah\n", __func__); 920d4afb5ceSopenharmony_ci 921d4afb5ceSopenharmony_ci return 1; 922d4afb5ceSopenharmony_ci } 923d4afb5ceSopenharmony_ci 924d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER) && defined(LWS_WITH_SECURE_STREAMS) 925d4afb5ceSopenharmony_ci if (wsi->a.vhost->ss_handle && 926d4afb5ceSopenharmony_ci wsi->a.vhost->ss_handle->policy->protocol == LWSSSP_RAW) { 927d4afb5ceSopenharmony_ci lws_role_transition(wsi, LWSIFR_SERVER, (type & LWS_ADOPT_ALLOW_SSL) ? 928d4afb5ceSopenharmony_ci LRS_SSL_INIT : LRS_ESTABLISHED, &role_ops_raw_skt); 929d4afb5ceSopenharmony_ci return 1; 930d4afb5ceSopenharmony_ci } 931d4afb5ceSopenharmony_ci#endif 932d4afb5ceSopenharmony_ci 933d4afb5ceSopenharmony_ci /* If Non-TLS and HTTP2 prior knowledge is enabled, skip to clear text HTTP2 */ 934d4afb5ceSopenharmony_ci 935d4afb5ceSopenharmony_ci#if defined(LWS_WITH_HTTP2) 936d4afb5ceSopenharmony_ci if ((!(type & LWS_ADOPT_ALLOW_SSL)) && (wsi->a.vhost->options & LWS_SERVER_OPTION_H2_PRIOR_KNOWLEDGE)) { 937d4afb5ceSopenharmony_ci lwsl_info("http/2 prior knowledge\n"); 938d4afb5ceSopenharmony_ci lws_metrics_tag_wsi_add(wsi, "upg", "h2_prior"); 939d4afb5ceSopenharmony_ci lws_role_call_alpn_negotiated(wsi, "h2"); 940d4afb5ceSopenharmony_ci } 941d4afb5ceSopenharmony_ci else 942d4afb5ceSopenharmony_ci#endif 943d4afb5ceSopenharmony_ci lws_role_transition(wsi, LWSIFR_SERVER, (type & LWS_ADOPT_ALLOW_SSL) ? 944d4afb5ceSopenharmony_ci LRS_SSL_INIT : LRS_HEADERS, &role_ops_h1); 945d4afb5ceSopenharmony_ci 946d4afb5ceSopenharmony_ci /* 947d4afb5ceSopenharmony_ci * Otherwise, we have to bind to h1 as a default even when we're actually going to 948d4afb5ceSopenharmony_ci * replace it as an h2 bind later. So don't take this seriously if the 949d4afb5ceSopenharmony_ci * default is disabled (ws upgrade caees properly about it) 950d4afb5ceSopenharmony_ci */ 951d4afb5ceSopenharmony_ci 952d4afb5ceSopenharmony_ci if (!vh_prot_name && wsi->a.vhost->default_protocol_index < 953d4afb5ceSopenharmony_ci wsi->a.vhost->count_protocols) 954d4afb5ceSopenharmony_ci wsi->a.protocol = &wsi->a.vhost->protocols[ 955d4afb5ceSopenharmony_ci wsi->a.vhost->default_protocol_index]; 956d4afb5ceSopenharmony_ci else 957d4afb5ceSopenharmony_ci wsi->a.protocol = &wsi->a.vhost->protocols[0]; 958d4afb5ceSopenharmony_ci 959d4afb5ceSopenharmony_ci /* the transport is accepted... give him time to negotiate */ 960d4afb5ceSopenharmony_ci lws_set_timeout(wsi, PENDING_TIMEOUT_ESTABLISH_WITH_SERVER, 961d4afb5ceSopenharmony_ci (int)wsi->a.context->timeout_secs); 962d4afb5ceSopenharmony_ci 963d4afb5ceSopenharmony_ci return 1; /* bound */ 964d4afb5ceSopenharmony_ci} 965d4afb5ceSopenharmony_ci 966d4afb5ceSopenharmony_ci#endif 967d4afb5ceSopenharmony_ci 968d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CLIENT) 969d4afb5ceSopenharmony_ci 970d4afb5ceSopenharmony_cistatic const char * const http_methods[] = { 971d4afb5ceSopenharmony_ci "GET", "POST", "OPTIONS", "HEAD", "PUT", "PATCH", "DELETE", "CONNECT" 972d4afb5ceSopenharmony_ci}; 973d4afb5ceSopenharmony_ci 974d4afb5ceSopenharmony_cistatic int 975d4afb5ceSopenharmony_cirops_client_bind_h1(struct lws *wsi, const struct lws_client_connect_info *i) 976d4afb5ceSopenharmony_ci{ 977d4afb5ceSopenharmony_ci int n; 978d4afb5ceSopenharmony_ci 979d4afb5ceSopenharmony_ci if (!i) { 980d4afb5ceSopenharmony_ci /* we are finalizing an already-selected role */ 981d4afb5ceSopenharmony_ci 982d4afb5ceSopenharmony_ci /* 983d4afb5ceSopenharmony_ci * If we stay in http, assuming there wasn't already-set 984d4afb5ceSopenharmony_ci * external user_space, since we know our initial protocol 985d4afb5ceSopenharmony_ci * we can assign the user space now, otherwise do it after the 986d4afb5ceSopenharmony_ci * ws subprotocol negotiated 987d4afb5ceSopenharmony_ci */ 988d4afb5ceSopenharmony_ci if (!wsi->user_space && wsi->stash->cis[CIS_METHOD]) 989d4afb5ceSopenharmony_ci if (lws_ensure_user_space(wsi)) 990d4afb5ceSopenharmony_ci return 1; 991d4afb5ceSopenharmony_ci 992d4afb5ceSopenharmony_ci /* 993d4afb5ceSopenharmony_ci * For ws, default to http/1.1 only. If i->alpn had been set 994d4afb5ceSopenharmony_ci * though, defer to whatever he has set in there (eg, "h2"). 995d4afb5ceSopenharmony_ci * 996d4afb5ceSopenharmony_ci * The problem is he has to commit to h2 before he can find 997d4afb5ceSopenharmony_ci * out if the server has the SETTINGS for ws-over-h2 enabled; 998d4afb5ceSopenharmony_ci * if not then ws is not possible on that connection. So we 999d4afb5ceSopenharmony_ci * only try h2 if he assertively said to use h2 alpn, otherwise 1000d4afb5ceSopenharmony_ci * ws implies alpn restriction to h1. 1001d4afb5ceSopenharmony_ci */ 1002d4afb5ceSopenharmony_ci if (!wsi->stash->cis[CIS_METHOD] && !wsi->stash->cis[CIS_ALPN]) 1003d4afb5ceSopenharmony_ci wsi->stash->cis[CIS_ALPN] = "http/1.1"; 1004d4afb5ceSopenharmony_ci 1005d4afb5ceSopenharmony_ci /* if we went on the ah waiting list, it's ok, we can wait. 1006d4afb5ceSopenharmony_ci * 1007d4afb5ceSopenharmony_ci * When we do get the ah, now or later, he will end up at 1008d4afb5ceSopenharmony_ci * lws_http_client_connect_via_info2(). 1009d4afb5ceSopenharmony_ci */ 1010d4afb5ceSopenharmony_ci if (lws_header_table_attach(wsi, 0) 1011d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CLIENT) 1012d4afb5ceSopenharmony_ci < 0) 1013d4afb5ceSopenharmony_ci /* 1014d4afb5ceSopenharmony_ci * if we failed here, the connection is already closed 1015d4afb5ceSopenharmony_ci * and freed. 1016d4afb5ceSopenharmony_ci */ 1017d4afb5ceSopenharmony_ci return -1; 1018d4afb5ceSopenharmony_ci#else 1019d4afb5ceSopenharmony_ci ) 1020d4afb5ceSopenharmony_ci return 0; 1021d4afb5ceSopenharmony_ci#endif 1022d4afb5ceSopenharmony_ci 1023d4afb5ceSopenharmony_ci return 0; 1024d4afb5ceSopenharmony_ci } 1025d4afb5ceSopenharmony_ci 1026d4afb5ceSopenharmony_ci /* 1027d4afb5ceSopenharmony_ci * Clients that want to be h1, h2, or ws all start out as h1 1028d4afb5ceSopenharmony_ci * (we don't yet know if the server supports h2 or ws), unless their 1029d4afb5ceSopenharmony_ci * alpn is only "h2" 1030d4afb5ceSopenharmony_ci */ 1031d4afb5ceSopenharmony_ci 1032d4afb5ceSopenharmony_ci// if (i->alpn && !strcmp(i->alpn, "h2")) 1033d4afb5ceSopenharmony_ci// return 0; /* we are h1, he only wants h2 */ 1034d4afb5ceSopenharmony_ci 1035d4afb5ceSopenharmony_ci if (!i->method) { /* websockets */ 1036d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_WS) 1037d4afb5ceSopenharmony_ci if (lws_create_client_ws_object(i, wsi)) 1038d4afb5ceSopenharmony_ci goto fail_wsi; 1039d4afb5ceSopenharmony_ci 1040d4afb5ceSopenharmony_ci goto bind_h1; 1041d4afb5ceSopenharmony_ci#else 1042d4afb5ceSopenharmony_ci lwsl_err("%s: ws role not configured\n", __func__); 1043d4afb5ceSopenharmony_ci 1044d4afb5ceSopenharmony_ci goto fail_wsi; 1045d4afb5ceSopenharmony_ci#endif 1046d4afb5ceSopenharmony_ci } 1047d4afb5ceSopenharmony_ci 1048d4afb5ceSopenharmony_ci /* if a recognized http method, bind to it */ 1049d4afb5ceSopenharmony_ci 1050d4afb5ceSopenharmony_ci for (n = 0; n < (int)LWS_ARRAY_SIZE(http_methods); n++) 1051d4afb5ceSopenharmony_ci if (!strcmp(i->method, http_methods[n])) 1052d4afb5ceSopenharmony_ci goto bind_h1; 1053d4afb5ceSopenharmony_ci 1054d4afb5ceSopenharmony_ci /* other roles may bind to it */ 1055d4afb5ceSopenharmony_ci 1056d4afb5ceSopenharmony_ci return 0; /* no match */ 1057d4afb5ceSopenharmony_ci 1058d4afb5ceSopenharmony_cibind_h1: 1059d4afb5ceSopenharmony_ci /* assert the mode and union status (hdr) clearly */ 1060d4afb5ceSopenharmony_ci lws_role_transition(wsi, LWSIFR_CLIENT, LRS_UNCONNECTED, &role_ops_h1); 1061d4afb5ceSopenharmony_ci 1062d4afb5ceSopenharmony_ci return 1; /* matched */ 1063d4afb5ceSopenharmony_ci 1064d4afb5ceSopenharmony_cifail_wsi: 1065d4afb5ceSopenharmony_ci return -1; 1066d4afb5ceSopenharmony_ci} 1067d4afb5ceSopenharmony_ci#endif 1068d4afb5ceSopenharmony_ci 1069d4afb5ceSopenharmony_cistatic int 1070d4afb5ceSopenharmony_cirops_close_kill_connection_h1(struct lws *wsi, enum lws_close_status reason) 1071d4afb5ceSopenharmony_ci{ 1072d4afb5ceSopenharmony_ci#if defined(LWS_WITH_HTTP_PROXY) 1073d4afb5ceSopenharmony_ci if (!wsi->http.proxy_clientside) 1074d4afb5ceSopenharmony_ci return 0; 1075d4afb5ceSopenharmony_ci 1076d4afb5ceSopenharmony_ci wsi->http.proxy_clientside = 0; 1077d4afb5ceSopenharmony_ci 1078d4afb5ceSopenharmony_ci if (user_callback_handle_rxflow(wsi->a.protocol->callback, wsi, 1079d4afb5ceSopenharmony_ci LWS_CALLBACK_COMPLETED_CLIENT_HTTP, 1080d4afb5ceSopenharmony_ci wsi->user_space, NULL, 0)) 1081d4afb5ceSopenharmony_ci return 0; 1082d4afb5ceSopenharmony_ci#endif 1083d4afb5ceSopenharmony_ci return 0; 1084d4afb5ceSopenharmony_ci} 1085d4afb5ceSopenharmony_ci 1086d4afb5ceSopenharmony_ciint 1087d4afb5ceSopenharmony_cirops_pt_init_destroy_h1(struct lws_context *context, 1088d4afb5ceSopenharmony_ci const struct lws_context_creation_info *info, 1089d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt, int destroy) 1090d4afb5ceSopenharmony_ci{ 1091d4afb5ceSopenharmony_ci /* 1092d4afb5ceSopenharmony_ci * We only want to do this once... we will do it if no h2 support 1093d4afb5ceSopenharmony_ci * otherwise let h2 ops do it. 1094d4afb5ceSopenharmony_ci */ 1095d4afb5ceSopenharmony_ci#if !defined(LWS_ROLE_H2) && defined(LWS_WITH_SERVER) 1096d4afb5ceSopenharmony_ci if (!destroy) { 1097d4afb5ceSopenharmony_ci 1098d4afb5ceSopenharmony_ci pt->sul_ah_lifecheck.cb = lws_sul_http_ah_lifecheck; 1099d4afb5ceSopenharmony_ci 1100d4afb5ceSopenharmony_ci __lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], 1101d4afb5ceSopenharmony_ci &pt->sul_ah_lifecheck, 30 * LWS_US_PER_SEC); 1102d4afb5ceSopenharmony_ci } else 1103d4afb5ceSopenharmony_ci lws_dll2_remove(&pt->sul_ah_lifecheck.list); 1104d4afb5ceSopenharmony_ci#endif 1105d4afb5ceSopenharmony_ci 1106d4afb5ceSopenharmony_ci return 0; 1107d4afb5ceSopenharmony_ci} 1108d4afb5ceSopenharmony_ci 1109d4afb5ceSopenharmony_cistatic const lws_rops_t rops_table_h1[] = { 1110d4afb5ceSopenharmony_ci /* 1 */ { .pt_init_destroy = rops_pt_init_destroy_h1 }, 1111d4afb5ceSopenharmony_ci /* 2 */ { .handle_POLLIN = rops_handle_POLLIN_h1 }, 1112d4afb5ceSopenharmony_ci /* 3 */ { .handle_POLLOUT = rops_handle_POLLOUT_h1 }, 1113d4afb5ceSopenharmony_ci /* 4 */ { .write_role_protocol = rops_write_role_protocol_h1 }, 1114d4afb5ceSopenharmony_ci /* 5 */ { .alpn_negotiated = rops_alpn_negotiated_h1 }, 1115d4afb5ceSopenharmony_ci /* 6 */ { .close_kill_connection = rops_close_kill_connection_h1 }, 1116d4afb5ceSopenharmony_ci /* 7 */ { .destroy_role = rops_destroy_role_h1 }, 1117d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER) 1118d4afb5ceSopenharmony_ci /* 8 */ { .adoption_bind = rops_adoption_bind_h1 }, 1119d4afb5ceSopenharmony_ci#endif 1120d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CLIENT) 1121d4afb5ceSopenharmony_ci /* 8 if client and no server */ 1122d4afb5ceSopenharmony_ci /* 9 */ { .client_bind = rops_client_bind_h1 }, 1123d4afb5ceSopenharmony_ci#endif 1124d4afb5ceSopenharmony_ci}; 1125d4afb5ceSopenharmony_ci 1126d4afb5ceSopenharmony_ciconst struct lws_role_ops role_ops_h1 = { 1127d4afb5ceSopenharmony_ci /* role name */ "h1", 1128d4afb5ceSopenharmony_ci /* alpn id */ "http/1.1", 1129d4afb5ceSopenharmony_ci /* rops_table */ rops_table_h1, 1130d4afb5ceSopenharmony_ci /* rops_idx */ { 1131d4afb5ceSopenharmony_ci /* LWS_ROPS_check_upgrades */ 1132d4afb5ceSopenharmony_ci /* LWS_ROPS_pt_init_destroy */ 0x01, 1133d4afb5ceSopenharmony_ci /* LWS_ROPS_init_vhost */ 1134d4afb5ceSopenharmony_ci /* LWS_ROPS_destroy_vhost */ 0x00, 1135d4afb5ceSopenharmony_ci /* LWS_ROPS_service_flag_pending */ 1136d4afb5ceSopenharmony_ci /* LWS_ROPS_handle_POLLIN */ 0x02, 1137d4afb5ceSopenharmony_ci /* LWS_ROPS_handle_POLLOUT */ 1138d4afb5ceSopenharmony_ci /* LWS_ROPS_perform_user_POLLOUT */ 0x30, 1139d4afb5ceSopenharmony_ci /* LWS_ROPS_callback_on_writable */ 1140d4afb5ceSopenharmony_ci /* LWS_ROPS_tx_credit */ 0x00, 1141d4afb5ceSopenharmony_ci /* LWS_ROPS_write_role_protocol */ 1142d4afb5ceSopenharmony_ci /* LWS_ROPS_encapsulation_parent */ 0x40, 1143d4afb5ceSopenharmony_ci /* LWS_ROPS_alpn_negotiated */ 1144d4afb5ceSopenharmony_ci /* LWS_ROPS_close_via_role_protocol */ 0x50, 1145d4afb5ceSopenharmony_ci /* LWS_ROPS_close_role */ 1146d4afb5ceSopenharmony_ci /* LWS_ROPS_close_kill_connection */ 0x06, 1147d4afb5ceSopenharmony_ci /* LWS_ROPS_destroy_role */ 1148d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER) 1149d4afb5ceSopenharmony_ci /* LWS_ROPS_adoption_bind */ 0x78, 1150d4afb5ceSopenharmony_ci#else 1151d4afb5ceSopenharmony_ci /* LWS_ROPS_adoption_bind */ 0x70, 1152d4afb5ceSopenharmony_ci#endif 1153d4afb5ceSopenharmony_ci /* LWS_ROPS_client_bind */ 1154d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CLIENT) 1155d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER) 1156d4afb5ceSopenharmony_ci /* LWS_ROPS_issue_keepalive */ 0x90, 1157d4afb5ceSopenharmony_ci#else 1158d4afb5ceSopenharmony_ci /* LWS_ROPS_issue_keepalive */ 0x80, 1159d4afb5ceSopenharmony_ci#endif 1160d4afb5ceSopenharmony_ci#else 1161d4afb5ceSopenharmony_ci /* LWS_ROPS_issue_keepalive */ 0x00, 1162d4afb5ceSopenharmony_ci#endif 1163d4afb5ceSopenharmony_ci }, 1164d4afb5ceSopenharmony_ci /* adoption_cb clnt, srv */ { LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED, 1165d4afb5ceSopenharmony_ci LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED }, 1166d4afb5ceSopenharmony_ci /* rx_cb clnt, srv */ { LWS_CALLBACK_RECEIVE_CLIENT_HTTP, 1167d4afb5ceSopenharmony_ci 0 /* may be POST, etc */ }, 1168d4afb5ceSopenharmony_ci /* writeable cb clnt, srv */ { LWS_CALLBACK_CLIENT_HTTP_WRITEABLE, 1169d4afb5ceSopenharmony_ci LWS_CALLBACK_HTTP_WRITEABLE }, 1170d4afb5ceSopenharmony_ci /* close cb clnt, srv */ { LWS_CALLBACK_CLOSED_CLIENT_HTTP, 1171d4afb5ceSopenharmony_ci LWS_CALLBACK_CLOSED_HTTP }, 1172d4afb5ceSopenharmony_ci /* protocol_bind cb c, srv */ { LWS_CALLBACK_CLIENT_HTTP_BIND_PROTOCOL, 1173d4afb5ceSopenharmony_ci LWS_CALLBACK_HTTP_BIND_PROTOCOL }, 1174d4afb5ceSopenharmony_ci /* protocol_unbind cb c, srv */ { LWS_CALLBACK_CLIENT_HTTP_DROP_PROTOCOL, 1175d4afb5ceSopenharmony_ci LWS_CALLBACK_HTTP_DROP_PROTOCOL }, 1176d4afb5ceSopenharmony_ci /* file_handle */ 0, 1177d4afb5ceSopenharmony_ci}; 1178