xref: /aosp_15_r20/external/libwebsockets/lib/system/smd/smd.c (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker  * lws System Message Distribution
3*1c60b9acSAndroid Build Coastguard Worker  *
4*1c60b9acSAndroid Build Coastguard Worker  * Copyright (C) 2019 - 2021 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 #include "private-lib-core.h"
26*1c60b9acSAndroid Build Coastguard Worker #include <assert.h>
27*1c60b9acSAndroid Build Coastguard Worker 
28*1c60b9acSAndroid Build Coastguard Worker /* comment me to remove extra debug and sanity checks */
29*1c60b9acSAndroid Build Coastguard Worker // #define LWS_SMD_DEBUG
30*1c60b9acSAndroid Build Coastguard Worker 
31*1c60b9acSAndroid Build Coastguard Worker 
32*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_SMD_DEBUG)
33*1c60b9acSAndroid Build Coastguard Worker #define lwsl_smd lwsl_notice
34*1c60b9acSAndroid Build Coastguard Worker #else
35*1c60b9acSAndroid Build Coastguard Worker #define lwsl_smd(_s, ...)
36*1c60b9acSAndroid Build Coastguard Worker #endif
37*1c60b9acSAndroid Build Coastguard Worker 
38*1c60b9acSAndroid Build Coastguard Worker void *
lws_smd_msg_alloc(struct lws_context * ctx,lws_smd_class_t _class,size_t len)39*1c60b9acSAndroid Build Coastguard Worker lws_smd_msg_alloc(struct lws_context *ctx, lws_smd_class_t _class, size_t len)
40*1c60b9acSAndroid Build Coastguard Worker {
41*1c60b9acSAndroid Build Coastguard Worker 	lws_smd_msg_t *msg;
42*1c60b9acSAndroid Build Coastguard Worker 
43*1c60b9acSAndroid Build Coastguard Worker 	/* only allow it if someone wants to consume this class of event */
44*1c60b9acSAndroid Build Coastguard Worker 
45*1c60b9acSAndroid Build Coastguard Worker 	if (!(ctx->smd._class_filter & _class)) {
46*1c60b9acSAndroid Build Coastguard Worker 		lwsl_cx_info(ctx, "rejecting class 0x%x as no participant wants",
47*1c60b9acSAndroid Build Coastguard Worker 				(unsigned int)_class);
48*1c60b9acSAndroid Build Coastguard Worker 		return NULL;
49*1c60b9acSAndroid Build Coastguard Worker 	}
50*1c60b9acSAndroid Build Coastguard Worker 
51*1c60b9acSAndroid Build Coastguard Worker 	assert(len <= LWS_SMD_MAX_PAYLOAD);
52*1c60b9acSAndroid Build Coastguard Worker 
53*1c60b9acSAndroid Build Coastguard Worker 
54*1c60b9acSAndroid Build Coastguard Worker 	/*
55*1c60b9acSAndroid Build Coastguard Worker 	 * If SS configured, over-allocate LWS_SMD_SS_RX_HEADER_LEN behind
56*1c60b9acSAndroid Build Coastguard Worker 	 * payload, ie,  msg_t (gap LWS_SMD_SS_RX_HEADER_LEN) payload
57*1c60b9acSAndroid Build Coastguard Worker 	 */
58*1c60b9acSAndroid Build Coastguard Worker 	msg = lws_malloc(sizeof(*msg) + LWS_SMD_SS_RX_HEADER_LEN_EFF + len,
59*1c60b9acSAndroid Build Coastguard Worker 			 __func__);
60*1c60b9acSAndroid Build Coastguard Worker 	if (!msg)
61*1c60b9acSAndroid Build Coastguard Worker 		return NULL;
62*1c60b9acSAndroid Build Coastguard Worker 
63*1c60b9acSAndroid Build Coastguard Worker 	memset(msg, 0, sizeof(*msg));
64*1c60b9acSAndroid Build Coastguard Worker 	msg->timestamp = lws_now_usecs();
65*1c60b9acSAndroid Build Coastguard Worker 	msg->length = (uint16_t)len;
66*1c60b9acSAndroid Build Coastguard Worker 	msg->_class = _class;
67*1c60b9acSAndroid Build Coastguard Worker 
68*1c60b9acSAndroid Build Coastguard Worker 	return ((uint8_t *)&msg[1]) + LWS_SMD_SS_RX_HEADER_LEN_EFF;
69*1c60b9acSAndroid Build Coastguard Worker }
70*1c60b9acSAndroid Build Coastguard Worker 
71*1c60b9acSAndroid Build Coastguard Worker void
lws_smd_msg_free(void ** ppay)72*1c60b9acSAndroid Build Coastguard Worker lws_smd_msg_free(void **ppay)
73*1c60b9acSAndroid Build Coastguard Worker {
74*1c60b9acSAndroid Build Coastguard Worker 	lws_smd_msg_t *msg = (lws_smd_msg_t *)(((uint8_t *)*ppay) -
75*1c60b9acSAndroid Build Coastguard Worker 				LWS_SMD_SS_RX_HEADER_LEN_EFF - sizeof(*msg));
76*1c60b9acSAndroid Build Coastguard Worker 
77*1c60b9acSAndroid Build Coastguard Worker 	/* if SS configured, actual alloc is LWS_SMD_SS_RX_HEADER_LEN behind */
78*1c60b9acSAndroid Build Coastguard Worker 	lws_free(msg);
79*1c60b9acSAndroid Build Coastguard Worker 	*ppay = NULL;
80*1c60b9acSAndroid Build Coastguard Worker }
81*1c60b9acSAndroid Build Coastguard Worker 
82*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_SMD_DEBUG)
83*1c60b9acSAndroid Build Coastguard Worker static void
lws_smd_dump(lws_smd_t * smd)84*1c60b9acSAndroid Build Coastguard Worker lws_smd_dump(lws_smd_t *smd)
85*1c60b9acSAndroid Build Coastguard Worker {
86*1c60b9acSAndroid Build Coastguard Worker 	int n = 1;
87*1c60b9acSAndroid Build Coastguard Worker 
88*1c60b9acSAndroid Build Coastguard Worker 	lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1,
89*1c60b9acSAndroid Build Coastguard Worker 				   smd->owner_messages.head) {
90*1c60b9acSAndroid Build Coastguard Worker 		lws_smd_msg_t *msg = lws_container_of(p, lws_smd_msg_t, list);
91*1c60b9acSAndroid Build Coastguard Worker 
92*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info(" msg %d: %p: ref %d, lat %dms, cls: 0x%x, len %u: '%s'\n",
93*1c60b9acSAndroid Build Coastguard Worker 			    n++, msg, msg->refcount,
94*1c60b9acSAndroid Build Coastguard Worker 			    (unsigned int)((lws_now_usecs() - msg->timestamp) / 1000),
95*1c60b9acSAndroid Build Coastguard Worker 			    msg->length, msg->_class,
96*1c60b9acSAndroid Build Coastguard Worker 			    (const char *)&msg[1] + LWS_SMD_SS_RX_HEADER_LEN_EFF);
97*1c60b9acSAndroid Build Coastguard Worker 
98*1c60b9acSAndroid Build Coastguard Worker 	} lws_end_foreach_dll_safe(p, p1);
99*1c60b9acSAndroid Build Coastguard Worker 
100*1c60b9acSAndroid Build Coastguard Worker 	n = 1;
101*1c60b9acSAndroid Build Coastguard Worker 	lws_start_foreach_dll(struct lws_dll2 *, p, smd->owner_peers.head) {
102*1c60b9acSAndroid Build Coastguard Worker 		lws_smd_peer_t *pr = lws_container_of(p, lws_smd_peer_t, list);
103*1c60b9acSAndroid Build Coastguard Worker 
104*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info(" peer %d: %p: tail: %p, filt 0x%x\n",
105*1c60b9acSAndroid Build Coastguard Worker 			    n++, pr, pr->tail, pr->_class_filter);
106*1c60b9acSAndroid Build Coastguard Worker 	} lws_end_foreach_dll(p);
107*1c60b9acSAndroid Build Coastguard Worker }
108*1c60b9acSAndroid Build Coastguard Worker #endif
109*1c60b9acSAndroid Build Coastguard Worker 
110*1c60b9acSAndroid Build Coastguard Worker static int
_lws_smd_msg_peer_interested_in_msg(lws_smd_peer_t * pr,lws_smd_msg_t * msg)111*1c60b9acSAndroid Build Coastguard Worker _lws_smd_msg_peer_interested_in_msg(lws_smd_peer_t *pr, lws_smd_msg_t *msg)
112*1c60b9acSAndroid Build Coastguard Worker {
113*1c60b9acSAndroid Build Coastguard Worker     return !!(msg->_class & pr->_class_filter);
114*1c60b9acSAndroid Build Coastguard Worker }
115*1c60b9acSAndroid Build Coastguard Worker 
116*1c60b9acSAndroid Build Coastguard Worker /*
117*1c60b9acSAndroid Build Coastguard Worker  * Figure out what to set the initial refcount for the message to
118*1c60b9acSAndroid Build Coastguard Worker  */
119*1c60b9acSAndroid Build Coastguard Worker 
120*1c60b9acSAndroid Build Coastguard Worker static int
_lws_smd_msg_assess_peers_interested(lws_smd_t * smd,lws_smd_msg_t * msg,struct lws_smd_peer * exc)121*1c60b9acSAndroid Build Coastguard Worker _lws_smd_msg_assess_peers_interested(lws_smd_t *smd, lws_smd_msg_t *msg,
122*1c60b9acSAndroid Build Coastguard Worker 				     struct lws_smd_peer *exc)
123*1c60b9acSAndroid Build Coastguard Worker {
124*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context *ctx = lws_container_of(smd, struct lws_context, smd);
125*1c60b9acSAndroid Build Coastguard Worker 	int interested = 0;
126*1c60b9acSAndroid Build Coastguard Worker 
127*1c60b9acSAndroid Build Coastguard Worker 	lws_start_foreach_dll(struct lws_dll2 *, p, ctx->smd.owner_peers.head) {
128*1c60b9acSAndroid Build Coastguard Worker 		lws_smd_peer_t *pr = lws_container_of(p, lws_smd_peer_t, list);
129*1c60b9acSAndroid Build Coastguard Worker 
130*1c60b9acSAndroid Build Coastguard Worker 		if (pr != exc && _lws_smd_msg_peer_interested_in_msg(pr, msg))
131*1c60b9acSAndroid Build Coastguard Worker 			/*
132*1c60b9acSAndroid Build Coastguard Worker 			 * This peer wants to consume it
133*1c60b9acSAndroid Build Coastguard Worker 			 */
134*1c60b9acSAndroid Build Coastguard Worker 			interested++;
135*1c60b9acSAndroid Build Coastguard Worker 
136*1c60b9acSAndroid Build Coastguard Worker 	} lws_end_foreach_dll(p);
137*1c60b9acSAndroid Build Coastguard Worker 
138*1c60b9acSAndroid Build Coastguard Worker 	return interested;
139*1c60b9acSAndroid Build Coastguard Worker }
140*1c60b9acSAndroid Build Coastguard Worker 
141*1c60b9acSAndroid Build Coastguard Worker static int
_lws_smd_class_mask_union(lws_smd_t * smd)142*1c60b9acSAndroid Build Coastguard Worker _lws_smd_class_mask_union(lws_smd_t *smd)
143*1c60b9acSAndroid Build Coastguard Worker {
144*1c60b9acSAndroid Build Coastguard Worker 	uint32_t mask = 0;
145*1c60b9acSAndroid Build Coastguard Worker 
146*1c60b9acSAndroid Build Coastguard Worker 	lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1,
147*1c60b9acSAndroid Build Coastguard Worker 				   smd->owner_peers.head) {
148*1c60b9acSAndroid Build Coastguard Worker 		lws_smd_peer_t *pr = lws_container_of(p, lws_smd_peer_t, list);
149*1c60b9acSAndroid Build Coastguard Worker 
150*1c60b9acSAndroid Build Coastguard Worker 		mask |= pr->_class_filter;
151*1c60b9acSAndroid Build Coastguard Worker 
152*1c60b9acSAndroid Build Coastguard Worker 	} lws_end_foreach_dll_safe(p, p1);
153*1c60b9acSAndroid Build Coastguard Worker 
154*1c60b9acSAndroid Build Coastguard Worker 	smd->_class_filter = mask;
155*1c60b9acSAndroid Build Coastguard Worker 
156*1c60b9acSAndroid Build Coastguard Worker 	return 0;
157*1c60b9acSAndroid Build Coastguard Worker }
158*1c60b9acSAndroid Build Coastguard Worker 
159*1c60b9acSAndroid Build Coastguard Worker /* Call with message lock held */
160*1c60b9acSAndroid Build Coastguard Worker 
161*1c60b9acSAndroid Build Coastguard Worker static void
_lws_smd_msg_destroy(struct lws_context * cx,lws_smd_t * smd,lws_smd_msg_t * msg)162*1c60b9acSAndroid Build Coastguard Worker _lws_smd_msg_destroy(struct lws_context *cx, lws_smd_t *smd, lws_smd_msg_t *msg)
163*1c60b9acSAndroid Build Coastguard Worker {
164*1c60b9acSAndroid Build Coastguard Worker 	/*
165*1c60b9acSAndroid Build Coastguard Worker 	 * We think we gave the message to everyone and can destroy it.
166*1c60b9acSAndroid Build Coastguard Worker 	 * Sanity check that no peer holds a pointer to this guy
167*1c60b9acSAndroid Build Coastguard Worker 	 */
168*1c60b9acSAndroid Build Coastguard Worker 
169*1c60b9acSAndroid Build Coastguard Worker 	lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1,
170*1c60b9acSAndroid Build Coastguard Worker 				   smd->owner_peers.head) {
171*1c60b9acSAndroid Build Coastguard Worker 		lws_smd_peer_t *xpr = lws_container_of(p, lws_smd_peer_t, list);
172*1c60b9acSAndroid Build Coastguard Worker 
173*1c60b9acSAndroid Build Coastguard Worker 		if (xpr->tail == msg) {
174*1c60b9acSAndroid Build Coastguard Worker 			lwsl_cx_err(cx, "peer %p has msg %p "
175*1c60b9acSAndroid Build Coastguard Worker 				 "we are about to destroy as tail", xpr, msg);
176*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_PLAT_FREERTOS)
177*1c60b9acSAndroid Build Coastguard Worker 			assert(0);
178*1c60b9acSAndroid Build Coastguard Worker #endif
179*1c60b9acSAndroid Build Coastguard Worker 		}
180*1c60b9acSAndroid Build Coastguard Worker 
181*1c60b9acSAndroid Build Coastguard Worker 	} lws_end_foreach_dll_safe(p, p1);
182*1c60b9acSAndroid Build Coastguard Worker 
183*1c60b9acSAndroid Build Coastguard Worker 	/*
184*1c60b9acSAndroid Build Coastguard Worker 	 * We have fully delivered the message now, it
185*1c60b9acSAndroid Build Coastguard Worker 	 * can be unlinked and destroyed
186*1c60b9acSAndroid Build Coastguard Worker 	 */
187*1c60b9acSAndroid Build Coastguard Worker 	lwsl_cx_info(cx, "destroy msg %p", msg);
188*1c60b9acSAndroid Build Coastguard Worker 	lws_dll2_remove(&msg->list);
189*1c60b9acSAndroid Build Coastguard Worker 	lws_free(msg);
190*1c60b9acSAndroid Build Coastguard Worker }
191*1c60b9acSAndroid Build Coastguard Worker 
192*1c60b9acSAndroid Build Coastguard Worker /*
193*1c60b9acSAndroid Build Coastguard Worker  * This is wanting to be threadsafe, limiting the apis we can call
194*1c60b9acSAndroid Build Coastguard Worker  */
195*1c60b9acSAndroid Build Coastguard Worker 
196*1c60b9acSAndroid Build Coastguard Worker int
_lws_smd_msg_send(struct lws_context * ctx,void * pay,struct lws_smd_peer * exc)197*1c60b9acSAndroid Build Coastguard Worker _lws_smd_msg_send(struct lws_context *ctx, void *pay, struct lws_smd_peer *exc)
198*1c60b9acSAndroid Build Coastguard Worker {
199*1c60b9acSAndroid Build Coastguard Worker 	lws_smd_msg_t *msg = (lws_smd_msg_t *)(((uint8_t *)pay) -
200*1c60b9acSAndroid Build Coastguard Worker 				LWS_SMD_SS_RX_HEADER_LEN_EFF - sizeof(*msg));
201*1c60b9acSAndroid Build Coastguard Worker 
202*1c60b9acSAndroid Build Coastguard Worker 	if (ctx->smd.owner_messages.count >= ctx->smd_queue_depth) {
203*1c60b9acSAndroid Build Coastguard Worker 		lwsl_cx_warn(ctx, "rejecting message on queue depth %d",
204*1c60b9acSAndroid Build Coastguard Worker 				  (int)ctx->smd.owner_messages.count);
205*1c60b9acSAndroid Build Coastguard Worker 		/* reject the message due to max queue depth reached */
206*1c60b9acSAndroid Build Coastguard Worker 		return 1;
207*1c60b9acSAndroid Build Coastguard Worker 	}
208*1c60b9acSAndroid Build Coastguard Worker 
209*1c60b9acSAndroid Build Coastguard Worker 	if (!ctx->smd.delivering &&
210*1c60b9acSAndroid Build Coastguard Worker 	    lws_mutex_lock(ctx->smd.lock_peers)) /* +++++++++++++++ peers */
211*1c60b9acSAndroid Build Coastguard Worker 		return 1; /* For Coverity */
212*1c60b9acSAndroid Build Coastguard Worker 
213*1c60b9acSAndroid Build Coastguard Worker 	if (lws_mutex_lock(ctx->smd.lock_messages)) /* +++++++++++++++++ messages */
214*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
215*1c60b9acSAndroid Build Coastguard Worker 
216*1c60b9acSAndroid Build Coastguard Worker 	msg->refcount = (uint16_t)_lws_smd_msg_assess_peers_interested(
217*1c60b9acSAndroid Build Coastguard Worker 							&ctx->smd, msg, exc);
218*1c60b9acSAndroid Build Coastguard Worker 	if (!msg->refcount) {
219*1c60b9acSAndroid Build Coastguard Worker 		/* possible, condsidering exc and no other participants */
220*1c60b9acSAndroid Build Coastguard Worker 		lws_mutex_unlock(ctx->smd.lock_messages); /* --------------- messages */
221*1c60b9acSAndroid Build Coastguard Worker 
222*1c60b9acSAndroid Build Coastguard Worker 		lws_free(msg);
223*1c60b9acSAndroid Build Coastguard Worker 		if (!ctx->smd.delivering)
224*1c60b9acSAndroid Build Coastguard Worker 			lws_mutex_unlock(ctx->smd.lock_peers); /* ------------- peers */
225*1c60b9acSAndroid Build Coastguard Worker 
226*1c60b9acSAndroid Build Coastguard Worker 		return 0;
227*1c60b9acSAndroid Build Coastguard Worker 	}
228*1c60b9acSAndroid Build Coastguard Worker 
229*1c60b9acSAndroid Build Coastguard Worker 	msg->exc = exc;
230*1c60b9acSAndroid Build Coastguard Worker 
231*1c60b9acSAndroid Build Coastguard Worker 	/* let's add him on the queue... */
232*1c60b9acSAndroid Build Coastguard Worker 
233*1c60b9acSAndroid Build Coastguard Worker 	lws_dll2_add_tail(&msg->list, &ctx->smd.owner_messages);
234*1c60b9acSAndroid Build Coastguard Worker 
235*1c60b9acSAndroid Build Coastguard Worker 	/*
236*1c60b9acSAndroid Build Coastguard Worker 	 * Any peer with no active tail needs to check our class to see if we
237*1c60b9acSAndroid Build Coastguard Worker 	 * should become his tail
238*1c60b9acSAndroid Build Coastguard Worker 	 */
239*1c60b9acSAndroid Build Coastguard Worker 
240*1c60b9acSAndroid Build Coastguard Worker 	lws_start_foreach_dll(struct lws_dll2 *, p, ctx->smd.owner_peers.head) {
241*1c60b9acSAndroid Build Coastguard Worker 		lws_smd_peer_t *pr = lws_container_of(p, lws_smd_peer_t, list);
242*1c60b9acSAndroid Build Coastguard Worker 
243*1c60b9acSAndroid Build Coastguard Worker 		if (pr != exc &&
244*1c60b9acSAndroid Build Coastguard Worker                    !pr->tail && _lws_smd_msg_peer_interested_in_msg(pr, msg)) {
245*1c60b9acSAndroid Build Coastguard Worker 			pr->tail = msg;
246*1c60b9acSAndroid Build Coastguard Worker 			/* tail message has to actually be of interest to the peer */
247*1c60b9acSAndroid Build Coastguard Worker 			assert(!pr->tail || (pr->tail->_class & pr->_class_filter));
248*1c60b9acSAndroid Build Coastguard Worker 		}
249*1c60b9acSAndroid Build Coastguard Worker 
250*1c60b9acSAndroid Build Coastguard Worker 	} lws_end_foreach_dll(p);
251*1c60b9acSAndroid Build Coastguard Worker 
252*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_SMD_DEBUG)
253*1c60b9acSAndroid Build Coastguard Worker 	lwsl_smd("%s: added %p (refc %u) depth now %d\n", __func__,
254*1c60b9acSAndroid Build Coastguard Worker 		 msg, msg->refcount, ctx->smd.owner_messages.count);
255*1c60b9acSAndroid Build Coastguard Worker 	lws_smd_dump(&ctx->smd);
256*1c60b9acSAndroid Build Coastguard Worker #endif
257*1c60b9acSAndroid Build Coastguard Worker 
258*1c60b9acSAndroid Build Coastguard Worker 	lws_mutex_unlock(ctx->smd.lock_messages); /* --------------- messages */
259*1c60b9acSAndroid Build Coastguard Worker 
260*1c60b9acSAndroid Build Coastguard Worker bail:
261*1c60b9acSAndroid Build Coastguard Worker 	if (!ctx->smd.delivering)
262*1c60b9acSAndroid Build Coastguard Worker 		lws_mutex_unlock(ctx->smd.lock_peers); /* ------------- peers */
263*1c60b9acSAndroid Build Coastguard Worker 
264*1c60b9acSAndroid Build Coastguard Worker 	/* we may be happening from another thread context */
265*1c60b9acSAndroid Build Coastguard Worker 	lws_cancel_service(ctx);
266*1c60b9acSAndroid Build Coastguard Worker 
267*1c60b9acSAndroid Build Coastguard Worker 	return 0;
268*1c60b9acSAndroid Build Coastguard Worker }
269*1c60b9acSAndroid Build Coastguard Worker 
270*1c60b9acSAndroid Build Coastguard Worker /*
271*1c60b9acSAndroid Build Coastguard Worker  * This is wanting to be threadsafe, limiting the apis we can call
272*1c60b9acSAndroid Build Coastguard Worker  */
273*1c60b9acSAndroid Build Coastguard Worker 
274*1c60b9acSAndroid Build Coastguard Worker int
lws_smd_msg_send(struct lws_context * ctx,void * pay)275*1c60b9acSAndroid Build Coastguard Worker lws_smd_msg_send(struct lws_context *ctx, void *pay)
276*1c60b9acSAndroid Build Coastguard Worker {
277*1c60b9acSAndroid Build Coastguard Worker 	return _lws_smd_msg_send(ctx, pay, NULL);
278*1c60b9acSAndroid Build Coastguard Worker }
279*1c60b9acSAndroid Build Coastguard Worker 
280*1c60b9acSAndroid Build Coastguard Worker /*
281*1c60b9acSAndroid Build Coastguard Worker  * This is wanting to be threadsafe, limiting the apis we can call
282*1c60b9acSAndroid Build Coastguard Worker  */
283*1c60b9acSAndroid Build Coastguard Worker 
284*1c60b9acSAndroid Build Coastguard Worker int
lws_smd_msg_printf(struct lws_context * ctx,lws_smd_class_t _class,const char * format,...)285*1c60b9acSAndroid Build Coastguard Worker lws_smd_msg_printf(struct lws_context *ctx, lws_smd_class_t _class,
286*1c60b9acSAndroid Build Coastguard Worker 		   const char *format, ...)
287*1c60b9acSAndroid Build Coastguard Worker {
288*1c60b9acSAndroid Build Coastguard Worker 	lws_smd_msg_t *msg;
289*1c60b9acSAndroid Build Coastguard Worker 	va_list ap;
290*1c60b9acSAndroid Build Coastguard Worker 	void *p;
291*1c60b9acSAndroid Build Coastguard Worker 	int n;
292*1c60b9acSAndroid Build Coastguard Worker 
293*1c60b9acSAndroid Build Coastguard Worker 	if (!(ctx->smd._class_filter & _class))
294*1c60b9acSAndroid Build Coastguard Worker 		/*
295*1c60b9acSAndroid Build Coastguard Worker 		 * There's nobody interested in messages of this class atm.
296*1c60b9acSAndroid Build Coastguard Worker 		 * Don't bother generating it, and act like all is well.
297*1c60b9acSAndroid Build Coastguard Worker 		 */
298*1c60b9acSAndroid Build Coastguard Worker 		return 0;
299*1c60b9acSAndroid Build Coastguard Worker 
300*1c60b9acSAndroid Build Coastguard Worker 	va_start(ap, format);
301*1c60b9acSAndroid Build Coastguard Worker 	n = vsnprintf(NULL, 0, format, ap);
302*1c60b9acSAndroid Build Coastguard Worker 	va_end(ap);
303*1c60b9acSAndroid Build Coastguard Worker 	if (n > LWS_SMD_MAX_PAYLOAD)
304*1c60b9acSAndroid Build Coastguard Worker 		/* too large to send */
305*1c60b9acSAndroid Build Coastguard Worker 		return 1;
306*1c60b9acSAndroid Build Coastguard Worker 
307*1c60b9acSAndroid Build Coastguard Worker 	p = lws_smd_msg_alloc(ctx, _class, (size_t)n + 2);
308*1c60b9acSAndroid Build Coastguard Worker 	if (!p)
309*1c60b9acSAndroid Build Coastguard Worker 		return 1;
310*1c60b9acSAndroid Build Coastguard Worker 	msg = (lws_smd_msg_t *)(((uint8_t *)p) - LWS_SMD_SS_RX_HEADER_LEN_EFF -
311*1c60b9acSAndroid Build Coastguard Worker 								sizeof(*msg));
312*1c60b9acSAndroid Build Coastguard Worker 	msg->length = (uint16_t)n;
313*1c60b9acSAndroid Build Coastguard Worker 	va_start(ap, format);
314*1c60b9acSAndroid Build Coastguard Worker 	vsnprintf((char *)p, (unsigned int)n + 2, format, ap);
315*1c60b9acSAndroid Build Coastguard Worker 	va_end(ap);
316*1c60b9acSAndroid Build Coastguard Worker 
317*1c60b9acSAndroid Build Coastguard Worker 	/*
318*1c60b9acSAndroid Build Coastguard Worker 	 * locks taken and released in here
319*1c60b9acSAndroid Build Coastguard Worker 	 */
320*1c60b9acSAndroid Build Coastguard Worker 
321*1c60b9acSAndroid Build Coastguard Worker 	if (lws_smd_msg_send(ctx, p)) {
322*1c60b9acSAndroid Build Coastguard Worker 		lws_smd_msg_free(&p);
323*1c60b9acSAndroid Build Coastguard Worker 		return 1;
324*1c60b9acSAndroid Build Coastguard Worker 	}
325*1c60b9acSAndroid Build Coastguard Worker 
326*1c60b9acSAndroid Build Coastguard Worker 	return 0;
327*1c60b9acSAndroid Build Coastguard Worker }
328*1c60b9acSAndroid Build Coastguard Worker 
329*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SECURE_STREAMS)
330*1c60b9acSAndroid Build Coastguard Worker int
lws_smd_ss_msg_printf(const char * tag,uint8_t * buf,size_t * len,lws_smd_class_t _class,const char * format,...)331*1c60b9acSAndroid Build Coastguard Worker lws_smd_ss_msg_printf(const char *tag, uint8_t *buf, size_t *len,
332*1c60b9acSAndroid Build Coastguard Worker 		      lws_smd_class_t _class, const char *format, ...)
333*1c60b9acSAndroid Build Coastguard Worker {
334*1c60b9acSAndroid Build Coastguard Worker 	char *content = (char *)buf + LWS_SMD_SS_RX_HEADER_LEN;
335*1c60b9acSAndroid Build Coastguard Worker 	va_list ap;
336*1c60b9acSAndroid Build Coastguard Worker 	int n;
337*1c60b9acSAndroid Build Coastguard Worker 
338*1c60b9acSAndroid Build Coastguard Worker 	if (*len < LWS_SMD_SS_RX_HEADER_LEN)
339*1c60b9acSAndroid Build Coastguard Worker 		return 1;
340*1c60b9acSAndroid Build Coastguard Worker 
341*1c60b9acSAndroid Build Coastguard Worker 	lws_ser_wu64be(buf, _class);
342*1c60b9acSAndroid Build Coastguard Worker 	lws_ser_wu64be(buf + 8, 0); /* valgrind notices uninitialized if left */
343*1c60b9acSAndroid Build Coastguard Worker 
344*1c60b9acSAndroid Build Coastguard Worker 	va_start(ap, format);
345*1c60b9acSAndroid Build Coastguard Worker 	n = vsnprintf(content, (*len) - LWS_SMD_SS_RX_HEADER_LEN, format, ap);
346*1c60b9acSAndroid Build Coastguard Worker 	va_end(ap);
347*1c60b9acSAndroid Build Coastguard Worker 
348*1c60b9acSAndroid Build Coastguard Worker 	if (n > LWS_SMD_MAX_PAYLOAD ||
349*1c60b9acSAndroid Build Coastguard Worker 	    (unsigned int)n > (*len) - LWS_SMD_SS_RX_HEADER_LEN)
350*1c60b9acSAndroid Build Coastguard Worker 		/* too large to send */
351*1c60b9acSAndroid Build Coastguard Worker 		return 1;
352*1c60b9acSAndroid Build Coastguard Worker 
353*1c60b9acSAndroid Build Coastguard Worker 	*len = LWS_SMD_SS_RX_HEADER_LEN + (unsigned int)n;
354*1c60b9acSAndroid Build Coastguard Worker 
355*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s: %s send cl 0x%x, len %u\n", __func__, tag, (unsigned int)_class,
356*1c60b9acSAndroid Build Coastguard Worker 			(unsigned int)n);
357*1c60b9acSAndroid Build Coastguard Worker 
358*1c60b9acSAndroid Build Coastguard Worker 	return 0;
359*1c60b9acSAndroid Build Coastguard Worker }
360*1c60b9acSAndroid Build Coastguard Worker 
361*1c60b9acSAndroid Build Coastguard Worker /*
362*1c60b9acSAndroid Build Coastguard Worker  * This is a helper that user rx handler for LWS_SMD_STREAMTYPENAME SS can
363*1c60b9acSAndroid Build Coastguard Worker  * call through to with the payload it received from the proxy.  It will then
364*1c60b9acSAndroid Build Coastguard Worker  * forward the recieved SMD message to all local (same-context) participants
365*1c60b9acSAndroid Build Coastguard Worker  * that are interested in that class (except ones with callback skip_cb, so
366*1c60b9acSAndroid Build Coastguard Worker  * we don't loop).
367*1c60b9acSAndroid Build Coastguard Worker  */
368*1c60b9acSAndroid Build Coastguard Worker 
369*1c60b9acSAndroid Build Coastguard Worker static int
_lws_smd_ss_rx_forward(struct lws_context * ctx,const char * tag,struct lws_smd_peer * pr,const uint8_t * buf,size_t len)370*1c60b9acSAndroid Build Coastguard Worker _lws_smd_ss_rx_forward(struct lws_context *ctx, const char *tag,
371*1c60b9acSAndroid Build Coastguard Worker 		       struct lws_smd_peer *pr, const uint8_t *buf, size_t len)
372*1c60b9acSAndroid Build Coastguard Worker {
373*1c60b9acSAndroid Build Coastguard Worker 	lws_smd_class_t _class;
374*1c60b9acSAndroid Build Coastguard Worker 	lws_smd_msg_t *msg;
375*1c60b9acSAndroid Build Coastguard Worker 	void *p;
376*1c60b9acSAndroid Build Coastguard Worker 
377*1c60b9acSAndroid Build Coastguard Worker 	if (len < LWS_SMD_SS_RX_HEADER_LEN_EFF)
378*1c60b9acSAndroid Build Coastguard Worker 		return 1;
379*1c60b9acSAndroid Build Coastguard Worker 
380*1c60b9acSAndroid Build Coastguard Worker 	if (len >= LWS_SMD_MAX_PAYLOAD + LWS_SMD_SS_RX_HEADER_LEN_EFF)
381*1c60b9acSAndroid Build Coastguard Worker 		return 1;
382*1c60b9acSAndroid Build Coastguard Worker 
383*1c60b9acSAndroid Build Coastguard Worker 	_class = (lws_smd_class_t)lws_ser_ru64be(buf);
384*1c60b9acSAndroid Build Coastguard Worker 
385*1c60b9acSAndroid Build Coastguard Worker 	if (_class == LWSSMDCL_METRICS) {
386*1c60b9acSAndroid Build Coastguard Worker 
387*1c60b9acSAndroid Build Coastguard Worker 	}
388*1c60b9acSAndroid Build Coastguard Worker 
389*1c60b9acSAndroid Build Coastguard Worker 	/* only locally forward messages that we care about in this process */
390*1c60b9acSAndroid Build Coastguard Worker 
391*1c60b9acSAndroid Build Coastguard Worker 	if (!(ctx->smd._class_filter & _class))
392*1c60b9acSAndroid Build Coastguard Worker 		/*
393*1c60b9acSAndroid Build Coastguard Worker 		 * There's nobody interested in messages of this class atm.
394*1c60b9acSAndroid Build Coastguard Worker 		 * Don't bother generating it, and act like all is well.
395*1c60b9acSAndroid Build Coastguard Worker 		 */
396*1c60b9acSAndroid Build Coastguard Worker 		return 0;
397*1c60b9acSAndroid Build Coastguard Worker 
398*1c60b9acSAndroid Build Coastguard Worker 	p = lws_smd_msg_alloc(ctx, _class, len);
399*1c60b9acSAndroid Build Coastguard Worker 	if (!p)
400*1c60b9acSAndroid Build Coastguard Worker 		return 1;
401*1c60b9acSAndroid Build Coastguard Worker 
402*1c60b9acSAndroid Build Coastguard Worker 	msg = (lws_smd_msg_t *)(((uint8_t *)p) - LWS_SMD_SS_RX_HEADER_LEN_EFF -
403*1c60b9acSAndroid Build Coastguard Worker 								sizeof(*msg));
404*1c60b9acSAndroid Build Coastguard Worker 	msg->length = (uint16_t)(len - LWS_SMD_SS_RX_HEADER_LEN_EFF);
405*1c60b9acSAndroid Build Coastguard Worker 	/* adopt the original source timestamp, not time we forwarded it */
406*1c60b9acSAndroid Build Coastguard Worker 	msg->timestamp = (lws_usec_t)lws_ser_ru64be(buf + 8);
407*1c60b9acSAndroid Build Coastguard Worker 
408*1c60b9acSAndroid Build Coastguard Worker 	/* copy the message payload in */
409*1c60b9acSAndroid Build Coastguard Worker 	memcpy(p, buf + LWS_SMD_SS_RX_HEADER_LEN_EFF, msg->length);
410*1c60b9acSAndroid Build Coastguard Worker 
411*1c60b9acSAndroid Build Coastguard Worker 	/*
412*1c60b9acSAndroid Build Coastguard Worker 	 * locks taken and released in here
413*1c60b9acSAndroid Build Coastguard Worker 	 */
414*1c60b9acSAndroid Build Coastguard Worker 
415*1c60b9acSAndroid Build Coastguard Worker 	if (_lws_smd_msg_send(ctx, p, pr)) {
416*1c60b9acSAndroid Build Coastguard Worker 		/* we couldn't send it after all that... */
417*1c60b9acSAndroid Build Coastguard Worker 		lws_smd_msg_free(&p);
418*1c60b9acSAndroid Build Coastguard Worker 
419*1c60b9acSAndroid Build Coastguard Worker 		return 1;
420*1c60b9acSAndroid Build Coastguard Worker 	}
421*1c60b9acSAndroid Build Coastguard Worker 
422*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s: %s send cl 0x%x, len %u, ts %llu\n", __func__,
423*1c60b9acSAndroid Build Coastguard Worker 		    tag, (unsigned int)_class, msg->length,
424*1c60b9acSAndroid Build Coastguard Worker 		    (unsigned long long)msg->timestamp);
425*1c60b9acSAndroid Build Coastguard Worker 
426*1c60b9acSAndroid Build Coastguard Worker 	return 0;
427*1c60b9acSAndroid Build Coastguard Worker }
428*1c60b9acSAndroid Build Coastguard Worker 
429*1c60b9acSAndroid Build Coastguard Worker int
lws_smd_ss_rx_forward(void * ss_user,const uint8_t * buf,size_t len)430*1c60b9acSAndroid Build Coastguard Worker lws_smd_ss_rx_forward(void *ss_user, const uint8_t *buf, size_t len)
431*1c60b9acSAndroid Build Coastguard Worker {
432*1c60b9acSAndroid Build Coastguard Worker 	struct lws_ss_handle *h = (struct lws_ss_handle *)
433*1c60b9acSAndroid Build Coastguard Worker 					(((char *)ss_user) - sizeof(*h));
434*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context *ctx = lws_ss_get_context(h);
435*1c60b9acSAndroid Build Coastguard Worker 
436*1c60b9acSAndroid Build Coastguard Worker 	return _lws_smd_ss_rx_forward(ctx, lws_ss_tag(h), h->u.smd.smd_peer, buf, len);
437*1c60b9acSAndroid Build Coastguard Worker }
438*1c60b9acSAndroid Build Coastguard Worker 
439*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)
440*1c60b9acSAndroid Build Coastguard Worker int
lws_smd_sspc_rx_forward(void * ss_user,const uint8_t * buf,size_t len)441*1c60b9acSAndroid Build Coastguard Worker lws_smd_sspc_rx_forward(void *ss_user, const uint8_t *buf, size_t len)
442*1c60b9acSAndroid Build Coastguard Worker {
443*1c60b9acSAndroid Build Coastguard Worker 	struct lws_sspc_handle *h = (struct lws_sspc_handle *)
444*1c60b9acSAndroid Build Coastguard Worker 					(((char *)ss_user) - sizeof(*h));
445*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context *ctx = lws_sspc_get_context(h);
446*1c60b9acSAndroid Build Coastguard Worker 
447*1c60b9acSAndroid Build Coastguard Worker 	return _lws_smd_ss_rx_forward(ctx, lws_sspc_tag(h), NULL, buf, len);
448*1c60b9acSAndroid Build Coastguard Worker }
449*1c60b9acSAndroid Build Coastguard Worker #endif
450*1c60b9acSAndroid Build Coastguard Worker 
451*1c60b9acSAndroid Build Coastguard Worker #endif
452*1c60b9acSAndroid Build Coastguard Worker 
453*1c60b9acSAndroid Build Coastguard Worker /*
454*1c60b9acSAndroid Build Coastguard Worker  * Peers that deregister need to adjust the refcount of messages they would
455*1c60b9acSAndroid Build Coastguard Worker  * have been interested in, but didn't take delivery of yet
456*1c60b9acSAndroid Build Coastguard Worker  */
457*1c60b9acSAndroid Build Coastguard Worker 
458*1c60b9acSAndroid Build Coastguard Worker static void
_lws_smd_peer_destroy(lws_smd_peer_t * pr)459*1c60b9acSAndroid Build Coastguard Worker _lws_smd_peer_destroy(lws_smd_peer_t *pr)
460*1c60b9acSAndroid Build Coastguard Worker {
461*1c60b9acSAndroid Build Coastguard Worker 	lws_smd_t *smd = lws_container_of(pr->list.owner, lws_smd_t,
462*1c60b9acSAndroid Build Coastguard Worker 					  owner_peers);
463*1c60b9acSAndroid Build Coastguard Worker 
464*1c60b9acSAndroid Build Coastguard Worker 	if (lws_mutex_lock(smd->lock_messages)) /* +++++++++ messages */
465*1c60b9acSAndroid Build Coastguard Worker 		return; /* For Coverity */
466*1c60b9acSAndroid Build Coastguard Worker 
467*1c60b9acSAndroid Build Coastguard Worker 	lws_dll2_remove(&pr->list);
468*1c60b9acSAndroid Build Coastguard Worker 
469*1c60b9acSAndroid Build Coastguard Worker 	/*
470*1c60b9acSAndroid Build Coastguard Worker 	 * We take the approach to adjust the refcount of every would-have-been
471*1c60b9acSAndroid Build Coastguard Worker 	 * delivered message we were interested in
472*1c60b9acSAndroid Build Coastguard Worker 	 */
473*1c60b9acSAndroid Build Coastguard Worker 
474*1c60b9acSAndroid Build Coastguard Worker 	while (pr->tail) {
475*1c60b9acSAndroid Build Coastguard Worker 
476*1c60b9acSAndroid Build Coastguard Worker 		lws_smd_msg_t *m1 = lws_container_of(pr->tail->list.next,
477*1c60b9acSAndroid Build Coastguard Worker 							lws_smd_msg_t, list);
478*1c60b9acSAndroid Build Coastguard Worker 
479*1c60b9acSAndroid Build Coastguard Worker 		if (_lws_smd_msg_peer_interested_in_msg(pr, pr->tail)) {
480*1c60b9acSAndroid Build Coastguard Worker 			if (!--pr->tail->refcount)
481*1c60b9acSAndroid Build Coastguard Worker 				_lws_smd_msg_destroy(pr->ctx, smd, pr->tail);
482*1c60b9acSAndroid Build Coastguard Worker 		}
483*1c60b9acSAndroid Build Coastguard Worker 
484*1c60b9acSAndroid Build Coastguard Worker 		pr->tail = m1;
485*1c60b9acSAndroid Build Coastguard Worker 	}
486*1c60b9acSAndroid Build Coastguard Worker 
487*1c60b9acSAndroid Build Coastguard Worker 	lws_free(pr);
488*1c60b9acSAndroid Build Coastguard Worker 
489*1c60b9acSAndroid Build Coastguard Worker 	lws_mutex_unlock(smd->lock_messages); /* messages ------- */
490*1c60b9acSAndroid Build Coastguard Worker }
491*1c60b9acSAndroid Build Coastguard Worker 
492*1c60b9acSAndroid Build Coastguard Worker static lws_smd_msg_t *
_lws_smd_msg_next_matching_filter(lws_smd_peer_t * pr)493*1c60b9acSAndroid Build Coastguard Worker _lws_smd_msg_next_matching_filter(lws_smd_peer_t *pr)
494*1c60b9acSAndroid Build Coastguard Worker {
495*1c60b9acSAndroid Build Coastguard Worker 	lws_dll2_t *tail = &pr->tail->list;
496*1c60b9acSAndroid Build Coastguard Worker 	lws_smd_msg_t *msg;
497*1c60b9acSAndroid Build Coastguard Worker 
498*1c60b9acSAndroid Build Coastguard Worker 	do {
499*1c60b9acSAndroid Build Coastguard Worker 		tail = tail->next;
500*1c60b9acSAndroid Build Coastguard Worker 		if (!tail)
501*1c60b9acSAndroid Build Coastguard Worker 			return NULL;
502*1c60b9acSAndroid Build Coastguard Worker 
503*1c60b9acSAndroid Build Coastguard Worker 		msg = lws_container_of(tail, lws_smd_msg_t, list);
504*1c60b9acSAndroid Build Coastguard Worker 		if (msg->exc != pr &&
505*1c60b9acSAndroid Build Coastguard Worker 		    _lws_smd_msg_peer_interested_in_msg(pr, msg))
506*1c60b9acSAndroid Build Coastguard Worker 			return msg;
507*1c60b9acSAndroid Build Coastguard Worker 	} while (1);
508*1c60b9acSAndroid Build Coastguard Worker 
509*1c60b9acSAndroid Build Coastguard Worker 	return NULL;
510*1c60b9acSAndroid Build Coastguard Worker }
511*1c60b9acSAndroid Build Coastguard Worker 
512*1c60b9acSAndroid Build Coastguard Worker /*
513*1c60b9acSAndroid Build Coastguard Worker  * Delivers only one message to the peer and advances the tail, or sets to NULL
514*1c60b9acSAndroid Build Coastguard Worker  * if no more filtered queued messages.  Returns nonzero if tail non-NULL.
515*1c60b9acSAndroid Build Coastguard Worker  *
516*1c60b9acSAndroid Build Coastguard Worker  * For Proxied SS, only asks for writeable and does not advance or change the
517*1c60b9acSAndroid Build Coastguard Worker  * tail.
518*1c60b9acSAndroid Build Coastguard Worker  *
519*1c60b9acSAndroid Build Coastguard Worker  * This is done so if multiple messages queued, we don't get a situation where
520*1c60b9acSAndroid Build Coastguard Worker  * one participant gets them all spammed, then the next etc.  Instead they are
521*1c60b9acSAndroid Build Coastguard Worker  * delivered round-robin.
522*1c60b9acSAndroid Build Coastguard Worker  *
523*1c60b9acSAndroid Build Coastguard Worker  * Requires peer lock, may take message lock
524*1c60b9acSAndroid Build Coastguard Worker  */
525*1c60b9acSAndroid Build Coastguard Worker 
526*1c60b9acSAndroid Build Coastguard Worker static int
_lws_smd_msg_deliver_peer(struct lws_context * ctx,lws_smd_peer_t * pr)527*1c60b9acSAndroid Build Coastguard Worker _lws_smd_msg_deliver_peer(struct lws_context *ctx, lws_smd_peer_t *pr)
528*1c60b9acSAndroid Build Coastguard Worker {
529*1c60b9acSAndroid Build Coastguard Worker 	lws_smd_msg_t *msg;
530*1c60b9acSAndroid Build Coastguard Worker 
531*1c60b9acSAndroid Build Coastguard Worker 	if (!pr->tail)
532*1c60b9acSAndroid Build Coastguard Worker 		return 0;
533*1c60b9acSAndroid Build Coastguard Worker 
534*1c60b9acSAndroid Build Coastguard Worker 	msg = lws_container_of(pr->tail, lws_smd_msg_t, list);
535*1c60b9acSAndroid Build Coastguard Worker 
536*1c60b9acSAndroid Build Coastguard Worker 
537*1c60b9acSAndroid Build Coastguard Worker 	lwsl_cx_info(ctx, "deliver cl 0x%x, len %d, refc %d, to peer %p",
538*1c60b9acSAndroid Build Coastguard Worker 		    (unsigned int)msg->_class, (int)msg->length,
539*1c60b9acSAndroid Build Coastguard Worker 		    (int)msg->refcount, pr);
540*1c60b9acSAndroid Build Coastguard Worker 
541*1c60b9acSAndroid Build Coastguard Worker 	pr->cb(pr->opaque, msg->_class, msg->timestamp,
542*1c60b9acSAndroid Build Coastguard Worker 	       ((uint8_t *)&msg[1]) + LWS_SMD_SS_RX_HEADER_LEN_EFF,
543*1c60b9acSAndroid Build Coastguard Worker 	       (size_t)msg->length);
544*1c60b9acSAndroid Build Coastguard Worker 
545*1c60b9acSAndroid Build Coastguard Worker 	assert(msg->refcount);
546*1c60b9acSAndroid Build Coastguard Worker 
547*1c60b9acSAndroid Build Coastguard Worker 	/*
548*1c60b9acSAndroid Build Coastguard Worker 	 * If there is one, move forward to the next queued
549*1c60b9acSAndroid Build Coastguard Worker 	 * message that meets the filters of this peer
550*1c60b9acSAndroid Build Coastguard Worker 	 */
551*1c60b9acSAndroid Build Coastguard Worker 	pr->tail = _lws_smd_msg_next_matching_filter(pr);
552*1c60b9acSAndroid Build Coastguard Worker 
553*1c60b9acSAndroid Build Coastguard Worker 	/* tail message has to actually be of interest to the peer */
554*1c60b9acSAndroid Build Coastguard Worker 	assert(!pr->tail || (pr->tail->_class & pr->_class_filter));
555*1c60b9acSAndroid Build Coastguard Worker 
556*1c60b9acSAndroid Build Coastguard Worker 	if (lws_mutex_lock(ctx->smd.lock_messages)) /* +++++++++ messages */
557*1c60b9acSAndroid Build Coastguard Worker 		return 1; /* For Coverity */
558*1c60b9acSAndroid Build Coastguard Worker 
559*1c60b9acSAndroid Build Coastguard Worker 	if (!--msg->refcount)
560*1c60b9acSAndroid Build Coastguard Worker 		_lws_smd_msg_destroy(ctx, &ctx->smd, msg);
561*1c60b9acSAndroid Build Coastguard Worker 	lws_mutex_unlock(ctx->smd.lock_messages); /* messages ------- */
562*1c60b9acSAndroid Build Coastguard Worker 
563*1c60b9acSAndroid Build Coastguard Worker 	return !!pr->tail;
564*1c60b9acSAndroid Build Coastguard Worker }
565*1c60b9acSAndroid Build Coastguard Worker 
566*1c60b9acSAndroid Build Coastguard Worker /*
567*1c60b9acSAndroid Build Coastguard Worker  * Called when the event loop could deliver messages synchronously, eg, on
568*1c60b9acSAndroid Build Coastguard Worker  * entry to idle
569*1c60b9acSAndroid Build Coastguard Worker  */
570*1c60b9acSAndroid Build Coastguard Worker 
571*1c60b9acSAndroid Build Coastguard Worker int
lws_smd_msg_distribute(struct lws_context * ctx)572*1c60b9acSAndroid Build Coastguard Worker lws_smd_msg_distribute(struct lws_context *ctx)
573*1c60b9acSAndroid Build Coastguard Worker {
574*1c60b9acSAndroid Build Coastguard Worker 	char more;
575*1c60b9acSAndroid Build Coastguard Worker 
576*1c60b9acSAndroid Build Coastguard Worker 	/* commonly, no messages and nothing to do... */
577*1c60b9acSAndroid Build Coastguard Worker 
578*1c60b9acSAndroid Build Coastguard Worker 	if (!ctx->smd.owner_messages.count)
579*1c60b9acSAndroid Build Coastguard Worker 		return 0;
580*1c60b9acSAndroid Build Coastguard Worker 
581*1c60b9acSAndroid Build Coastguard Worker 	ctx->smd.delivering = 1;
582*1c60b9acSAndroid Build Coastguard Worker 
583*1c60b9acSAndroid Build Coastguard Worker 	do {
584*1c60b9acSAndroid Build Coastguard Worker 		more = 0;
585*1c60b9acSAndroid Build Coastguard Worker 		if (lws_mutex_lock(ctx->smd.lock_peers)) /* +++++++++++++++ peers */
586*1c60b9acSAndroid Build Coastguard Worker 			return 1; /* For Coverity */
587*1c60b9acSAndroid Build Coastguard Worker 
588*1c60b9acSAndroid Build Coastguard Worker 		lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1,
589*1c60b9acSAndroid Build Coastguard Worker 					   ctx->smd.owner_peers.head) {
590*1c60b9acSAndroid Build Coastguard Worker 			lws_smd_peer_t *pr = lws_container_of(p, lws_smd_peer_t, list);
591*1c60b9acSAndroid Build Coastguard Worker 
592*1c60b9acSAndroid Build Coastguard Worker 			more = (char)(more | !!_lws_smd_msg_deliver_peer(ctx, pr));
593*1c60b9acSAndroid Build Coastguard Worker 
594*1c60b9acSAndroid Build Coastguard Worker 		} lws_end_foreach_dll_safe(p, p1);
595*1c60b9acSAndroid Build Coastguard Worker 
596*1c60b9acSAndroid Build Coastguard Worker 		lws_mutex_unlock(ctx->smd.lock_peers); /* ------------- peers */
597*1c60b9acSAndroid Build Coastguard Worker 	} while (more);
598*1c60b9acSAndroid Build Coastguard Worker 
599*1c60b9acSAndroid Build Coastguard Worker 	ctx->smd.delivering = 0;
600*1c60b9acSAndroid Build Coastguard Worker 
601*1c60b9acSAndroid Build Coastguard Worker 	return 0;
602*1c60b9acSAndroid Build Coastguard Worker }
603*1c60b9acSAndroid Build Coastguard Worker 
604*1c60b9acSAndroid Build Coastguard Worker struct lws_smd_peer *
lws_smd_register(struct lws_context * ctx,void * opaque,int flags,lws_smd_class_t _class_filter,lws_smd_notification_cb_t cb)605*1c60b9acSAndroid Build Coastguard Worker lws_smd_register(struct lws_context *ctx, void *opaque, int flags,
606*1c60b9acSAndroid Build Coastguard Worker 		 lws_smd_class_t _class_filter, lws_smd_notification_cb_t cb)
607*1c60b9acSAndroid Build Coastguard Worker {
608*1c60b9acSAndroid Build Coastguard Worker 	lws_smd_peer_t *pr = lws_zalloc(sizeof(*pr), __func__);
609*1c60b9acSAndroid Build Coastguard Worker 
610*1c60b9acSAndroid Build Coastguard Worker 	if (!pr)
611*1c60b9acSAndroid Build Coastguard Worker 		return NULL;
612*1c60b9acSAndroid Build Coastguard Worker 
613*1c60b9acSAndroid Build Coastguard Worker 	pr->cb = cb;
614*1c60b9acSAndroid Build Coastguard Worker 	pr->opaque = opaque;
615*1c60b9acSAndroid Build Coastguard Worker 	pr->_class_filter = _class_filter;
616*1c60b9acSAndroid Build Coastguard Worker 	pr->ctx = ctx;
617*1c60b9acSAndroid Build Coastguard Worker 
618*1c60b9acSAndroid Build Coastguard Worker 	if (!ctx->smd.delivering &&
619*1c60b9acSAndroid Build Coastguard Worker 	    lws_mutex_lock(ctx->smd.lock_peers)) { /* +++++++++++++++ peers */
620*1c60b9acSAndroid Build Coastguard Worker 			lws_free(pr);
621*1c60b9acSAndroid Build Coastguard Worker 			return NULL; /* For Coverity */
622*1c60b9acSAndroid Build Coastguard Worker 		}
623*1c60b9acSAndroid Build Coastguard Worker 
624*1c60b9acSAndroid Build Coastguard Worker 	/*
625*1c60b9acSAndroid Build Coastguard Worker 	 * Let's lock the message list before adding this peer... because...
626*1c60b9acSAndroid Build Coastguard Worker 	 */
627*1c60b9acSAndroid Build Coastguard Worker 
628*1c60b9acSAndroid Build Coastguard Worker 	if (lws_mutex_lock(ctx->smd.lock_messages)) { /* +++++++++ messages */
629*1c60b9acSAndroid Build Coastguard Worker 		lws_free(pr);
630*1c60b9acSAndroid Build Coastguard Worker 		pr = NULL;
631*1c60b9acSAndroid Build Coastguard Worker 		goto bail1; /* For Coverity */
632*1c60b9acSAndroid Build Coastguard Worker 	}
633*1c60b9acSAndroid Build Coastguard Worker 
634*1c60b9acSAndroid Build Coastguard Worker 	lws_dll2_add_tail(&pr->list, &ctx->smd.owner_peers);
635*1c60b9acSAndroid Build Coastguard Worker 
636*1c60b9acSAndroid Build Coastguard Worker 	/* update the global class mask union to account for new peer mask */
637*1c60b9acSAndroid Build Coastguard Worker 	_lws_smd_class_mask_union(&ctx->smd);
638*1c60b9acSAndroid Build Coastguard Worker 
639*1c60b9acSAndroid Build Coastguard Worker 	/*
640*1c60b9acSAndroid Build Coastguard Worker 	 * Now there's a new peer added, any messages we have stashed will try
641*1c60b9acSAndroid Build Coastguard Worker 	 * to deliver to this guy too, if he's interested in that class.  So we
642*1c60b9acSAndroid Build Coastguard Worker 	 * have to update the message refcounts for queued messages-he's-
643*1c60b9acSAndroid Build Coastguard Worker 	 * interested-in accordingly.
644*1c60b9acSAndroid Build Coastguard Worker 	 */
645*1c60b9acSAndroid Build Coastguard Worker 
646*1c60b9acSAndroid Build Coastguard Worker 	lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1,
647*1c60b9acSAndroid Build Coastguard Worker 				   ctx->smd.owner_messages.head) {
648*1c60b9acSAndroid Build Coastguard Worker 		lws_smd_msg_t *msg = lws_container_of(p, lws_smd_msg_t, list);
649*1c60b9acSAndroid Build Coastguard Worker 
650*1c60b9acSAndroid Build Coastguard Worker 		if (_lws_smd_msg_peer_interested_in_msg(pr, msg))
651*1c60b9acSAndroid Build Coastguard Worker 			msg->refcount++;
652*1c60b9acSAndroid Build Coastguard Worker 
653*1c60b9acSAndroid Build Coastguard Worker 	} lws_end_foreach_dll_safe(p, p1);
654*1c60b9acSAndroid Build Coastguard Worker 
655*1c60b9acSAndroid Build Coastguard Worker 	/* ... ok we are done adding the peer */
656*1c60b9acSAndroid Build Coastguard Worker 
657*1c60b9acSAndroid Build Coastguard Worker 	lws_mutex_unlock(ctx->smd.lock_messages); /* messages ------- */
658*1c60b9acSAndroid Build Coastguard Worker 
659*1c60b9acSAndroid Build Coastguard Worker 	lwsl_cx_info(ctx, "peer %p (count %u) registered", pr,
660*1c60b9acSAndroid Build Coastguard Worker 			(unsigned int)ctx->smd.owner_peers.count);
661*1c60b9acSAndroid Build Coastguard Worker 
662*1c60b9acSAndroid Build Coastguard Worker bail1:
663*1c60b9acSAndroid Build Coastguard Worker 	if (!ctx->smd.delivering)
664*1c60b9acSAndroid Build Coastguard Worker 		lws_mutex_unlock(ctx->smd.lock_peers); /* ------------- peers */
665*1c60b9acSAndroid Build Coastguard Worker 
666*1c60b9acSAndroid Build Coastguard Worker 	return pr;
667*1c60b9acSAndroid Build Coastguard Worker }
668*1c60b9acSAndroid Build Coastguard Worker 
669*1c60b9acSAndroid Build Coastguard Worker void
lws_smd_unregister(struct lws_smd_peer * pr)670*1c60b9acSAndroid Build Coastguard Worker lws_smd_unregister(struct lws_smd_peer *pr)
671*1c60b9acSAndroid Build Coastguard Worker {
672*1c60b9acSAndroid Build Coastguard Worker 	lws_smd_t *smd = lws_container_of(pr->list.owner, lws_smd_t, owner_peers);
673*1c60b9acSAndroid Build Coastguard Worker 
674*1c60b9acSAndroid Build Coastguard Worker 	if (!smd->delivering &&
675*1c60b9acSAndroid Build Coastguard Worker 	    lws_mutex_lock(smd->lock_peers)) /* +++++++++++++++++++ peers */
676*1c60b9acSAndroid Build Coastguard Worker 		return; /* For Coverity */
677*1c60b9acSAndroid Build Coastguard Worker 	lwsl_cx_notice(pr->ctx, "destroying peer %p", pr);
678*1c60b9acSAndroid Build Coastguard Worker 	_lws_smd_peer_destroy(pr);
679*1c60b9acSAndroid Build Coastguard Worker 	if (!smd->delivering)
680*1c60b9acSAndroid Build Coastguard Worker 		lws_mutex_unlock(smd->lock_peers); /* ----------------- peers */
681*1c60b9acSAndroid Build Coastguard Worker }
682*1c60b9acSAndroid Build Coastguard Worker 
683*1c60b9acSAndroid Build Coastguard Worker int
lws_smd_message_pending(struct lws_context * ctx)684*1c60b9acSAndroid Build Coastguard Worker lws_smd_message_pending(struct lws_context *ctx)
685*1c60b9acSAndroid Build Coastguard Worker {
686*1c60b9acSAndroid Build Coastguard Worker 	int ret = 1;
687*1c60b9acSAndroid Build Coastguard Worker 
688*1c60b9acSAndroid Build Coastguard Worker 	/*
689*1c60b9acSAndroid Build Coastguard Worker 	 * First cheaply check the common case no messages pending, so there's
690*1c60b9acSAndroid Build Coastguard Worker 	 * definitely nothing for this tsi or anything else
691*1c60b9acSAndroid Build Coastguard Worker 	 */
692*1c60b9acSAndroid Build Coastguard Worker 
693*1c60b9acSAndroid Build Coastguard Worker 	if (!ctx->smd.owner_messages.count)
694*1c60b9acSAndroid Build Coastguard Worker 		return 0;
695*1c60b9acSAndroid Build Coastguard Worker 
696*1c60b9acSAndroid Build Coastguard Worker 	/*
697*1c60b9acSAndroid Build Coastguard Worker 	 * If there are any messages, check their age and expire ones that
698*1c60b9acSAndroid Build Coastguard Worker 	 * have been hanging around too long
699*1c60b9acSAndroid Build Coastguard Worker 	 */
700*1c60b9acSAndroid Build Coastguard Worker 
701*1c60b9acSAndroid Build Coastguard Worker 	if (lws_mutex_lock(ctx->smd.lock_peers)) /* +++++++++++++++++++++++ peers */
702*1c60b9acSAndroid Build Coastguard Worker 		return 1; /* For Coverity */
703*1c60b9acSAndroid Build Coastguard Worker 	if (lws_mutex_lock(ctx->smd.lock_messages)) /* +++++++++++++++++ messages */
704*1c60b9acSAndroid Build Coastguard Worker 		goto bail; /* For Coverity */
705*1c60b9acSAndroid Build Coastguard Worker 
706*1c60b9acSAndroid Build Coastguard Worker 	lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1,
707*1c60b9acSAndroid Build Coastguard Worker 				   ctx->smd.owner_messages.head) {
708*1c60b9acSAndroid Build Coastguard Worker 		lws_smd_msg_t *msg = lws_container_of(p, lws_smd_msg_t, list);
709*1c60b9acSAndroid Build Coastguard Worker 
710*1c60b9acSAndroid Build Coastguard Worker 		if ((lws_now_usecs() - msg->timestamp) > ctx->smd_ttl_us) {
711*1c60b9acSAndroid Build Coastguard Worker 			lwsl_cx_warn(ctx, "timing out queued message %p",
712*1c60b9acSAndroid Build Coastguard Worker 					msg);
713*1c60b9acSAndroid Build Coastguard Worker 
714*1c60b9acSAndroid Build Coastguard Worker 			/*
715*1c60b9acSAndroid Build Coastguard Worker 			 * We're forcibly yanking this guy, we can expect that
716*1c60b9acSAndroid Build Coastguard Worker 			 * there might be peers that point to it as their tail.
717*1c60b9acSAndroid Build Coastguard Worker 			 *
718*1c60b9acSAndroid Build Coastguard Worker 			 * In that case, move their tails on to the next guy
719*1c60b9acSAndroid Build Coastguard Worker 			 * they are interested in, if any.
720*1c60b9acSAndroid Build Coastguard Worker 			 */
721*1c60b9acSAndroid Build Coastguard Worker 
722*1c60b9acSAndroid Build Coastguard Worker 			lws_start_foreach_dll_safe(struct lws_dll2 *, pp, pp1,
723*1c60b9acSAndroid Build Coastguard Worker 						   ctx->smd.owner_peers.head) {
724*1c60b9acSAndroid Build Coastguard Worker 				lws_smd_peer_t *pr = lws_container_of(pp,
725*1c60b9acSAndroid Build Coastguard Worker 							lws_smd_peer_t, list);
726*1c60b9acSAndroid Build Coastguard Worker 
727*1c60b9acSAndroid Build Coastguard Worker 				if (pr->tail == msg)
728*1c60b9acSAndroid Build Coastguard Worker 					pr->tail = _lws_smd_msg_next_matching_filter(pr);
729*1c60b9acSAndroid Build Coastguard Worker 
730*1c60b9acSAndroid Build Coastguard Worker 			} lws_end_foreach_dll_safe(pp, pp1);
731*1c60b9acSAndroid Build Coastguard Worker 
732*1c60b9acSAndroid Build Coastguard Worker 			/*
733*1c60b9acSAndroid Build Coastguard Worker 			 * No peer should fall foul of the peer tail checks
734*1c60b9acSAndroid Build Coastguard Worker 			 * when destroying the message now.
735*1c60b9acSAndroid Build Coastguard Worker 			 */
736*1c60b9acSAndroid Build Coastguard Worker 
737*1c60b9acSAndroid Build Coastguard Worker 			_lws_smd_msg_destroy(ctx, &ctx->smd, msg);
738*1c60b9acSAndroid Build Coastguard Worker 		}
739*1c60b9acSAndroid Build Coastguard Worker 	} lws_end_foreach_dll_safe(p, p1);
740*1c60b9acSAndroid Build Coastguard Worker 
741*1c60b9acSAndroid Build Coastguard Worker 	lws_mutex_unlock(ctx->smd.lock_messages); /* --------------- messages */
742*1c60b9acSAndroid Build Coastguard Worker 
743*1c60b9acSAndroid Build Coastguard Worker 	/*
744*1c60b9acSAndroid Build Coastguard Worker 	 * Walk the peer list
745*1c60b9acSAndroid Build Coastguard Worker 	 */
746*1c60b9acSAndroid Build Coastguard Worker 
747*1c60b9acSAndroid Build Coastguard Worker 	lws_start_foreach_dll(struct lws_dll2 *, p, ctx->smd.owner_peers.head) {
748*1c60b9acSAndroid Build Coastguard Worker 		lws_smd_peer_t *pr = lws_container_of(p, lws_smd_peer_t, list);
749*1c60b9acSAndroid Build Coastguard Worker 
750*1c60b9acSAndroid Build Coastguard Worker 		if (pr->tail)
751*1c60b9acSAndroid Build Coastguard Worker 			goto bail;
752*1c60b9acSAndroid Build Coastguard Worker 
753*1c60b9acSAndroid Build Coastguard Worker 	} lws_end_foreach_dll(p);
754*1c60b9acSAndroid Build Coastguard Worker 
755*1c60b9acSAndroid Build Coastguard Worker 	/*
756*1c60b9acSAndroid Build Coastguard Worker 	 * There's no message pending that we need to handle
757*1c60b9acSAndroid Build Coastguard Worker 	 */
758*1c60b9acSAndroid Build Coastguard Worker 
759*1c60b9acSAndroid Build Coastguard Worker 	ret = 0;
760*1c60b9acSAndroid Build Coastguard Worker 
761*1c60b9acSAndroid Build Coastguard Worker bail:
762*1c60b9acSAndroid Build Coastguard Worker 	lws_mutex_unlock(ctx->smd.lock_peers); /* --------------------- peers */
763*1c60b9acSAndroid Build Coastguard Worker 
764*1c60b9acSAndroid Build Coastguard Worker 	return ret;
765*1c60b9acSAndroid Build Coastguard Worker }
766*1c60b9acSAndroid Build Coastguard Worker 
767*1c60b9acSAndroid Build Coastguard Worker int
_lws_smd_destroy(struct lws_context * ctx)768*1c60b9acSAndroid Build Coastguard Worker _lws_smd_destroy(struct lws_context *ctx)
769*1c60b9acSAndroid Build Coastguard Worker {
770*1c60b9acSAndroid Build Coastguard Worker 	/* stop any message creation */
771*1c60b9acSAndroid Build Coastguard Worker 
772*1c60b9acSAndroid Build Coastguard Worker 	ctx->smd._class_filter = 0;
773*1c60b9acSAndroid Build Coastguard Worker 
774*1c60b9acSAndroid Build Coastguard Worker 	/*
775*1c60b9acSAndroid Build Coastguard Worker 	 * Walk the message list, destroying them
776*1c60b9acSAndroid Build Coastguard Worker 	 */
777*1c60b9acSAndroid Build Coastguard Worker 
778*1c60b9acSAndroid Build Coastguard Worker 	lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1,
779*1c60b9acSAndroid Build Coastguard Worker 				   ctx->smd.owner_messages.head) {
780*1c60b9acSAndroid Build Coastguard Worker 		lws_smd_msg_t *msg = lws_container_of(p, lws_smd_msg_t, list);
781*1c60b9acSAndroid Build Coastguard Worker 
782*1c60b9acSAndroid Build Coastguard Worker 		lws_dll2_remove(&msg->list);
783*1c60b9acSAndroid Build Coastguard Worker 		lws_free(msg);
784*1c60b9acSAndroid Build Coastguard Worker 
785*1c60b9acSAndroid Build Coastguard Worker 	} lws_end_foreach_dll_safe(p, p1);
786*1c60b9acSAndroid Build Coastguard Worker 
787*1c60b9acSAndroid Build Coastguard Worker 	/*
788*1c60b9acSAndroid Build Coastguard Worker 	 * Walk the peer list, destroying them
789*1c60b9acSAndroid Build Coastguard Worker 	 */
790*1c60b9acSAndroid Build Coastguard Worker 
791*1c60b9acSAndroid Build Coastguard Worker 	lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1,
792*1c60b9acSAndroid Build Coastguard Worker 				   ctx->smd.owner_peers.head) {
793*1c60b9acSAndroid Build Coastguard Worker 		lws_smd_peer_t *pr = lws_container_of(p, lws_smd_peer_t, list);
794*1c60b9acSAndroid Build Coastguard Worker 
795*1c60b9acSAndroid Build Coastguard Worker 		pr->tail = NULL; /* we just nuked all the messages, ignore */
796*1c60b9acSAndroid Build Coastguard Worker 		_lws_smd_peer_destroy(pr);
797*1c60b9acSAndroid Build Coastguard Worker 
798*1c60b9acSAndroid Build Coastguard Worker 	} lws_end_foreach_dll_safe(p, p1);
799*1c60b9acSAndroid Build Coastguard Worker 
800*1c60b9acSAndroid Build Coastguard Worker 	lws_mutex_destroy(ctx->smd.lock_messages);
801*1c60b9acSAndroid Build Coastguard Worker 	lws_mutex_destroy(ctx->smd.lock_peers);
802*1c60b9acSAndroid Build Coastguard Worker 
803*1c60b9acSAndroid Build Coastguard Worker 	return 0;
804*1c60b9acSAndroid Build Coastguard Worker }
805