1d4afb5ceSopenharmony_ci/* 2d4afb5ceSopenharmony_ci * libwebsockets - small server side websockets and web server implementation 3d4afb5ceSopenharmony_ci * 4d4afb5ceSopenharmony_ci * Copyright (C) 2010 - 2021 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_cistruct lws * 28d4afb5ceSopenharmony_cilws_client_connect_4_established(struct lws *wsi, struct lws *wsi_piggyback, 29d4afb5ceSopenharmony_ci ssize_t plen) 30d4afb5ceSopenharmony_ci{ 31d4afb5ceSopenharmony_ci#if defined(LWS_CLIENT_HTTP_PROXYING) 32d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; 33d4afb5ceSopenharmony_ci#endif 34d4afb5ceSopenharmony_ci const char *meth; 35d4afb5ceSopenharmony_ci struct lws_pollfd pfd; 36d4afb5ceSopenharmony_ci const char *cce = ""; 37d4afb5ceSopenharmony_ci int n, m, rawish = 0; 38d4afb5ceSopenharmony_ci 39d4afb5ceSopenharmony_ci meth = lws_wsi_client_stash_item(wsi, CIS_METHOD, 40d4afb5ceSopenharmony_ci _WSI_TOKEN_CLIENT_METHOD); 41d4afb5ceSopenharmony_ci 42d4afb5ceSopenharmony_ci if (meth && (!strcmp(meth, "RAW") 43d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_MQTT) 44d4afb5ceSopenharmony_ci || !strcmp(meth, "MQTT") 45d4afb5ceSopenharmony_ci#endif 46d4afb5ceSopenharmony_ci )) 47d4afb5ceSopenharmony_ci rawish = 1; 48d4afb5ceSopenharmony_ci 49d4afb5ceSopenharmony_ci if (wsi_piggyback) 50d4afb5ceSopenharmony_ci goto send_hs; 51d4afb5ceSopenharmony_ci 52d4afb5ceSopenharmony_ci#if defined(LWS_CLIENT_HTTP_PROXYING) 53d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) 54d4afb5ceSopenharmony_ci /* we are connected to server, or proxy */ 55d4afb5ceSopenharmony_ci 56d4afb5ceSopenharmony_ci /* http proxy */ 57d4afb5ceSopenharmony_ci if (wsi->a.vhost->http.http_proxy_port) { 58d4afb5ceSopenharmony_ci const char *cpa; 59d4afb5ceSopenharmony_ci 60d4afb5ceSopenharmony_ci cpa = lws_wsi_client_stash_item(wsi, CIS_ADDRESS, 61d4afb5ceSopenharmony_ci _WSI_TOKEN_CLIENT_PEER_ADDRESS); 62d4afb5ceSopenharmony_ci if (!cpa) 63d4afb5ceSopenharmony_ci goto failed; 64d4afb5ceSopenharmony_ci 65d4afb5ceSopenharmony_ci lwsl_wsi_info(wsi, "going via proxy"); 66d4afb5ceSopenharmony_ci 67d4afb5ceSopenharmony_ci plen = lws_snprintf((char *)pt->serv_buf, 256, 68d4afb5ceSopenharmony_ci "CONNECT %s:%u HTTP/1.1\x0d\x0a" 69d4afb5ceSopenharmony_ci "Host: %s:%u\x0d\x0a" 70d4afb5ceSopenharmony_ci "User-agent: lws\x0d\x0a", cpa, wsi->ocport, 71d4afb5ceSopenharmony_ci cpa, wsi->ocport); 72d4afb5ceSopenharmony_ci 73d4afb5ceSopenharmony_ci#if defined(LWS_WITH_HTTP_BASIC_AUTH) 74d4afb5ceSopenharmony_ci if (wsi->a.vhost->proxy_basic_auth_token[0]) 75d4afb5ceSopenharmony_ci plen += lws_snprintf((char *)pt->serv_buf + plen, 256, 76d4afb5ceSopenharmony_ci "Proxy-authorization: basic %s\x0d\x0a", 77d4afb5ceSopenharmony_ci wsi->a.vhost->proxy_basic_auth_token); 78d4afb5ceSopenharmony_ci#endif 79d4afb5ceSopenharmony_ci 80d4afb5ceSopenharmony_ci plen += lws_snprintf((char *)pt->serv_buf + plen, 5, 81d4afb5ceSopenharmony_ci "\x0d\x0a"); 82d4afb5ceSopenharmony_ci 83d4afb5ceSopenharmony_ci /* lwsl_hexdump_notice(pt->serv_buf, plen); */ 84d4afb5ceSopenharmony_ci 85d4afb5ceSopenharmony_ci /* 86d4afb5ceSopenharmony_ci * OK from now on we talk via the proxy, so connect to that 87d4afb5ceSopenharmony_ci */ 88d4afb5ceSopenharmony_ci if (wsi->stash) 89d4afb5ceSopenharmony_ci wsi->stash->cis[CIS_ADDRESS] = 90d4afb5ceSopenharmony_ci wsi->a.vhost->http.http_proxy_address; 91d4afb5ceSopenharmony_ci else 92d4afb5ceSopenharmony_ci if (lws_hdr_simple_create(wsi, 93d4afb5ceSopenharmony_ci _WSI_TOKEN_CLIENT_PEER_ADDRESS, 94d4afb5ceSopenharmony_ci wsi->a.vhost->http.http_proxy_address)) 95d4afb5ceSopenharmony_ci goto failed; 96d4afb5ceSopenharmony_ci wsi->c_port = (uint16_t)wsi->a.vhost->http.http_proxy_port; 97d4afb5ceSopenharmony_ci 98d4afb5ceSopenharmony_ci n = (int)send(wsi->desc.sockfd, (char *)pt->serv_buf, 99d4afb5ceSopenharmony_ci (unsigned int)plen, 100d4afb5ceSopenharmony_ci MSG_NOSIGNAL); 101d4afb5ceSopenharmony_ci if (n < 0) { 102d4afb5ceSopenharmony_ci lwsl_wsi_debug(wsi, "ERROR writing to proxy socket"); 103d4afb5ceSopenharmony_ci cce = "proxy write failed"; 104d4afb5ceSopenharmony_ci goto failed; 105d4afb5ceSopenharmony_ci } 106d4afb5ceSopenharmony_ci 107d4afb5ceSopenharmony_ci lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_PROXY_RESPONSE, 108d4afb5ceSopenharmony_ci (int)wsi->a.context->timeout_secs); 109d4afb5ceSopenharmony_ci 110d4afb5ceSopenharmony_ci wsi->conn_port = wsi->c_port; 111d4afb5ceSopenharmony_ci lwsi_set_state(wsi, LRS_WAITING_PROXY_REPLY); 112d4afb5ceSopenharmony_ci 113d4afb5ceSopenharmony_ci return wsi; 114d4afb5ceSopenharmony_ci } 115d4afb5ceSopenharmony_ci#endif 116d4afb5ceSopenharmony_ci#endif 117d4afb5ceSopenharmony_ci 118d4afb5ceSopenharmony_ci /* coverity */ 119d4afb5ceSopenharmony_ci if (!wsi->a.protocol) 120d4afb5ceSopenharmony_ci return NULL; 121d4afb5ceSopenharmony_ci 122d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SOCKS5) 123d4afb5ceSopenharmony_ci if (lwsi_state(wsi) != LRS_ESTABLISHED) 124d4afb5ceSopenharmony_ci switch (lws_socks5c_greet(wsi, &cce)) { 125d4afb5ceSopenharmony_ci case -1: 126d4afb5ceSopenharmony_ci goto failed; 127d4afb5ceSopenharmony_ci case 1: 128d4afb5ceSopenharmony_ci return wsi; 129d4afb5ceSopenharmony_ci default: 130d4afb5ceSopenharmony_ci break; 131d4afb5ceSopenharmony_ci } 132d4afb5ceSopenharmony_ci#endif 133d4afb5ceSopenharmony_ci 134d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) 135d4afb5ceSopenharmony_cisend_hs: 136d4afb5ceSopenharmony_ci 137d4afb5ceSopenharmony_ci if (wsi_piggyback && 138d4afb5ceSopenharmony_ci !lws_dll2_is_detached(&wsi->dll2_cli_txn_queue)) { 139d4afb5ceSopenharmony_ci /* 140d4afb5ceSopenharmony_ci * We are pipelining on an already-established connection... 141d4afb5ceSopenharmony_ci * we can skip tls establishment. 142d4afb5ceSopenharmony_ci * 143d4afb5ceSopenharmony_ci * Set these queued guys to a state where they won't actually 144d4afb5ceSopenharmony_ci * send their headers until we decide later. 145d4afb5ceSopenharmony_ci */ 146d4afb5ceSopenharmony_ci 147d4afb5ceSopenharmony_ci lwsi_set_state(wsi, LRS_H2_WAITING_TO_SEND_HEADERS); 148d4afb5ceSopenharmony_ci 149d4afb5ceSopenharmony_ci /* 150d4afb5ceSopenharmony_ci * we can't send our headers directly, because they have to 151d4afb5ceSopenharmony_ci * be sent when the parent is writeable. The parent will check 152d4afb5ceSopenharmony_ci * for anybody on his client transaction queue that is in 153d4afb5ceSopenharmony_ci * LRS_H1C_ISSUE_HANDSHAKE2, and let them write. 154d4afb5ceSopenharmony_ci * 155d4afb5ceSopenharmony_ci * If we are trying to do this too early, before the network 156d4afb5ceSopenharmony_ci * connection has written his own headers, then it will just 157d4afb5ceSopenharmony_ci * wait in the queue until it's possible to send them. 158d4afb5ceSopenharmony_ci */ 159d4afb5ceSopenharmony_ci lws_callback_on_writable(wsi_piggyback); 160d4afb5ceSopenharmony_ci 161d4afb5ceSopenharmony_ci lwsl_wsi_info(wsi, "waiting to send hdrs (par state 0x%x)", 162d4afb5ceSopenharmony_ci lwsi_state(wsi_piggyback)); 163d4afb5ceSopenharmony_ci } else { 164d4afb5ceSopenharmony_ci lwsl_wsi_info(wsi, "%s %s client created own conn " 165d4afb5ceSopenharmony_ci "(raw %d) vh %s st 0x%x", 166d4afb5ceSopenharmony_ci wsi->role_ops->name, wsi->a.protocol->name, rawish, 167d4afb5ceSopenharmony_ci wsi->a.vhost->name, lwsi_state(wsi)); 168d4afb5ceSopenharmony_ci 169d4afb5ceSopenharmony_ci /* we are making our own connection */ 170d4afb5ceSopenharmony_ci 171d4afb5ceSopenharmony_ci if (!rawish 172d4afb5ceSopenharmony_ci#if defined(LWS_WITH_TLS) 173d4afb5ceSopenharmony_ci // && (!(wsi->tls.use_ssl & LCCSCF_USE_SSL) || wsi->tls.ssl) 174d4afb5ceSopenharmony_ci#endif 175d4afb5ceSopenharmony_ci ) { 176d4afb5ceSopenharmony_ci 177d4afb5ceSopenharmony_ci if (lwsi_state(wsi) != LRS_H1C_ISSUE_HANDSHAKE2) 178d4afb5ceSopenharmony_ci lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE); 179d4afb5ceSopenharmony_ci } else { 180d4afb5ceSopenharmony_ci /* for a method = "RAW" connection, this makes us 181d4afb5ceSopenharmony_ci * established */ 182d4afb5ceSopenharmony_ci 183d4afb5ceSopenharmony_ci#if defined(LWS_WITH_TLS)// && !defined(LWS_WITH_MBEDTLS) 184d4afb5ceSopenharmony_ci 185d4afb5ceSopenharmony_ci /* we have connected if we got here */ 186d4afb5ceSopenharmony_ci 187d4afb5ceSopenharmony_ci if (lwsi_state(wsi) == LRS_WAITING_CONNECT && 188d4afb5ceSopenharmony_ci (wsi->tls.use_ssl & LCCSCF_USE_SSL)) { 189d4afb5ceSopenharmony_ci int result; 190d4afb5ceSopenharmony_ci 191d4afb5ceSopenharmony_ci //lwsi_set_state(wsi, LRS_WAITING_SSL); 192d4afb5ceSopenharmony_ci 193d4afb5ceSopenharmony_ci /* 194d4afb5ceSopenharmony_ci * We can retry this... just cook the SSL BIO 195d4afb5ceSopenharmony_ci * the first time 196d4afb5ceSopenharmony_ci */ 197d4afb5ceSopenharmony_ci 198d4afb5ceSopenharmony_ci result = lws_client_create_tls(wsi, &cce, 1); 199d4afb5ceSopenharmony_ci switch (result) { 200d4afb5ceSopenharmony_ci case CCTLS_RETURN_DONE: 201d4afb5ceSopenharmony_ci break; 202d4afb5ceSopenharmony_ci case CCTLS_RETURN_RETRY: 203d4afb5ceSopenharmony_ci lwsl_wsi_debug(wsi, "create_tls RETRY"); 204d4afb5ceSopenharmony_ci return wsi; 205d4afb5ceSopenharmony_ci default: 206d4afb5ceSopenharmony_ci lwsl_wsi_debug(wsi, "create_tls FAIL"); 207d4afb5ceSopenharmony_ci goto failed; 208d4afb5ceSopenharmony_ci } 209d4afb5ceSopenharmony_ci 210d4afb5ceSopenharmony_ci /* 211d4afb5ceSopenharmony_ci * We succeeded to negotiate a new client tls 212d4afb5ceSopenharmony_ci * tunnel. If it's h2 alpn, we have arranged 213d4afb5ceSopenharmony_ci * to send the h2 prefix and set our state to 214d4afb5ceSopenharmony_ci * LRS_H2_WAITING_TO_SEND_HEADERS already. 215d4afb5ceSopenharmony_ci */ 216d4afb5ceSopenharmony_ci 217d4afb5ceSopenharmony_ci lwsl_wsi_notice(wsi, "tls established st 0x%x, " 218d4afb5ceSopenharmony_ci "client_h2_alpn %d", lwsi_state(wsi), 219d4afb5ceSopenharmony_ci wsi->client_h2_alpn); 220d4afb5ceSopenharmony_ci 221d4afb5ceSopenharmony_ci if (lwsi_state(wsi) != 222d4afb5ceSopenharmony_ci LRS_H2_WAITING_TO_SEND_HEADERS) 223d4afb5ceSopenharmony_ci lwsi_set_state(wsi, 224d4afb5ceSopenharmony_ci LRS_H1C_ISSUE_HANDSHAKE2); 225d4afb5ceSopenharmony_ci lws_set_timeout(wsi, 226d4afb5ceSopenharmony_ci PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND, 227d4afb5ceSopenharmony_ci (int)wsi->a.context->timeout_secs); 228d4afb5ceSopenharmony_ci#if 0 229d4afb5ceSopenharmony_ci /* ensure pollin enabled */ 230d4afb5ceSopenharmony_ci if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) 231d4afb5ceSopenharmony_ci lwsl_wsi_notice(wsi, 232d4afb5ceSopenharmony_ci "unable to set POLLIN"); 233d4afb5ceSopenharmony_ci#endif 234d4afb5ceSopenharmony_ci 235d4afb5ceSopenharmony_ci goto provoke_service; 236d4afb5ceSopenharmony_ci } 237d4afb5ceSopenharmony_ci#endif 238d4afb5ceSopenharmony_ci 239d4afb5ceSopenharmony_ci /* clear his established timeout */ 240d4afb5ceSopenharmony_ci lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0); 241d4afb5ceSopenharmony_ci 242d4afb5ceSopenharmony_ci m = wsi->role_ops->adoption_cb[0]; 243d4afb5ceSopenharmony_ci if (m) { 244d4afb5ceSopenharmony_ci n = user_callback_handle_rxflow( 245d4afb5ceSopenharmony_ci wsi->a.protocol->callback, wsi, 246d4afb5ceSopenharmony_ci (enum lws_callback_reasons)m, 247d4afb5ceSopenharmony_ci wsi->user_space, NULL, 0); 248d4afb5ceSopenharmony_ci if (n < 0) { 249d4afb5ceSopenharmony_ci lwsl_wsi_info(wsi, "RAW_PROXY_CLI_ADOPT err"); 250d4afb5ceSopenharmony_ci goto failed; 251d4afb5ceSopenharmony_ci } 252d4afb5ceSopenharmony_ci } 253d4afb5ceSopenharmony_ci 254d4afb5ceSopenharmony_ci /* service.c pollout processing wants this */ 255d4afb5ceSopenharmony_ci wsi->hdr_parsing_completed = 1; 256d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_MQTT) 257d4afb5ceSopenharmony_ci if (meth && !strcmp(meth, "MQTT")) { 258d4afb5ceSopenharmony_ci#if defined(LWS_WITH_TLS) 259d4afb5ceSopenharmony_ci if (wsi->tls.use_ssl & LCCSCF_USE_SSL) { 260d4afb5ceSopenharmony_ci lwsi_set_state(wsi, LRS_WAITING_SSL); 261d4afb5ceSopenharmony_ci return wsi; 262d4afb5ceSopenharmony_ci } 263d4afb5ceSopenharmony_ci#endif 264d4afb5ceSopenharmony_ci lwsl_wsi_info(wsi, "settings LRS_MQTTC_IDLE"); 265d4afb5ceSopenharmony_ci lwsi_set_state(wsi, LRS_MQTTC_IDLE); 266d4afb5ceSopenharmony_ci 267d4afb5ceSopenharmony_ci /* 268d4afb5ceSopenharmony_ci * provoke service to issue the CONNECT 269d4afb5ceSopenharmony_ci * directly. 270d4afb5ceSopenharmony_ci */ 271d4afb5ceSopenharmony_ci lws_set_timeout(wsi, 272d4afb5ceSopenharmony_ci PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE, 273d4afb5ceSopenharmony_ci (int)wsi->a.context->timeout_secs); 274d4afb5ceSopenharmony_ci 275d4afb5ceSopenharmony_ci assert(lws_socket_is_valid(wsi->desc.sockfd)); 276d4afb5ceSopenharmony_ci 277d4afb5ceSopenharmony_ci pfd.fd = wsi->desc.sockfd; 278d4afb5ceSopenharmony_ci pfd.events = LWS_POLLIN; 279d4afb5ceSopenharmony_ci pfd.revents = LWS_POLLOUT; 280d4afb5ceSopenharmony_ci 281d4afb5ceSopenharmony_ci lwsl_wsi_info(wsi, "going to service fd"); 282d4afb5ceSopenharmony_ci n = lws_service_fd(wsi->a.context, &pfd); 283d4afb5ceSopenharmony_ci if (n < 0) { 284d4afb5ceSopenharmony_ci cce = "first service failed"; 285d4afb5ceSopenharmony_ci goto failed; 286d4afb5ceSopenharmony_ci } 287d4afb5ceSopenharmony_ci if (n) 288d4afb5ceSopenharmony_ci /* returns 1 on fail after close wsi */ 289d4afb5ceSopenharmony_ci return NULL; 290d4afb5ceSopenharmony_ci return wsi; 291d4afb5ceSopenharmony_ci } 292d4afb5ceSopenharmony_ci#endif 293d4afb5ceSopenharmony_ci lwsl_wsi_info(wsi, "setting ESTABLISHED"); 294d4afb5ceSopenharmony_ci lwsi_set_state(wsi, LRS_ESTABLISHED); 295d4afb5ceSopenharmony_ci 296d4afb5ceSopenharmony_ci return wsi; 297d4afb5ceSopenharmony_ci } 298d4afb5ceSopenharmony_ci 299d4afb5ceSopenharmony_ci /* 300d4afb5ceSopenharmony_ci * provoke service to issue the handshake directly. 301d4afb5ceSopenharmony_ci * 302d4afb5ceSopenharmony_ci * we need to do it this way because in the proxy case, this is 303d4afb5ceSopenharmony_ci * the next state and executed only if and when we get a good 304d4afb5ceSopenharmony_ci * proxy response inside the state machine... but notice in 305d4afb5ceSopenharmony_ci * SSL case this may not have sent anything yet with 0 return, 306d4afb5ceSopenharmony_ci * and won't until many retries from main loop. To stop that 307d4afb5ceSopenharmony_ci * becoming endless, cover with a timeout. 308d4afb5ceSopenharmony_ci */ 309d4afb5ceSopenharmony_ci#if defined(LWS_WITH_TLS) //&& !defined(LWS_WITH_MBEDTLS) 310d4afb5ceSopenharmony_ciprovoke_service: 311d4afb5ceSopenharmony_ci#endif 312d4afb5ceSopenharmony_ci lws_set_timeout(wsi, PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE, 313d4afb5ceSopenharmony_ci (int)wsi->a.context->timeout_secs); 314d4afb5ceSopenharmony_ci 315d4afb5ceSopenharmony_ci assert(lws_socket_is_valid(wsi->desc.sockfd)); 316d4afb5ceSopenharmony_ci 317d4afb5ceSopenharmony_ci pfd.fd = wsi->desc.sockfd; 318d4afb5ceSopenharmony_ci pfd.events = LWS_POLLIN; 319d4afb5ceSopenharmony_ci pfd.revents = LWS_POLLIN; 320d4afb5ceSopenharmony_ci 321d4afb5ceSopenharmony_ci n = lws_service_fd(wsi->a.context, &pfd); 322d4afb5ceSopenharmony_ci if (n < 0) { 323d4afb5ceSopenharmony_ci cce = "first service failed"; 324d4afb5ceSopenharmony_ci goto failed; 325d4afb5ceSopenharmony_ci } 326d4afb5ceSopenharmony_ci if (n) /* returns 1 on failure after closing wsi */ 327d4afb5ceSopenharmony_ci return NULL; 328d4afb5ceSopenharmony_ci } 329d4afb5ceSopenharmony_ci#endif 330d4afb5ceSopenharmony_ci return wsi; 331d4afb5ceSopenharmony_ci 332d4afb5ceSopenharmony_cifailed: 333d4afb5ceSopenharmony_ci lws_inform_client_conn_fail(wsi, (void *)cce, strlen(cce)); 334d4afb5ceSopenharmony_ci 335d4afb5ceSopenharmony_ci lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "client_connect4"); 336d4afb5ceSopenharmony_ci 337d4afb5ceSopenharmony_ci return NULL; 338d4afb5ceSopenharmony_ci} 339