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