system.c 5.6 KB

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