libev.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. /*
  2. * libwebsockets - small server side websockets and web server implementation
  3. *
  4. * Copyright (C) 2010 - 2020 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. #include "private-lib-event-libs-libev.h"
  26. #define pt_to_priv_ev(_pt) ((struct lws_pt_eventlibs_libev *)(_pt)->evlib_pt)
  27. #define vh_to_priv_ev(_vh) ((struct lws_vh_eventlibs_libev *)(_vh)->evlib_vh)
  28. #define wsi_to_priv_ev(_w) ((struct lws_wsi_eventlibs_libev *)(_w)->evlib_wsi)
  29. static void
  30. lws_ev_hrtimer_cb(struct ev_loop *loop, struct ev_timer *watcher, int revents)
  31. {
  32. struct lws_pt_eventlibs_libev *ptpr = lws_container_of(watcher,
  33. struct lws_pt_eventlibs_libev, hrtimer);
  34. struct lws_context_per_thread *pt = ptpr->pt;
  35. lws_usec_t us;
  36. lws_pt_lock(pt, __func__);
  37. us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS,
  38. lws_now_usecs());
  39. if (us) {
  40. ev_timer_set(&ptpr->hrtimer, ((float)us) / 1000000.0, 0);
  41. ev_timer_start(ptpr->io_loop, &ptpr->hrtimer);
  42. }
  43. lws_pt_unlock(pt);
  44. }
  45. static void
  46. lws_ev_idle_cb(struct ev_loop *loop, struct ev_idle *handle, int revents)
  47. {
  48. struct lws_pt_eventlibs_libev *ptpr = lws_container_of(handle,
  49. struct lws_pt_eventlibs_libev, idle);
  50. struct lws_context_per_thread *pt = ptpr->pt;
  51. int reschedule = 0;
  52. lws_usec_t us;
  53. lws_service_do_ripe_rxflow(pt);
  54. /*
  55. * is there anybody with pending stuff that needs service forcing?
  56. */
  57. if (!lws_service_adjust_timeout(pt->context, 1, pt->tid))
  58. /* -1 timeout means just do forced service */
  59. reschedule = _lws_plat_service_forced_tsi(pt->context, pt->tid);
  60. /* account for hrtimer */
  61. lws_pt_lock(pt, __func__);
  62. us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS,
  63. lws_now_usecs());
  64. if (us) {
  65. ev_timer_set(&ptpr->hrtimer, ((float)us) / 1000000.0, 0);
  66. ev_timer_start(ptpr->io_loop, &ptpr->hrtimer);
  67. }
  68. lws_pt_unlock(pt);
  69. /* there is nobody who needs service forcing, shut down idle */
  70. if (!reschedule)
  71. ev_idle_stop(loop, handle);
  72. if (pt->destroy_self)
  73. lws_context_destroy(pt->context);
  74. }
  75. static void
  76. lws_accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
  77. {
  78. struct lws_io_watcher_libev *lws_io = lws_container_of(watcher,
  79. struct lws_io_watcher_libev, watcher);
  80. struct lws_context *context = lws_io->context;
  81. struct lws_pt_eventlibs_libev *ptpr;
  82. struct lws_context_per_thread *pt;
  83. struct lws_pollfd eventfd;
  84. struct lws *wsi;
  85. if (revents & EV_ERROR)
  86. return;
  87. eventfd.fd = watcher->fd;
  88. eventfd.events = 0;
  89. eventfd.revents = EV_NONE;
  90. if (revents & EV_READ) {
  91. eventfd.events |= LWS_POLLIN;
  92. eventfd.revents |= LWS_POLLIN;
  93. }
  94. if (revents & EV_WRITE) {
  95. eventfd.events |= LWS_POLLOUT;
  96. eventfd.revents |= LWS_POLLOUT;
  97. }
  98. wsi = wsi_from_fd(context, watcher->fd);
  99. pt = &context->pt[(int)wsi->tsi];
  100. ptpr = pt_to_priv_ev(pt);
  101. lws_service_fd_tsi(context, &eventfd, (int)wsi->tsi);
  102. ev_idle_start(ptpr->io_loop, &ptpr->idle);
  103. }
  104. void
  105. lws_ev_sigint_cb(struct ev_loop *loop, struct ev_signal *watcher, int revents)
  106. {
  107. struct lws_context *context = watcher->data;
  108. if (context->eventlib_signal_cb) {
  109. context->eventlib_signal_cb((void *)watcher, watcher->signum);
  110. return;
  111. }
  112. ev_break(loop, EVBREAK_ALL);
  113. }
  114. static int
  115. elops_init_pt_ev(struct lws_context *context, void *_loop, int tsi)
  116. {
  117. struct lws_context_per_thread *pt = &context->pt[tsi];
  118. struct lws_pt_eventlibs_libev *ptpr = pt_to_priv_ev(pt);
  119. struct ev_signal *w_sigint = &ptpr->w_sigint.watcher;
  120. struct ev_loop *loop = (struct ev_loop *)_loop;
  121. struct lws_vhost *vh = context->vhost_list;
  122. const char *backend_name;
  123. int status = 0;
  124. int backend;
  125. lwsl_info("%s: loop %p\n", __func__, _loop);
  126. ptpr->pt = pt;
  127. if (!loop)
  128. loop = ev_loop_new(0);
  129. else
  130. context->pt[tsi].event_loop_foreign = 1;
  131. if (!loop) {
  132. lwsl_err("%s: creating event base failed\n", __func__);
  133. return -1;
  134. }
  135. ptpr->io_loop = loop;
  136. /*
  137. * Initialize the accept w_accept with all the listening sockets
  138. * and register a callback for read operations
  139. */
  140. while (vh) {
  141. if (vh->lserv_wsi) {
  142. struct lws_wsi_eventlibs_libev *w =
  143. wsi_to_priv_ev(vh->lserv_wsi);
  144. w->w_read.context = context;
  145. w->w_write.context = context;
  146. vh_to_priv_ev(vh)->w_accept.context = context;
  147. ev_io_init(&vh_to_priv_ev(vh)->w_accept.watcher,
  148. lws_accept_cb,
  149. vh->lserv_wsi->desc.sockfd, EV_READ);
  150. ev_io_start(loop, &vh_to_priv_ev(vh)->w_accept.watcher);
  151. }
  152. vh = vh->vhost_next;
  153. }
  154. /* Register the signal watcher unless it's a foreign loop */
  155. if (!context->pt[tsi].event_loop_foreign) {
  156. ev_signal_init(w_sigint, lws_ev_sigint_cb, SIGINT);
  157. w_sigint->data = context;
  158. ev_signal_start(loop, w_sigint);
  159. }
  160. backend = ev_backend(loop);
  161. switch (backend) {
  162. case EVBACKEND_SELECT:
  163. backend_name = "select";
  164. break;
  165. case EVBACKEND_POLL:
  166. backend_name = "poll";
  167. break;
  168. case EVBACKEND_EPOLL:
  169. backend_name = "epoll";
  170. break;
  171. #if defined(LWS_HAVE_EVBACKEND_LINUXAIO)
  172. case EVBACKEND_LINUXAIO:
  173. backend_name = "Linux AIO";
  174. break;
  175. #endif
  176. #if defined(LWS_HAVE_EVBACKEND_IOURING)
  177. case EVBACKEND_IOURING:
  178. backend_name = "Linux io_uring";
  179. break;
  180. #endif
  181. case EVBACKEND_KQUEUE:
  182. backend_name = "kqueue";
  183. break;
  184. case EVBACKEND_DEVPOLL:
  185. backend_name = "/dev/poll";
  186. break;
  187. case EVBACKEND_PORT:
  188. backend_name = "Solaris 10 \"port\"";
  189. break;
  190. default:
  191. backend_name = "Unknown libev backend";
  192. break;
  193. }
  194. lwsl_info(" libev backend: %s\n", backend_name);
  195. (void)backend_name;
  196. ev_timer_init(&ptpr->hrtimer, lws_ev_hrtimer_cb, 0, 0);
  197. ptpr->hrtimer.data = pt;
  198. ev_idle_init(&ptpr->idle, lws_ev_idle_cb);
  199. return status;
  200. }
  201. static void
  202. elops_destroy_pt_ev(struct lws_context *context, int tsi)
  203. {
  204. struct lws_context_per_thread *pt = &context->pt[tsi];
  205. struct lws_pt_eventlibs_libev *ptpr = pt_to_priv_ev(pt);
  206. struct lws_vhost *vh = context->vhost_list;
  207. while (vh) {
  208. if (vh->lserv_wsi)
  209. ev_io_stop(ptpr->io_loop,
  210. &vh_to_priv_ev(vh)->w_accept.watcher);
  211. vh = vh->vhost_next;
  212. }
  213. /* static assets */
  214. ev_timer_stop(ptpr->io_loop, &ptpr->hrtimer);
  215. ev_idle_stop(ptpr->io_loop, &ptpr->idle);
  216. if (!pt->event_loop_foreign)
  217. ev_signal_stop(ptpr->io_loop, &ptpr->w_sigint.watcher);
  218. }
  219. static int
  220. elops_init_context_ev(struct lws_context *context,
  221. const struct lws_context_creation_info *info)
  222. {
  223. int n;
  224. context->eventlib_signal_cb = info->signal_cb;
  225. for (n = 0; n < context->count_threads; n++)
  226. pt_to_priv_ev(&context->pt[n])->w_sigint.context = context;
  227. return 0;
  228. }
  229. static int
  230. elops_accept_ev(struct lws *wsi)
  231. {
  232. struct lws_wsi_eventlibs_libev *w = wsi_to_priv_ev(wsi);
  233. int fd;
  234. lwsl_notice("%s\n", __func__);
  235. if (wsi->role_ops->file_handle)
  236. fd = wsi->desc.filefd;
  237. else
  238. fd = wsi->desc.sockfd;
  239. w->w_read.context = wsi->a.context;
  240. w->w_write.context = wsi->a.context;
  241. ev_io_init(&w->w_read.watcher, lws_accept_cb, fd, EV_READ);
  242. ev_io_init(&w->w_write.watcher, lws_accept_cb, fd, EV_WRITE);
  243. return 0;
  244. }
  245. static void
  246. elops_io_ev(struct lws *wsi, int flags)
  247. {
  248. struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
  249. struct lws_pt_eventlibs_libev *ptpr = pt_to_priv_ev(pt);
  250. struct lws_wsi_eventlibs_libev *w = wsi_to_priv_ev(wsi);
  251. lwsl_notice("%s: wsi %p %s flags 0x%x %p %d\n", __func__,
  252. wsi, wsi->role_ops->name, flags,
  253. ptpr->io_loop, pt->is_destroyed);
  254. if (!ptpr->io_loop || pt->is_destroyed)
  255. return;
  256. assert((flags & (LWS_EV_START | LWS_EV_STOP)) &&
  257. (flags & (LWS_EV_READ | LWS_EV_WRITE)));
  258. if (flags & LWS_EV_START) {
  259. if (flags & LWS_EV_WRITE)
  260. ev_io_start(ptpr->io_loop, &w->w_write.watcher);
  261. if (flags & LWS_EV_READ)
  262. ev_io_start(ptpr->io_loop, &w->w_read.watcher);
  263. } else {
  264. if (flags & LWS_EV_WRITE)
  265. ev_io_stop(ptpr->io_loop, &w->w_write.watcher);
  266. if (flags & LWS_EV_READ)
  267. ev_io_stop(ptpr->io_loop, &w->w_read.watcher);
  268. }
  269. if (pt->destroy_self)
  270. lws_context_destroy(pt->context);
  271. }
  272. static void
  273. elops_run_pt_ev(struct lws_context *context, int tsi)
  274. {
  275. if (pt_to_priv_ev(&context->pt[tsi])->io_loop)
  276. ev_run(pt_to_priv_ev(&context->pt[tsi])->io_loop, 0);
  277. }
  278. static int
  279. elops_destroy_context2_ev(struct lws_context *context)
  280. {
  281. struct lws_context_per_thread *pt;
  282. struct lws_pt_eventlibs_libev *ptpr;
  283. int n, m;
  284. lwsl_debug("%s\n", __func__);
  285. for (n = 0; n < context->count_threads; n++) {
  286. int budget = 1000;
  287. pt = &context->pt[n];
  288. ptpr = pt_to_priv_ev(pt);
  289. /* only for internal loops... */
  290. if (pt->event_loop_foreign || !ptpr->io_loop)
  291. continue;
  292. if (!context->finalize_destroy_after_internal_loops_stopped) {
  293. ev_break(ptpr->io_loop, EVBREAK_ONE);
  294. continue;
  295. }
  296. while (budget-- &&
  297. (m = ev_run(ptpr->io_loop, 0)))
  298. ;
  299. ev_loop_destroy(ptpr->io_loop);
  300. }
  301. return 0;
  302. }
  303. static int
  304. elops_init_vhost_listen_wsi_ev(struct lws *wsi)
  305. {
  306. struct lws_wsi_eventlibs_libev *w;
  307. int fd;
  308. if (!wsi) {
  309. assert(0);
  310. return 0;
  311. }
  312. w = wsi_to_priv_ev(wsi);
  313. w->w_read.context = wsi->a.context;
  314. w->w_write.context = wsi->a.context;
  315. if (wsi->role_ops->file_handle)
  316. fd = wsi->desc.filefd;
  317. else
  318. fd = wsi->desc.sockfd;
  319. ev_io_init(&w->w_read.watcher, lws_accept_cb, fd, EV_READ);
  320. //ev_io_init(&w->w_write.watcher, lws_accept_cb, fd, EV_WRITE);
  321. elops_io_ev(wsi, LWS_EV_START | LWS_EV_READ);
  322. return 0;
  323. }
  324. static void
  325. elops_destroy_wsi_ev(struct lws *wsi)
  326. {
  327. struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
  328. struct lws_pt_eventlibs_libev *ptpr = pt_to_priv_ev(pt);
  329. struct lws_wsi_eventlibs_libev *w = wsi_to_priv_ev(wsi);
  330. ev_io_stop(ptpr->io_loop, &w->w_read.watcher);
  331. ev_io_stop(ptpr->io_loop, &w->w_write.watcher);
  332. }
  333. static const struct lws_event_loop_ops event_loop_ops_ev = {
  334. /* name */ "libev",
  335. /* init_context */ elops_init_context_ev,
  336. /* destroy_context1 */ NULL,
  337. /* destroy_context2 */ elops_destroy_context2_ev,
  338. /* init_vhost_listen_wsi */ elops_init_vhost_listen_wsi_ev,
  339. /* init_pt */ elops_init_pt_ev,
  340. /* wsi_logical_close */ NULL,
  341. /* check_client_connect_ok */ NULL,
  342. /* close_handle_manually */ NULL,
  343. /* accept */ elops_accept_ev,
  344. /* io */ elops_io_ev,
  345. /* run_pt */ elops_run_pt_ev,
  346. /* destroy_pt */ elops_destroy_pt_ev,
  347. /* destroy wsi */ elops_destroy_wsi_ev,
  348. /* flags */ 0,
  349. /* evlib_size_ctx */ 0,
  350. /* evlib_size_pt */ sizeof(struct lws_pt_eventlibs_libev),
  351. /* evlib_size_vh */ sizeof(struct lws_vh_eventlibs_libev),
  352. /* evlib_size_wsi */ sizeof(struct lws_wsi_eventlibs_libev),
  353. };
  354. #if defined(LWS_WITH_EVLIB_PLUGINS)
  355. LWS_VISIBLE
  356. #endif
  357. const lws_plugin_evlib_t evlib_ev = {
  358. .hdr = {
  359. "libev event loop",
  360. "lws_evlib_plugin",
  361. LWS_PLUGIN_API_MAGIC
  362. },
  363. .ops = &event_loop_ops_ev
  364. };