/src/libwebsockets/lib/system/system.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * libwebsockets - small server side websockets and web server implementation |
3 | | * |
4 | | * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com> |
5 | | * |
6 | | * Permission is hereby granted, free of charge, to any person obtaining a copy |
7 | | * of this software and associated documentation files (the "Software"), to |
8 | | * deal in the Software without restriction, including without limitation the |
9 | | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
10 | | * sell copies of the Software, and to permit persons to whom the Software is |
11 | | * furnished to do so, subject to the following conditions: |
12 | | * |
13 | | * The above copyright notice and this permission notice shall be included in |
14 | | * all copies or substantial portions of the Software. |
15 | | * |
16 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
17 | | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
18 | | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
19 | | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
20 | | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
21 | | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
22 | | * IN THE SOFTWARE. |
23 | | */ |
24 | | |
25 | | #include <private-lib-core.h> |
26 | | |
27 | | /* |
28 | | * It's either a buflist (.is_direct = 0) or |
29 | | * a direct pointer + len (.is_direct = 1) |
30 | | */ |
31 | | |
32 | | const lws_system_ops_t * |
33 | | lws_system_get_ops(struct lws_context *context) |
34 | 0 | { |
35 | 0 | return context->system_ops; |
36 | 0 | } |
37 | | |
38 | | |
39 | | void |
40 | | lws_system_blob_direct_set(lws_system_blob_t *b, const uint8_t *ptr, size_t len) |
41 | 0 | { |
42 | 0 | b->is_direct = 1; |
43 | 0 | b->u.direct.ptr = ptr; |
44 | 0 | b->u.direct.len = len; |
45 | 0 | } |
46 | | |
47 | | void |
48 | | lws_system_blob_heap_empty(lws_system_blob_t *b) |
49 | 0 | { |
50 | 0 | b->is_direct = 0; |
51 | 0 | lws_buflist_destroy_all_segments(&b->u.bl); |
52 | 0 | } |
53 | | |
54 | | int |
55 | | lws_system_blob_heap_append(lws_system_blob_t *b, const uint8_t *buf, size_t len) |
56 | 0 | { |
57 | 0 | assert(!b->is_direct); |
58 | | |
59 | 0 | lwsl_debug("%s: blob %p\n", __func__, b); |
60 | |
|
61 | 0 | if (lws_buflist_append_segment(&b->u.bl, buf, len) < 0) |
62 | 0 | return -1; |
63 | | |
64 | 0 | return 0; |
65 | 0 | } |
66 | | |
67 | | size_t |
68 | | lws_system_blob_get_size(lws_system_blob_t *b) |
69 | 0 | { |
70 | 0 | if (b->is_direct) |
71 | 0 | return b->u.direct.len; |
72 | | |
73 | 0 | return lws_buflist_total_len(&b->u.bl); |
74 | 0 | } |
75 | | |
76 | | int |
77 | | lws_system_blob_get(lws_system_blob_t *b, uint8_t *buf, size_t *len, size_t ofs) |
78 | 0 | { |
79 | 0 | int n; |
80 | |
|
81 | 0 | if (b->is_direct) { |
82 | |
|
83 | 0 | assert(b->u.direct.ptr); |
84 | | |
85 | 0 | if (ofs >= b->u.direct.len) { |
86 | 0 | *len = 0; |
87 | 0 | return 1; |
88 | 0 | } |
89 | | |
90 | 0 | if (*len > b->u.direct.len - ofs) |
91 | 0 | *len = b->u.direct.len - ofs; |
92 | |
|
93 | 0 | memcpy(buf, b->u.direct.ptr + ofs, *len); |
94 | |
|
95 | 0 | return 0; |
96 | 0 | } |
97 | | |
98 | 0 | n = lws_buflist_linear_copy(&b->u.bl, ofs, buf, *len); |
99 | 0 | if (n < 0) |
100 | 0 | return -2; |
101 | | |
102 | 0 | *len = (unsigned int)n; |
103 | |
|
104 | 0 | return 0; |
105 | 0 | } |
106 | | |
107 | | int |
108 | | lws_system_blob_get_single_ptr(lws_system_blob_t *b, const uint8_t **ptr) |
109 | 0 | { |
110 | 0 | if (b->is_direct) { |
111 | 0 | *ptr = b->u.direct.ptr; |
112 | 0 | return 0; |
113 | 0 | } |
114 | | |
115 | 0 | if (!b->u.bl) |
116 | 0 | return -1; |
117 | | |
118 | 0 | if (b->u.bl->next) |
119 | 0 | return -1; /* multipart buflist, no single pointer to it all */ |
120 | | |
121 | 0 | *ptr = (const uint8_t *)&b->u.bl[1] + LWS_PRE; |
122 | |
|
123 | 0 | return 0; |
124 | 0 | } |
125 | | |
126 | | void |
127 | | lws_system_blob_destroy(lws_system_blob_t *b) |
128 | 0 | { |
129 | 0 | if (!b) |
130 | 0 | return; |
131 | | // lwsl_info("%s: blob %p\n", __func__, b); |
132 | 0 | if (!b->is_direct) |
133 | 0 | lws_buflist_destroy_all_segments(&b->u.bl); |
134 | 0 | } |
135 | | |
136 | | lws_system_blob_t * |
137 | | lws_system_get_blob(struct lws_context *context, lws_system_blob_item_t type, |
138 | | int idx) |
139 | 0 | { |
140 | 0 | if (idx < 0 || |
141 | 0 | idx >= (int)LWS_ARRAY_SIZE(context->system_blobs)) |
142 | 0 | return NULL; |
143 | | |
144 | 0 | return &context->system_blobs[type + (unsigned int)idx]; |
145 | 0 | } |
146 | | |
147 | | #if defined(LWS_WITH_NETWORK) |
148 | | |
149 | | /* |
150 | | * Caller must protect the whole call with system-specific locking |
151 | | */ |
152 | | |
153 | | int |
154 | | __lws_system_attach(struct lws_context *context, int tsi, lws_attach_cb_t cb, |
155 | | lws_system_states_t state, void *opaque, |
156 | | struct lws_attach_item **get) |
157 | 0 | { |
158 | 0 | struct lws_context_per_thread *pt = &context->pt[tsi]; |
159 | 0 | struct lws_attach_item *item; |
160 | |
|
161 | 0 | if (!get) { |
162 | | /* |
163 | | * allocate and add to the head of the pt's attach list |
164 | | */ |
165 | |
|
166 | 0 | item = lws_zalloc(sizeof(*item), __func__); |
167 | 0 | if (!item) |
168 | 0 | return 1; |
169 | | |
170 | 0 | item->cb = cb; |
171 | 0 | item->opaque = opaque; |
172 | 0 | item->state = state; |
173 | |
|
174 | 0 | lws_dll2_add_head(&item->list, &pt->attach_owner); |
175 | |
|
176 | 0 | lws_cancel_service(context); |
177 | |
|
178 | 0 | return 0; |
179 | 0 | } |
180 | | |
181 | 0 | *get = NULL; |
182 | 0 | #if defined(LWS_WITH_SYS_STATE) |
183 | 0 | if (!pt->attach_owner.count) |
184 | 0 | return 0; |
185 | | |
186 | | /* |
187 | | * If any, return the first guy whose state requirement matches |
188 | | */ |
189 | | |
190 | 0 | lws_start_foreach_dll(struct lws_dll2 *, d, |
191 | 0 | lws_dll2_get_head(&pt->attach_owner)) { |
192 | 0 | item = lws_container_of(d, lws_attach_item_t, list); |
193 | |
|
194 | 0 | if (pt->context->mgr_system.state >= (int)item->state) { |
195 | 0 | *get = item; |
196 | 0 | lws_dll2_remove(d); |
197 | | |
198 | | /* |
199 | | * We detached it, but the caller now has the |
200 | | * responsibility to lws_free() *get. |
201 | | */ |
202 | |
|
203 | 0 | return 0; |
204 | 0 | } |
205 | 0 | } lws_end_foreach_dll(d); |
206 | 0 | #endif |
207 | | |
208 | | /* nobody ready to go... leave *get as NULL and return cleanly */ |
209 | |
|
210 | 0 | return 0; |
211 | 0 | } |
212 | | |
213 | | int |
214 | | lws_system_do_attach(struct lws_context_per_thread *pt) |
215 | 0 | { |
216 | | /* |
217 | | * If nothing to do, we just return immediately |
218 | | */ |
219 | |
|
220 | 0 | while (pt->attach_owner.count) { |
221 | |
|
222 | 0 | struct lws_attach_item *item; |
223 | | |
224 | | /* |
225 | | * If anybody used the attach apis, there must be an |
226 | | * implementation of the (*attach) lws_system op function |
227 | | */ |
228 | |
|
229 | 0 | assert(pt->context->system_ops->attach); |
230 | 0 | if (!pt->context->system_ops->attach) { |
231 | 0 | lwsl_err("%s: define (*attach)\n", __func__); |
232 | 0 | return 1; |
233 | 0 | } |
234 | | |
235 | | /* |
236 | | * System locking is applied only around this next call, while |
237 | | * we detach and get a pointer to the tail attach item. We |
238 | | * become responsible to free what we have detached. |
239 | | */ |
240 | | |
241 | 0 | if (pt->context->system_ops->attach(pt->context, pt->tid, NULL, |
242 | 0 | 0, NULL, &item)) { |
243 | 0 | lwsl_err("%s: attach problem\n", __func__); |
244 | 0 | return 1; |
245 | 0 | } |
246 | | |
247 | 0 | if (!item) |
248 | | /* there's nothing more to do at the moment */ |
249 | 0 | return 0; |
250 | | |
251 | | /* |
252 | | * Do the callback from the lws event loop thread |
253 | | */ |
254 | | |
255 | 0 | item->cb(pt->context, pt->tid, item->opaque); |
256 | | |
257 | | /* it's done, destroy the item */ |
258 | |
|
259 | 0 | lws_free(item); |
260 | 0 | } |
261 | | |
262 | 0 | return 0; |
263 | 0 | } |
264 | | |
265 | | #endif |