libevent.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  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. #include "private-lib-event-libs-libevent.h"
  26. #define pt_to_priv_event(_pt) ((struct lws_pt_eventlibs_libevent *)(_pt)->evlib_pt)
  27. #define wsi_to_priv_event(_w) ((struct lws_wsi_eventlibs_libevent *)(_w)->evlib_wsi)
  28. static void
  29. lws_event_hrtimer_cb(int fd, short event, void *p)
  30. {
  31. struct lws_context_per_thread *pt = (struct lws_context_per_thread *)p;
  32. struct lws_pt_eventlibs_libevent *ptpr = pt_to_priv_event(pt);
  33. struct timeval tv;
  34. lws_usec_t us;
  35. lws_pt_lock(pt, __func__);
  36. us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS,
  37. lws_now_usecs());
  38. if (us) {
  39. tv.tv_sec = us / LWS_US_PER_SEC;
  40. tv.tv_usec = us - (tv.tv_sec * LWS_US_PER_SEC);
  41. evtimer_add(ptpr->hrtimer, &tv);
  42. }
  43. lws_pt_unlock(pt);
  44. }
  45. static void
  46. lws_event_idle_timer_cb(int fd, short event, void *p)
  47. {
  48. struct lws_context_per_thread *pt = (struct lws_context_per_thread *)p;
  49. struct lws_pt_eventlibs_libevent *ptpr = pt_to_priv_event(pt);
  50. struct timeval tv;
  51. lws_usec_t us;
  52. if (pt->is_destroyed)
  53. return;
  54. lws_service_do_ripe_rxflow(pt);
  55. /*
  56. * is there anybody with pending stuff that needs service forcing?
  57. */
  58. if (!lws_service_adjust_timeout(pt->context, 1, pt->tid)) {
  59. /* -1 timeout means just do forced service */
  60. _lws_plat_service_forced_tsi(pt->context, pt->tid);
  61. /* still somebody left who wants forced service? */
  62. if (!lws_service_adjust_timeout(pt->context, 1, pt->tid)) {
  63. /* yes... come back again later */
  64. tv.tv_sec = 0;
  65. tv.tv_usec = 1000;
  66. evtimer_add(ptpr->idle_timer, &tv);
  67. return;
  68. }
  69. }
  70. lwsl_debug("%s: wait\n", __func__);
  71. /* account for hrtimer */
  72. lws_pt_lock(pt, __func__);
  73. us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS,
  74. lws_now_usecs());
  75. if (us) {
  76. tv.tv_sec = us / LWS_US_PER_SEC;
  77. tv.tv_usec = us - (tv.tv_sec * LWS_US_PER_SEC);
  78. evtimer_add(ptpr->hrtimer, &tv);
  79. }
  80. lws_pt_unlock(pt);
  81. if (pt->destroy_self)
  82. lws_context_destroy(pt->context);
  83. }
  84. static void
  85. lws_event_cb(evutil_socket_t sock_fd, short revents, void *ctx)
  86. {
  87. struct lws_signal_watcher_libevent *lws_io =
  88. (struct lws_signal_watcher_libevent *)ctx;
  89. struct lws_context *context = lws_io->context;
  90. struct lws_context_per_thread *pt;
  91. struct lws_pollfd eventfd;
  92. struct timeval tv;
  93. struct lws *wsi;
  94. if (revents & EV_TIMEOUT)
  95. return;
  96. /* !!! EV_CLOSED doesn't exist in libevent2 */
  97. #if LIBEVENT_VERSION_NUMBER < 0x02000000
  98. if (revents & EV_CLOSED) {
  99. event_del(lws_io->event.watcher);
  100. event_free(lws_io->event.watcher);
  101. return;
  102. }
  103. #endif
  104. eventfd.fd = sock_fd;
  105. eventfd.events = 0;
  106. eventfd.revents = 0;
  107. if (revents & EV_READ) {
  108. eventfd.events |= LWS_POLLIN;
  109. eventfd.revents |= LWS_POLLIN;
  110. }
  111. if (revents & EV_WRITE) {
  112. eventfd.events |= LWS_POLLOUT;
  113. eventfd.revents |= LWS_POLLOUT;
  114. }
  115. wsi = wsi_from_fd(context, sock_fd);
  116. if (!wsi)
  117. return;
  118. pt = &context->pt[(int)wsi->tsi];
  119. if (pt->is_destroyed)
  120. return;
  121. lws_service_fd_tsi(context, &eventfd, wsi->tsi);
  122. if (pt->destroy_self) {
  123. lwsl_notice("%s: pt destroy self coming true\n", __func__);
  124. lws_context_destroy(pt->context);
  125. return;
  126. }
  127. /* set the idle timer for 1ms ahead */
  128. tv.tv_sec = 0;
  129. tv.tv_usec = 1000;
  130. evtimer_add(pt_to_priv_event(pt)->idle_timer, &tv);
  131. }
  132. void
  133. lws_event_sigint_cb(evutil_socket_t sock_fd, short revents, void *ctx)
  134. {
  135. struct lws_context_per_thread *pt = ctx;
  136. struct event *signal = (struct event *)ctx;
  137. if (pt->context->eventlib_signal_cb) {
  138. pt->context->eventlib_signal_cb((void *)(lws_intptr_t)sock_fd,
  139. event_get_signal(signal));
  140. return;
  141. }
  142. if (!pt->event_loop_foreign)
  143. event_base_loopbreak(pt_to_priv_event(pt)->io_loop);
  144. }
  145. static int
  146. elops_init_pt_event(struct lws_context *context, void *_loop, int tsi)
  147. {
  148. struct lws_vhost *vh = context->vhost_list;
  149. struct event_base *loop = (struct event_base *)_loop;
  150. struct lws_context_per_thread *pt = &context->pt[tsi];
  151. struct lws_pt_eventlibs_libevent *ptpr = pt_to_priv_event(pt);
  152. lwsl_info("%s: loop %p\n", __func__, _loop);
  153. if (!loop)
  154. loop = event_base_new();
  155. else
  156. context->pt[tsi].event_loop_foreign = 1;
  157. if (!loop) {
  158. lwsl_err("%s: creating event base failed\n", __func__);
  159. return -1;
  160. }
  161. ptpr->io_loop = loop;
  162. /*
  163. * Initialize all events with the listening sockets
  164. * and register a callback for read operations
  165. */
  166. while (vh) {
  167. if (vh->lserv_wsi) {
  168. struct lws_io_watcher_libevent *w_read =
  169. &(wsi_to_priv_event(vh->lserv_wsi)->w_read);
  170. w_read->context = context;
  171. w_read->watcher = event_new(
  172. loop, vh->lserv_wsi->desc.sockfd,
  173. (EV_READ | EV_PERSIST), lws_event_cb,
  174. w_read);
  175. event_add(w_read->watcher, NULL);
  176. w_read->set = 1;
  177. }
  178. vh = vh->vhost_next;
  179. }
  180. /* static event loop objects */
  181. ptpr->hrtimer = event_new(loop, -1, EV_PERSIST,
  182. lws_event_hrtimer_cb, pt);
  183. ptpr->idle_timer = event_new(loop, -1, 0,
  184. lws_event_idle_timer_cb, pt);
  185. /* Register the signal watcher unless it's a foreign loop */
  186. if (pt->event_loop_foreign)
  187. return 0;
  188. ptpr->w_sigint.watcher = evsignal_new(loop, SIGINT,
  189. lws_event_sigint_cb, pt);
  190. event_add(ptpr->w_sigint.watcher, NULL);
  191. return 0;
  192. }
  193. static int
  194. elops_init_context_event(struct lws_context *context,
  195. const struct lws_context_creation_info *info)
  196. {
  197. int n;
  198. context->eventlib_signal_cb = info->signal_cb;
  199. for (n = 0; n < context->count_threads; n++)
  200. pt_to_priv_event(&context->pt[n])->w_sigint.context = context;
  201. return 0;
  202. }
  203. static int
  204. elops_accept_event(struct lws *wsi)
  205. {
  206. struct lws_context *context = lws_get_context(wsi);
  207. struct lws_context_per_thread *pt;
  208. struct lws_pt_eventlibs_libevent *ptpr;
  209. struct lws_wsi_eventlibs_libevent *wpr = wsi_to_priv_event(wsi);
  210. int fd;
  211. wpr->w_read.context = context;
  212. wpr->w_write.context = context;
  213. // Initialize the event
  214. pt = &context->pt[(int)wsi->tsi];
  215. ptpr = pt_to_priv_event(pt);
  216. if (wsi->role_ops->file_handle)
  217. fd = wsi->desc.filefd;
  218. else
  219. fd = wsi->desc.sockfd;
  220. wpr->w_read.watcher = event_new(ptpr->io_loop, fd,
  221. (EV_READ | EV_PERSIST), lws_event_cb, &wpr->w_read);
  222. wpr->w_write.watcher = event_new(ptpr->io_loop, fd,
  223. (EV_WRITE | EV_PERSIST), lws_event_cb, &wpr->w_write);
  224. return 0;
  225. }
  226. static void
  227. elops_io_event(struct lws *wsi, int flags)
  228. {
  229. struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
  230. struct lws_pt_eventlibs_libevent *ptpr = pt_to_priv_event(pt);
  231. struct lws_wsi_eventlibs_libevent *wpr = wsi_to_priv_event(wsi);
  232. if (!ptpr->io_loop || wsi->a.context->being_destroyed ||
  233. pt->is_destroyed)
  234. return;
  235. assert((flags & (LWS_EV_START | LWS_EV_STOP)) &&
  236. (flags & (LWS_EV_READ | LWS_EV_WRITE)));
  237. if (flags & LWS_EV_START) {
  238. if ((flags & LWS_EV_WRITE) && !wpr->w_write.set) {
  239. event_add(wpr->w_write.watcher, NULL);
  240. wpr->w_write.set = 1;
  241. }
  242. if ((flags & LWS_EV_READ) && !wpr->w_read.set) {
  243. event_add(wpr->w_read.watcher, NULL);
  244. wpr->w_read.set = 1;
  245. }
  246. } else {
  247. if ((flags & LWS_EV_WRITE) && wpr->w_write.set) {
  248. event_del(wpr->w_write.watcher);
  249. wpr->w_write.set = 0;
  250. }
  251. if ((flags & LWS_EV_READ) && wpr->w_read.set) {
  252. event_del(wpr->w_read.watcher);
  253. wpr->w_read.set = 0;
  254. }
  255. }
  256. }
  257. static void
  258. elops_run_pt_event(struct lws_context *context, int tsi)
  259. {
  260. /* Run / Dispatch the event_base loop */
  261. if (pt_to_priv_event(&context->pt[tsi])->io_loop)
  262. event_base_dispatch(
  263. pt_to_priv_event(&context->pt[tsi])->io_loop);
  264. }
  265. static void
  266. elops_destroy_pt_event(struct lws_context *context, int tsi)
  267. {
  268. struct lws_context_per_thread *pt = &context->pt[tsi];
  269. struct lws_pt_eventlibs_libevent *ptpr = pt_to_priv_event(pt);
  270. struct lws_vhost *vh = context->vhost_list;
  271. lwsl_info("%s\n", __func__);
  272. if (!ptpr->io_loop)
  273. return;
  274. /*
  275. * Free all events with the listening sockets
  276. */
  277. while (vh) {
  278. if (vh->lserv_wsi) {
  279. struct lws_wsi_eventlibs_libevent *w =
  280. wsi_to_priv_event(vh->lserv_wsi);
  281. event_free(w->w_read.watcher);
  282. w->w_read.watcher = NULL;
  283. event_free(w->w_write.watcher);
  284. w->w_write.watcher = NULL;
  285. }
  286. vh = vh->vhost_next;
  287. }
  288. event_free(ptpr->hrtimer);
  289. event_free(ptpr->idle_timer);
  290. if (!pt->event_loop_foreign) {
  291. event_del(ptpr->w_sigint.watcher);
  292. event_free(ptpr->w_sigint.watcher);
  293. event_base_loopexit(ptpr->io_loop, NULL);
  294. // event_base_free(pt->event.io_loop);
  295. // pt->event.io_loop = NULL;
  296. lwsl_notice("%s: set to exit loop\n", __func__);
  297. }
  298. }
  299. static void
  300. elops_destroy_wsi_event(struct lws *wsi)
  301. {
  302. struct lws_context_per_thread *pt;
  303. struct lws_wsi_eventlibs_libevent *w;
  304. if (!wsi)
  305. return;
  306. pt = &wsi->a.context->pt[(int)wsi->tsi];
  307. if (pt->is_destroyed)
  308. return;
  309. w = wsi_to_priv_event(wsi);
  310. if (w->w_read.watcher) {
  311. event_free(w->w_read.watcher);
  312. w->w_read.watcher = NULL;
  313. }
  314. if (w->w_write.watcher) {
  315. event_free(w->w_write.watcher);
  316. w->w_write.watcher = NULL;
  317. }
  318. }
  319. static int
  320. elops_wsi_logical_close_event(struct lws *wsi)
  321. {
  322. elops_destroy_wsi_event(wsi);
  323. return 0;
  324. }
  325. static int
  326. elops_init_vhost_listen_wsi_event(struct lws *wsi)
  327. {
  328. struct lws_context_per_thread *pt;
  329. struct lws_pt_eventlibs_libevent *ptpr;
  330. struct lws_wsi_eventlibs_libevent *w;
  331. int fd;
  332. if (!wsi) {
  333. assert(0);
  334. return 0;
  335. }
  336. w = wsi_to_priv_event(wsi);
  337. w->w_read.context = wsi->a.context;
  338. w->w_write.context = wsi->a.context;
  339. pt = &wsi->a.context->pt[(int)wsi->tsi];
  340. ptpr = pt_to_priv_event(pt);
  341. if (wsi->role_ops->file_handle)
  342. fd = wsi->desc.filefd;
  343. else
  344. fd = wsi->desc.sockfd;
  345. w->w_read.watcher = event_new(ptpr->io_loop, fd, (EV_READ | EV_PERSIST),
  346. lws_event_cb, &w->w_read);
  347. w->w_write.watcher = event_new(ptpr->io_loop, fd,
  348. (EV_WRITE | EV_PERSIST),
  349. lws_event_cb, &w->w_write);
  350. elops_io_event(wsi, LWS_EV_START | LWS_EV_READ);
  351. return 0;
  352. }
  353. static int
  354. elops_destroy_context2_event(struct lws_context *context)
  355. {
  356. struct lws_context_per_thread *pt;
  357. struct lws_pt_eventlibs_libevent *ptpr;
  358. int n, m;
  359. lwsl_debug("%s: in\n", __func__);
  360. for (n = 0; n < context->count_threads; n++) {
  361. int budget = 1000;
  362. pt = &context->pt[n];
  363. ptpr = pt_to_priv_event(pt);
  364. /* only for internal loops... */
  365. if (pt->event_loop_foreign || !ptpr->io_loop)
  366. continue;
  367. if (!context->finalize_destroy_after_internal_loops_stopped) {
  368. event_base_loopexit(ptpr->io_loop, NULL);
  369. continue;
  370. }
  371. while (budget-- &&
  372. (m = event_base_loop(ptpr->io_loop, EVLOOP_NONBLOCK)))
  373. ;
  374. #if 0
  375. if (m) {
  376. lwsl_err("%s: tsi %d: NOT everything closed\n",
  377. __func__, n);
  378. event_base_dump_events(ptpr->io_loop, stderr);
  379. } else
  380. lwsl_debug("%s: %d: everything closed OK\n", __func__, n);
  381. #endif
  382. lwsl_err("%s: event_base_free\n", __func__);
  383. event_base_free(ptpr->io_loop);
  384. ptpr->io_loop = NULL;
  385. }
  386. lwsl_debug("%s: out\n", __func__);
  387. return 0;
  388. }
  389. static const struct lws_event_loop_ops event_loop_ops_event = {
  390. /* name */ "libevent",
  391. /* init_context */ elops_init_context_event,
  392. /* destroy_context1 */ NULL,
  393. /* destroy_context2 */ elops_destroy_context2_event,
  394. /* init_vhost_listen_wsi */ elops_init_vhost_listen_wsi_event,
  395. /* init_pt */ elops_init_pt_event,
  396. /* wsi_logical_close */ elops_wsi_logical_close_event,
  397. /* check_client_connect_ok */ NULL,
  398. /* close_handle_manually */ NULL,
  399. /* accept */ elops_accept_event,
  400. /* io */ elops_io_event,
  401. /* run_pt */ elops_run_pt_event,
  402. /* destroy_pt */ elops_destroy_pt_event,
  403. /* destroy wsi */ elops_destroy_wsi_event,
  404. /* flags */ 0,
  405. /* evlib_size_ctx */ 0,
  406. /* evlib_size_pt */ sizeof(struct lws_pt_eventlibs_libevent),
  407. /* evlib_size_vh */ 0,
  408. /* evlib_size_wsi */ sizeof(struct lws_wsi_eventlibs_libevent),
  409. };
  410. #if defined(LWS_WITH_EVLIB_PLUGINS)
  411. LWS_VISIBLE
  412. #endif
  413. const lws_plugin_evlib_t evlib_event = {
  414. .hdr = {
  415. "libevent event loop",
  416. "lws_evlib_plugin",
  417. LWS_PLUGIN_API_MAGIC
  418. },
  419. .ops = &event_loop_ops_event
  420. };