xref: /aosp_15_r20/external/libwebsockets/lib/roles/mqtt/primitives.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  * MQTT v5
25*1c60b9acSAndroid Build Coastguard Worker  *
26*1c60b9acSAndroid Build Coastguard Worker  * http://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.html
27*1c60b9acSAndroid Build Coastguard Worker  */
28*1c60b9acSAndroid Build Coastguard Worker 
29*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-core.h"
30*1c60b9acSAndroid Build Coastguard Worker 
31*1c60b9acSAndroid Build Coastguard Worker #include <string.h>
32*1c60b9acSAndroid Build Coastguard Worker #include <sys/types.h>
33*1c60b9acSAndroid Build Coastguard Worker #include <assert.h>
34*1c60b9acSAndroid Build Coastguard Worker 
35*1c60b9acSAndroid Build Coastguard Worker 
36*1c60b9acSAndroid Build Coastguard Worker /*
37*1c60b9acSAndroid Build Coastguard Worker  * Encode is done into a buffer of at least 4 bytes space.
38*1c60b9acSAndroid Build Coastguard Worker  *
39*1c60b9acSAndroid Build Coastguard Worker  * Returns -1 for error, or number of bytes used
40*1c60b9acSAndroid Build Coastguard Worker  */
41*1c60b9acSAndroid Build Coastguard Worker 
42*1c60b9acSAndroid Build Coastguard Worker int
lws_mqtt_vbi_encode(uint32_t value,void * buf)43*1c60b9acSAndroid Build Coastguard Worker lws_mqtt_vbi_encode(uint32_t value, void *buf)
44*1c60b9acSAndroid Build Coastguard Worker {
45*1c60b9acSAndroid Build Coastguard Worker 	uint8_t *p = (uint8_t *)buf, b;
46*1c60b9acSAndroid Build Coastguard Worker 
47*1c60b9acSAndroid Build Coastguard Worker 	if (value > 0xfffffff) {
48*1c60b9acSAndroid Build Coastguard Worker 		assert(0);
49*1c60b9acSAndroid Build Coastguard Worker 		return -1;
50*1c60b9acSAndroid Build Coastguard Worker 	}
51*1c60b9acSAndroid Build Coastguard Worker 
52*1c60b9acSAndroid Build Coastguard Worker 	do {
53*1c60b9acSAndroid Build Coastguard Worker 		b = value & 0x7f;
54*1c60b9acSAndroid Build Coastguard Worker 		value >>= 7;
55*1c60b9acSAndroid Build Coastguard Worker 		if (value)
56*1c60b9acSAndroid Build Coastguard Worker 			*p++ = (0x80 | b);
57*1c60b9acSAndroid Build Coastguard Worker 		else
58*1c60b9acSAndroid Build Coastguard Worker 			*p++ = b;
59*1c60b9acSAndroid Build Coastguard Worker 	} while (value);
60*1c60b9acSAndroid Build Coastguard Worker 
61*1c60b9acSAndroid Build Coastguard Worker 	return lws_ptr_diff(p, (uint8_t *)buf);
62*1c60b9acSAndroid Build Coastguard Worker }
63*1c60b9acSAndroid Build Coastguard Worker 
64*1c60b9acSAndroid Build Coastguard Worker void
lws_mqtt_vbi_init(lws_mqtt_vbi * vbi)65*1c60b9acSAndroid Build Coastguard Worker lws_mqtt_vbi_init(lws_mqtt_vbi *vbi)
66*1c60b9acSAndroid Build Coastguard Worker {
67*1c60b9acSAndroid Build Coastguard Worker 	vbi->value = 0;
68*1c60b9acSAndroid Build Coastguard Worker 	vbi->consumed = 0;
69*1c60b9acSAndroid Build Coastguard Worker 	vbi->budget = 4;
70*1c60b9acSAndroid Build Coastguard Worker }
71*1c60b9acSAndroid Build Coastguard Worker 
72*1c60b9acSAndroid Build Coastguard Worker void
lws_mqtt_2byte_init(lws_mqtt_vbi * vbi)73*1c60b9acSAndroid Build Coastguard Worker lws_mqtt_2byte_init(lws_mqtt_vbi *vbi)
74*1c60b9acSAndroid Build Coastguard Worker {
75*1c60b9acSAndroid Build Coastguard Worker 	vbi->value = 0;
76*1c60b9acSAndroid Build Coastguard Worker 	vbi->consumed = 0;
77*1c60b9acSAndroid Build Coastguard Worker 	vbi->budget = 2;
78*1c60b9acSAndroid Build Coastguard Worker }
79*1c60b9acSAndroid Build Coastguard Worker 
80*1c60b9acSAndroid Build Coastguard Worker void
lws_mqtt_4byte_init(lws_mqtt_vbi * vbi)81*1c60b9acSAndroid Build Coastguard Worker lws_mqtt_4byte_init(lws_mqtt_vbi *vbi)
82*1c60b9acSAndroid Build Coastguard Worker {
83*1c60b9acSAndroid Build Coastguard Worker 	vbi->value = 0;
84*1c60b9acSAndroid Build Coastguard Worker 	vbi->consumed = 0;
85*1c60b9acSAndroid Build Coastguard Worker 	vbi->budget = 4;
86*1c60b9acSAndroid Build Coastguard Worker }
87*1c60b9acSAndroid Build Coastguard Worker 
88*1c60b9acSAndroid Build Coastguard Worker lws_mqtt_stateful_primitive_return_t
lws_mqtt_vbi_r(lws_mqtt_vbi * vbi,const uint8_t ** in,size_t * len)89*1c60b9acSAndroid Build Coastguard Worker lws_mqtt_vbi_r(lws_mqtt_vbi *vbi, const uint8_t **in, size_t *len)
90*1c60b9acSAndroid Build Coastguard Worker {
91*1c60b9acSAndroid Build Coastguard Worker 	uint8_t multiplier = 0;
92*1c60b9acSAndroid Build Coastguard Worker 	if (!vbi->budget) {
93*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: bad vbi\n", __func__);
94*1c60b9acSAndroid Build Coastguard Worker 
95*1c60b9acSAndroid Build Coastguard Worker 		return LMSPR_FAILED_ALREADY_COMPLETED;
96*1c60b9acSAndroid Build Coastguard Worker 	}
97*1c60b9acSAndroid Build Coastguard Worker 
98*1c60b9acSAndroid Build Coastguard Worker 	while (*len && vbi->budget--) {
99*1c60b9acSAndroid Build Coastguard Worker 		uint8_t u = *((*in)++);
100*1c60b9acSAndroid Build Coastguard Worker 
101*1c60b9acSAndroid Build Coastguard Worker 		(*len)--;
102*1c60b9acSAndroid Build Coastguard Worker 		vbi->consumed++;
103*1c60b9acSAndroid Build Coastguard Worker 		vbi->value = vbi->value + (uint32_t)((u & 0x7f) << multiplier);
104*1c60b9acSAndroid Build Coastguard Worker 		multiplier = (uint8_t)(multiplier + 7);
105*1c60b9acSAndroid Build Coastguard Worker 		if (!(u & 0x80))
106*1c60b9acSAndroid Build Coastguard Worker 			return LMSPR_COMPLETED; /* finished */
107*1c60b9acSAndroid Build Coastguard Worker 	}
108*1c60b9acSAndroid Build Coastguard Worker 
109*1c60b9acSAndroid Build Coastguard Worker 	if (!vbi->budget) { /* should have ended on b7 = 0 and exited then... */
110*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: bad vbi\n", __func__);
111*1c60b9acSAndroid Build Coastguard Worker 
112*1c60b9acSAndroid Build Coastguard Worker 		return LMSPR_FAILED_FORMAT;
113*1c60b9acSAndroid Build Coastguard Worker 	}
114*1c60b9acSAndroid Build Coastguard Worker 
115*1c60b9acSAndroid Build Coastguard Worker 	return LMSPR_NEED_MORE;
116*1c60b9acSAndroid Build Coastguard Worker }
117*1c60b9acSAndroid Build Coastguard Worker 
118*1c60b9acSAndroid Build Coastguard Worker lws_mqtt_stateful_primitive_return_t
lws_mqtt_mb_parse(lws_mqtt_vbi * vbi,const uint8_t ** in,size_t * len)119*1c60b9acSAndroid Build Coastguard Worker lws_mqtt_mb_parse(lws_mqtt_vbi *vbi, const uint8_t **in, size_t *len)
120*1c60b9acSAndroid Build Coastguard Worker {
121*1c60b9acSAndroid Build Coastguard Worker 	if (!vbi->budget)
122*1c60b9acSAndroid Build Coastguard Worker 		return LMSPR_FAILED_ALREADY_COMPLETED;
123*1c60b9acSAndroid Build Coastguard Worker 
124*1c60b9acSAndroid Build Coastguard Worker 	while (*len && vbi->budget--) {
125*1c60b9acSAndroid Build Coastguard Worker 		vbi->value = (vbi->value << 8) | *((*in)++);
126*1c60b9acSAndroid Build Coastguard Worker 		(*len)--;
127*1c60b9acSAndroid Build Coastguard Worker 		vbi->consumed++;
128*1c60b9acSAndroid Build Coastguard Worker 	}
129*1c60b9acSAndroid Build Coastguard Worker 
130*1c60b9acSAndroid Build Coastguard Worker 	return vbi->budget ? LMSPR_NEED_MORE : LMSPR_COMPLETED;
131*1c60b9acSAndroid Build Coastguard Worker }
132*1c60b9acSAndroid Build Coastguard Worker 
133*1c60b9acSAndroid Build Coastguard Worker /*
134*1c60b9acSAndroid Build Coastguard Worker  * You can leave buf NULL, if so it will be allocated on the heap once the
135*1c60b9acSAndroid Build Coastguard Worker  * actual length is known.  nf should be 0, it will be set at allocation time.
136*1c60b9acSAndroid Build Coastguard Worker  *
137*1c60b9acSAndroid Build Coastguard Worker  * Or you can ensure no allocation and use an external buffer by setting buf
138*1c60b9acSAndroid Build Coastguard Worker  * and lim.  But buf must be in the ep context somehow, since it may have to
139*1c60b9acSAndroid Build Coastguard Worker  * survive returns to the event loop unchanged.  Set nf to 0 in this case.
140*1c60b9acSAndroid Build Coastguard Worker  *
141*1c60b9acSAndroid Build Coastguard Worker  * Or you can set buf to an externally allocated buffer, in which case you may
142*1c60b9acSAndroid Build Coastguard Worker  * set nf so it will be freed when the string is "freed".
143*1c60b9acSAndroid Build Coastguard Worker  */
144*1c60b9acSAndroid Build Coastguard Worker 
145*1c60b9acSAndroid Build Coastguard Worker void
lws_mqtt_str_init(lws_mqtt_str_t * s,uint8_t * buf,uint16_t lim,char nf)146*1c60b9acSAndroid Build Coastguard Worker lws_mqtt_str_init(lws_mqtt_str_t *s, uint8_t *buf, uint16_t lim, char nf)
147*1c60b9acSAndroid Build Coastguard Worker {
148*1c60b9acSAndroid Build Coastguard Worker 	s->len = 0;	/* at COMPLETED, consumed count is s->len + 2 */
149*1c60b9acSAndroid Build Coastguard Worker 	s->pos = 0;
150*1c60b9acSAndroid Build Coastguard Worker 	s->buf = buf;
151*1c60b9acSAndroid Build Coastguard Worker 	s->limit = lim;
152*1c60b9acSAndroid Build Coastguard Worker 	s->len_valid = 0;
153*1c60b9acSAndroid Build Coastguard Worker 	s->needs_freeing = nf;
154*1c60b9acSAndroid Build Coastguard Worker }
155*1c60b9acSAndroid Build Coastguard Worker 
156*1c60b9acSAndroid Build Coastguard Worker lws_mqtt_str_t *
lws_mqtt_str_create(uint16_t lim)157*1c60b9acSAndroid Build Coastguard Worker lws_mqtt_str_create(uint16_t lim)
158*1c60b9acSAndroid Build Coastguard Worker {
159*1c60b9acSAndroid Build Coastguard Worker 	lws_mqtt_str_t *s = lws_malloc(sizeof(*s) + lim + 1, __func__);
160*1c60b9acSAndroid Build Coastguard Worker 
161*1c60b9acSAndroid Build Coastguard Worker 	if (!s)
162*1c60b9acSAndroid Build Coastguard Worker 		return NULL;
163*1c60b9acSAndroid Build Coastguard Worker 
164*1c60b9acSAndroid Build Coastguard Worker 	s->len = 0;
165*1c60b9acSAndroid Build Coastguard Worker 	s->pos = 0;
166*1c60b9acSAndroid Build Coastguard Worker 	s->buf = (uint8_t *)&s[1];
167*1c60b9acSAndroid Build Coastguard Worker 	s->limit = lim;
168*1c60b9acSAndroid Build Coastguard Worker 	s->len_valid = 0;
169*1c60b9acSAndroid Build Coastguard Worker 	s->needs_freeing = 1;
170*1c60b9acSAndroid Build Coastguard Worker 
171*1c60b9acSAndroid Build Coastguard Worker 	return s;
172*1c60b9acSAndroid Build Coastguard Worker }
173*1c60b9acSAndroid Build Coastguard Worker 
174*1c60b9acSAndroid Build Coastguard Worker lws_mqtt_str_t *
lws_mqtt_str_create_init(uint8_t * buf,uint16_t len,uint16_t lim)175*1c60b9acSAndroid Build Coastguard Worker lws_mqtt_str_create_init(uint8_t *buf, uint16_t len, uint16_t lim)
176*1c60b9acSAndroid Build Coastguard Worker {
177*1c60b9acSAndroid Build Coastguard Worker 	lws_mqtt_str_t *s;
178*1c60b9acSAndroid Build Coastguard Worker 
179*1c60b9acSAndroid Build Coastguard Worker 	if (!lim)
180*1c60b9acSAndroid Build Coastguard Worker 		lim = len;
181*1c60b9acSAndroid Build Coastguard Worker 
182*1c60b9acSAndroid Build Coastguard Worker 	s = lws_mqtt_str_create(lim);
183*1c60b9acSAndroid Build Coastguard Worker 
184*1c60b9acSAndroid Build Coastguard Worker 	if (!s)
185*1c60b9acSAndroid Build Coastguard Worker 		return NULL;
186*1c60b9acSAndroid Build Coastguard Worker 
187*1c60b9acSAndroid Build Coastguard Worker 	memcpy(s->buf, buf, len);
188*1c60b9acSAndroid Build Coastguard Worker 	s->len = len;
189*1c60b9acSAndroid Build Coastguard Worker 	s->len_valid = 1;
190*1c60b9acSAndroid Build Coastguard Worker 	s->pos = len;
191*1c60b9acSAndroid Build Coastguard Worker 
192*1c60b9acSAndroid Build Coastguard Worker 	return s;
193*1c60b9acSAndroid Build Coastguard Worker }
194*1c60b9acSAndroid Build Coastguard Worker 
195*1c60b9acSAndroid Build Coastguard Worker 
196*1c60b9acSAndroid Build Coastguard Worker lws_mqtt_str_t *
lws_mqtt_str_create_cstr_dup(const char * buf,uint16_t lim)197*1c60b9acSAndroid Build Coastguard Worker lws_mqtt_str_create_cstr_dup(const char *buf, uint16_t lim)
198*1c60b9acSAndroid Build Coastguard Worker {
199*1c60b9acSAndroid Build Coastguard Worker 	size_t len = strlen(buf);
200*1c60b9acSAndroid Build Coastguard Worker 
201*1c60b9acSAndroid Build Coastguard Worker 	if (!lim)
202*1c60b9acSAndroid Build Coastguard Worker 		lim = (uint16_t)len;
203*1c60b9acSAndroid Build Coastguard Worker 
204*1c60b9acSAndroid Build Coastguard Worker 	return lws_mqtt_str_create_init((uint8_t *)buf, (uint16_t)len, lim);
205*1c60b9acSAndroid Build Coastguard Worker }
206*1c60b9acSAndroid Build Coastguard Worker 
207*1c60b9acSAndroid Build Coastguard Worker uint8_t *
lws_mqtt_str_next(lws_mqtt_str_t * s,uint16_t * budget)208*1c60b9acSAndroid Build Coastguard Worker lws_mqtt_str_next(lws_mqtt_str_t *s, uint16_t *budget)
209*1c60b9acSAndroid Build Coastguard Worker {
210*1c60b9acSAndroid Build Coastguard Worker 	if (budget)
211*1c60b9acSAndroid Build Coastguard Worker 		*budget = (uint16_t)(s->limit - s->pos);
212*1c60b9acSAndroid Build Coastguard Worker 
213*1c60b9acSAndroid Build Coastguard Worker 	return &s->buf[s->pos];
214*1c60b9acSAndroid Build Coastguard Worker }
215*1c60b9acSAndroid Build Coastguard Worker 
216*1c60b9acSAndroid Build Coastguard Worker int
lws_mqtt_str_advance(lws_mqtt_str_t * s,int n)217*1c60b9acSAndroid Build Coastguard Worker lws_mqtt_str_advance(lws_mqtt_str_t *s, int n)
218*1c60b9acSAndroid Build Coastguard Worker {
219*1c60b9acSAndroid Build Coastguard Worker 	if (n > s->limit - s->pos) {
220*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: attempted overflow %d vs %d\n", __func__,
221*1c60b9acSAndroid Build Coastguard Worker 			 n, s->limit - s->pos);
222*1c60b9acSAndroid Build Coastguard Worker 		return 1;
223*1c60b9acSAndroid Build Coastguard Worker 	}
224*1c60b9acSAndroid Build Coastguard Worker 
225*1c60b9acSAndroid Build Coastguard Worker 	s->pos = (uint16_t)(s->pos + (uint16_t)n);
226*1c60b9acSAndroid Build Coastguard Worker 	s->len = (uint16_t)(s->len + (uint16_t)n);
227*1c60b9acSAndroid Build Coastguard Worker 
228*1c60b9acSAndroid Build Coastguard Worker 	return 0;
229*1c60b9acSAndroid Build Coastguard Worker }
230*1c60b9acSAndroid Build Coastguard Worker 
231*1c60b9acSAndroid Build Coastguard Worker void
lws_mqtt_str_free(lws_mqtt_str_t ** ps)232*1c60b9acSAndroid Build Coastguard Worker lws_mqtt_str_free(lws_mqtt_str_t **ps)
233*1c60b9acSAndroid Build Coastguard Worker {
234*1c60b9acSAndroid Build Coastguard Worker 	lws_mqtt_str_t *s = *ps;
235*1c60b9acSAndroid Build Coastguard Worker 
236*1c60b9acSAndroid Build Coastguard Worker 	if (!s || !s->needs_freeing)
237*1c60b9acSAndroid Build Coastguard Worker 		return;
238*1c60b9acSAndroid Build Coastguard Worker 
239*1c60b9acSAndroid Build Coastguard Worker 	/* buf may be independently allocated or allocated along with the
240*1c60b9acSAndroid Build Coastguard Worker 	 * lws_mqtt_str_t at the end... if so the whole lws_mqtt_str_t is freed.
241*1c60b9acSAndroid Build Coastguard Worker 	 */
242*1c60b9acSAndroid Build Coastguard Worker 
243*1c60b9acSAndroid Build Coastguard Worker 	if (s->buf != (uint8_t *)&s[1])
244*1c60b9acSAndroid Build Coastguard Worker 		lws_free_set_NULL(s->buf);
245*1c60b9acSAndroid Build Coastguard Worker 	else
246*1c60b9acSAndroid Build Coastguard Worker 		lws_free_set_NULL(*ps);
247*1c60b9acSAndroid Build Coastguard Worker }
248*1c60b9acSAndroid Build Coastguard Worker 
249*1c60b9acSAndroid Build Coastguard Worker /*
250*1c60b9acSAndroid Build Coastguard Worker  * Parses and allocates for lws_mqtt_str_t in a fragmentation-immune, but
251*1c60b9acSAndroid Build Coastguard Worker  * efficient for bulk data way.
252*1c60b9acSAndroid Build Coastguard Worker  *
253*1c60b9acSAndroid Build Coastguard Worker  * Returns: LMSPR_NEED_MORE if needs more data,
254*1c60b9acSAndroid Build Coastguard Worker  * 	    LMSPR_COMPLETED if complete, <0 for error
255*1c60b9acSAndroid Build Coastguard Worker  *
256*1c60b9acSAndroid Build Coastguard Worker  * *len is reduced by, and *in is advanced by, the amount of data actually used,
257*1c60b9acSAndroid Build Coastguard Worker  * except in error case
258*1c60b9acSAndroid Build Coastguard Worker  *
259*1c60b9acSAndroid Build Coastguard Worker  * lws_mqtt_str_free() must be called after calling this successfully
260*1c60b9acSAndroid Build Coastguard Worker  * or not.
261*1c60b9acSAndroid Build Coastguard Worker  */
262*1c60b9acSAndroid Build Coastguard Worker lws_mqtt_stateful_primitive_return_t
lws_mqtt_str_parse(lws_mqtt_str_t * s,const uint8_t ** in,size_t * len)263*1c60b9acSAndroid Build Coastguard Worker lws_mqtt_str_parse(lws_mqtt_str_t *s, const uint8_t **in, size_t *len)
264*1c60b9acSAndroid Build Coastguard Worker {
265*1c60b9acSAndroid Build Coastguard Worker 	const uint8_t *oin = *in;
266*1c60b9acSAndroid Build Coastguard Worker 
267*1c60b9acSAndroid Build Coastguard Worker 	/* handle the length + allocation if needed */
268*1c60b9acSAndroid Build Coastguard Worker 	while (*len && !s->len_valid && s->pos < 2) {
269*1c60b9acSAndroid Build Coastguard Worker 		s->len = (uint16_t)((s->len << 8) | *((*in)++));
270*1c60b9acSAndroid Build Coastguard Worker 		(*len)--;
271*1c60b9acSAndroid Build Coastguard Worker 		oin = *in;
272*1c60b9acSAndroid Build Coastguard Worker 		if (++s->pos == 2) {
273*1c60b9acSAndroid Build Coastguard Worker 			if (s->len > s->limit)
274*1c60b9acSAndroid Build Coastguard Worker 				return LMSPR_FAILED_OVERSIZE;
275*1c60b9acSAndroid Build Coastguard Worker 
276*1c60b9acSAndroid Build Coastguard Worker 			s->pos = 0;
277*1c60b9acSAndroid Build Coastguard Worker 			s->len_valid = 1;
278*1c60b9acSAndroid Build Coastguard Worker 
279*1c60b9acSAndroid Build Coastguard Worker 			if (!s->len) /* do not need to allocate */
280*1c60b9acSAndroid Build Coastguard Worker 				return LMSPR_COMPLETED;
281*1c60b9acSAndroid Build Coastguard Worker 
282*1c60b9acSAndroid Build Coastguard Worker 			if (!s->buf) {
283*1c60b9acSAndroid Build Coastguard Worker 				s->buf = lws_malloc(s->len, __func__);
284*1c60b9acSAndroid Build Coastguard Worker 				if (!s->buf)
285*1c60b9acSAndroid Build Coastguard Worker 					return LMSPR_FAILED_OOM;
286*1c60b9acSAndroid Build Coastguard Worker 
287*1c60b9acSAndroid Build Coastguard Worker 				s->needs_freeing = 1;
288*1c60b9acSAndroid Build Coastguard Worker 			}
289*1c60b9acSAndroid Build Coastguard Worker 		}
290*1c60b9acSAndroid Build Coastguard Worker 	}
291*1c60b9acSAndroid Build Coastguard Worker 
292*1c60b9acSAndroid Build Coastguard Worker 	/* handle copying bulk data into allocation */
293*1c60b9acSAndroid Build Coastguard Worker 	if (s->len_valid && *len) {
294*1c60b9acSAndroid Build Coastguard Worker 		uint16_t span = (uint16_t)(s->len - s->pos);
295*1c60b9acSAndroid Build Coastguard Worker 
296*1c60b9acSAndroid Build Coastguard Worker 		if (span > *len)
297*1c60b9acSAndroid Build Coastguard Worker 			span = (uint16_t)*len;
298*1c60b9acSAndroid Build Coastguard Worker 
299*1c60b9acSAndroid Build Coastguard Worker 		memcpy(s->buf + s->pos, *in, span);
300*1c60b9acSAndroid Build Coastguard Worker 		*in += span;
301*1c60b9acSAndroid Build Coastguard Worker 		s->pos = (uint16_t)(s->pos + (uint16_t)span);
302*1c60b9acSAndroid Build Coastguard Worker 	}
303*1c60b9acSAndroid Build Coastguard Worker 
304*1c60b9acSAndroid Build Coastguard Worker 	*len -= (unsigned long)(*in - oin);
305*1c60b9acSAndroid Build Coastguard Worker 
306*1c60b9acSAndroid Build Coastguard Worker 	return s->buf && s->pos == s->len ? LMSPR_COMPLETED : LMSPR_NEED_MORE;
307*1c60b9acSAndroid Build Coastguard Worker }
308*1c60b9acSAndroid Build Coastguard Worker 
309*1c60b9acSAndroid Build Coastguard Worker int
lws_mqtt_bindata_cmp(const lws_mqtt_str_t * bd1,const lws_mqtt_str_t * bd2)310*1c60b9acSAndroid Build Coastguard Worker lws_mqtt_bindata_cmp(const lws_mqtt_str_t *bd1,
311*1c60b9acSAndroid Build Coastguard Worker 		     const lws_mqtt_str_t *bd2)
312*1c60b9acSAndroid Build Coastguard Worker {
313*1c60b9acSAndroid Build Coastguard Worker 	if (bd1->len != bd2->len)
314*1c60b9acSAndroid Build Coastguard Worker 		return 1;
315*1c60b9acSAndroid Build Coastguard Worker 
316*1c60b9acSAndroid Build Coastguard Worker 	if (!!bd1->buf != !!bd2->buf)
317*1c60b9acSAndroid Build Coastguard Worker 		return 1;
318*1c60b9acSAndroid Build Coastguard Worker 
319*1c60b9acSAndroid Build Coastguard Worker 	if (!bd1->buf && !bd2->buf)
320*1c60b9acSAndroid Build Coastguard Worker 		return 0;
321*1c60b9acSAndroid Build Coastguard Worker 
322*1c60b9acSAndroid Build Coastguard Worker 	return memcmp(bd1->buf, bd2->buf, bd1->len);
323*1c60b9acSAndroid Build Coastguard Worker }
324*1c60b9acSAndroid Build Coastguard Worker 
325