xref: /aosp_15_r20/external/libwebsockets/lib/roles/mqtt/client/client-mqtt.c (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker  * libwebsockets - small server side websockets and web server implementation
3*1c60b9acSAndroid Build Coastguard Worker  *
4*1c60b9acSAndroid Build Coastguard Worker  * Copyright (C) 2010 - 2020 Andy Green <[email protected]>
5*1c60b9acSAndroid Build Coastguard Worker  *
6*1c60b9acSAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a copy
7*1c60b9acSAndroid Build Coastguard Worker  * of this software and associated documentation files (the "Software"), to
8*1c60b9acSAndroid Build Coastguard Worker  * deal in the Software without restriction, including without limitation the
9*1c60b9acSAndroid Build Coastguard Worker  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10*1c60b9acSAndroid Build Coastguard Worker  * sell copies of the Software, and to permit persons to whom the Software is
11*1c60b9acSAndroid Build Coastguard Worker  * furnished to do so, subject to the following conditions:
12*1c60b9acSAndroid Build Coastguard Worker  *
13*1c60b9acSAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included in
14*1c60b9acSAndroid Build Coastguard Worker  * all copies or substantial portions of the Software.
15*1c60b9acSAndroid Build Coastguard Worker  *
16*1c60b9acSAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*1c60b9acSAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*1c60b9acSAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19*1c60b9acSAndroid Build Coastguard Worker  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*1c60b9acSAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21*1c60b9acSAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22*1c60b9acSAndroid Build Coastguard Worker  * IN THE SOFTWARE.
23*1c60b9acSAndroid Build Coastguard Worker  */
24*1c60b9acSAndroid Build Coastguard Worker 
25*1c60b9acSAndroid Build Coastguard Worker /*
26*1c60b9acSAndroid Build Coastguard Worker  * You can leave buf NULL, if so it will be allocated on the heap once the
27*1c60b9acSAndroid Build Coastguard Worker  * actual length is known.  nf should be 0, it will be set at allocation time.
28*1c60b9acSAndroid Build Coastguard Worker  *
29*1c60b9acSAndroid Build Coastguard Worker  * Or you can ensure no allocation and use an external buffer by setting buf
30*1c60b9acSAndroid Build Coastguard Worker  * and lim.  But buf must be in the ep context somehow, since it may have to
31*1c60b9acSAndroid Build Coastguard Worker  * survive returns to the event loop unchanged.  Set nf to 0 in this case.
32*1c60b9acSAndroid Build Coastguard Worker  *
33*1c60b9acSAndroid Build Coastguard Worker  * Or you can set buf to an externally allocated buffer, in which case you may
34*1c60b9acSAndroid Build Coastguard Worker  * set nf so it will be freed when the string is "freed".
35*1c60b9acSAndroid Build Coastguard Worker  */
36*1c60b9acSAndroid Build Coastguard Worker 
37*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-core.h"
38*1c60b9acSAndroid Build Coastguard Worker /* #include "lws-mqtt.h" */
39*1c60b9acSAndroid Build Coastguard Worker /* 3.1.3.1-5: MUST allow... that contain only the characters... */
40*1c60b9acSAndroid Build Coastguard Worker 
41*1c60b9acSAndroid Build Coastguard Worker static const uint8_t *code = (const uint8_t *)
42*1c60b9acSAndroid Build Coastguard Worker 	"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
43*1c60b9acSAndroid Build Coastguard Worker 
44*1c60b9acSAndroid Build Coastguard Worker static int
lws_mqtt_generate_id(struct lws * wsi,lws_mqtt_str_t ** ms,const char * client_id)45*1c60b9acSAndroid Build Coastguard Worker lws_mqtt_generate_id(struct lws* wsi, lws_mqtt_str_t **ms, const char *client_id)
46*1c60b9acSAndroid Build Coastguard Worker {
47*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context *context = wsi->a.context;
48*1c60b9acSAndroid Build Coastguard Worker 	uint16_t ran[24]; /* 16-bit so wrap bias from %62 diluted by ~1000 */
49*1c60b9acSAndroid Build Coastguard Worker 	size_t n, len;
50*1c60b9acSAndroid Build Coastguard Worker 	uint8_t *buf;
51*1c60b9acSAndroid Build Coastguard Worker 
52*1c60b9acSAndroid Build Coastguard Worker 	if (client_id)
53*1c60b9acSAndroid Build Coastguard Worker 		len = strlen(client_id);
54*1c60b9acSAndroid Build Coastguard Worker 	else
55*1c60b9acSAndroid Build Coastguard Worker 		len = LWS_MQTT_RANDOM_CIDLEN;
56*1c60b9acSAndroid Build Coastguard Worker 
57*1c60b9acSAndroid Build Coastguard Worker 	*ms = lws_mqtt_str_create((uint16_t)(len + 1));
58*1c60b9acSAndroid Build Coastguard Worker 	if (!*ms)
59*1c60b9acSAndroid Build Coastguard Worker 		return 1;
60*1c60b9acSAndroid Build Coastguard Worker 
61*1c60b9acSAndroid Build Coastguard Worker 	buf = lws_mqtt_str_next(*ms, NULL);
62*1c60b9acSAndroid Build Coastguard Worker 
63*1c60b9acSAndroid Build Coastguard Worker 	if (client_id) {
64*1c60b9acSAndroid Build Coastguard Worker 		lws_strnncpy((char *)buf, client_id, len, len + 1);
65*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: User space provided a client ID '%s'\n",
66*1c60b9acSAndroid Build Coastguard Worker 			    __func__, (const char *)buf);
67*1c60b9acSAndroid Build Coastguard Worker 	} else {
68*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: generating random client id\n", __func__);
69*1c60b9acSAndroid Build Coastguard Worker 		n = len * sizeof(ran[0]);
70*1c60b9acSAndroid Build Coastguard Worker 		if (lws_get_random(context, ran, n) != n) {
71*1c60b9acSAndroid Build Coastguard Worker 			lws_mqtt_str_free(ms);
72*1c60b9acSAndroid Build Coastguard Worker 
73*1c60b9acSAndroid Build Coastguard Worker 			return 1;
74*1c60b9acSAndroid Build Coastguard Worker 		}
75*1c60b9acSAndroid Build Coastguard Worker 
76*1c60b9acSAndroid Build Coastguard Worker 		for (n = 0; n < len; n++)
77*1c60b9acSAndroid Build Coastguard Worker 			buf[n] = code[ran[n] % 62];
78*1c60b9acSAndroid Build Coastguard Worker 		buf[len] = '\0';
79*1c60b9acSAndroid Build Coastguard Worker 	}
80*1c60b9acSAndroid Build Coastguard Worker 
81*1c60b9acSAndroid Build Coastguard Worker 	if (lws_mqtt_str_advance(*ms, (uint16_t)len)) {
82*1c60b9acSAndroid Build Coastguard Worker 		lws_mqtt_str_free(ms);
83*1c60b9acSAndroid Build Coastguard Worker 
84*1c60b9acSAndroid Build Coastguard Worker 		return 1;
85*1c60b9acSAndroid Build Coastguard Worker 	}
86*1c60b9acSAndroid Build Coastguard Worker 
87*1c60b9acSAndroid Build Coastguard Worker 	return 0;
88*1c60b9acSAndroid Build Coastguard Worker }
89*1c60b9acSAndroid Build Coastguard Worker 
90*1c60b9acSAndroid Build Coastguard Worker int
lws_read_mqtt(struct lws * wsi,unsigned char * buf,lws_filepos_t len)91*1c60b9acSAndroid Build Coastguard Worker lws_read_mqtt(struct lws *wsi, unsigned char *buf, lws_filepos_t len)
92*1c60b9acSAndroid Build Coastguard Worker {
93*1c60b9acSAndroid Build Coastguard Worker 	lws_mqttc_t *c = &wsi->mqtt->client;
94*1c60b9acSAndroid Build Coastguard Worker 
95*1c60b9acSAndroid Build Coastguard Worker 	return _lws_mqtt_rx_parser(wsi, &c->par, buf, (size_t)len);
96*1c60b9acSAndroid Build Coastguard Worker }
97*1c60b9acSAndroid Build Coastguard Worker 
98*1c60b9acSAndroid Build Coastguard Worker int
lws_create_client_mqtt_object(const struct lws_client_connect_info * i,struct lws * wsi)99*1c60b9acSAndroid Build Coastguard Worker lws_create_client_mqtt_object(const struct lws_client_connect_info *i,
100*1c60b9acSAndroid Build Coastguard Worker 			      struct lws *wsi)
101*1c60b9acSAndroid Build Coastguard Worker {
102*1c60b9acSAndroid Build Coastguard Worker 	lws_mqttc_t *c;
103*1c60b9acSAndroid Build Coastguard Worker 	const lws_mqtt_client_connect_param_t *cp = i->mqtt_cp;
104*1c60b9acSAndroid Build Coastguard Worker 
105*1c60b9acSAndroid Build Coastguard Worker 	/* allocate the ws struct for the wsi */
106*1c60b9acSAndroid Build Coastguard Worker 	wsi->mqtt = lws_zalloc(sizeof(*wsi->mqtt), "client mqtt struct");
107*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->mqtt)
108*1c60b9acSAndroid Build Coastguard Worker 		goto oom;
109*1c60b9acSAndroid Build Coastguard Worker 
110*1c60b9acSAndroid Build Coastguard Worker 	wsi->mqtt->wsi = wsi;
111*1c60b9acSAndroid Build Coastguard Worker 	c = &wsi->mqtt->client;
112*1c60b9acSAndroid Build Coastguard Worker 
113*1c60b9acSAndroid Build Coastguard Worker 	if (lws_mqtt_generate_id(wsi, &c->id, cp->client_id)) {
114*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: Error generating client ID\n", __func__);
115*1c60b9acSAndroid Build Coastguard Worker 		return 1;
116*1c60b9acSAndroid Build Coastguard Worker 	}
117*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s: using client id '%.*s'\n", __func__, c->id->len,
118*1c60b9acSAndroid Build Coastguard Worker 			(const char *)c->id->buf);
119*1c60b9acSAndroid Build Coastguard Worker 
120*1c60b9acSAndroid Build Coastguard Worker 	if (cp->clean_start || !(cp->client_id &&
121*1c60b9acSAndroid Build Coastguard Worker 				 cp->client_id[0]))
122*1c60b9acSAndroid Build Coastguard Worker 		c->conn_flags = LMQCFT_CLEAN_START;
123*1c60b9acSAndroid Build Coastguard Worker 	if (cp->client_id_nofree)
124*1c60b9acSAndroid Build Coastguard Worker 		c->conn_flags |= LMQCFT_CLIENT_ID_NOFREE;
125*1c60b9acSAndroid Build Coastguard Worker 	if (cp->username_nofree)
126*1c60b9acSAndroid Build Coastguard Worker 		c->conn_flags |= LMQCFT_USERNAME_NOFREE;
127*1c60b9acSAndroid Build Coastguard Worker 	if (cp->password_nofree)
128*1c60b9acSAndroid Build Coastguard Worker 		c->conn_flags |= LMQCFT_PASSWORD_NOFREE;
129*1c60b9acSAndroid Build Coastguard Worker 
130*1c60b9acSAndroid Build Coastguard Worker 	if (!(c->conn_flags & LMQCFT_CLIENT_ID_NOFREE))
131*1c60b9acSAndroid Build Coastguard Worker 		lws_free((void *)cp->client_id);
132*1c60b9acSAndroid Build Coastguard Worker 
133*1c60b9acSAndroid Build Coastguard Worker 	c->keep_alive_secs = cp->keep_alive;
134*1c60b9acSAndroid Build Coastguard Worker 	c->aws_iot = cp->aws_iot;
135*1c60b9acSAndroid Build Coastguard Worker 
136*1c60b9acSAndroid Build Coastguard Worker 	if (cp->will_param.topic &&
137*1c60b9acSAndroid Build Coastguard Worker 	    *cp->will_param.topic) {
138*1c60b9acSAndroid Build Coastguard Worker 		c->will.topic = lws_mqtt_str_create_cstr_dup(
139*1c60b9acSAndroid Build Coastguard Worker 						cp->will_param.topic, 0);
140*1c60b9acSAndroid Build Coastguard Worker 		if (!c->will.topic)
141*1c60b9acSAndroid Build Coastguard Worker 			goto oom1;
142*1c60b9acSAndroid Build Coastguard Worker 		c->conn_flags |= LMQCFT_WILL_FLAG;
143*1c60b9acSAndroid Build Coastguard Worker 		if (cp->will_param.message) {
144*1c60b9acSAndroid Build Coastguard Worker 			c->will.message = lws_mqtt_str_create_cstr_dup(
145*1c60b9acSAndroid Build Coastguard Worker 						cp->will_param.message, 0);
146*1c60b9acSAndroid Build Coastguard Worker 			if (!c->will.message)
147*1c60b9acSAndroid Build Coastguard Worker 				goto oom2;
148*1c60b9acSAndroid Build Coastguard Worker 		}
149*1c60b9acSAndroid Build Coastguard Worker 		c->conn_flags = (uint16_t)(unsigned int)(c->conn_flags | ((cp->will_param.qos << 3) & LMQCFT_WILL_QOS_MASK));
150*1c60b9acSAndroid Build Coastguard Worker 		c->conn_flags |= (uint16_t)((!!cp->will_param.retain) * LMQCFT_WILL_RETAIN);
151*1c60b9acSAndroid Build Coastguard Worker 	}
152*1c60b9acSAndroid Build Coastguard Worker 
153*1c60b9acSAndroid Build Coastguard Worker 	if (cp->username &&
154*1c60b9acSAndroid Build Coastguard Worker 	    *cp->username) {
155*1c60b9acSAndroid Build Coastguard Worker 		c->username = lws_mqtt_str_create_cstr_dup(cp->username, 0);
156*1c60b9acSAndroid Build Coastguard Worker 		if (!c->username)
157*1c60b9acSAndroid Build Coastguard Worker 			goto oom3;
158*1c60b9acSAndroid Build Coastguard Worker 		c->conn_flags |= LMQCFT_USERNAME;
159*1c60b9acSAndroid Build Coastguard Worker 		if (!(c->conn_flags & LMQCFT_USERNAME_NOFREE))
160*1c60b9acSAndroid Build Coastguard Worker 			lws_free((void *)cp->username);
161*1c60b9acSAndroid Build Coastguard Worker 		if (cp->password) {
162*1c60b9acSAndroid Build Coastguard Worker 			c->password =
163*1c60b9acSAndroid Build Coastguard Worker 				lws_mqtt_str_create_cstr_dup(cp->password, 0);
164*1c60b9acSAndroid Build Coastguard Worker 			if (!c->password)
165*1c60b9acSAndroid Build Coastguard Worker 				goto oom4;
166*1c60b9acSAndroid Build Coastguard Worker 			c->conn_flags |= LMQCFT_PASSWORD;
167*1c60b9acSAndroid Build Coastguard Worker 			if (!(c->conn_flags & LMQCFT_PASSWORD_NOFREE))
168*1c60b9acSAndroid Build Coastguard Worker 				lws_free((void *)cp->password);
169*1c60b9acSAndroid Build Coastguard Worker 		}
170*1c60b9acSAndroid Build Coastguard Worker 	}
171*1c60b9acSAndroid Build Coastguard Worker 
172*1c60b9acSAndroid Build Coastguard Worker 	return 0;
173*1c60b9acSAndroid Build Coastguard Worker oom4:
174*1c60b9acSAndroid Build Coastguard Worker 	lws_mqtt_str_free(&c->username);
175*1c60b9acSAndroid Build Coastguard Worker oom3:
176*1c60b9acSAndroid Build Coastguard Worker 	lws_mqtt_str_free(&c->will.message);
177*1c60b9acSAndroid Build Coastguard Worker oom2:
178*1c60b9acSAndroid Build Coastguard Worker 	lws_mqtt_str_free(&c->will.topic);
179*1c60b9acSAndroid Build Coastguard Worker oom1:
180*1c60b9acSAndroid Build Coastguard Worker 	lws_mqtt_str_free(&c->id);
181*1c60b9acSAndroid Build Coastguard Worker oom:
182*1c60b9acSAndroid Build Coastguard Worker 	lwsl_err("%s: OOM!\n", __func__);
183*1c60b9acSAndroid Build Coastguard Worker 	return 1;
184*1c60b9acSAndroid Build Coastguard Worker }
185*1c60b9acSAndroid Build Coastguard Worker 
186*1c60b9acSAndroid Build Coastguard Worker int
lws_mqtt_client_socket_service(struct lws * wsi,struct lws_pollfd * pollfd,struct lws * wsi_conn)187*1c60b9acSAndroid Build Coastguard Worker lws_mqtt_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd,
188*1c60b9acSAndroid Build Coastguard Worker 			  struct lws *wsi_conn)
189*1c60b9acSAndroid Build Coastguard Worker {
190*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context *context = wsi->a.context;
191*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
192*1c60b9acSAndroid Build Coastguard Worker 	int n = 0, m = 0;
193*1c60b9acSAndroid Build Coastguard Worker 	struct lws_tokens ebuf;
194*1c60b9acSAndroid Build Coastguard Worker 	int buffered = 0;
195*1c60b9acSAndroid Build Coastguard Worker 	int pending = 0;
196*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_TLS)
197*1c60b9acSAndroid Build Coastguard Worker 	char erbuf[128];
198*1c60b9acSAndroid Build Coastguard Worker #endif
199*1c60b9acSAndroid Build Coastguard Worker 	const char *cce = NULL;
200*1c60b9acSAndroid Build Coastguard Worker 
201*1c60b9acSAndroid Build Coastguard Worker 	switch (lwsi_state(wsi)) {
202*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SOCKS5)
203*1c60b9acSAndroid Build Coastguard Worker 	/* SOCKS Greeting Reply */
204*1c60b9acSAndroid Build Coastguard Worker 	case LRS_WAITING_SOCKS_GREETING_REPLY:
205*1c60b9acSAndroid Build Coastguard Worker 	case LRS_WAITING_SOCKS_AUTH_REPLY:
206*1c60b9acSAndroid Build Coastguard Worker 	case LRS_WAITING_SOCKS_CONNECT_REPLY:
207*1c60b9acSAndroid Build Coastguard Worker 
208*1c60b9acSAndroid Build Coastguard Worker 		switch (lws_socks5c_handle_state(wsi, pollfd, &cce)) {
209*1c60b9acSAndroid Build Coastguard Worker 		case LW5CHS_RET_RET0:
210*1c60b9acSAndroid Build Coastguard Worker 			return 0;
211*1c60b9acSAndroid Build Coastguard Worker 		case LW5CHS_RET_BAIL3:
212*1c60b9acSAndroid Build Coastguard Worker 			goto bail3;
213*1c60b9acSAndroid Build Coastguard Worker 		case LW5CHS_RET_STARTHS:
214*1c60b9acSAndroid Build Coastguard Worker 
215*1c60b9acSAndroid Build Coastguard Worker 			/*
216*1c60b9acSAndroid Build Coastguard Worker 			 * Now we got the socks5 connection, we need to go down
217*1c60b9acSAndroid Build Coastguard Worker 			 * the tls path on it if that's what we want
218*1c60b9acSAndroid Build Coastguard Worker 			 */
219*1c60b9acSAndroid Build Coastguard Worker 
220*1c60b9acSAndroid Build Coastguard Worker 			if (!(wsi->tls.use_ssl & LCCSCF_USE_SSL))
221*1c60b9acSAndroid Build Coastguard Worker 				goto start_ws_handshake;
222*1c60b9acSAndroid Build Coastguard Worker 
223*1c60b9acSAndroid Build Coastguard Worker 			switch (lws_client_create_tls(wsi, &cce, 0)) {
224*1c60b9acSAndroid Build Coastguard Worker 			case 0:
225*1c60b9acSAndroid Build Coastguard Worker 				break;
226*1c60b9acSAndroid Build Coastguard Worker 			case 1:
227*1c60b9acSAndroid Build Coastguard Worker 				return 0;
228*1c60b9acSAndroid Build Coastguard Worker 			default:
229*1c60b9acSAndroid Build Coastguard Worker 				goto bail3;
230*1c60b9acSAndroid Build Coastguard Worker 			}
231*1c60b9acSAndroid Build Coastguard Worker 
232*1c60b9acSAndroid Build Coastguard Worker 			break;
233*1c60b9acSAndroid Build Coastguard Worker 
234*1c60b9acSAndroid Build Coastguard Worker 		default:
235*1c60b9acSAndroid Build Coastguard Worker 			break;
236*1c60b9acSAndroid Build Coastguard Worker 		}
237*1c60b9acSAndroid Build Coastguard Worker 		break;
238*1c60b9acSAndroid Build Coastguard Worker #endif
239*1c60b9acSAndroid Build Coastguard Worker 	case LRS_WAITING_DNS:
240*1c60b9acSAndroid Build Coastguard Worker 		/*
241*1c60b9acSAndroid Build Coastguard Worker 		 * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
242*1c60b9acSAndroid Build Coastguard Worker 		 * timeout protection set in client-handshake.c
243*1c60b9acSAndroid Build Coastguard Worker 		 */
244*1c60b9acSAndroid Build Coastguard Worker 		if (!lws_client_connect_2_dnsreq(wsi)) {
245*1c60b9acSAndroid Build Coastguard Worker 			/* closed */
246*1c60b9acSAndroid Build Coastguard Worker 			lwsl_client("closed\n");
247*1c60b9acSAndroid Build Coastguard Worker 			return -1;
248*1c60b9acSAndroid Build Coastguard Worker 		}
249*1c60b9acSAndroid Build Coastguard Worker 
250*1c60b9acSAndroid Build Coastguard Worker 		/* either still pending connection, or changed mode */
251*1c60b9acSAndroid Build Coastguard Worker 		return 0;
252*1c60b9acSAndroid Build Coastguard Worker 
253*1c60b9acSAndroid Build Coastguard Worker 	case LRS_WAITING_CONNECT:
254*1c60b9acSAndroid Build Coastguard Worker 
255*1c60b9acSAndroid Build Coastguard Worker 		/*
256*1c60b9acSAndroid Build Coastguard Worker 		 * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
257*1c60b9acSAndroid Build Coastguard Worker 		 * timeout protection set in client-handshake.c
258*1c60b9acSAndroid Build Coastguard Worker 		 */
259*1c60b9acSAndroid Build Coastguard Worker 		if (pollfd->revents & LWS_POLLOUT)
260*1c60b9acSAndroid Build Coastguard Worker 			lws_client_connect_3_connect(wsi, NULL, NULL, 0, NULL);
261*1c60b9acSAndroid Build Coastguard Worker 		break;
262*1c60b9acSAndroid Build Coastguard Worker 
263*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_TLS)
264*1c60b9acSAndroid Build Coastguard Worker 	case LRS_WAITING_SSL:
265*1c60b9acSAndroid Build Coastguard Worker 
266*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->tls.use_ssl & LCCSCF_USE_SSL) {
267*1c60b9acSAndroid Build Coastguard Worker 			n = lws_ssl_client_connect2(wsi, erbuf, sizeof(erbuf));
268*1c60b9acSAndroid Build Coastguard Worker 			if (!n)
269*1c60b9acSAndroid Build Coastguard Worker 				return 0;
270*1c60b9acSAndroid Build Coastguard Worker 			if (n < 0) {
271*1c60b9acSAndroid Build Coastguard Worker 				cce = erbuf;
272*1c60b9acSAndroid Build Coastguard Worker 				goto bail3;
273*1c60b9acSAndroid Build Coastguard Worker 			}
274*1c60b9acSAndroid Build Coastguard Worker 		} else
275*1c60b9acSAndroid Build Coastguard Worker 			wsi->tls.ssl = NULL;
276*1c60b9acSAndroid Build Coastguard Worker #endif /* LWS_WITH_TLS */
277*1c60b9acSAndroid Build Coastguard Worker 
278*1c60b9acSAndroid Build Coastguard Worker 		/* fallthru */
279*1c60b9acSAndroid Build Coastguard Worker 
280*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SOCKS5)
281*1c60b9acSAndroid Build Coastguard Worker start_ws_handshake:
282*1c60b9acSAndroid Build Coastguard Worker #endif
283*1c60b9acSAndroid Build Coastguard Worker 		lwsi_set_state(wsi, LRS_MQTTC_IDLE);
284*1c60b9acSAndroid Build Coastguard Worker 		lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND,
285*1c60b9acSAndroid Build Coastguard Worker 				(int)context->timeout_secs);
286*1c60b9acSAndroid Build Coastguard Worker 
287*1c60b9acSAndroid Build Coastguard Worker 		/* fallthru */
288*1c60b9acSAndroid Build Coastguard Worker 
289*1c60b9acSAndroid Build Coastguard Worker 	case LRS_MQTTC_IDLE:
290*1c60b9acSAndroid Build Coastguard Worker 		/*
291*1c60b9acSAndroid Build Coastguard Worker 		 * we should be ready to send out MQTT CONNECT
292*1c60b9acSAndroid Build Coastguard Worker 		 */
293*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: %s: Transport established, send out CONNECT\n",
294*1c60b9acSAndroid Build Coastguard Worker 				__func__, lws_wsi_tag(wsi));
295*1c60b9acSAndroid Build Coastguard Worker 		if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
296*1c60b9acSAndroid Build Coastguard Worker 			return -1;
297*1c60b9acSAndroid Build Coastguard Worker 		if (!lws_mqtt_client_send_connect(wsi)) {
298*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: Unable to send MQTT CONNECT\n", __func__);
299*1c60b9acSAndroid Build Coastguard Worker 			return -1;
300*1c60b9acSAndroid Build Coastguard Worker 		}
301*1c60b9acSAndroid Build Coastguard Worker 		if (lws_change_pollfd(wsi, 0, LWS_POLLIN))
302*1c60b9acSAndroid Build Coastguard Worker 			return -1;
303*1c60b9acSAndroid Build Coastguard Worker 
304*1c60b9acSAndroid Build Coastguard Worker 		lwsi_set_state(wsi, LRS_MQTTC_AWAIT_CONNACK);
305*1c60b9acSAndroid Build Coastguard Worker 		return 0;
306*1c60b9acSAndroid Build Coastguard Worker 
307*1c60b9acSAndroid Build Coastguard Worker 	case LRS_ESTABLISHED:
308*1c60b9acSAndroid Build Coastguard Worker 	case LRS_MQTTC_AWAIT_CONNACK:
309*1c60b9acSAndroid Build Coastguard Worker 		buffered = 0;
310*1c60b9acSAndroid Build Coastguard Worker 		ebuf.token = pt->serv_buf;
311*1c60b9acSAndroid Build Coastguard Worker 		ebuf.len = (int)wsi->a.context->pt_serv_buf_size;
312*1c60b9acSAndroid Build Coastguard Worker 
313*1c60b9acSAndroid Build Coastguard Worker 		if ((unsigned int)ebuf.len > wsi->a.context->pt_serv_buf_size)
314*1c60b9acSAndroid Build Coastguard Worker 			ebuf.len = (int)wsi->a.context->pt_serv_buf_size;
315*1c60b9acSAndroid Build Coastguard Worker 
316*1c60b9acSAndroid Build Coastguard Worker 		if ((int)pending > ebuf.len)
317*1c60b9acSAndroid Build Coastguard Worker 			pending = (char)ebuf.len;
318*1c60b9acSAndroid Build Coastguard Worker 
319*1c60b9acSAndroid Build Coastguard Worker 		ebuf.len = lws_ssl_capable_read(wsi, ebuf.token,
320*1c60b9acSAndroid Build Coastguard Worker 						(unsigned int)(pending ? pending :
321*1c60b9acSAndroid Build Coastguard Worker 						ebuf.len));
322*1c60b9acSAndroid Build Coastguard Worker 		switch (ebuf.len) {
323*1c60b9acSAndroid Build Coastguard Worker 		case 0:
324*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("%s: zero length read\n",
325*1c60b9acSAndroid Build Coastguard Worker 				  __func__);
326*1c60b9acSAndroid Build Coastguard Worker 			goto fail;
327*1c60b9acSAndroid Build Coastguard Worker 		case LWS_SSL_CAPABLE_MORE_SERVICE:
328*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("SSL Capable more service\n");
329*1c60b9acSAndroid Build Coastguard Worker 			return 0;
330*1c60b9acSAndroid Build Coastguard Worker 		case LWS_SSL_CAPABLE_ERROR:
331*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("%s: LWS_SSL_CAPABLE_ERROR\n",
332*1c60b9acSAndroid Build Coastguard Worker 					__func__);
333*1c60b9acSAndroid Build Coastguard Worker 			goto fail;
334*1c60b9acSAndroid Build Coastguard Worker 		}
335*1c60b9acSAndroid Build Coastguard Worker 
336*1c60b9acSAndroid Build Coastguard Worker 		if (ebuf.len < 0)
337*1c60b9acSAndroid Build Coastguard Worker 			n = -1;
338*1c60b9acSAndroid Build Coastguard Worker 		else
339*1c60b9acSAndroid Build Coastguard Worker 			n = lws_read_mqtt(wsi, ebuf.token, (unsigned int)ebuf.len);
340*1c60b9acSAndroid Build Coastguard Worker 		if (n < 0) {
341*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: Parsing packet failed\n", __func__);
342*1c60b9acSAndroid Build Coastguard Worker 			goto fail;
343*1c60b9acSAndroid Build Coastguard Worker 		}
344*1c60b9acSAndroid Build Coastguard Worker 
345*1c60b9acSAndroid Build Coastguard Worker 		m = ebuf.len - n;
346*1c60b9acSAndroid Build Coastguard Worker 		// lws_buflist_describe(&wsi->buflist, wsi, __func__);
347*1c60b9acSAndroid Build Coastguard Worker 		lwsl_debug("%s: consuming %d / %d\n", __func__, n, ebuf.len);
348*1c60b9acSAndroid Build Coastguard Worker 		if (lws_buflist_aware_finished_consuming(wsi, &ebuf, m,
349*1c60b9acSAndroid Build Coastguard Worker 							 buffered,
350*1c60b9acSAndroid Build Coastguard Worker 							 __func__))
351*1c60b9acSAndroid Build Coastguard Worker 			return -1;
352*1c60b9acSAndroid Build Coastguard Worker 
353*1c60b9acSAndroid Build Coastguard Worker 		return 0;
354*1c60b9acSAndroid Build Coastguard Worker 
355*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_TLS) || defined(LWS_WITH_SOCKS5)
356*1c60b9acSAndroid Build Coastguard Worker bail3:
357*1c60b9acSAndroid Build Coastguard Worker #endif
358*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("closing conn at LWS_CONNMODE...SERVER_REPLY\n");
359*1c60b9acSAndroid Build Coastguard Worker 		if (cce)
360*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("reason: %s\n", cce);
361*1c60b9acSAndroid Build Coastguard Worker 		lws_inform_client_conn_fail(wsi, (void *)cce, strlen(cce));
362*1c60b9acSAndroid Build Coastguard Worker 
363*1c60b9acSAndroid Build Coastguard Worker 		lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "cbail3");
364*1c60b9acSAndroid Build Coastguard Worker 		return -1;
365*1c60b9acSAndroid Build Coastguard Worker 
366*1c60b9acSAndroid Build Coastguard Worker 	default:
367*1c60b9acSAndroid Build Coastguard Worker 		break;
368*1c60b9acSAndroid Build Coastguard Worker 	}
369*1c60b9acSAndroid Build Coastguard Worker 
370*1c60b9acSAndroid Build Coastguard Worker 	return 0;
371*1c60b9acSAndroid Build Coastguard Worker fail:
372*1c60b9acSAndroid Build Coastguard Worker 	lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "mqtt svc fail");
373*1c60b9acSAndroid Build Coastguard Worker 
374*1c60b9acSAndroid Build Coastguard Worker 	return LWS_HPI_RET_WSI_ALREADY_DIED;
375*1c60b9acSAndroid Build Coastguard Worker }
376