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 - 2019 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
27*1c60b9acSAndroid Build Coastguard Worker /*
28*1c60b9acSAndroid Build Coastguard Worker * It's either a buflist (.is_direct = 0) or
29*1c60b9acSAndroid Build Coastguard Worker * a direct pointer + len (.is_direct = 1)
30*1c60b9acSAndroid Build Coastguard Worker */
31*1c60b9acSAndroid Build Coastguard Worker
32*1c60b9acSAndroid Build Coastguard Worker const lws_system_ops_t *
lws_system_get_ops(struct lws_context * context)33*1c60b9acSAndroid Build Coastguard Worker lws_system_get_ops(struct lws_context *context)
34*1c60b9acSAndroid Build Coastguard Worker {
35*1c60b9acSAndroid Build Coastguard Worker return context->system_ops;
36*1c60b9acSAndroid Build Coastguard Worker }
37*1c60b9acSAndroid Build Coastguard Worker
38*1c60b9acSAndroid Build Coastguard Worker
39*1c60b9acSAndroid Build Coastguard Worker void
lws_system_blob_direct_set(lws_system_blob_t * b,const uint8_t * ptr,size_t len)40*1c60b9acSAndroid Build Coastguard Worker lws_system_blob_direct_set(lws_system_blob_t *b, const uint8_t *ptr, size_t len)
41*1c60b9acSAndroid Build Coastguard Worker {
42*1c60b9acSAndroid Build Coastguard Worker b->is_direct = 1;
43*1c60b9acSAndroid Build Coastguard Worker b->u.direct.ptr = ptr;
44*1c60b9acSAndroid Build Coastguard Worker b->u.direct.len = len;
45*1c60b9acSAndroid Build Coastguard Worker }
46*1c60b9acSAndroid Build Coastguard Worker
47*1c60b9acSAndroid Build Coastguard Worker void
lws_system_blob_heap_empty(lws_system_blob_t * b)48*1c60b9acSAndroid Build Coastguard Worker lws_system_blob_heap_empty(lws_system_blob_t *b)
49*1c60b9acSAndroid Build Coastguard Worker {
50*1c60b9acSAndroid Build Coastguard Worker b->is_direct = 0;
51*1c60b9acSAndroid Build Coastguard Worker lws_buflist_destroy_all_segments(&b->u.bl);
52*1c60b9acSAndroid Build Coastguard Worker }
53*1c60b9acSAndroid Build Coastguard Worker
54*1c60b9acSAndroid Build Coastguard Worker int
lws_system_blob_heap_append(lws_system_blob_t * b,const uint8_t * buf,size_t len)55*1c60b9acSAndroid Build Coastguard Worker lws_system_blob_heap_append(lws_system_blob_t *b, const uint8_t *buf, size_t len)
56*1c60b9acSAndroid Build Coastguard Worker {
57*1c60b9acSAndroid Build Coastguard Worker assert(!b->is_direct);
58*1c60b9acSAndroid Build Coastguard Worker
59*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: blob %p\n", __func__, b);
60*1c60b9acSAndroid Build Coastguard Worker
61*1c60b9acSAndroid Build Coastguard Worker if (lws_buflist_append_segment(&b->u.bl, buf, len) < 0)
62*1c60b9acSAndroid Build Coastguard Worker return -1;
63*1c60b9acSAndroid Build Coastguard Worker
64*1c60b9acSAndroid Build Coastguard Worker return 0;
65*1c60b9acSAndroid Build Coastguard Worker }
66*1c60b9acSAndroid Build Coastguard Worker
67*1c60b9acSAndroid Build Coastguard Worker size_t
lws_system_blob_get_size(lws_system_blob_t * b)68*1c60b9acSAndroid Build Coastguard Worker lws_system_blob_get_size(lws_system_blob_t *b)
69*1c60b9acSAndroid Build Coastguard Worker {
70*1c60b9acSAndroid Build Coastguard Worker if (b->is_direct)
71*1c60b9acSAndroid Build Coastguard Worker return b->u.direct.len;
72*1c60b9acSAndroid Build Coastguard Worker
73*1c60b9acSAndroid Build Coastguard Worker return lws_buflist_total_len(&b->u.bl);
74*1c60b9acSAndroid Build Coastguard Worker }
75*1c60b9acSAndroid Build Coastguard Worker
76*1c60b9acSAndroid Build Coastguard Worker int
lws_system_blob_get(lws_system_blob_t * b,uint8_t * buf,size_t * len,size_t ofs)77*1c60b9acSAndroid Build Coastguard Worker lws_system_blob_get(lws_system_blob_t *b, uint8_t *buf, size_t *len, size_t ofs)
78*1c60b9acSAndroid Build Coastguard Worker {
79*1c60b9acSAndroid Build Coastguard Worker int n;
80*1c60b9acSAndroid Build Coastguard Worker
81*1c60b9acSAndroid Build Coastguard Worker if (b->is_direct) {
82*1c60b9acSAndroid Build Coastguard Worker
83*1c60b9acSAndroid Build Coastguard Worker assert(b->u.direct.ptr);
84*1c60b9acSAndroid Build Coastguard Worker
85*1c60b9acSAndroid Build Coastguard Worker if (ofs >= b->u.direct.len) {
86*1c60b9acSAndroid Build Coastguard Worker *len = 0;
87*1c60b9acSAndroid Build Coastguard Worker return 1;
88*1c60b9acSAndroid Build Coastguard Worker }
89*1c60b9acSAndroid Build Coastguard Worker
90*1c60b9acSAndroid Build Coastguard Worker if (*len > b->u.direct.len - ofs)
91*1c60b9acSAndroid Build Coastguard Worker *len = b->u.direct.len - ofs;
92*1c60b9acSAndroid Build Coastguard Worker
93*1c60b9acSAndroid Build Coastguard Worker memcpy(buf, b->u.direct.ptr + ofs, *len);
94*1c60b9acSAndroid Build Coastguard Worker
95*1c60b9acSAndroid Build Coastguard Worker return 0;
96*1c60b9acSAndroid Build Coastguard Worker }
97*1c60b9acSAndroid Build Coastguard Worker
98*1c60b9acSAndroid Build Coastguard Worker n = lws_buflist_linear_copy(&b->u.bl, ofs, buf, *len);
99*1c60b9acSAndroid Build Coastguard Worker if (n < 0)
100*1c60b9acSAndroid Build Coastguard Worker return -2;
101*1c60b9acSAndroid Build Coastguard Worker
102*1c60b9acSAndroid Build Coastguard Worker *len = (unsigned int)n;
103*1c60b9acSAndroid Build Coastguard Worker
104*1c60b9acSAndroid Build Coastguard Worker return 0;
105*1c60b9acSAndroid Build Coastguard Worker }
106*1c60b9acSAndroid Build Coastguard Worker
107*1c60b9acSAndroid Build Coastguard Worker int
lws_system_blob_get_single_ptr(lws_system_blob_t * b,const uint8_t ** ptr)108*1c60b9acSAndroid Build Coastguard Worker lws_system_blob_get_single_ptr(lws_system_blob_t *b, const uint8_t **ptr)
109*1c60b9acSAndroid Build Coastguard Worker {
110*1c60b9acSAndroid Build Coastguard Worker if (b->is_direct) {
111*1c60b9acSAndroid Build Coastguard Worker *ptr = b->u.direct.ptr;
112*1c60b9acSAndroid Build Coastguard Worker return 0;
113*1c60b9acSAndroid Build Coastguard Worker }
114*1c60b9acSAndroid Build Coastguard Worker
115*1c60b9acSAndroid Build Coastguard Worker if (!b->u.bl)
116*1c60b9acSAndroid Build Coastguard Worker return -1;
117*1c60b9acSAndroid Build Coastguard Worker
118*1c60b9acSAndroid Build Coastguard Worker if (b->u.bl->next)
119*1c60b9acSAndroid Build Coastguard Worker return -1; /* multipart buflist, no single pointer to it all */
120*1c60b9acSAndroid Build Coastguard Worker
121*1c60b9acSAndroid Build Coastguard Worker *ptr = (const uint8_t *)&b->u.bl[1] + LWS_PRE;
122*1c60b9acSAndroid Build Coastguard Worker
123*1c60b9acSAndroid Build Coastguard Worker return 0;
124*1c60b9acSAndroid Build Coastguard Worker }
125*1c60b9acSAndroid Build Coastguard Worker
126*1c60b9acSAndroid Build Coastguard Worker void
lws_system_blob_destroy(lws_system_blob_t * b)127*1c60b9acSAndroid Build Coastguard Worker lws_system_blob_destroy(lws_system_blob_t *b)
128*1c60b9acSAndroid Build Coastguard Worker {
129*1c60b9acSAndroid Build Coastguard Worker if (!b)
130*1c60b9acSAndroid Build Coastguard Worker return;
131*1c60b9acSAndroid Build Coastguard Worker // lwsl_info("%s: blob %p\n", __func__, b);
132*1c60b9acSAndroid Build Coastguard Worker if (!b->is_direct)
133*1c60b9acSAndroid Build Coastguard Worker lws_buflist_destroy_all_segments(&b->u.bl);
134*1c60b9acSAndroid Build Coastguard Worker }
135*1c60b9acSAndroid Build Coastguard Worker
136*1c60b9acSAndroid Build Coastguard Worker lws_system_blob_t *
lws_system_get_blob(struct lws_context * context,lws_system_blob_item_t type,int idx)137*1c60b9acSAndroid Build Coastguard Worker lws_system_get_blob(struct lws_context *context, lws_system_blob_item_t type,
138*1c60b9acSAndroid Build Coastguard Worker int idx)
139*1c60b9acSAndroid Build Coastguard Worker {
140*1c60b9acSAndroid Build Coastguard Worker if (idx < 0 ||
141*1c60b9acSAndroid Build Coastguard Worker idx >= (int)LWS_ARRAY_SIZE(context->system_blobs))
142*1c60b9acSAndroid Build Coastguard Worker return NULL;
143*1c60b9acSAndroid Build Coastguard Worker
144*1c60b9acSAndroid Build Coastguard Worker return &context->system_blobs[type + (unsigned int)idx];
145*1c60b9acSAndroid Build Coastguard Worker }
146*1c60b9acSAndroid Build Coastguard Worker
147*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_NETWORK)
148*1c60b9acSAndroid Build Coastguard Worker
149*1c60b9acSAndroid Build Coastguard Worker /*
150*1c60b9acSAndroid Build Coastguard Worker * Caller must protect the whole call with system-specific locking
151*1c60b9acSAndroid Build Coastguard Worker */
152*1c60b9acSAndroid Build Coastguard Worker
153*1c60b9acSAndroid Build Coastguard Worker int
__lws_system_attach(struct lws_context * context,int tsi,lws_attach_cb_t cb,lws_system_states_t state,void * opaque,struct lws_attach_item ** get)154*1c60b9acSAndroid Build Coastguard Worker __lws_system_attach(struct lws_context *context, int tsi, lws_attach_cb_t cb,
155*1c60b9acSAndroid Build Coastguard Worker lws_system_states_t state, void *opaque,
156*1c60b9acSAndroid Build Coastguard Worker struct lws_attach_item **get)
157*1c60b9acSAndroid Build Coastguard Worker {
158*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt = &context->pt[tsi];
159*1c60b9acSAndroid Build Coastguard Worker struct lws_attach_item *item;
160*1c60b9acSAndroid Build Coastguard Worker
161*1c60b9acSAndroid Build Coastguard Worker if (!get) {
162*1c60b9acSAndroid Build Coastguard Worker /*
163*1c60b9acSAndroid Build Coastguard Worker * allocate and add to the head of the pt's attach list
164*1c60b9acSAndroid Build Coastguard Worker */
165*1c60b9acSAndroid Build Coastguard Worker
166*1c60b9acSAndroid Build Coastguard Worker item = lws_zalloc(sizeof(*item), __func__);
167*1c60b9acSAndroid Build Coastguard Worker if (!item)
168*1c60b9acSAndroid Build Coastguard Worker return 1;
169*1c60b9acSAndroid Build Coastguard Worker
170*1c60b9acSAndroid Build Coastguard Worker item->cb = cb;
171*1c60b9acSAndroid Build Coastguard Worker item->opaque = opaque;
172*1c60b9acSAndroid Build Coastguard Worker item->state = state;
173*1c60b9acSAndroid Build Coastguard Worker
174*1c60b9acSAndroid Build Coastguard Worker lws_dll2_add_head(&item->list, &pt->attach_owner);
175*1c60b9acSAndroid Build Coastguard Worker
176*1c60b9acSAndroid Build Coastguard Worker lws_cancel_service(context);
177*1c60b9acSAndroid Build Coastguard Worker
178*1c60b9acSAndroid Build Coastguard Worker return 0;
179*1c60b9acSAndroid Build Coastguard Worker }
180*1c60b9acSAndroid Build Coastguard Worker
181*1c60b9acSAndroid Build Coastguard Worker *get = NULL;
182*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SYS_STATE)
183*1c60b9acSAndroid Build Coastguard Worker if (!pt->attach_owner.count)
184*1c60b9acSAndroid Build Coastguard Worker return 0;
185*1c60b9acSAndroid Build Coastguard Worker
186*1c60b9acSAndroid Build Coastguard Worker /*
187*1c60b9acSAndroid Build Coastguard Worker * If any, return the first guy whose state requirement matches
188*1c60b9acSAndroid Build Coastguard Worker */
189*1c60b9acSAndroid Build Coastguard Worker
190*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_dll(struct lws_dll2 *, d,
191*1c60b9acSAndroid Build Coastguard Worker lws_dll2_get_head(&pt->attach_owner)) {
192*1c60b9acSAndroid Build Coastguard Worker item = lws_container_of(d, lws_attach_item_t, list);
193*1c60b9acSAndroid Build Coastguard Worker
194*1c60b9acSAndroid Build Coastguard Worker if (pt->context->mgr_system.state >= (int)item->state) {
195*1c60b9acSAndroid Build Coastguard Worker *get = item;
196*1c60b9acSAndroid Build Coastguard Worker lws_dll2_remove(d);
197*1c60b9acSAndroid Build Coastguard Worker
198*1c60b9acSAndroid Build Coastguard Worker /*
199*1c60b9acSAndroid Build Coastguard Worker * We detached it, but the caller now has the
200*1c60b9acSAndroid Build Coastguard Worker * responsibility to lws_free() *get.
201*1c60b9acSAndroid Build Coastguard Worker */
202*1c60b9acSAndroid Build Coastguard Worker
203*1c60b9acSAndroid Build Coastguard Worker return 0;
204*1c60b9acSAndroid Build Coastguard Worker }
205*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_dll(d);
206*1c60b9acSAndroid Build Coastguard Worker #endif
207*1c60b9acSAndroid Build Coastguard Worker
208*1c60b9acSAndroid Build Coastguard Worker /* nobody ready to go... leave *get as NULL and return cleanly */
209*1c60b9acSAndroid Build Coastguard Worker
210*1c60b9acSAndroid Build Coastguard Worker return 0;
211*1c60b9acSAndroid Build Coastguard Worker }
212*1c60b9acSAndroid Build Coastguard Worker
213*1c60b9acSAndroid Build Coastguard Worker int
lws_system_do_attach(struct lws_context_per_thread * pt)214*1c60b9acSAndroid Build Coastguard Worker lws_system_do_attach(struct lws_context_per_thread *pt)
215*1c60b9acSAndroid Build Coastguard Worker {
216*1c60b9acSAndroid Build Coastguard Worker /*
217*1c60b9acSAndroid Build Coastguard Worker * If nothing to do, we just return immediately
218*1c60b9acSAndroid Build Coastguard Worker */
219*1c60b9acSAndroid Build Coastguard Worker
220*1c60b9acSAndroid Build Coastguard Worker while (pt->attach_owner.count) {
221*1c60b9acSAndroid Build Coastguard Worker
222*1c60b9acSAndroid Build Coastguard Worker struct lws_attach_item *item;
223*1c60b9acSAndroid Build Coastguard Worker
224*1c60b9acSAndroid Build Coastguard Worker /*
225*1c60b9acSAndroid Build Coastguard Worker * If anybody used the attach apis, there must be an
226*1c60b9acSAndroid Build Coastguard Worker * implementation of the (*attach) lws_system op function
227*1c60b9acSAndroid Build Coastguard Worker */
228*1c60b9acSAndroid Build Coastguard Worker
229*1c60b9acSAndroid Build Coastguard Worker assert(pt->context->system_ops->attach);
230*1c60b9acSAndroid Build Coastguard Worker if (!pt->context->system_ops->attach) {
231*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: define (*attach)\n", __func__);
232*1c60b9acSAndroid Build Coastguard Worker return 1;
233*1c60b9acSAndroid Build Coastguard Worker }
234*1c60b9acSAndroid Build Coastguard Worker
235*1c60b9acSAndroid Build Coastguard Worker /*
236*1c60b9acSAndroid Build Coastguard Worker * System locking is applied only around this next call, while
237*1c60b9acSAndroid Build Coastguard Worker * we detach and get a pointer to the tail attach item. We
238*1c60b9acSAndroid Build Coastguard Worker * become responsible to free what we have detached.
239*1c60b9acSAndroid Build Coastguard Worker */
240*1c60b9acSAndroid Build Coastguard Worker
241*1c60b9acSAndroid Build Coastguard Worker if (pt->context->system_ops->attach(pt->context, pt->tid, NULL,
242*1c60b9acSAndroid Build Coastguard Worker 0, NULL, &item)) {
243*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: attach problem\n", __func__);
244*1c60b9acSAndroid Build Coastguard Worker return 1;
245*1c60b9acSAndroid Build Coastguard Worker }
246*1c60b9acSAndroid Build Coastguard Worker
247*1c60b9acSAndroid Build Coastguard Worker if (!item)
248*1c60b9acSAndroid Build Coastguard Worker /* there's nothing more to do at the moment */
249*1c60b9acSAndroid Build Coastguard Worker return 0;
250*1c60b9acSAndroid Build Coastguard Worker
251*1c60b9acSAndroid Build Coastguard Worker /*
252*1c60b9acSAndroid Build Coastguard Worker * Do the callback from the lws event loop thread
253*1c60b9acSAndroid Build Coastguard Worker */
254*1c60b9acSAndroid Build Coastguard Worker
255*1c60b9acSAndroid Build Coastguard Worker item->cb(pt->context, pt->tid, item->opaque);
256*1c60b9acSAndroid Build Coastguard Worker
257*1c60b9acSAndroid Build Coastguard Worker /* it's done, destroy the item */
258*1c60b9acSAndroid Build Coastguard Worker
259*1c60b9acSAndroid Build Coastguard Worker lws_free(item);
260*1c60b9acSAndroid Build Coastguard Worker }
261*1c60b9acSAndroid Build Coastguard Worker
262*1c60b9acSAndroid Build Coastguard Worker return 0;
263*1c60b9acSAndroid Build Coastguard Worker }
264*1c60b9acSAndroid Build Coastguard Worker
265*1c60b9acSAndroid Build Coastguard Worker #endif
266