/** * lws_client_reset() - retarget a connected wsi to start over with a new connection (ie, redirect) * this only works if still in HTTP, ie, not upgraded yet * wsi: connection to reset * address: network address of the new server * port: port to connect to * path: uri path to connect to on the new server * host: host header to send to the new server */ LWS_VISIBLE struct lws * lws_client_reset(struct lws **pwsi, int ssl, const char *address, int port, const char *path, const char *host) { char origin[300] = "", protocol[300] = "", method[32] = "", iface[16] = "", *p; struct lws *wsi = *pwsi; if (wsi->redirects == 3) { lwsl_err("%s: Too many redirects\n", __func__); return NULL; } wsi->redirects++; p = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN); if (p) strncpy(origin, p, sizeof(origin) - 1); p = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS); if (p) strncpy(protocol, p, sizeof(protocol) - 1); p = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_METHOD); if (p) strncpy(method, p, sizeof(method) - 1); p = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_IFACE); if (p) strncpy(method, p, sizeof(iface) - 1); lwsl_info("redirect ads='%s', port=%d, path='%s', ssl = %d\n", address, port, path, ssl); /* close the connection by hand */ #ifdef LWS_OPENSSL_SUPPORT lws_ssl_close(wsi); #endif #ifdef LWS_USE_LIBUV if (LWS_LIBUV_ENABLED(wsi->context)) { lwsl_debug("%s: lws_libuv_closehandle: wsi %p\n", __func__, wsi); /* * libuv has to do his own close handle processing asynchronously * but once it starts we can do everything else synchronously, * including trash wsi->desc.sockfd since it took a copy. * * When it completes it will call compatible_close() */ lws_libuv_closehandle_manually(wsi); } else #else compatible_close(wsi->desc.sockfd); #endif remove_wsi_socket_from_fds(wsi); #ifdef LWS_OPENSSL_SUPPORT wsi->use_ssl = ssl; #else if (ssl) { lwsl_err("%s: not configured for ssl\n", __func__); return NULL; } #endif wsi->desc.sockfd = LWS_SOCK_INVALID; wsi->state = LWSS_CLIENT_UNCONNECTED; wsi->protocol = NULL; wsi->pending_timeout = NO_PENDING_TIMEOUT; wsi->c_port = port; wsi->hdr_parsing_completed = 0; _lws_header_table_reset(wsi->u.hdr.ah); if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS, address)) return NULL; if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_HOST, host)) return NULL; if (origin[0]) if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_ORIGIN, origin)) return NULL; if (protocol[0]) if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS, protocol)) return NULL; if (method[0]) if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_METHOD, method)) return NULL; if (iface[0]) if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_IFACE, iface)) return NULL; origin[0] = '/'; strncpy(&origin[1], path, sizeof(origin) - 2); if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_URI, origin)) return NULL; *pwsi = lws_client_connect_2(wsi); return *pwsi; }
/** * lws_client_reset() - retarget a connected wsi to start over with a new connection (ie, redirect) * this only works if still in HTTP, ie, not upgraded yet * wsi: connection to reset * address: network address of the new server * port: port to connect to * path: uri path to connect to on the new server * host: host header to send to the new server */ LWS_VISIBLE struct lws * lws_client_reset(struct lws **pwsi, int ssl, const char *address, int port, const char *path, const char *host) { char origin[300] = "", protocol[300] = "", method[32] = "", iface[16] = "", alpn[32] = "", *p; struct lws *wsi = *pwsi; if (wsi->redirects == 3) { lwsl_err("%s: Too many redirects\n", __func__); return NULL; } wsi->redirects++; p = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN); if (p) lws_strncpy(origin, p, sizeof(origin)); p = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS); if (p) lws_strncpy(protocol, p, sizeof(protocol)); p = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_METHOD); if (p) lws_strncpy(method, p, sizeof(method)); p = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_IFACE); if (p) lws_strncpy(iface, p, sizeof(iface)); p = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ALPN); if (p) lws_strncpy(alpn, p, sizeof(alpn)); lwsl_info("redirect ads='%s', port=%d, path='%s', ssl = %d\n", address, port, path, ssl); /* close the connection by hand */ #if defined(LWS_WITH_TLS) lws_ssl_close(wsi); #endif __remove_wsi_socket_from_fds(wsi); if (wsi->context->event_loop_ops->close_handle_manually) wsi->context->event_loop_ops->close_handle_manually(wsi); else compatible_close(wsi->desc.sockfd); #if defined(LWS_WITH_TLS) wsi->tls.use_ssl = ssl; #else if (ssl) { lwsl_err("%s: not configured for ssl\n", __func__); return NULL; } #endif wsi->desc.sockfd = LWS_SOCK_INVALID; lwsi_set_state(wsi, LRS_UNCONNECTED); wsi->protocol = NULL; wsi->pending_timeout = NO_PENDING_TIMEOUT; wsi->c_port = port; wsi->hdr_parsing_completed = 0; _lws_header_table_reset(wsi->http.ah); if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS, address)) return NULL; if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_HOST, host)) return NULL; if (origin[0]) if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_ORIGIN, origin)) return NULL; if (protocol[0]) if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS, protocol)) return NULL; if (method[0]) if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_METHOD, method)) return NULL; if (iface[0]) if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_IFACE, iface)) return NULL; if (alpn[0]) if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_ALPN, alpn)) return NULL; origin[0] = '/'; strncpy(&origin[1], path, sizeof(origin) - 2); if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_URI, origin)) return NULL; *pwsi = lws_client_connect_2(wsi); return *pwsi; }