1 | /* |
2 | * libwebsockets - small server side websockets and web server implementation |
3 | * |
4 | * Copyright (C) 2010 - 2021 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 | #if defined(LWS_WITH_SPAWN) |
26 | |
27 | #if defined(WIN32) || defined(_WIN32) |
28 | #else |
29 | #include <sys/wait.h> |
30 | #include <sys/times.h> |
31 | #endif |
32 | #endif |
33 | |
34 | #if defined(__OpenBSD__) |
35 | #include <sys/siginfo.h> |
36 | #endif |
37 | |
38 | /** \defgroup misc Miscellaneous APIs |
39 | * ##Miscellaneous APIs |
40 | * |
41 | * Various APIs outside of other categories |
42 | */ |
43 | ///@{ |
44 | |
45 | struct lws_buflist; |
46 | |
47 | /** |
48 | * lws_buflist_append_segment(): add buffer to buflist at head |
49 | * |
50 | * \param head: list head |
51 | * \param buf: buffer to stash |
52 | * \param len: length of buffer to stash |
53 | * |
54 | * Returns -1 on OOM, 1 if this was the first segment on the list, and 0 if |
55 | * it was a subsequent segment. |
56 | */ |
57 | LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
58 | lws_buflist_append_segment(struct lws_buflist **head, const uint8_t *buf, |
59 | size_t len); |
60 | /** |
61 | * lws_buflist_next_segment_len(): number of bytes left in current segment |
62 | * |
63 | * \param head: list head |
64 | * \param buf: if non-NULL, *buf is written with the address of the start of |
65 | * the remaining data in the segment |
66 | * |
67 | * Returns the number of bytes left in the current segment. 0 indicates |
68 | * that the buflist is empty (there are no segments on the buflist). |
69 | */ |
70 | LWS_VISIBLE LWS_EXTERN size_t |
71 | lws_buflist_next_segment_len(struct lws_buflist **head, uint8_t **buf); |
72 | |
73 | /** |
74 | * lws_buflist_use_segment(): remove len bytes from the current segment |
75 | * |
76 | * \param head: list head |
77 | * \param len: number of bytes to mark as used |
78 | * |
79 | * If len is less than the remaining length of the current segment, the position |
80 | * in the current segment is simply advanced and it returns. |
81 | * |
82 | * If len uses up the remaining length of the current segment, then the segment |
83 | * is deleted and the list head moves to the next segment if any. |
84 | * |
85 | * Returns the number of bytes left in the current segment. 0 indicates |
86 | * that the buflist is empty (there are no segments on the buflist). |
87 | */ |
88 | LWS_VISIBLE LWS_EXTERN size_t |
89 | lws_buflist_use_segment(struct lws_buflist **head, size_t len); |
90 | |
91 | /** |
92 | * lws_buflist_total_len(): Get the total size of the buflist |
93 | * |
94 | * \param head: list head |
95 | * |
96 | * Returns the total number of bytes held on all segments of the buflist |
97 | */ |
98 | LWS_VISIBLE LWS_EXTERN size_t |
99 | lws_buflist_total_len(struct lws_buflist **head); |
100 | |
101 | /** |
102 | * lws_buflist_linear_copy(): copy everything out as one without consuming |
103 | * |
104 | * \param head: list head |
105 | * \param ofs: start offset into buflist in bytes |
106 | * \param buf: buffer to copy linearly into |
107 | * \param len: length of buffer available |
108 | * |
109 | * Returns -1 if len is too small, or bytes copied. Happy to do partial |
110 | * copies, returns 0 when there are no more bytes to copy. |
111 | */ |
112 | LWS_VISIBLE LWS_EXTERN int |
113 | lws_buflist_linear_copy(struct lws_buflist **head, size_t ofs, uint8_t *buf, |
114 | size_t len); |
115 | |
116 | /** |
117 | * lws_buflist_linear_use(): copy and consume from buflist head |
118 | * |
119 | * \param head: list head |
120 | * \param buf: buffer to copy linearly into |
121 | * \param len: length of buffer available |
122 | * |
123 | * Copies a possibly fragmented buflist from the head into the linear output |
124 | * buffer \p buf for up to length \p len, and consumes the buflist content that |
125 | * was copied out. |
126 | * |
127 | * Since it was consumed, calling again will resume copying out and consuming |
128 | * from as far as it got the first time. |
129 | * |
130 | * Returns the number of bytes written into \p buf. |
131 | */ |
132 | LWS_VISIBLE LWS_EXTERN int |
133 | lws_buflist_linear_use(struct lws_buflist **head, uint8_t *buf, size_t len); |
134 | |
135 | /** |
136 | * lws_buflist_fragment_use(): copy and consume <= 1 frag from buflist head |
137 | * |
138 | * \param head: list head |
139 | * \param buf: buffer to copy linearly into |
140 | * \param len: length of buffer available |
141 | * \param frag_first: pointer to char written on exit to if this is start of frag |
142 | * \param frag_fin: pointer to char written on exit to if this is end of frag |
143 | * |
144 | * Copies all or part of the fragment at the start of a buflist from the head |
145 | * into the output buffer \p buf for up to length \p len, and consumes the |
146 | * buflist content that was copied out. |
147 | * |
148 | * Since it was consumed, calling again will resume copying out and consuming |
149 | * from as far as it got the first time. |
150 | * |
151 | * Returns the number of bytes written into \p buf. |
152 | */ |
153 | LWS_VISIBLE LWS_EXTERN int |
154 | lws_buflist_fragment_use(struct lws_buflist **head, uint8_t *buf, |
155 | size_t len, char *frag_first, char *frag_fin); |
156 | |
157 | /** |
158 | * lws_buflist_destroy_all_segments(): free all segments on the list |
159 | * |
160 | * \param head: list head |
161 | * |
162 | * This frees everything on the list unconditionally. *head is always |
163 | * NULL after this. |
164 | */ |
165 | LWS_VISIBLE LWS_EXTERN void |
166 | lws_buflist_destroy_all_segments(struct lws_buflist **head); |
167 | |
168 | /** |
169 | * lws_buflist_describe(): debug helper logging buflist status |
170 | * |
171 | * \param head: list head |
172 | * \param id: pointer shown in debug list |
173 | * \param reason: reason string show in debug list |
174 | * |
175 | * Iterates through the buflist segments showing position and size. |
176 | * This only exists when lws was built in debug mode |
177 | */ |
178 | LWS_VISIBLE LWS_EXTERN void |
179 | lws_buflist_describe(struct lws_buflist **head, void *id, const char *reason); |
180 | |
181 | /** |
182 | * lws_ptr_diff(): helper to report distance between pointers as an int |
183 | * |
184 | * \param head: the pointer with the larger address |
185 | * \param tail: the pointer with the smaller address |
186 | * |
187 | * This helper gives you an int representing the number of bytes further |
188 | * forward the first pointer is compared to the second pointer. |
189 | */ |
190 | #define lws_ptr_diff(head, tail) \ |
191 | ((int)((char *)(head) - (char *)(tail))) |
192 | |
193 | #define lws_ptr_diff_size_t(head, tail) \ |
194 | ((size_t)(ssize_t)((char *)(head) - (char *)(tail))) |
195 | |
196 | /** |
197 | * lws_snprintf(): snprintf that truncates the returned length too |
198 | * |
199 | * \param str: destination buffer |
200 | * \param size: bytes left in destination buffer |
201 | * \param format: format string |
202 | * \param ...: args for format |
203 | * |
204 | * This lets you correctly truncate buffers by concatenating lengths, if you |
205 | * reach the limit the reported length doesn't exceed the limit. |
206 | */ |
207 | LWS_VISIBLE LWS_EXTERN int |
208 | lws_snprintf(char *str, size_t size, const char *format, ...) LWS_FORMAT(3); |
209 | |
210 | /** |
211 | * lws_strncpy(): strncpy that guarantees NUL on truncated copy |
212 | * |
213 | * \param dest: destination buffer |
214 | * \param src: source buffer |
215 | * \param size: bytes left in destination buffer |
216 | * |
217 | * This lets you correctly truncate buffers by concatenating lengths, if you |
218 | * reach the limit the reported length doesn't exceed the limit. |
219 | */ |
220 | LWS_VISIBLE LWS_EXTERN char * |
221 | lws_strncpy(char *dest, const char *src, size_t size); |
222 | |
223 | /* |
224 | * Variation where we want to use the smaller of two lengths, useful when the |
225 | * source string is not NUL terminated |
226 | */ |
227 | #define lws_strnncpy(dest, src, size1, destsize) \ |
228 | lws_strncpy(dest, src, (size_t)(size1 + 1) < (size_t)(destsize) ? \ |
229 | (size_t)(size1 + 1) : (size_t)(destsize)) |
230 | |
231 | /** |
232 | * lws_nstrstr(): like strstr for length-based strings without terminating NUL |
233 | * |
234 | * \param buf: the string to search |
235 | * \param len: the length of the string to search |
236 | * \param name: the substring to search for |
237 | * \param nl: the length of name |
238 | * |
239 | * Returns NULL if \p name is not present in \p buf. Otherwise returns the |
240 | * address of the first instance of \p name in \p buf. |
241 | * |
242 | * Neither buf nor name need to be NUL-terminated. |
243 | */ |
244 | LWS_VISIBLE LWS_EXTERN const char * |
245 | lws_nstrstr(const char *buf, size_t len, const char *name, size_t nl); |
246 | |
247 | /** |
248 | * lws_json_simple_find(): dumb JSON string parser |
249 | * |
250 | * \param buf: the JSON to search |
251 | * \param len: the length of the JSON to search |
252 | * \param name: the name field to search the JSON for, eg, "\"myname\":" |
253 | * \param alen: set to the length of the argument part if non-NULL return |
254 | * |
255 | * Either returns NULL if \p name is not present in buf, or returns a pointer |
256 | * to the argument body of the first instance of \p name, and sets *alen to the |
257 | * length of the argument body. |
258 | * |
259 | * This can cheaply handle fishing out, eg, myarg from {"myname": "myarg"} by |
260 | * searching for "\"myname\":". It will return a pointer to myarg and set *alen |
261 | * to 5. It equally handles args like "myname": true, or "myname":false, and |
262 | * null or numbers are all returned as delimited strings. |
263 | * |
264 | * Anything more complicated like the value is a subobject or array, you should |
265 | * parse it using a full parser like lejp. This is suitable is the JSON is |
266 | * and will remain short and simple, and contains well-known names amongst other |
267 | * extensible JSON members. |
268 | */ |
269 | LWS_VISIBLE LWS_EXTERN const char * |
270 | lws_json_simple_find(const char *buf, size_t len, const char *name, size_t *alen); |
271 | |
272 | /** |
273 | * lws_json_simple_strcmp(): dumb JSON string comparison |
274 | * |
275 | * \param buf: the JSON to search |
276 | * \param len: the length of the JSON to search |
277 | * \param name: the name field to search the JSON for, eg, "\"myname\":" |
278 | * \param comp: return a strcmp of this and the discovered argument |
279 | * |
280 | * Helper that combines lws_json_simple_find() with strcmp() if it was found. |
281 | * If the \p name was not found, returns -1. Otherwise returns a strcmp() |
282 | * between what was found and \p comp, ie, return 0 if they match or something |
283 | * else if they don't. |
284 | * |
285 | * If the JSON is relatively simple and you want to target constrained |
286 | * devices, this can be a good choice. If the JSON may be complex, you |
287 | * should use a full JSON parser. |
288 | */ |
289 | LWS_VISIBLE LWS_EXTERN int |
290 | lws_json_simple_strcmp(const char *buf, size_t len, const char *name, const char *comp); |
291 | |
292 | |
293 | /** |
294 | * lws_hex_to_byte_array(): convert hex string like 0123456789ab into byte data |
295 | * |
296 | * \param h: incoming NUL-terminated hex string |
297 | * \param dest: array to fill with binary decodes of hex pairs from h |
298 | * \param max: maximum number of bytes dest can hold, must be at least half |
299 | * the size of strlen(h) |
300 | * |
301 | * This converts hex strings into an array of 8-bit representations, ie the |
302 | * input "abcd" produces two bytes of value 0xab and 0xcd. |
303 | * |
304 | * Returns number of bytes produced into \p dest, or -1 on error. |
305 | * |
306 | * Errors include non-hex chars and an odd count of hex chars in the input |
307 | * string. |
308 | */ |
309 | LWS_VISIBLE LWS_EXTERN int |
310 | lws_hex_to_byte_array(const char *h, uint8_t *dest, int max); |
311 | |
312 | /** |
313 | * lws_hex_from_byte_array(): render byte array as hex char string |
314 | * |
315 | * \param src: incoming binary source array |
316 | * \param slen: length of src in bytes |
317 | * \param dest: array to fill with hex chars representing src |
318 | * \param len: max extent of dest |
319 | * |
320 | * This converts binary data of length slen at src, into a hex string at dest |
321 | * of maximum length len. Even if truncated, the result will be NUL-terminated. |
322 | */ |
323 | LWS_VISIBLE LWS_EXTERN void |
324 | lws_hex_from_byte_array(const uint8_t *src, size_t slen, char *dest, size_t len); |
325 | |
326 | /** |
327 | * lws_hex_random(): generate len - 1 or - 2 characters of random ascii hex |
328 | * |
329 | * \param context: the lws_context used to get the random |
330 | * \param dest: destination for hex ascii chars |
331 | * \param len: the number of bytes the buffer dest points to can hold |
332 | * |
333 | * This creates random ascii-hex strings up to a given length, with a |
334 | * terminating NUL. |
335 | * |
336 | * There will not be any characters produced that are not 0-9, a-f, so it's |
337 | * safe to go straight into, eg, JSON. |
338 | */ |
339 | LWS_VISIBLE LWS_EXTERN int |
340 | lws_hex_random(struct lws_context *context, char *dest, size_t len); |
341 | |
342 | /* |
343 | * lws_timingsafe_bcmp(): constant time memcmp |
344 | * |
345 | * \param a: first buffer |
346 | * \param b: second buffer |
347 | * \param len: count of bytes to compare |
348 | * |
349 | * Return 0 if the two buffers are the same, else nonzero. |
350 | * |
351 | * Always compares all of the buffer before returning, so it can't be used as |
352 | * a timing oracle. |
353 | */ |
354 | |
355 | LWS_VISIBLE LWS_EXTERN int |
356 | lws_timingsafe_bcmp(const void *a, const void *b, uint32_t len); |
357 | |
358 | /** |
359 | * lws_get_random(): fill a buffer with platform random data |
360 | * |
361 | * \param context: the lws context |
362 | * \param buf: buffer to fill |
363 | * \param len: how much to fill |
364 | * |
365 | * Fills buf with len bytes of random. Returns the number of bytes set, if |
366 | * not equal to len, then getting the random failed. |
367 | */ |
368 | LWS_VISIBLE LWS_EXTERN size_t |
369 | lws_get_random(struct lws_context *context, void *buf, size_t len); |
370 | /** |
371 | * lws_daemonize(): make current process run in the background |
372 | * |
373 | * \param _lock_path: the filepath to write the lock file |
374 | * |
375 | * Spawn lws as a background process, taking care of various things |
376 | */ |
377 | LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
378 | lws_daemonize(const char *_lock_path); |
379 | /** |
380 | * lws_get_library_version(): return string describing the version of lws |
381 | * |
382 | * On unix, also includes the git describe |
383 | */ |
384 | LWS_VISIBLE LWS_EXTERN const char * LWS_WARN_UNUSED_RESULT |
385 | lws_get_library_version(void); |
386 | |
387 | /** |
388 | * lws_wsi_user() - get the user data associated with the connection |
389 | * \param wsi: lws connection |
390 | * |
391 | * Not normally needed since it's passed into the callback |
392 | */ |
393 | LWS_VISIBLE LWS_EXTERN void * |
394 | lws_wsi_user(struct lws *wsi); |
395 | |
396 | /** |
397 | * lws_wsi_tsi() - get the service thread index the wsi is bound to |
398 | * \param wsi: lws connection |
399 | * |
400 | * Only useful is LWS_MAX_SMP > 1 |
401 | */ |
402 | LWS_VISIBLE LWS_EXTERN int |
403 | lws_wsi_tsi(struct lws *wsi); |
404 | |
405 | /** |
406 | * lws_set_wsi_user() - set the user data associated with the client connection |
407 | * \param wsi: lws connection |
408 | * \param user: user data |
409 | * |
410 | * By default lws allocates this and it's not legal to externally set it |
411 | * yourself. However client connections may have it set externally when the |
412 | * connection is created... if so, this api can be used to modify it at |
413 | * runtime additionally. |
414 | */ |
415 | LWS_VISIBLE LWS_EXTERN void |
416 | lws_set_wsi_user(struct lws *wsi, void *user); |
417 | |
418 | /** |
419 | * lws_parse_uri: cut up prot:/ads:port/path into pieces |
420 | * Notice it does so by dropping '\0' into input string |
421 | * and the leading / on the path is consequently lost |
422 | * |
423 | * \param p: incoming uri string.. will get written to |
424 | * \param prot: result pointer for protocol part (https://) |
425 | * \param ads: result pointer for address part |
426 | * \param port: result pointer for port part |
427 | * \param path: result pointer for path part |
428 | * |
429 | * You may also refer to unix socket addresses, using a '+' at the start of |
430 | * the address. In this case, the address should end with ':', which is |
431 | * treated as the separator between the address and path (the normal separator |
432 | * '/' is a valid part of the socket path). Eg, |
433 | * |
434 | * http://+/var/run/mysocket:/my/path |
435 | * |
436 | * If the first character after the + is '@', it's interpreted by lws client |
437 | * processing as meaning to use linux abstract namespace sockets, the @ is |
438 | * replaced with a '\0' before use. |
439 | */ |
440 | LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
441 | lws_parse_uri(char *p, const char **prot, const char **ads, int *port, |
442 | const char **path); |
443 | /** |
444 | * lws_cmdline_option(): simple commandline parser |
445 | * |
446 | * \param argc: count of argument strings |
447 | * \param argv: argument strings |
448 | * \param val: string to find |
449 | * |
450 | * Returns NULL if the string \p val is not found in the arguments. |
451 | * |
452 | * If it is found, then it returns a pointer to the next character after \p val. |
453 | * So if \p val is "-d", then for the commandlines "myapp -d15" and |
454 | * "myapp -d 15", in both cases the return will point to the "15". |
455 | * |
456 | * In the case there is no argument, like "myapp -d", the return will |
457 | * either point to the '\\0' at the end of -d, or to the start of the |
458 | * next argument, ie, will be non-NULL. |
459 | */ |
460 | LWS_VISIBLE LWS_EXTERN const char * |
461 | lws_cmdline_option(int argc, const char **argv, const char *val); |
462 | |
463 | /** |
464 | * lws_cmdline_option_handle_builtin(): apply standard cmdline options |
465 | * |
466 | * \param argc: count of argument strings |
467 | * \param argv: argument strings |
468 | * \param info: context creation info |
469 | * |
470 | * Applies standard options to the context creation info to save them having |
471 | * to be (unevenly) copied into the minimal examples. |
472 | * |
473 | * Applies default log levels that can be overriden by -d |
474 | */ |
475 | LWS_VISIBLE LWS_EXTERN void |
476 | lws_cmdline_option_handle_builtin(int argc, const char **argv, |
477 | struct lws_context_creation_info *info); |
478 | |
479 | /** |
480 | * lws_now_secs(): return seconds since 1970-1-1 |
481 | */ |
482 | LWS_VISIBLE LWS_EXTERN unsigned long |
483 | lws_now_secs(void); |
484 | |
485 | /** |
486 | * lws_now_usecs(): return useconds since 1970-1-1 |
487 | */ |
488 | LWS_VISIBLE LWS_EXTERN lws_usec_t |
489 | lws_now_usecs(void); |
490 | |
491 | /** |
492 | * lws_get_context - Allow getting lws_context from a Websocket connection |
493 | * instance |
494 | * |
495 | * With this function, users can access context in the callback function. |
496 | * Otherwise users may have to declare context as a global variable. |
497 | * |
498 | * \param wsi: Websocket connection instance |
499 | */ |
500 | LWS_VISIBLE LWS_EXTERN struct lws_context * LWS_WARN_UNUSED_RESULT |
501 | lws_get_context(const struct lws *wsi); |
502 | |
503 | /** |
504 | * lws_get_vhost_listen_port - Find out the port number a vhost is listening on |
505 | * |
506 | * In the case you passed 0 for the port number at context creation time, you |
507 | * can discover the port number that was actually chosen for the vhost using |
508 | * this api. |
509 | * |
510 | * \param vhost: Vhost to get listen port from |
511 | */ |
512 | LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
513 | lws_get_vhost_listen_port(struct lws_vhost *vhost); |
514 | |
515 | /** |
516 | * lws_get_count_threads(): how many service threads the context uses |
517 | * |
518 | * \param context: the lws context |
519 | * |
520 | * By default this is always 1, if you asked for more than lws can handle it |
521 | * will clip the number of threads. So you can use this to find out how many |
522 | * threads are actually in use. |
523 | */ |
524 | LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
525 | lws_get_count_threads(struct lws_context *context); |
526 | |
527 | /** |
528 | * lws_get_parent() - get parent wsi or NULL |
529 | * \param wsi: lws connection |
530 | * |
531 | * Specialized wsi like cgi stdin/out/err are associated to a parent wsi, |
532 | * this allows you to get their parent. |
533 | */ |
534 | LWS_VISIBLE LWS_EXTERN struct lws * LWS_WARN_UNUSED_RESULT |
535 | lws_get_parent(const struct lws *wsi); |
536 | |
537 | /** |
538 | * lws_get_child() - get child wsi or NULL |
539 | * \param wsi: lws connection |
540 | * |
541 | * Allows you to find a related wsi from the parent wsi. |
542 | */ |
543 | LWS_VISIBLE LWS_EXTERN struct lws * LWS_WARN_UNUSED_RESULT |
544 | lws_get_child(const struct lws *wsi); |
545 | |
546 | /** |
547 | * lws_get_effective_uid_gid() - find out eventual uid and gid while still root |
548 | * |
549 | * \param context: lws context |
550 | * \param uid: pointer to uid result |
551 | * \param gid: pointer to gid result |
552 | * |
553 | * This helper allows you to find out what the uid and gid for the process will |
554 | * be set to after the privileges are dropped, beforehand. So while still root, |
555 | * eg in LWS_CALLBACK_PROTOCOL_INIT, you can arrange things like cache dir |
556 | * and subdir creation / permissions down /var/cache dynamically. |
557 | */ |
558 | LWS_VISIBLE LWS_EXTERN void |
559 | lws_get_effective_uid_gid(struct lws_context *context, uid_t *uid, gid_t *gid); |
560 | |
561 | /** |
562 | * lws_get_udp() - get wsi's udp struct |
563 | * |
564 | * \param wsi: lws connection |
565 | * |
566 | * Returns NULL or pointer to the wsi's UDP-specific information |
567 | */ |
568 | LWS_VISIBLE LWS_EXTERN const struct lws_udp * LWS_WARN_UNUSED_RESULT |
569 | lws_get_udp(const struct lws *wsi); |
570 | |
571 | LWS_VISIBLE LWS_EXTERN void * |
572 | lws_get_opaque_parent_data(const struct lws *wsi); |
573 | |
574 | LWS_VISIBLE LWS_EXTERN void |
575 | lws_set_opaque_parent_data(struct lws *wsi, void *data); |
576 | |
577 | LWS_VISIBLE LWS_EXTERN void * |
578 | lws_get_opaque_user_data(const struct lws *wsi); |
579 | |
580 | LWS_VISIBLE LWS_EXTERN void |
581 | lws_set_opaque_user_data(struct lws *wsi, void *data); |
582 | |
583 | LWS_VISIBLE LWS_EXTERN int |
584 | lws_get_child_pending_on_writable(const struct lws *wsi); |
585 | |
586 | LWS_VISIBLE LWS_EXTERN void |
587 | lws_clear_child_pending_on_writable(struct lws *wsi); |
588 | |
589 | LWS_VISIBLE LWS_EXTERN int |
590 | lws_get_close_length(struct lws *wsi); |
591 | |
592 | LWS_VISIBLE LWS_EXTERN unsigned char * |
593 | lws_get_close_payload(struct lws *wsi); |
594 | |
595 | /** |
596 | * lws_get_network_wsi() - Returns wsi that has the tcp connection for this wsi |
597 | * |
598 | * \param wsi: wsi you have |
599 | * |
600 | * Returns wsi that has the tcp connection (which may be the incoming wsi) |
601 | * |
602 | * HTTP/1 connections will always return the incoming wsi |
603 | * HTTP/2 connections may return a different wsi that has the tcp connection |
604 | */ |
605 | LWS_VISIBLE LWS_EXTERN |
606 | struct lws *lws_get_network_wsi(struct lws *wsi); |
607 | |
608 | /** |
609 | * lws_set_allocator() - custom allocator support |
610 | * |
611 | * \param realloc |
612 | * |
613 | * Allows you to replace the allocator (and deallocator) used by lws |
614 | */ |
615 | LWS_VISIBLE LWS_EXTERN void |
616 | lws_set_allocator(void *(*realloc)(void *ptr, size_t size, const char *reason)); |
617 | |
618 | enum { |
619 | /* |
620 | * Flags for enable and disable rxflow with reason bitmap and with |
621 | * backwards-compatible single bool |
622 | */ |
623 | LWS_RXFLOW_REASON_USER_BOOL = (1 << 0), |
624 | LWS_RXFLOW_REASON_HTTP_RXBUFFER = (1 << 6), |
625 | LWS_RXFLOW_REASON_H2_PPS_PENDING = (1 << 7), |
626 | |
627 | LWS_RXFLOW_REASON_APPLIES = (1 << 14), |
628 | LWS_RXFLOW_REASON_APPLIES_ENABLE_BIT = (1 << 13), |
629 | LWS_RXFLOW_REASON_APPLIES_ENABLE = LWS_RXFLOW_REASON_APPLIES | |
630 | LWS_RXFLOW_REASON_APPLIES_ENABLE_BIT, |
631 | LWS_RXFLOW_REASON_APPLIES_DISABLE = LWS_RXFLOW_REASON_APPLIES, |
632 | LWS_RXFLOW_REASON_FLAG_PROCESS_NOW = (1 << 12), |
633 | |
634 | }; |
635 | |
636 | /** |
637 | * lws_rx_flow_control() - Enable and disable socket servicing for |
638 | * received packets. |
639 | * |
640 | * If the output side of a server process becomes choked, this allows flow |
641 | * control for the input side. |
642 | * |
643 | * \param wsi: Websocket connection instance to get callback for |
644 | * \param enable: 0 = disable read servicing for this connection, 1 = enable |
645 | * |
646 | * If you need more than one additive reason for rxflow control, you can give |
647 | * iLWS_RXFLOW_REASON_APPLIES_ENABLE or _DISABLE together with one or more of |
648 | * b5..b0 set to idicate which bits to enable or disable. If any bits are |
649 | * enabled, rx on the connection is suppressed. |
650 | * |
651 | * LWS_RXFLOW_REASON_FLAG_PROCESS_NOW flag may also be given to force any change |
652 | * in rxflowbstatus to benapplied immediately, this should be used when you are |
653 | * changing a wsi flow control state from outside a callback on that wsi. |
654 | */ |
655 | LWS_VISIBLE LWS_EXTERN int |
656 | lws_rx_flow_control(struct lws *wsi, int enable); |
657 | |
658 | /** |
659 | * lws_rx_flow_allow_all_protocol() - Allow all connections with this protocol to receive |
660 | * |
661 | * When the user server code realizes it can accept more input, it can |
662 | * call this to have the RX flow restriction removed from all connections using |
663 | * the given protocol. |
664 | * \param context: lws_context |
665 | * \param protocol: all connections using this protocol will be allowed to receive |
666 | */ |
667 | LWS_VISIBLE LWS_EXTERN void |
668 | lws_rx_flow_allow_all_protocol(const struct lws_context *context, |
669 | const struct lws_protocols *protocol); |
670 | |
671 | /** |
672 | * lws_remaining_packet_payload() - Bytes to come before "overall" |
673 | * rx fragment is complete |
674 | * \param wsi: Websocket instance (available from user callback) |
675 | * |
676 | * This tracks how many bytes are left in the current ws fragment, according |
677 | * to the ws length given in the fragment header. |
678 | * |
679 | * If the message was in a single fragment, and there is no compression, this |
680 | * is the same as "how much data is left to read for this message". |
681 | * |
682 | * However, if the message is being sent in multiple fragments, this will |
683 | * reflect the unread amount of the current **fragment**, not the message. With |
684 | * ws, it is legal to not know the length of the message before it completes. |
685 | * |
686 | * Additionally if the message is sent via the negotiated permessage-deflate |
687 | * extension, this number only tells the amount of **compressed** data left to |
688 | * be read, since that is the only information available at the ws layer. |
689 | */ |
690 | LWS_VISIBLE LWS_EXTERN size_t |
691 | lws_remaining_packet_payload(struct lws *wsi); |
692 | |
693 | #if defined(LWS_WITH_DIR) |
694 | |
695 | typedef enum { |
696 | LDOT_UNKNOWN, |
697 | LDOT_FILE, |
698 | LDOT_DIR, |
699 | LDOT_LINK, |
700 | LDOT_FIFO, |
701 | LDOTT_SOCKET, |
702 | LDOT_CHAR, |
703 | LDOT_BLOCK |
704 | } lws_dir_obj_type_t; |
705 | |
706 | struct lws_dir_entry { |
707 | const char *name; |
708 | lws_dir_obj_type_t type; |
709 | }; |
710 | |
711 | typedef int |
712 | lws_dir_callback_function(const char *dirpath, void *user, |
713 | struct lws_dir_entry *lde); |
714 | |
715 | /** |
716 | * lws_dir() - get a callback for everything in a directory |
717 | * |
718 | * \param dirpath: the directory to scan |
719 | * \param user: pointer to give to callback |
720 | * \param cb: callback to receive information on each file or dir |
721 | * |
722 | * Calls \p cb (with \p user) for every object in dirpath. |
723 | * |
724 | * This wraps whether it's using POSIX apis, or libuv (as needed for windows, |
725 | * since it refuses to support POSIX apis for this). |
726 | */ |
727 | LWS_VISIBLE LWS_EXTERN int |
728 | lws_dir(const char *dirpath, void *user, lws_dir_callback_function cb); |
729 | |
730 | /** |
731 | * lws_dir_rm_rf_cb() - callback for lws_dir that performs recursive rm -rf |
732 | * |
733 | * \param dirpath: directory we are at in lws_dir |
734 | * \param user: ignored |
735 | * \param lde: lws_dir info on the file or directory we are at |
736 | * |
737 | * This is a readymade rm -rf callback for use with lws_dir. It recursively |
738 | * removes everything below the starting dir and then the starting dir itself. |
739 | * Works on linux, OSX and Windows at least. |
740 | */ |
741 | LWS_VISIBLE LWS_EXTERN int |
742 | lws_dir_rm_rf_cb(const char *dirpath, void *user, struct lws_dir_entry *lde); |
743 | |
744 | /* |
745 | * We pass every file in the base dir through a filter, and call back on the |
746 | * ones that match. Directories are ignored. |
747 | * |
748 | * The original path filter string may look like, eg, "sai-*.deb" or "*.txt" |
749 | */ |
750 | |
751 | typedef int (*lws_dir_glob_cb_t)(void *data, const char *path); |
752 | |
753 | typedef struct lws_dir_glob { |
754 | const char *filter; |
755 | lws_dir_glob_cb_t cb; |
756 | void *user; |
757 | } lws_dir_glob_t; |
758 | |
759 | /** |
760 | * lws_dir_glob_cb() - callback for lws_dir that performs filename globbing |
761 | * |
762 | * \param dirpath: directory we are at in lws_dir |
763 | * \param user: pointer to your prepared lws_dir_glob_cb_t |
764 | * \param lde: lws_dir info on the file or directory we are at |
765 | * |
766 | * \p user is prepared with an `lws_dir_glob_t` containing a callback for paths |
767 | * that pass the filtering, a user pointer to pass to that callback, and a |
768 | * glob string like "*.txt". It may not contain directories, the lws_dir musr |
769 | * be started at the correct dir. |
770 | * |
771 | * Only the base path passed to lws_dir is scanned, it does not look in subdirs. |
772 | */ |
773 | LWS_VISIBLE LWS_EXTERN int |
774 | lws_dir_glob_cb(const char *dirpath, void *user, struct lws_dir_entry *lde); |
775 | |
776 | #endif |
777 | |
778 | /** |
779 | * lws_get_allocated_heap() - if the platform supports it, returns amount of |
780 | * heap allocated by lws itself |
781 | * |
782 | * On glibc currently, this reports the total amount of current logical heap |
783 | * allocation, found by tracking the amount allocated by lws_malloc() and |
784 | * friends and accounting for freed allocations via lws_free(). |
785 | * |
786 | * This is useful for confirming where processwide heap allocations actually |
787 | * come from... this number represents all lws internal allocations, for |
788 | * fd tables, wsi allocations, ah, etc combined. It doesn't include allocations |
789 | * from user code, since lws_malloc() etc are not exported from the library. |
790 | * |
791 | * On other platforms, it always returns 0. |
792 | */ |
793 | size_t lws_get_allocated_heap(void); |
794 | |
795 | /** |
796 | * lws_get_tsi() - Get thread service index wsi belong to |
797 | * \param wsi: websocket connection to check |
798 | * |
799 | * Returns more than zero (or zero if only one service thread as is the default). |
800 | */ |
801 | LWS_VISIBLE LWS_EXTERN int |
802 | lws_get_tsi(struct lws *wsi); |
803 | |
804 | /** |
805 | * lws_is_ssl() - Find out if connection is using SSL |
806 | * \param wsi: websocket connection to check |
807 | * |
808 | * Returns nonzero if the wsi is inside a tls tunnel, else zero. |
809 | */ |
810 | LWS_VISIBLE LWS_EXTERN int |
811 | lws_is_ssl(struct lws *wsi); |
812 | /** |
813 | * lws_is_cgi() - find out if this wsi is running a cgi process |
814 | * |
815 | * \param wsi: lws connection |
816 | */ |
817 | LWS_VISIBLE LWS_EXTERN int |
818 | lws_is_cgi(struct lws *wsi); |
819 | |
820 | /** |
821 | * lws_tls_jit_trust_blob_queury_skid() - walk jit trust blob for skid |
822 | * |
823 | * \param _blob: the start of the blob in memory |
824 | * \param blen: the length of the blob in memory |
825 | * \param skid: the SKID we are looking for |
826 | * \param skid_len: the length of the SKID we are looking for |
827 | * \param prpder: result pointer to receive a pointer to the matching DER |
828 | * \param prder_len: result pointer to receive matching DER length |
829 | * |
830 | * Helper to scan a JIT Trust blob in memory for a trusted CA cert matching |
831 | * a given SKID. Returns 0 if found and *prpder and *prder_len are set, else |
832 | * nonzero. |
833 | */ |
834 | LWS_VISIBLE LWS_EXTERN int |
835 | lws_tls_jit_trust_blob_queury_skid(const void *_blob, size_t blen, |
836 | const uint8_t *skid, size_t skid_len, |
837 | const uint8_t **prpder, size_t *prder_len); |
838 | |
839 | /** |
840 | * lws_open() - platform-specific wrapper for open that prepares the fd |
841 | * |
842 | * \param __file: the filepath to open |
843 | * \param __oflag: option flags |
844 | * |
845 | * This is a wrapper around platform open() that sets options on the fd |
846 | * according to lws policy. Currently that is FD_CLOEXEC to stop the opened |
847 | * fd being available to any child process forked by user code. |
848 | */ |
849 | LWS_VISIBLE LWS_EXTERN int |
850 | lws_open(const char *__file, int __oflag, ...); |
851 | |
852 | struct lws_wifi_scan { /* generic wlan scan item */ |
853 | struct lws_wifi_scan *next; |
854 | char ssid[32]; |
855 | int32_t ; /* divide by .count to get db */ |
856 | uint8_t bssid[6]; |
857 | uint8_t count; |
858 | uint8_t channel; |
859 | uint8_t authmode; |
860 | }; |
861 | |
862 | #if defined(LWS_WITH_TLS) && !defined(LWS_WITH_MBEDTLS) |
863 | /** |
864 | * lws_get_ssl() - Return wsi's SSL context structure |
865 | * \param wsi: websocket connection |
866 | * |
867 | * Returns pointer to the SSL library's context structure |
868 | */ |
869 | LWS_VISIBLE LWS_EXTERN SSL* |
870 | lws_get_ssl(struct lws *wsi); |
871 | #endif |
872 | |
873 | LWS_VISIBLE LWS_EXTERN void |
874 | lws_explicit_bzero(void *p, size_t len); |
875 | |
876 | typedef struct lws_humanize_unit { |
877 | const char *name; /* array ends with NULL name */ |
878 | uint64_t factor; |
879 | } lws_humanize_unit_t; |
880 | |
881 | LWS_VISIBLE extern const lws_humanize_unit_t humanize_schema_si[7]; |
882 | LWS_VISIBLE extern const lws_humanize_unit_t humanize_schema_si_bytes[7]; |
883 | LWS_VISIBLE extern const lws_humanize_unit_t humanize_schema_us[8]; |
884 | |
885 | /** |
886 | * lws_humanize() - Convert possibly large number to human-readable uints |
887 | * |
888 | * \param buf: result string buffer |
889 | * \param len: remaining length in \p buf |
890 | * \param value: the uint64_t value to represent |
891 | * \param schema: and array of scaling factors and units |
892 | * |
893 | * This produces a concise string representation of \p value, referencing the |
894 | * schema \p schema of scaling factors and units to find the smallest way to |
895 | * render it. |
896 | * |
897 | * Three schema are exported from lws for general use, humanize_schema_si, which |
898 | * represents as, eg, " 22.130Gi" or " 128 "; humanize_schema_si_bytes |
899 | * which is the same but shows, eg, " 22.130GiB", and humanize_schema_us, |
900 | * which represents a count of us as a human-readable time like " 14.350min", |
901 | * or " 1.500d". |
902 | * |
903 | * You can produce your own schema. |
904 | */ |
905 | |
906 | LWS_VISIBLE LWS_EXTERN int |
907 | lws_humanize(char *buf, size_t len, uint64_t value, |
908 | const lws_humanize_unit_t *schema); |
909 | |
910 | LWS_VISIBLE LWS_EXTERN void |
911 | lws_ser_wu16be(uint8_t *b, uint16_t u); |
912 | |
913 | LWS_VISIBLE LWS_EXTERN void |
914 | lws_ser_wu32be(uint8_t *b, uint32_t u32); |
915 | |
916 | LWS_VISIBLE LWS_EXTERN void |
917 | lws_ser_wu64be(uint8_t *b, uint64_t u64); |
918 | |
919 | LWS_VISIBLE LWS_EXTERN uint16_t |
920 | lws_ser_ru16be(const uint8_t *b); |
921 | |
922 | LWS_VISIBLE LWS_EXTERN uint32_t |
923 | lws_ser_ru32be(const uint8_t *b); |
924 | |
925 | LWS_VISIBLE LWS_EXTERN uint64_t |
926 | lws_ser_ru64be(const uint8_t *b); |
927 | |
928 | LWS_VISIBLE LWS_EXTERN int |
929 | lws_vbi_encode(uint64_t value, void *buf); |
930 | |
931 | LWS_VISIBLE LWS_EXTERN int |
932 | lws_vbi_decode(const void *buf, uint64_t *value, size_t len); |
933 | |
934 | ///@} |
935 | |
936 | #if defined(LWS_WITH_SPAWN) |
937 | |
938 | /* opaque internal struct */ |
939 | struct lws_spawn_piped; |
940 | |
941 | #if defined(WIN32) |
942 | struct _lws_siginfo_t { |
943 | int retcode; |
944 | }; |
945 | typedef struct _lws_siginfo_t siginfo_t; |
946 | #endif |
947 | |
948 | typedef void (*lsp_cb_t)(void *opaque, lws_usec_t *accounting, siginfo_t *si, |
949 | int we_killed_him); |
950 | |
951 | |
952 | /** |
953 | * lws_spawn_piped_info - details given to create a spawned pipe |
954 | * |
955 | * \p owner: lws_dll2_owner_t that lists all active spawns, or NULL |
956 | * \p vh: vhost to bind stdwsi to... from opt_parent if given |
957 | * \p opt_parent: optional parent wsi for stdwsi |
958 | * \p exec_array: argv for process to spawn |
959 | * \p env_array: environment for spawned process, NULL ends env list |
960 | * \p protocol_name: NULL, or vhost protocol name to bind stdwsi to |
961 | * \p chroot_path: NULL, or chroot patch for child process |
962 | * \p wd: working directory to cd to after fork, NULL defaults to /tmp |
963 | * \p plsp: NULL, or pointer to the outer lsp pointer so it can be set NULL when destroyed |
964 | * \p opaque: pointer passed to the reap callback, if any |
965 | * \p timeout: optional us-resolution timeout, or zero |
966 | * \p reap_cb: callback when child process has been reaped and the lsp destroyed |
967 | * \p tsi: tsi to bind stdwsi to... from opt_parent if given |
968 | */ |
969 | struct lws_spawn_piped_info { |
970 | struct lws_dll2_owner *owner; |
971 | struct lws_vhost *vh; |
972 | struct lws *opt_parent; |
973 | |
974 | const char * const *exec_array; |
975 | const char **env_array; |
976 | const char *protocol_name; |
977 | const char *chroot_path; |
978 | const char *wd; |
979 | |
980 | struct lws_spawn_piped **plsp; |
981 | |
982 | void *opaque; |
983 | |
984 | lsp_cb_t reap_cb; |
985 | |
986 | lws_usec_t timeout_us; |
987 | int max_log_lines; |
988 | int tsi; |
989 | |
990 | const struct lws_role_ops *ops; /* NULL is raw file */ |
991 | |
992 | uint8_t disable_ctrlc; |
993 | }; |
994 | |
995 | /** |
996 | * lws_spawn_piped() - spawn a child process with stdxxx redirected |
997 | * |
998 | * \p lspi: info struct describing details of spawn to create |
999 | * |
1000 | * This spawns a child process managed in the lsp object and with attributes |
1001 | * set in the arguments. The stdin/out/err streams are redirected to pipes |
1002 | * which are instantiated into wsi that become child wsi of \p parent if non- |
1003 | * NULL. .opaque_user_data on the stdwsi created is set to point to the |
1004 | * lsp object, so this can be recovered easily in the protocol handler. |
1005 | * |
1006 | * If \p owner is non-NULL, successful spawns join the given dll2 owner in the |
1007 | * original process. |
1008 | * |
1009 | * If \p timeout is non-zero, successful spawns register a sul with the us- |
1010 | * resolution timeout to callback \p timeout_cb, in the original process. |
1011 | * |
1012 | * Returns 0 if the spawn went OK or nonzero if it failed and was cleaned up. |
1013 | * The spawned process continues asynchronously and this will return after |
1014 | * starting it if all went well. |
1015 | */ |
1016 | LWS_VISIBLE LWS_EXTERN struct lws_spawn_piped * |
1017 | lws_spawn_piped(const struct lws_spawn_piped_info *lspi); |
1018 | |
1019 | /* |
1020 | * lws_spawn_piped_kill_child_process() - attempt to kill child process |
1021 | * |
1022 | * \p lsp: child object to kill |
1023 | * |
1024 | * Attempts to signal the child process in \p lsp to terminate. |
1025 | */ |
1026 | LWS_VISIBLE LWS_EXTERN int |
1027 | lws_spawn_piped_kill_child_process(struct lws_spawn_piped *lsp); |
1028 | |
1029 | /** |
1030 | * lws_spawn_stdwsi_closed() - inform the spawn one of its stdxxx pipes closed |
1031 | * |
1032 | * \p lsp: the spawn object |
1033 | * \p wsi: the wsi that is closing |
1034 | * |
1035 | * When you notice one of the spawn stdxxx pipes closed, inform the spawn |
1036 | * instance using this api. When it sees all three have closed, it will |
1037 | * automatically try to reap the child process. |
1038 | * |
1039 | * This is the mechanism whereby the spawn object can understand its child |
1040 | * has closed. |
1041 | */ |
1042 | LWS_VISIBLE LWS_EXTERN void |
1043 | lws_spawn_stdwsi_closed(struct lws_spawn_piped *lsp, struct lws *wsi); |
1044 | |
1045 | /** |
1046 | * lws_spawn_get_stdfd() - return std channel index for stdwsi |
1047 | * |
1048 | * \p wsi: the wsi |
1049 | * |
1050 | * If you know wsi is a stdwsi from a spawn, you can determine its original |
1051 | * channel index / fd before the pipes replaced the default fds. It will return |
1052 | * one of 0 (STDIN), 1 (STDOUT) or 2 (STDERR). You can handle all three in the |
1053 | * same protocol handler and then disambiguate them using this api. |
1054 | */ |
1055 | LWS_VISIBLE LWS_EXTERN int |
1056 | lws_spawn_get_stdfd(struct lws *wsi); |
1057 | |
1058 | #endif |
1059 | |
1060 | struct lws_fsmount { |
1061 | const char *layers_path; /* where layers live */ |
1062 | const char *overlay_path; /* where overlay instantiations live */ |
1063 | |
1064 | char mp[256]; /* mountpoint path */ |
1065 | char ovname[64]; /* unique name for mount instance */ |
1066 | char distro[64]; /* unique name for layer source */ |
1067 | |
1068 | #if defined(__linux__) |
1069 | const char *layers[4]; /* distro layers, like "base", "env" */ |
1070 | #endif |
1071 | }; |
1072 | |
1073 | /** |
1074 | * lws_fsmount_mount() - Mounts an overlayfs stack of layers |
1075 | * |
1076 | * \p fsm: struct lws_fsmount specifying the mount layout |
1077 | * |
1078 | * This api is able to assemble up to 4 layer directories on to a mountpoint |
1079 | * using overlayfs mount (Linux only). |
1080 | * |
1081 | * Set fsm.layers_path to the base dir where the layers themselves live, the |
1082 | * entries in fsm.layers[] specifies the relative path to the layer, comprising |
1083 | * fsm.layers_path/fsm.distro/fsm.layers[], with [0] being the deepest, earliest |
1084 | * layer and the rest being progressively on top of [0]; NULL indicates the |
1085 | * layer is unused. |
1086 | * |
1087 | * fsm.overlay_path is the base path of the overlayfs instantiations... empty |
1088 | * dirs must exist at |
1089 | * |
1090 | * fsm.overlay_path/overlays/fsm.ovname/work |
1091 | * fsm.overlay_path/overlays/fsm.ovname/session |
1092 | * |
1093 | * Set fsm.mp to the path of an already-existing empty dir that will be the |
1094 | * mountpoint, this can be whereever you like. |
1095 | * |
1096 | * Overlayfs merges the union of all the contributing layers at the mountpoint, |
1097 | * the mount is writeable but the layer themselves are immutable, all additions |
1098 | * and changes are stored in |
1099 | * |
1100 | * fsm.overlay_path/overlays/fsm.ovname/session |
1101 | * |
1102 | * Returns 0 if mounted OK, nonzero if errors. |
1103 | * |
1104 | * Retain fsm for use with unmounting. |
1105 | */ |
1106 | LWS_VISIBLE LWS_EXTERN int |
1107 | lws_fsmount_mount(struct lws_fsmount *fsm); |
1108 | |
1109 | /** |
1110 | * lws_fsmount_unmount() - Unmounts an overlayfs dir |
1111 | * |
1112 | * \p fsm: struct lws_fsmount specifying the mount layout |
1113 | * |
1114 | * Unmounts the mountpoint in fsm.mp. |
1115 | * |
1116 | * Delete fsm.overlay_path/overlays/fsm.ovname/session to permanently eradicate |
1117 | * all changes from the time the mountpoint was in use. |
1118 | * |
1119 | * Returns 0 if unmounted OK. |
1120 | */ |
1121 | LWS_VISIBLE LWS_EXTERN int |
1122 | lws_fsmount_unmount(struct lws_fsmount *fsm); |
1123 | |