unix-fds.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  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. #if !defined(_GNU_SOURCE)
  25. #define _GNU_SOURCE
  26. #endif
  27. #include "private-lib-core.h"
  28. struct lws *
  29. wsi_from_fd(const struct lws_context *context, int fd)
  30. {
  31. struct lws **p, **done;
  32. if (!context->max_fds_unrelated_to_ulimit)
  33. return context->lws_lookup[fd - lws_plat_socket_offset()];
  34. /* slow fds handling */
  35. p = context->lws_lookup;
  36. done = &p[context->max_fds];
  37. while (p != done) {
  38. if (*p && (*p)->desc.sockfd == fd)
  39. return *p;
  40. p++;
  41. }
  42. return NULL;
  43. }
  44. #if defined(_DEBUG)
  45. int
  46. sanity_assert_no_wsi_traces(const struct lws_context *context, struct lws *wsi)
  47. {
  48. struct lws **p, **done;
  49. if (!context->max_fds_unrelated_to_ulimit)
  50. /* can't tell */
  51. return 0;
  52. /* slow fds handling */
  53. p = context->lws_lookup;
  54. done = &p[context->max_fds];
  55. /* confirm the wsi doesn't already exist */
  56. while (p != done && *p != wsi)
  57. p++;
  58. if (p == done)
  59. return 0;
  60. assert(0); /* this wsi is still mentioned inside lws */
  61. return 1;
  62. }
  63. int
  64. sanity_assert_no_sockfd_traces(const struct lws_context *context,
  65. lws_sockfd_type sfd)
  66. {
  67. #if LWS_MAX_SMP > 1
  68. /*
  69. * We can't really do this test... another thread can accept and
  70. * reuse the closed fd
  71. */
  72. return 0;
  73. #else
  74. struct lws **p, **done;
  75. if (sfd == LWS_SOCK_INVALID)
  76. return 0;
  77. if (!context->max_fds_unrelated_to_ulimit &&
  78. context->lws_lookup[sfd - lws_plat_socket_offset()]) {
  79. assert(0); /* the fd is still in use */
  80. return 1;
  81. }
  82. /* slow fds handling */
  83. p = context->lws_lookup;
  84. done = &p[context->max_fds];
  85. /* confirm the sfd not already in use */
  86. while (p != done && (!*p || (*p)->desc.sockfd != sfd))
  87. p++;
  88. if (p == done)
  89. return 0;
  90. assert(0); /* this fd is still in the tables */
  91. return 1;
  92. #endif
  93. }
  94. #endif
  95. int
  96. insert_wsi(const struct lws_context *context, struct lws *wsi)
  97. {
  98. struct lws **p, **done;
  99. if (sanity_assert_no_wsi_traces(context, wsi))
  100. return 0;
  101. if (!context->max_fds_unrelated_to_ulimit) {
  102. assert(context->lws_lookup[wsi->desc.sockfd -
  103. lws_plat_socket_offset()] == 0);
  104. context->lws_lookup[wsi->desc.sockfd - \
  105. lws_plat_socket_offset()] = wsi;
  106. return 0;
  107. }
  108. /* slow fds handling */
  109. p = context->lws_lookup;
  110. done = &p[context->max_fds];
  111. /* confirm fd isn't already in use by a wsi */
  112. if (sanity_assert_no_sockfd_traces(context, wsi->desc.sockfd))
  113. return 0;
  114. p = context->lws_lookup;
  115. /* find an empty slot */
  116. while (p != done && *p)
  117. p++;
  118. if (p == done) {
  119. lwsl_err("%s: reached max fds\n", __func__);
  120. return 1;
  121. }
  122. *p = wsi;
  123. return 0;
  124. }
  125. void
  126. delete_from_fd(const struct lws_context *context, int fd)
  127. {
  128. struct lws **p, **done;
  129. if (!context->max_fds_unrelated_to_ulimit) {
  130. context->lws_lookup[fd - lws_plat_socket_offset()] = NULL;
  131. return;
  132. }
  133. /* slow fds handling */
  134. p = context->lws_lookup;
  135. done = &p[context->max_fds];
  136. /* find the match */
  137. while (p != done && (!*p || (*p)->desc.sockfd != fd))
  138. p++;
  139. if (p == done)
  140. lwsl_debug("%s: fd %d not found\n", __func__, fd);
  141. else
  142. *p = NULL;
  143. #if defined(_DEBUG)
  144. p = context->lws_lookup;
  145. while (p != done && (!*p || (*p)->desc.sockfd != fd))
  146. p++;
  147. if (p != done) {
  148. lwsl_err("%s: fd %d in lws_lookup again at %d\n", __func__,
  149. fd, (int)(p - context->lws_lookup));
  150. assert(0);
  151. }
  152. #endif
  153. }
  154. void
  155. delete_from_fdwsi(const struct lws_context *context, struct lws *wsi)
  156. {
  157. struct lws **p, **done;
  158. if (!context->max_fds_unrelated_to_ulimit)
  159. return;
  160. /* slow fds handling */
  161. p = context->lws_lookup;
  162. done = &p[context->max_fds];
  163. /* find the match */
  164. while (p != done && (!*p || (*p) != wsi))
  165. p++;
  166. if (p != done)
  167. *p = NULL;
  168. }
  169. void
  170. lws_plat_insert_socket_into_fds(struct lws_context *context, struct lws *wsi)
  171. {
  172. struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
  173. if (context->event_loop_ops->io)
  174. context->event_loop_ops->io(wsi, LWS_EV_START | LWS_EV_READ);
  175. pt->fds[pt->fds_count++].revents = 0;
  176. }
  177. void
  178. lws_plat_delete_socket_from_fds(struct lws_context *context,
  179. struct lws *wsi, int m)
  180. {
  181. struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
  182. if (context->event_loop_ops->io)
  183. context->event_loop_ops->io(wsi,
  184. LWS_EV_STOP | LWS_EV_READ | LWS_EV_WRITE);
  185. pt->fds_count--;
  186. }
  187. int
  188. lws_plat_change_pollfd(struct lws_context *context,
  189. struct lws *wsi, struct lws_pollfd *pfd)
  190. {
  191. return 0;
  192. }