1d4afb5ceSopenharmony_ci/* 2d4afb5ceSopenharmony_ci * libwebsockets - small server side websockets and web server implementation 3d4afb5ceSopenharmony_ci * 4d4afb5ceSopenharmony_ci * Copyright (C) 2010 - 2020 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 * Socks5 Client -related helpers 25d4afb5ceSopenharmony_ci */ 26d4afb5ceSopenharmony_ci 27d4afb5ceSopenharmony_ci#include "private-lib-core.h" 28d4afb5ceSopenharmony_ci 29d4afb5ceSopenharmony_ciint 30d4afb5ceSopenharmony_cilws_set_socks(struct lws_vhost *vhost, const char *socks) 31d4afb5ceSopenharmony_ci{ 32d4afb5ceSopenharmony_ci char *p_at, *p_colon; 33d4afb5ceSopenharmony_ci char user[96]; 34d4afb5ceSopenharmony_ci char password[96]; 35d4afb5ceSopenharmony_ci 36d4afb5ceSopenharmony_ci if (!socks) 37d4afb5ceSopenharmony_ci return -1; 38d4afb5ceSopenharmony_ci 39d4afb5ceSopenharmony_ci vhost->socks_user[0] = '\0'; 40d4afb5ceSopenharmony_ci vhost->socks_password[0] = '\0'; 41d4afb5ceSopenharmony_ci 42d4afb5ceSopenharmony_ci p_at = strrchr(socks, '@'); 43d4afb5ceSopenharmony_ci if (p_at) { /* auth is around */ 44d4afb5ceSopenharmony_ci if (lws_ptr_diff_size_t(p_at, socks) > (sizeof(user) + 45d4afb5ceSopenharmony_ci sizeof(password) - 2)) { 46d4afb5ceSopenharmony_ci lwsl_vhost_err(vhost, "auth too long"); 47d4afb5ceSopenharmony_ci goto bail; 48d4afb5ceSopenharmony_ci } 49d4afb5ceSopenharmony_ci 50d4afb5ceSopenharmony_ci p_colon = strchr(socks, ':'); 51d4afb5ceSopenharmony_ci if (p_colon) { 52d4afb5ceSopenharmony_ci if (lws_ptr_diff_size_t(p_colon, socks) > 53d4afb5ceSopenharmony_ci sizeof(user) - 1) { 54d4afb5ceSopenharmony_ci lwsl_vhost_err(vhost, "user too long"); 55d4afb5ceSopenharmony_ci goto bail; 56d4afb5ceSopenharmony_ci } 57d4afb5ceSopenharmony_ci if (lws_ptr_diff_size_t(p_at, p_colon) > 58d4afb5ceSopenharmony_ci sizeof(password) - 1) { 59d4afb5ceSopenharmony_ci lwsl_vhost_err(vhost, "pw too long"); 60d4afb5ceSopenharmony_ci goto bail; 61d4afb5ceSopenharmony_ci } 62d4afb5ceSopenharmony_ci 63d4afb5ceSopenharmony_ci lws_strncpy(vhost->socks_user, socks, 64d4afb5ceSopenharmony_ci lws_ptr_diff_size_t(p_colon, socks) + 1); 65d4afb5ceSopenharmony_ci lws_strncpy(vhost->socks_password, p_colon + 1, 66d4afb5ceSopenharmony_ci lws_ptr_diff_size_t(p_at, (p_colon + 1)) + 1); 67d4afb5ceSopenharmony_ci } 68d4afb5ceSopenharmony_ci 69d4afb5ceSopenharmony_ci lwsl_vhost_info(vhost, " Socks auth, user: %s, password: %s", 70d4afb5ceSopenharmony_ci vhost->socks_user, 71d4afb5ceSopenharmony_ci vhost->socks_password); 72d4afb5ceSopenharmony_ci 73d4afb5ceSopenharmony_ci socks = p_at + 1; 74d4afb5ceSopenharmony_ci } 75d4afb5ceSopenharmony_ci 76d4afb5ceSopenharmony_ci lws_strncpy(vhost->socks_proxy_address, socks, 77d4afb5ceSopenharmony_ci sizeof(vhost->socks_proxy_address)); 78d4afb5ceSopenharmony_ci 79d4afb5ceSopenharmony_ci p_colon = strchr(vhost->socks_proxy_address, ':'); 80d4afb5ceSopenharmony_ci if (!p_colon && !vhost->socks_proxy_port) { 81d4afb5ceSopenharmony_ci lwsl_vhost_err(vhost, "socks_proxy needs to be address:port"); 82d4afb5ceSopenharmony_ci 83d4afb5ceSopenharmony_ci return -1; 84d4afb5ceSopenharmony_ci } 85d4afb5ceSopenharmony_ci 86d4afb5ceSopenharmony_ci if (p_colon) { 87d4afb5ceSopenharmony_ci *p_colon = '\0'; 88d4afb5ceSopenharmony_ci vhost->socks_proxy_port = (unsigned int)atoi(p_colon + 1); 89d4afb5ceSopenharmony_ci } 90d4afb5ceSopenharmony_ci 91d4afb5ceSopenharmony_ci lwsl_vhost_debug(vhost, "Connections via Socks5 %s:%u", 92d4afb5ceSopenharmony_ci vhost->socks_proxy_address, 93d4afb5ceSopenharmony_ci vhost->socks_proxy_port); 94d4afb5ceSopenharmony_ci 95d4afb5ceSopenharmony_ci return 0; 96d4afb5ceSopenharmony_ci 97d4afb5ceSopenharmony_cibail: 98d4afb5ceSopenharmony_ci return -1; 99d4afb5ceSopenharmony_ci} 100d4afb5ceSopenharmony_ci 101d4afb5ceSopenharmony_ciint 102d4afb5ceSopenharmony_cilws_socks5c_generate_msg(struct lws *wsi, enum socks_msg_type type, 103d4afb5ceSopenharmony_ci ssize_t *msg_len) 104d4afb5ceSopenharmony_ci{ 105d4afb5ceSopenharmony_ci struct lws_context *context = wsi->a.context; 106d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; 107d4afb5ceSopenharmony_ci uint8_t *p = pt->serv_buf, *end = &p[context->pt_serv_buf_size]; 108d4afb5ceSopenharmony_ci ssize_t n, passwd_len; 109d4afb5ceSopenharmony_ci short net_num; 110d4afb5ceSopenharmony_ci char *cp; 111d4afb5ceSopenharmony_ci 112d4afb5ceSopenharmony_ci switch (type) { 113d4afb5ceSopenharmony_ci case SOCKS_MSG_GREETING: 114d4afb5ceSopenharmony_ci if (lws_ptr_diff(end, p) < 4) 115d4afb5ceSopenharmony_ci return 1; 116d4afb5ceSopenharmony_ci /* socks version, version 5 only */ 117d4afb5ceSopenharmony_ci *p++ = SOCKS_VERSION_5; 118d4afb5ceSopenharmony_ci /* number of methods */ 119d4afb5ceSopenharmony_ci *p++ = 2; 120d4afb5ceSopenharmony_ci /* username password method */ 121d4afb5ceSopenharmony_ci *p++ = SOCKS_AUTH_USERNAME_PASSWORD; 122d4afb5ceSopenharmony_ci /* no authentication method */ 123d4afb5ceSopenharmony_ci *p++ = SOCKS_AUTH_NO_AUTH; 124d4afb5ceSopenharmony_ci break; 125d4afb5ceSopenharmony_ci 126d4afb5ceSopenharmony_ci case SOCKS_MSG_USERNAME_PASSWORD: 127d4afb5ceSopenharmony_ci n = (ssize_t)strlen(wsi->a.vhost->socks_user); 128d4afb5ceSopenharmony_ci passwd_len = (ssize_t)strlen(wsi->a.vhost->socks_password); 129d4afb5ceSopenharmony_ci 130d4afb5ceSopenharmony_ci if (n > 254 || passwd_len > 254) 131d4afb5ceSopenharmony_ci return 1; 132d4afb5ceSopenharmony_ci 133d4afb5ceSopenharmony_ci if (lws_ptr_diff(end, p) < 3 + n + passwd_len) 134d4afb5ceSopenharmony_ci return 1; 135d4afb5ceSopenharmony_ci 136d4afb5ceSopenharmony_ci /* the subnegotiation version */ 137d4afb5ceSopenharmony_ci *p++ = SOCKS_SUBNEGOTIATION_VERSION_1; 138d4afb5ceSopenharmony_ci 139d4afb5ceSopenharmony_ci /* length of the user name */ 140d4afb5ceSopenharmony_ci *p++ = (uint8_t)n; 141d4afb5ceSopenharmony_ci /* user name */ 142d4afb5ceSopenharmony_ci memcpy(p, wsi->a.vhost->socks_user, (size_t)n); 143d4afb5ceSopenharmony_ci p += (uint8_t)n; 144d4afb5ceSopenharmony_ci 145d4afb5ceSopenharmony_ci /* length of the password */ 146d4afb5ceSopenharmony_ci *p++ = (uint8_t)passwd_len; 147d4afb5ceSopenharmony_ci 148d4afb5ceSopenharmony_ci /* password */ 149d4afb5ceSopenharmony_ci memcpy(p, wsi->a.vhost->socks_password, (size_t)passwd_len); 150d4afb5ceSopenharmony_ci p += passwd_len; 151d4afb5ceSopenharmony_ci break; 152d4afb5ceSopenharmony_ci 153d4afb5ceSopenharmony_ci case SOCKS_MSG_CONNECT: 154d4afb5ceSopenharmony_ci n = (ssize_t)strlen(wsi->stash->cis[CIS_ADDRESS]); 155d4afb5ceSopenharmony_ci 156d4afb5ceSopenharmony_ci if (n > 254 || lws_ptr_diff(end, p) < 5 + n + 2) 157d4afb5ceSopenharmony_ci return 1; 158d4afb5ceSopenharmony_ci 159d4afb5ceSopenharmony_ci cp = (char *)&net_num; 160d4afb5ceSopenharmony_ci 161d4afb5ceSopenharmony_ci /* socks version */ 162d4afb5ceSopenharmony_ci *p++ = SOCKS_VERSION_5; 163d4afb5ceSopenharmony_ci /* socks command */ 164d4afb5ceSopenharmony_ci *p++ = SOCKS_COMMAND_CONNECT; 165d4afb5ceSopenharmony_ci /* reserved */ 166d4afb5ceSopenharmony_ci *p++ = 0; 167d4afb5ceSopenharmony_ci /* address type */ 168d4afb5ceSopenharmony_ci *p++ = SOCKS_ATYP_DOMAINNAME; 169d4afb5ceSopenharmony_ci /* length of ---> */ 170d4afb5ceSopenharmony_ci *p++ = (uint8_t)n; 171d4afb5ceSopenharmony_ci 172d4afb5ceSopenharmony_ci /* the address we tell SOCKS proxy to connect to */ 173d4afb5ceSopenharmony_ci memcpy(p, wsi->stash->cis[CIS_ADDRESS], (size_t)n); 174d4afb5ceSopenharmony_ci p += n; 175d4afb5ceSopenharmony_ci 176d4afb5ceSopenharmony_ci net_num = (short)htons(wsi->c_port); 177d4afb5ceSopenharmony_ci 178d4afb5ceSopenharmony_ci /* the port we tell SOCKS proxy to connect to */ 179d4afb5ceSopenharmony_ci *p++ = (uint8_t)cp[0]; 180d4afb5ceSopenharmony_ci *p++ = (uint8_t)cp[1]; 181d4afb5ceSopenharmony_ci 182d4afb5ceSopenharmony_ci break; 183d4afb5ceSopenharmony_ci 184d4afb5ceSopenharmony_ci default: 185d4afb5ceSopenharmony_ci return 1; 186d4afb5ceSopenharmony_ci } 187d4afb5ceSopenharmony_ci 188d4afb5ceSopenharmony_ci *msg_len = lws_ptr_diff(p, pt->serv_buf); 189d4afb5ceSopenharmony_ci 190d4afb5ceSopenharmony_ci return 0; 191d4afb5ceSopenharmony_ci} 192d4afb5ceSopenharmony_ci 193d4afb5ceSopenharmony_ciint 194d4afb5ceSopenharmony_cilws_socks5c_ads_server(struct lws_vhost *vh, 195d4afb5ceSopenharmony_ci const struct lws_context_creation_info *info) 196d4afb5ceSopenharmony_ci{ 197d4afb5ceSopenharmony_ci /* socks proxy */ 198d4afb5ceSopenharmony_ci if (info->socks_proxy_address) { 199d4afb5ceSopenharmony_ci /* override for backwards compatibility */ 200d4afb5ceSopenharmony_ci if (info->socks_proxy_port) 201d4afb5ceSopenharmony_ci vh->socks_proxy_port = info->socks_proxy_port; 202d4afb5ceSopenharmony_ci lws_set_socks(vh, info->socks_proxy_address); 203d4afb5ceSopenharmony_ci 204d4afb5ceSopenharmony_ci return 0; 205d4afb5ceSopenharmony_ci } 206d4afb5ceSopenharmony_ci#ifdef LWS_HAVE_GETENV 207d4afb5ceSopenharmony_ci { 208d4afb5ceSopenharmony_ci char *p = getenv("socks_proxy"); 209d4afb5ceSopenharmony_ci 210d4afb5ceSopenharmony_ci if (p && strlen(p) > 0 && strlen(p) < 95) 211d4afb5ceSopenharmony_ci lws_set_socks(vh, p); 212d4afb5ceSopenharmony_ci } 213d4afb5ceSopenharmony_ci#endif 214d4afb5ceSopenharmony_ci 215d4afb5ceSopenharmony_ci return 0; 216d4afb5ceSopenharmony_ci} 217d4afb5ceSopenharmony_ci 218d4afb5ceSopenharmony_ci/* 219d4afb5ceSopenharmony_ci * Returns 0 = nothing for caller to do, 1 = return wsi, -1 = goto failed 220d4afb5ceSopenharmony_ci */ 221d4afb5ceSopenharmony_ci 222d4afb5ceSopenharmony_ciint 223d4afb5ceSopenharmony_cilws_socks5c_greet(struct lws *wsi, const char **pcce) 224d4afb5ceSopenharmony_ci{ 225d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; 226d4afb5ceSopenharmony_ci ssize_t plen; 227d4afb5ceSopenharmony_ci int n; 228d4afb5ceSopenharmony_ci 229d4afb5ceSopenharmony_ci /* socks proxy */ 230d4afb5ceSopenharmony_ci if (!wsi->a.vhost->socks_proxy_port) 231d4afb5ceSopenharmony_ci return 0; 232d4afb5ceSopenharmony_ci 233d4afb5ceSopenharmony_ci if (lws_socks5c_generate_msg(wsi, SOCKS_MSG_GREETING, &plen)) { 234d4afb5ceSopenharmony_ci *pcce = "socks msg too large"; 235d4afb5ceSopenharmony_ci return -1; 236d4afb5ceSopenharmony_ci } 237d4afb5ceSopenharmony_ci // lwsl_hexdump_notice(pt->serv_buf, plen); 238d4afb5ceSopenharmony_ci n = (int)send(wsi->desc.sockfd, (char *)pt->serv_buf, (size_t)plen, 239d4afb5ceSopenharmony_ci MSG_NOSIGNAL); 240d4afb5ceSopenharmony_ci if (n < 0) { 241d4afb5ceSopenharmony_ci lwsl_wsi_debug(wsi, "ERROR writing socks greeting"); 242d4afb5ceSopenharmony_ci *pcce = "socks write failed"; 243d4afb5ceSopenharmony_ci return -1; 244d4afb5ceSopenharmony_ci } 245d4afb5ceSopenharmony_ci 246d4afb5ceSopenharmony_ci lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SOCKS_GREETING_REPLY, 247d4afb5ceSopenharmony_ci (int)wsi->a.context->timeout_secs); 248d4afb5ceSopenharmony_ci 249d4afb5ceSopenharmony_ci lwsi_set_state(wsi, LRS_WAITING_SOCKS_GREETING_REPLY); 250d4afb5ceSopenharmony_ci 251d4afb5ceSopenharmony_ci return 1; 252d4afb5ceSopenharmony_ci} 253d4afb5ceSopenharmony_ci 254d4afb5ceSopenharmony_ciint 255d4afb5ceSopenharmony_cilws_socks5c_handle_state(struct lws *wsi, struct lws_pollfd *pollfd, 256d4afb5ceSopenharmony_ci const char **pcce) 257d4afb5ceSopenharmony_ci{ 258d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; 259d4afb5ceSopenharmony_ci int conn_mode = 0, pending_timeout = 0; 260d4afb5ceSopenharmony_ci ssize_t len; 261d4afb5ceSopenharmony_ci int n; 262d4afb5ceSopenharmony_ci 263d4afb5ceSopenharmony_ci /* handle proxy hung up on us */ 264d4afb5ceSopenharmony_ci 265d4afb5ceSopenharmony_ci if (pollfd->revents & LWS_POLLHUP) { 266d4afb5ceSopenharmony_ci lwsl_wsi_warn(wsi, "SOCKS fd=%d dead", pollfd->fd); 267d4afb5ceSopenharmony_ci *pcce = "socks conn dead"; 268d4afb5ceSopenharmony_ci return LW5CHS_RET_BAIL3; 269d4afb5ceSopenharmony_ci } 270d4afb5ceSopenharmony_ci 271d4afb5ceSopenharmony_ci n = (int)recv(wsi->desc.sockfd, (void *)pt->serv_buf, 272d4afb5ceSopenharmony_ci wsi->a.context->pt_serv_buf_size, 0); 273d4afb5ceSopenharmony_ci if (n < 0) { 274d4afb5ceSopenharmony_ci if (LWS_ERRNO == LWS_EAGAIN) { 275d4afb5ceSopenharmony_ci lwsl_wsi_debug(wsi, "SOCKS read EAGAIN, retrying"); 276d4afb5ceSopenharmony_ci return LW5CHS_RET_RET0; 277d4afb5ceSopenharmony_ci } 278d4afb5ceSopenharmony_ci lwsl_wsi_err(wsi, "ERROR reading from SOCKS socket"); 279d4afb5ceSopenharmony_ci *pcce = "socks recv fail"; 280d4afb5ceSopenharmony_ci return LW5CHS_RET_BAIL3; 281d4afb5ceSopenharmony_ci } 282d4afb5ceSopenharmony_ci 283d4afb5ceSopenharmony_ci // lwsl_hexdump_warn(pt->serv_buf, n); 284d4afb5ceSopenharmony_ci 285d4afb5ceSopenharmony_ci switch (lwsi_state(wsi)) { 286d4afb5ceSopenharmony_ci 287d4afb5ceSopenharmony_ci case LRS_WAITING_SOCKS_GREETING_REPLY: 288d4afb5ceSopenharmony_ci if (pt->serv_buf[0] != SOCKS_VERSION_5) 289d4afb5ceSopenharmony_ci goto socks_reply_fail; 290d4afb5ceSopenharmony_ci 291d4afb5ceSopenharmony_ci if (pt->serv_buf[1] == SOCKS_AUTH_NO_AUTH) { 292d4afb5ceSopenharmony_ci lwsl_wsi_client(wsi, "SOCKS GR: No Auth Method"); 293d4afb5ceSopenharmony_ci if (lws_socks5c_generate_msg(wsi, SOCKS_MSG_CONNECT, 294d4afb5ceSopenharmony_ci &len)) { 295d4afb5ceSopenharmony_ci lwsl_wsi_err(wsi, "generate connect msg fail"); 296d4afb5ceSopenharmony_ci goto socks_send_msg_fail; 297d4afb5ceSopenharmony_ci } 298d4afb5ceSopenharmony_ci conn_mode = LRS_WAITING_SOCKS_CONNECT_REPLY; 299d4afb5ceSopenharmony_ci pending_timeout = 300d4afb5ceSopenharmony_ci PENDING_TIMEOUT_AWAITING_SOCKS_CONNECT_REPLY; 301d4afb5ceSopenharmony_ci goto socks_send; 302d4afb5ceSopenharmony_ci } 303d4afb5ceSopenharmony_ci 304d4afb5ceSopenharmony_ci if (pt->serv_buf[1] == SOCKS_AUTH_USERNAME_PASSWORD) { 305d4afb5ceSopenharmony_ci lwsl_wsi_client(wsi, "SOCKS GR: User/Pw Method"); 306d4afb5ceSopenharmony_ci if (lws_socks5c_generate_msg(wsi, 307d4afb5ceSopenharmony_ci SOCKS_MSG_USERNAME_PASSWORD, 308d4afb5ceSopenharmony_ci &len)) 309d4afb5ceSopenharmony_ci goto socks_send_msg_fail; 310d4afb5ceSopenharmony_ci conn_mode = LRS_WAITING_SOCKS_AUTH_REPLY; 311d4afb5ceSopenharmony_ci pending_timeout = 312d4afb5ceSopenharmony_ci PENDING_TIMEOUT_AWAITING_SOCKS_AUTH_REPLY; 313d4afb5ceSopenharmony_ci goto socks_send; 314d4afb5ceSopenharmony_ci } 315d4afb5ceSopenharmony_ci goto socks_reply_fail; 316d4afb5ceSopenharmony_ci 317d4afb5ceSopenharmony_ci case LRS_WAITING_SOCKS_AUTH_REPLY: 318d4afb5ceSopenharmony_ci if (pt->serv_buf[0] != SOCKS_SUBNEGOTIATION_VERSION_1 || 319d4afb5ceSopenharmony_ci pt->serv_buf[1] != 320d4afb5ceSopenharmony_ci SOCKS_SUBNEGOTIATION_STATUS_SUCCESS) 321d4afb5ceSopenharmony_ci goto socks_reply_fail; 322d4afb5ceSopenharmony_ci 323d4afb5ceSopenharmony_ci lwsl_wsi_client(wsi, "SOCKS password OK, sending connect"); 324d4afb5ceSopenharmony_ci if (lws_socks5c_generate_msg(wsi, SOCKS_MSG_CONNECT, &len)) { 325d4afb5ceSopenharmony_cisocks_send_msg_fail: 326d4afb5ceSopenharmony_ci *pcce = "socks gen msg fail"; 327d4afb5ceSopenharmony_ci return LW5CHS_RET_BAIL3; 328d4afb5ceSopenharmony_ci } 329d4afb5ceSopenharmony_ci conn_mode = LRS_WAITING_SOCKS_CONNECT_REPLY; 330d4afb5ceSopenharmony_ci pending_timeout = 331d4afb5ceSopenharmony_ci PENDING_TIMEOUT_AWAITING_SOCKS_CONNECT_REPLY; 332d4afb5ceSopenharmony_cisocks_send: 333d4afb5ceSopenharmony_ci // lwsl_hexdump_notice(pt->serv_buf, len); 334d4afb5ceSopenharmony_ci n = (int)send(wsi->desc.sockfd, (char *)pt->serv_buf, 335d4afb5ceSopenharmony_ci (size_t)len, MSG_NOSIGNAL); 336d4afb5ceSopenharmony_ci if (n < 0) { 337d4afb5ceSopenharmony_ci lwsl_wsi_debug(wsi, "ERROR writing to socks proxy"); 338d4afb5ceSopenharmony_ci *pcce = "socks write fail"; 339d4afb5ceSopenharmony_ci return LW5CHS_RET_BAIL3; 340d4afb5ceSopenharmony_ci } 341d4afb5ceSopenharmony_ci 342d4afb5ceSopenharmony_ci lws_set_timeout(wsi, (enum pending_timeout)pending_timeout, 343d4afb5ceSopenharmony_ci (int)wsi->a.context->timeout_secs); 344d4afb5ceSopenharmony_ci lwsi_set_state(wsi, (lws_wsi_state_t)conn_mode); 345d4afb5ceSopenharmony_ci break; 346d4afb5ceSopenharmony_ci 347d4afb5ceSopenharmony_cisocks_reply_fail: 348d4afb5ceSopenharmony_ci lwsl_wsi_err(wsi, "socks reply: v%d, err %d", 349d4afb5ceSopenharmony_ci pt->serv_buf[0], pt->serv_buf[1]); 350d4afb5ceSopenharmony_ci *pcce = "socks reply fail"; 351d4afb5ceSopenharmony_ci return LW5CHS_RET_BAIL3; 352d4afb5ceSopenharmony_ci 353d4afb5ceSopenharmony_ci case LRS_WAITING_SOCKS_CONNECT_REPLY: 354d4afb5ceSopenharmony_ci if (pt->serv_buf[0] != SOCKS_VERSION_5 || 355d4afb5ceSopenharmony_ci pt->serv_buf[1] != SOCKS_REQUEST_REPLY_SUCCESS) 356d4afb5ceSopenharmony_ci goto socks_reply_fail; 357d4afb5ceSopenharmony_ci 358d4afb5ceSopenharmony_ci lwsl_wsi_client(wsi, "socks connect OK"); 359d4afb5ceSopenharmony_ci 360d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) 361d4afb5ceSopenharmony_ci if (lwsi_role_http(wsi) && 362d4afb5ceSopenharmony_ci lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS, 363d4afb5ceSopenharmony_ci wsi->a.vhost->socks_proxy_address)) { 364d4afb5ceSopenharmony_ci *pcce = "socks connect fail"; 365d4afb5ceSopenharmony_ci return LW5CHS_RET_BAIL3; 366d4afb5ceSopenharmony_ci } 367d4afb5ceSopenharmony_ci#endif 368d4afb5ceSopenharmony_ci 369d4afb5ceSopenharmony_ci wsi->c_port = (uint16_t)wsi->a.vhost->socks_proxy_port; 370d4afb5ceSopenharmony_ci 371d4afb5ceSopenharmony_ci /* clear his proxy connection timeout */ 372d4afb5ceSopenharmony_ci lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0); 373d4afb5ceSopenharmony_ci return LW5CHS_RET_STARTHS; 374d4afb5ceSopenharmony_ci default: 375d4afb5ceSopenharmony_ci break; 376d4afb5ceSopenharmony_ci } 377d4afb5ceSopenharmony_ci 378d4afb5ceSopenharmony_ci return LW5CHS_RET_NOTHING; 379d4afb5ceSopenharmony_ci} 380