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
25d4afb5ceSopenharmony_ci#include "private-lib-core.h"
26d4afb5ceSopenharmony_ci
27d4afb5ceSopenharmony_ci#if !defined(WIN32)
28d4afb5ceSopenharmony_ci#include <netdb.h>
29d4afb5ceSopenharmony_ci#endif
30d4afb5ceSopenharmony_ci
31d4afb5ceSopenharmony_ci#if !defined(LWS_WITH_SYS_ASYNC_DNS)
32d4afb5ceSopenharmony_cistatic int
33d4afb5ceSopenharmony_cilws_getaddrinfo46(struct lws *wsi, const char *ads, struct addrinfo **result)
34d4afb5ceSopenharmony_ci{
35d4afb5ceSopenharmony_ci	lws_metrics_caliper_declare(cal, wsi->a.context->mt_conn_dns);
36d4afb5ceSopenharmony_ci	struct addrinfo hints;
37d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_METRICS)
38d4afb5ceSopenharmony_ci	char buckname[32];
39d4afb5ceSopenharmony_ci#endif
40d4afb5ceSopenharmony_ci	int n;
41d4afb5ceSopenharmony_ci
42d4afb5ceSopenharmony_ci	memset(&hints, 0, sizeof(hints));
43d4afb5ceSopenharmony_ci	*result = NULL;
44d4afb5ceSopenharmony_ci
45d4afb5ceSopenharmony_ci	hints.ai_socktype = SOCK_STREAM;
46d4afb5ceSopenharmony_ci
47d4afb5ceSopenharmony_ci#ifdef LWS_WITH_IPV6
48d4afb5ceSopenharmony_ci	if (wsi->ipv6) {
49d4afb5ceSopenharmony_ci
50d4afb5ceSopenharmony_ci#if !defined(__ANDROID__)
51d4afb5ceSopenharmony_ci		hints.ai_family = AF_UNSPEC;
52d4afb5ceSopenharmony_ci#if !defined(__OpenBSD__) && !defined(__OPENBSD)
53d4afb5ceSopenharmony_ci		hints.ai_flags = AI_V4MAPPED;
54d4afb5ceSopenharmony_ci#endif
55d4afb5ceSopenharmony_ci#endif
56d4afb5ceSopenharmony_ci	} else
57d4afb5ceSopenharmony_ci#endif
58d4afb5ceSopenharmony_ci	{
59d4afb5ceSopenharmony_ci		hints.ai_family = PF_UNSPEC;
60d4afb5ceSopenharmony_ci	}
61d4afb5ceSopenharmony_ci
62d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CONMON)
63d4afb5ceSopenharmony_ci	wsi->conmon_datum = lws_now_usecs();
64d4afb5ceSopenharmony_ci#endif
65d4afb5ceSopenharmony_ci
66d4afb5ceSopenharmony_ci	wsi->dns_reachability = 0;
67d4afb5ceSopenharmony_ci	if (lws_fi(&wsi->fic, "dnsfail"))
68d4afb5ceSopenharmony_ci		n = EAI_FAIL;
69d4afb5ceSopenharmony_ci	else
70d4afb5ceSopenharmony_ci		n = getaddrinfo(ads, NULL, &hints, result);
71d4afb5ceSopenharmony_ci
72d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CONMON)
73d4afb5ceSopenharmony_ci	wsi->conmon.ciu_dns = (lws_conmon_interval_us_t)
74d4afb5ceSopenharmony_ci					(lws_now_usecs() - wsi->conmon_datum);
75d4afb5ceSopenharmony_ci#endif
76d4afb5ceSopenharmony_ci
77d4afb5ceSopenharmony_ci	/*
78d4afb5ceSopenharmony_ci	 * Which EAI_* are available and the meanings are highly platform-
79d4afb5ceSopenharmony_ci	 * dependent, even different linux distros differ.
80d4afb5ceSopenharmony_ci	 */
81d4afb5ceSopenharmony_ci
82d4afb5ceSopenharmony_ci	if (0
83d4afb5ceSopenharmony_ci#if defined(EAI_SYSTEM)
84d4afb5ceSopenharmony_ci			|| n == EAI_SYSTEM
85d4afb5ceSopenharmony_ci#endif
86d4afb5ceSopenharmony_ci#if defined(EAI_NODATA)
87d4afb5ceSopenharmony_ci			|| n == EAI_NODATA
88d4afb5ceSopenharmony_ci#endif
89d4afb5ceSopenharmony_ci#if defined(EAI_FAIL)
90d4afb5ceSopenharmony_ci			|| n == EAI_FAIL
91d4afb5ceSopenharmony_ci#endif
92d4afb5ceSopenharmony_ci#if defined(EAI_AGAIN)
93d4afb5ceSopenharmony_ci			|| n == EAI_AGAIN
94d4afb5ceSopenharmony_ci#endif
95d4afb5ceSopenharmony_ci			) {
96d4afb5ceSopenharmony_ci		wsi->dns_reachability = 1;
97d4afb5ceSopenharmony_ci		lws_metrics_caliper_report(cal, METRES_NOGO);
98d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_METRICS)
99d4afb5ceSopenharmony_ci		lws_snprintf(buckname, sizeof(buckname), "dns=\"unreachable %d\"", n);
100d4afb5ceSopenharmony_ci		lws_metrics_hist_bump_priv_wsi(wsi, mth_conn_failures, buckname);
101d4afb5ceSopenharmony_ci#endif
102d4afb5ceSopenharmony_ci
103d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CONMON)
104d4afb5ceSopenharmony_ci		wsi->conmon.dns_disposition = LWSCONMON_DNS_SERVER_UNREACHABLE;
105d4afb5ceSopenharmony_ci#endif
106d4afb5ceSopenharmony_ci
107d4afb5ceSopenharmony_ci#if 0
108d4afb5ceSopenharmony_ci		lwsl_wsi_debug(wsi, "asking to recheck CPD in 1s");
109d4afb5ceSopenharmony_ci		lws_system_cpd_start_defer(wsi->a.context, LWS_US_PER_SEC);
110d4afb5ceSopenharmony_ci#endif
111d4afb5ceSopenharmony_ci	}
112d4afb5ceSopenharmony_ci
113d4afb5ceSopenharmony_ci	lwsl_wsi_info(wsi, "getaddrinfo '%s' says %d", ads, n);
114d4afb5ceSopenharmony_ci
115d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_METRICS)
116d4afb5ceSopenharmony_ci	if (n < 0) {
117d4afb5ceSopenharmony_ci		lws_snprintf(buckname, sizeof(buckname), "dns=\"nores %d\"", n);
118d4afb5ceSopenharmony_ci		lws_metrics_hist_bump_priv_wsi(wsi, mth_conn_failures, buckname);
119d4afb5ceSopenharmony_ci	}
120d4afb5ceSopenharmony_ci#endif
121d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CONMON)
122d4afb5ceSopenharmony_ci	wsi->conmon.dns_disposition = n < 0 ? LWSCONMON_DNS_NO_RESULT :
123d4afb5ceSopenharmony_ci					      LWSCONMON_DNS_OK;
124d4afb5ceSopenharmony_ci#endif
125d4afb5ceSopenharmony_ci
126d4afb5ceSopenharmony_ci	lws_metrics_caliper_report(cal, n >= 0 ? METRES_GO : METRES_NOGO);
127d4afb5ceSopenharmony_ci
128d4afb5ceSopenharmony_ci	return n;
129d4afb5ceSopenharmony_ci}
130d4afb5ceSopenharmony_ci#endif
131d4afb5ceSopenharmony_ci
132d4afb5ceSopenharmony_ci#if !defined(LWS_WITH_SYS_ASYNC_DNS) && defined(EAI_NONAME)
133d4afb5ceSopenharmony_cistatic const char * const dns_nxdomain = "DNS NXDOMAIN";
134d4afb5ceSopenharmony_ci#endif
135d4afb5ceSopenharmony_ci
136d4afb5ceSopenharmony_cistruct lws *
137d4afb5ceSopenharmony_cilws_client_connect_2_dnsreq(struct lws *wsi)
138d4afb5ceSopenharmony_ci{
139d4afb5ceSopenharmony_ci	struct addrinfo *result = NULL;
140d4afb5ceSopenharmony_ci	const char *meth = NULL;
141d4afb5ceSopenharmony_ci#if defined(LWS_WITH_IPV6)
142d4afb5ceSopenharmony_ci	struct sockaddr_in addr;
143d4afb5ceSopenharmony_ci	const char *iface;
144d4afb5ceSopenharmony_ci#endif
145d4afb5ceSopenharmony_ci	const char *adsin;
146d4afb5ceSopenharmony_ci	int n, port = 0;
147d4afb5ceSopenharmony_ci	struct lws *w;
148d4afb5ceSopenharmony_ci
149d4afb5ceSopenharmony_ci	if (lwsi_state(wsi) == LRS_WAITING_DNS ||
150d4afb5ceSopenharmony_ci	    lwsi_state(wsi) == LRS_WAITING_CONNECT) {
151d4afb5ceSopenharmony_ci		lwsl_wsi_info(wsi, "LRS_WAITING_DNS / CONNECT");
152d4afb5ceSopenharmony_ci
153d4afb5ceSopenharmony_ci		return wsi;
154d4afb5ceSopenharmony_ci	}
155d4afb5ceSopenharmony_ci
156d4afb5ceSopenharmony_ci	/*
157d4afb5ceSopenharmony_ci	 * clients who will create their own fresh connection keep a copy of
158d4afb5ceSopenharmony_ci	 * the hostname they originally connected to, in case other connections
159d4afb5ceSopenharmony_ci	 * want to use it too
160d4afb5ceSopenharmony_ci	 */
161d4afb5ceSopenharmony_ci
162d4afb5ceSopenharmony_ci	if (!wsi->cli_hostname_copy) {
163d4afb5ceSopenharmony_ci		const char *pa = lws_wsi_client_stash_item(wsi, CIS_HOST,
164d4afb5ceSopenharmony_ci					_WSI_TOKEN_CLIENT_PEER_ADDRESS);
165d4afb5ceSopenharmony_ci
166d4afb5ceSopenharmony_ci		if (pa)
167d4afb5ceSopenharmony_ci			wsi->cli_hostname_copy = lws_strdup(pa);
168d4afb5ceSopenharmony_ci	}
169d4afb5ceSopenharmony_ci
170d4afb5ceSopenharmony_ci	/*
171d4afb5ceSopenharmony_ci	 * The first job is figure out if we want to pipeline on or just join
172d4afb5ceSopenharmony_ci	 * an existing "active connection" to the same place
173d4afb5ceSopenharmony_ci	 */
174d4afb5ceSopenharmony_ci
175d4afb5ceSopenharmony_ci	meth = lws_wsi_client_stash_item(wsi, CIS_METHOD,
176d4afb5ceSopenharmony_ci					 _WSI_TOKEN_CLIENT_METHOD);
177d4afb5ceSopenharmony_ci	/* consult active connections to find out disposition */
178d4afb5ceSopenharmony_ci
179d4afb5ceSopenharmony_ci	adsin = lws_wsi_client_stash_item(wsi, CIS_ADDRESS,
180d4afb5ceSopenharmony_ci					  _WSI_TOKEN_CLIENT_PEER_ADDRESS);
181d4afb5ceSopenharmony_ci
182d4afb5ceSopenharmony_ci	/* we only pipeline connections that said it was okay */
183d4afb5ceSopenharmony_ci
184d4afb5ceSopenharmony_ci	if (!wsi->client_pipeline) {
185d4afb5ceSopenharmony_ci		lwsl_wsi_debug(wsi, "new conn on no pipeline flag");
186d4afb5ceSopenharmony_ci
187d4afb5ceSopenharmony_ci		goto solo;
188d4afb5ceSopenharmony_ci	}
189d4afb5ceSopenharmony_ci
190d4afb5ceSopenharmony_ci	/* only pipeline things we associate with being a stream */
191d4afb5ceSopenharmony_ci
192d4afb5ceSopenharmony_ci	if (meth && strcmp(meth, "RAW") && strcmp(meth, "GET") &&
193d4afb5ceSopenharmony_ci		    strcmp(meth, "POST") && strcmp(meth, "PUT") &&
194d4afb5ceSopenharmony_ci		    strcmp(meth, "UDP") && strcmp(meth, "MQTT"))
195d4afb5ceSopenharmony_ci		goto solo;
196d4afb5ceSopenharmony_ci
197d4afb5ceSopenharmony_ci	if (!adsin)
198d4afb5ceSopenharmony_ci		/*
199d4afb5ceSopenharmony_ci		 * This cannot happen since user code must provide the client
200d4afb5ceSopenharmony_ci		 * address to get this far, it's here to satisfy Coverity
201d4afb5ceSopenharmony_ci		 */
202d4afb5ceSopenharmony_ci		return NULL;
203d4afb5ceSopenharmony_ci
204d4afb5ceSopenharmony_ci	switch (lws_vhost_active_conns(wsi, &w, adsin)) {
205d4afb5ceSopenharmony_ci	case ACTIVE_CONNS_SOLO:
206d4afb5ceSopenharmony_ci		break;
207d4afb5ceSopenharmony_ci	case ACTIVE_CONNS_MUXED:
208d4afb5ceSopenharmony_ci		lwsl_wsi_notice(wsi, "ACTIVE_CONNS_MUXED");
209d4afb5ceSopenharmony_ci		if (lwsi_role_h2(wsi)) {
210d4afb5ceSopenharmony_ci
211d4afb5ceSopenharmony_ci			if (wsi->a.protocol->callback(wsi,
212d4afb5ceSopenharmony_ci					LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP,
213d4afb5ceSopenharmony_ci					wsi->user_space, NULL, 0))
214d4afb5ceSopenharmony_ci				goto failed1;
215d4afb5ceSopenharmony_ci
216d4afb5ceSopenharmony_ci			//lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE2);
217d4afb5ceSopenharmony_ci			//lwsi_set_state(w, LRS_ESTABLISHED);
218d4afb5ceSopenharmony_ci			lws_callback_on_writable(wsi);
219d4afb5ceSopenharmony_ci		}
220d4afb5ceSopenharmony_ci
221d4afb5ceSopenharmony_ci		return wsi;
222d4afb5ceSopenharmony_ci	case ACTIVE_CONNS_QUEUED:
223d4afb5ceSopenharmony_ci		lwsl_wsi_debug(wsi, "ACTIVE_CONNS_QUEUED st 0x%x: ",
224d4afb5ceSopenharmony_ci							lwsi_state(wsi));
225d4afb5ceSopenharmony_ci
226d4afb5ceSopenharmony_ci		if (lwsi_state(wsi) == LRS_UNCONNECTED) {
227d4afb5ceSopenharmony_ci			if (lwsi_role_h2(w))
228d4afb5ceSopenharmony_ci				lwsi_set_state(wsi,
229d4afb5ceSopenharmony_ci					       LRS_H2_WAITING_TO_SEND_HEADERS);
230d4afb5ceSopenharmony_ci			else
231d4afb5ceSopenharmony_ci				lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE2);
232d4afb5ceSopenharmony_ci		}
233d4afb5ceSopenharmony_ci
234d4afb5ceSopenharmony_ci		return lws_client_connect_4_established(wsi, w, 0);
235d4afb5ceSopenharmony_ci	}
236d4afb5ceSopenharmony_ci
237d4afb5ceSopenharmony_cisolo:
238d4afb5ceSopenharmony_ci
239d4afb5ceSopenharmony_ci	/*
240d4afb5ceSopenharmony_ci	 * If we made our own connection, and we're doing a method that can
241d4afb5ceSopenharmony_ci	 * take a pipeline, we are an "active client connection".
242d4afb5ceSopenharmony_ci	 *
243d4afb5ceSopenharmony_ci	 * Add ourselves to the vhost list of those so that others can
244d4afb5ceSopenharmony_ci	 * piggyback on our transaction queue
245d4afb5ceSopenharmony_ci	 */
246d4afb5ceSopenharmony_ci
247d4afb5ceSopenharmony_ci	if (meth && (!strcmp(meth, "RAW") || !strcmp(meth, "GET") ||
248d4afb5ceSopenharmony_ci		     !strcmp(meth, "POST") || !strcmp(meth, "PUT") ||
249d4afb5ceSopenharmony_ci		     !strcmp(meth, "MQTT")) &&
250d4afb5ceSopenharmony_ci	    lws_dll2_is_detached(&wsi->dll2_cli_txn_queue) &&
251d4afb5ceSopenharmony_ci	    lws_dll2_is_detached(&wsi->dll_cli_active_conns)) {
252d4afb5ceSopenharmony_ci		lws_context_lock(wsi->a.context, __func__);
253d4afb5ceSopenharmony_ci		lws_vhost_lock(wsi->a.vhost);
254d4afb5ceSopenharmony_ci		lwsl_wsi_info(wsi, "adding as active conn");
255d4afb5ceSopenharmony_ci		/* caution... we will have to unpick this on oom4 path */
256d4afb5ceSopenharmony_ci		lws_dll2_add_head(&wsi->dll_cli_active_conns,
257d4afb5ceSopenharmony_ci				 &wsi->a.vhost->dll_cli_active_conns_owner);
258d4afb5ceSopenharmony_ci		lws_vhost_unlock(wsi->a.vhost);
259d4afb5ceSopenharmony_ci		lws_context_unlock(wsi->a.context);
260d4afb5ceSopenharmony_ci	}
261d4afb5ceSopenharmony_ci
262d4afb5ceSopenharmony_ci	/*
263d4afb5ceSopenharmony_ci	 * Since address must be given at client creation, should not be
264d4afb5ceSopenharmony_ci	 * possible, but necessary to satisfy coverity
265d4afb5ceSopenharmony_ci	 */
266d4afb5ceSopenharmony_ci	if (!adsin)
267d4afb5ceSopenharmony_ci		return NULL;
268d4afb5ceSopenharmony_ci
269d4afb5ceSopenharmony_ci#if defined(LWS_WITH_UNIX_SOCK)
270d4afb5ceSopenharmony_ci	/*
271d4afb5ceSopenharmony_ci	 * unix socket destination?
272d4afb5ceSopenharmony_ci	 */
273d4afb5ceSopenharmony_ci
274d4afb5ceSopenharmony_ci	if (*adsin == '+') {
275d4afb5ceSopenharmony_ci		wsi->unix_skt = 1;
276d4afb5ceSopenharmony_ci		n = 0;
277d4afb5ceSopenharmony_ci		goto next_step;
278d4afb5ceSopenharmony_ci	}
279d4afb5ceSopenharmony_ci#endif
280d4afb5ceSopenharmony_ci
281d4afb5ceSopenharmony_ci	/*
282d4afb5ceSopenharmony_ci	 * start off allowing ipv6 on connection if vhost allows it
283d4afb5ceSopenharmony_ci	 */
284d4afb5ceSopenharmony_ci	wsi->ipv6 = LWS_IPV6_ENABLED(wsi->a.vhost);
285d4afb5ceSopenharmony_ci#ifdef LWS_WITH_IPV6
286d4afb5ceSopenharmony_ci	if (wsi->stash)
287d4afb5ceSopenharmony_ci		iface = wsi->stash->cis[CIS_IFACE];
288d4afb5ceSopenharmony_ci	else
289d4afb5ceSopenharmony_ci		iface = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_IFACE);
290d4afb5ceSopenharmony_ci
291d4afb5ceSopenharmony_ci	if (wsi->ipv6 && iface &&
292d4afb5ceSopenharmony_ci	    inet_pton(AF_INET, iface, &addr.sin_addr) == 1) {
293d4afb5ceSopenharmony_ci		lwsl_wsi_notice(wsi, "client connection forced to IPv4");
294d4afb5ceSopenharmony_ci		wsi->ipv6 = 0;
295d4afb5ceSopenharmony_ci	}
296d4afb5ceSopenharmony_ci#endif
297d4afb5ceSopenharmony_ci
298d4afb5ceSopenharmony_ci#if defined(LWS_CLIENT_HTTP_PROXYING) && \
299d4afb5ceSopenharmony_ci	(defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2))
300d4afb5ceSopenharmony_ci
301d4afb5ceSopenharmony_ci	/* Decide what it is we need to connect to:
302d4afb5ceSopenharmony_ci	 *
303d4afb5ceSopenharmony_ci	 * Priority 1: connect to http proxy */
304d4afb5ceSopenharmony_ci
305d4afb5ceSopenharmony_ci	if (wsi->a.vhost->http.http_proxy_port) {
306d4afb5ceSopenharmony_ci		adsin = wsi->a.vhost->http.http_proxy_address;
307d4afb5ceSopenharmony_ci		port = (int)wsi->a.vhost->http.http_proxy_port;
308d4afb5ceSopenharmony_ci#else
309d4afb5ceSopenharmony_ci		if (0) {
310d4afb5ceSopenharmony_ci#endif
311d4afb5ceSopenharmony_ci
312d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SOCKS5)
313d4afb5ceSopenharmony_ci
314d4afb5ceSopenharmony_ci	/* Priority 2: Connect to SOCK5 Proxy */
315d4afb5ceSopenharmony_ci
316d4afb5ceSopenharmony_ci	} else if (wsi->a.vhost->socks_proxy_port) {
317d4afb5ceSopenharmony_ci		lwsl_wsi_client(wsi, "Sending SOCKS Greeting");
318d4afb5ceSopenharmony_ci		adsin = wsi->a.vhost->socks_proxy_address;
319d4afb5ceSopenharmony_ci		port = (int)wsi->a.vhost->socks_proxy_port;
320d4afb5ceSopenharmony_ci#endif
321d4afb5ceSopenharmony_ci	} else {
322d4afb5ceSopenharmony_ci
323d4afb5ceSopenharmony_ci		/* Priority 3: Connect directly */
324d4afb5ceSopenharmony_ci
325d4afb5ceSopenharmony_ci		/* ads already set */
326d4afb5ceSopenharmony_ci		port = wsi->c_port;
327d4afb5ceSopenharmony_ci	}
328d4afb5ceSopenharmony_ci
329d4afb5ceSopenharmony_ci	/*
330d4afb5ceSopenharmony_ci	 * prepare the actual connection
331d4afb5ceSopenharmony_ci	 * to whatever we decided to connect to
332d4afb5ceSopenharmony_ci	 */
333d4afb5ceSopenharmony_ci	lwsi_set_state(wsi, LRS_WAITING_DNS);
334d4afb5ceSopenharmony_ci
335d4afb5ceSopenharmony_ci	lwsl_wsi_info(wsi, "lookup %s:%u", adsin, port);
336d4afb5ceSopenharmony_ci	wsi->conn_port = (uint16_t)port;
337d4afb5ceSopenharmony_ci
338d4afb5ceSopenharmony_ci#if !defined(LWS_WITH_SYS_ASYNC_DNS)
339d4afb5ceSopenharmony_ci	n = 0;
340d4afb5ceSopenharmony_ci	if (!wsi->dns_sorted_list.count) {
341d4afb5ceSopenharmony_ci		/*
342d4afb5ceSopenharmony_ci		 * blocking dns resolution
343d4afb5ceSopenharmony_ci		 */
344d4afb5ceSopenharmony_ci		n = lws_getaddrinfo46(wsi, adsin, &result);
345d4afb5ceSopenharmony_ci#if defined(EAI_NONAME)
346d4afb5ceSopenharmony_ci		if (n == EAI_NONAME) {
347d4afb5ceSopenharmony_ci			/*
348d4afb5ceSopenharmony_ci			 * The DNS server responded with NXDOMAIN... even
349d4afb5ceSopenharmony_ci			 * though this is still in the client creation call,
350d4afb5ceSopenharmony_ci			 * we need to make a CCE, otherwise there won't be
351d4afb5ceSopenharmony_ci			 * any user indication of what went wrong
352d4afb5ceSopenharmony_ci			 */
353d4afb5ceSopenharmony_ci			wsi->client_suppress_CONNECTION_ERROR = 0;
354d4afb5ceSopenharmony_ci			lws_inform_client_conn_fail(wsi, (void *)dns_nxdomain,
355d4afb5ceSopenharmony_ci						    strlen(dns_nxdomain));
356d4afb5ceSopenharmony_ci			goto failed1;
357d4afb5ceSopenharmony_ci		}
358d4afb5ceSopenharmony_ci#endif
359d4afb5ceSopenharmony_ci	}
360d4afb5ceSopenharmony_ci#else
361d4afb5ceSopenharmony_ci	/* this is either FAILED, CONTINUING, or already called connect_4 */
362d4afb5ceSopenharmony_ci
363d4afb5ceSopenharmony_ci	if (lws_fi(&wsi->fic, "dnsfail"))
364d4afb5ceSopenharmony_ci		return lws_client_connect_3_connect(wsi, NULL, NULL, -4, NULL);
365d4afb5ceSopenharmony_ci	else
366d4afb5ceSopenharmony_ci		n = lws_async_dns_query(wsi->a.context, wsi->tsi, adsin,
367d4afb5ceSopenharmony_ci				LWS_ADNS_RECORD_A, lws_client_connect_3_connect,
368d4afb5ceSopenharmony_ci				wsi, NULL);
369d4afb5ceSopenharmony_ci
370d4afb5ceSopenharmony_ci	if (n == LADNS_RET_FAILED_WSI_CLOSED)
371d4afb5ceSopenharmony_ci		return NULL;
372d4afb5ceSopenharmony_ci
373d4afb5ceSopenharmony_ci	if (n == LADNS_RET_FAILED)
374d4afb5ceSopenharmony_ci		goto failed1;
375d4afb5ceSopenharmony_ci
376d4afb5ceSopenharmony_ci	return wsi;
377d4afb5ceSopenharmony_ci#endif
378d4afb5ceSopenharmony_ci
379d4afb5ceSopenharmony_ci#if defined(LWS_WITH_UNIX_SOCK)
380d4afb5ceSopenharmony_cinext_step:
381d4afb5ceSopenharmony_ci#endif
382d4afb5ceSopenharmony_ci	return lws_client_connect_3_connect(wsi, adsin, result, n, NULL);
383d4afb5ceSopenharmony_ci
384d4afb5ceSopenharmony_ci//#if defined(LWS_WITH_SYS_ASYNC_DNS)
385d4afb5ceSopenharmony_cifailed1:
386d4afb5ceSopenharmony_ci	lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "client_connect2");
387d4afb5ceSopenharmony_ci
388d4afb5ceSopenharmony_ci	return NULL;
389d4afb5ceSopenharmony_ci//#endif
390d4afb5ceSopenharmony_ci}
391