libev.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /*
  2. * libwebsockets - small server side websockets and web server implementation
  3. *
  4. * Copyright (C) 2010-2014 Andy Green <andy@warmcat.com>
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation:
  9. * version 2.1 of the License.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  19. * MA 02110-1301 USA
  20. */
  21. #include "private-libwebsockets.h"
  22. void lws_feature_status_libev(struct lws_context_creation_info *info)
  23. {
  24. if (lws_check_opt(info->options, LWS_SERVER_OPTION_LIBEV))
  25. lwsl_notice("libev support compiled in and enabled\n");
  26. else
  27. lwsl_notice("libev support compiled in but disabled\n");
  28. }
  29. static void
  30. lws_accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
  31. {
  32. struct lws_io_watcher *lws_io = lws_container_of(watcher,
  33. struct lws_io_watcher, ev_watcher);
  34. struct lws_context *context = lws_io->context;
  35. struct lws_pollfd eventfd;
  36. if (revents & EV_ERROR)
  37. return;
  38. eventfd.fd = watcher->fd;
  39. eventfd.events = 0;
  40. eventfd.revents = EV_NONE;
  41. if (revents & EV_READ) {
  42. eventfd.events |= LWS_POLLIN;
  43. eventfd.revents |= LWS_POLLIN;
  44. }
  45. if (revents & EV_WRITE) {
  46. eventfd.events |= LWS_POLLOUT;
  47. eventfd.revents |= LWS_POLLOUT;
  48. }
  49. lws_service_fd(context, &eventfd);
  50. }
  51. LWS_VISIBLE void
  52. lws_ev_sigint_cb(struct ev_loop *loop, struct ev_signal *watcher, int revents)
  53. {
  54. ev_break(loop, EVBREAK_ALL);
  55. }
  56. LWS_VISIBLE int
  57. lws_ev_sigint_cfg(struct lws_context *context, int use_ev_sigint,
  58. lws_ev_signal_cb_t *cb)
  59. {
  60. context->use_ev_sigint = use_ev_sigint;
  61. if (cb)
  62. context->lws_ev_sigint_cb = cb;
  63. else
  64. context->lws_ev_sigint_cb = &lws_ev_sigint_cb;
  65. return 0;
  66. }
  67. LWS_VISIBLE int
  68. lws_ev_initloop(struct lws_context *context, struct ev_loop *loop, int tsi)
  69. {
  70. struct ev_signal *w_sigint = &context->pt[tsi].w_sigint.ev_watcher;
  71. struct ev_io *w_accept = &context->pt[tsi].w_accept.ev_watcher;
  72. struct lws_vhost *vh = context->vhost_list;
  73. const char * backend_name;
  74. int status = 0;
  75. int backend;
  76. if (!loop)
  77. loop = ev_loop_new(0);
  78. else
  79. context->pt[tsi].ev_loop_foreign = 1;
  80. context->pt[tsi].io_loop_ev = loop;
  81. /*
  82. * Initialize the accept w_accept with all the listening sockets
  83. * and register a callback for read operations
  84. */
  85. while (vh) {
  86. if (vh->lserv_wsi) {
  87. vh->lserv_wsi->w_read.context = context;
  88. ev_io_init(w_accept, lws_accept_cb, vh->lserv_wsi->desc.sockfd,
  89. EV_READ);
  90. }
  91. vh = vh->vhost_next;
  92. }
  93. ev_io_start(context->pt[tsi].io_loop_ev, w_accept);
  94. /* Register the signal watcher unless the user says not to */
  95. if (context->use_ev_sigint) {
  96. ev_signal_init(w_sigint, context->lws_ev_sigint_cb, SIGINT);
  97. ev_signal_start(context->pt[tsi].io_loop_ev, w_sigint);
  98. }
  99. backend = ev_backend(loop);
  100. switch (backend) {
  101. case EVBACKEND_SELECT:
  102. backend_name = "select";
  103. break;
  104. case EVBACKEND_POLL:
  105. backend_name = "poll";
  106. break;
  107. case EVBACKEND_EPOLL:
  108. backend_name = "epoll";
  109. break;
  110. case EVBACKEND_KQUEUE:
  111. backend_name = "kqueue";
  112. break;
  113. case EVBACKEND_DEVPOLL:
  114. backend_name = "/dev/poll";
  115. break;
  116. case EVBACKEND_PORT:
  117. backend_name = "Solaris 10 \"port\"";
  118. break;
  119. default:
  120. backend_name = "Unknown libev backend";
  121. break;
  122. }
  123. lwsl_notice(" libev backend: %s\n", backend_name);
  124. return status;
  125. }
  126. void
  127. lws_libev_destroyloop(struct lws_context *context, int tsi)
  128. {
  129. struct lws_context_per_thread *pt = &context->pt[tsi];
  130. if (!lws_check_opt(context->options, LWS_SERVER_OPTION_LIBEV))
  131. return;
  132. if (!pt->io_loop_ev)
  133. return;
  134. ev_io_stop(pt->io_loop_ev, &pt->w_accept.ev_watcher);
  135. if (context->use_ev_sigint)
  136. ev_signal_stop(pt->io_loop_ev,
  137. &pt->w_sigint.ev_watcher);
  138. if (!pt->ev_loop_foreign)
  139. ev_loop_destroy(pt->io_loop_ev);
  140. }
  141. LWS_VISIBLE void
  142. lws_libev_accept(struct lws *new_wsi, lws_sock_file_fd_type desc)
  143. {
  144. struct lws_context *context = lws_get_context(new_wsi);
  145. struct ev_io *r = &new_wsi->w_read.ev_watcher;
  146. struct ev_io *w = &new_wsi->w_write.ev_watcher;
  147. int fd;
  148. if (!LWS_LIBEV_ENABLED(context))
  149. return;
  150. if (new_wsi->mode == LWSCM_RAW_FILEDESC)
  151. fd = desc.filefd;
  152. else
  153. fd = desc.sockfd;
  154. new_wsi->w_read.context = context;
  155. new_wsi->w_write.context = context;
  156. ev_io_init(r, lws_accept_cb, fd, EV_READ);
  157. ev_io_init(w, lws_accept_cb, fd, EV_WRITE);
  158. }
  159. LWS_VISIBLE void
  160. lws_libev_io(struct lws *wsi, int flags)
  161. {
  162. struct lws_context *context = lws_get_context(wsi);
  163. struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
  164. if (!LWS_LIBEV_ENABLED(context))
  165. return;
  166. if (!pt->io_loop_ev)
  167. return;
  168. assert((flags & (LWS_EV_START | LWS_EV_STOP)) &&
  169. (flags & (LWS_EV_READ | LWS_EV_WRITE)));
  170. if (flags & LWS_EV_START) {
  171. if (flags & LWS_EV_WRITE)
  172. ev_io_start(pt->io_loop_ev, &wsi->w_write.ev_watcher);
  173. if (flags & LWS_EV_READ)
  174. ev_io_start(pt->io_loop_ev, &wsi->w_read.ev_watcher);
  175. } else {
  176. if (flags & LWS_EV_WRITE)
  177. ev_io_stop(pt->io_loop_ev, &wsi->w_write.ev_watcher);
  178. if (flags & LWS_EV_READ)
  179. ev_io_stop(pt->io_loop_ev, &wsi->w_read.ev_watcher);
  180. }
  181. }
  182. LWS_VISIBLE int
  183. lws_libev_init_fd_table(struct lws_context *context)
  184. {
  185. int n;
  186. if (!LWS_LIBEV_ENABLED(context))
  187. return 0;
  188. for (n = 0; n < context->count_threads; n++) {
  189. context->pt[n].w_accept.context = context;
  190. context->pt[n].w_sigint.context = context;
  191. }
  192. return 1;
  193. }
  194. LWS_VISIBLE void
  195. lws_libev_run(const struct lws_context *context, int tsi)
  196. {
  197. if (context->pt[tsi].io_loop_ev && LWS_LIBEV_ENABLED(context))
  198. ev_run(context->pt[tsi].io_loop_ev, 0);
  199. }