Project homepage Mailing List  Warmcat.com  API Docs  Github Mirror 
{"schema":"libjg2-1", "vpath":"/git/", "avatar":"/git/avatar/", "alang":"en-US,en;q\u003d0.5", "gen_ut":1638758803, "reponame":"libwebsockets", "desc":"libwebsockets lightweight C networking library", "owner": { "name": "Andy Green", "email": "andy@warmcat.com", "md5": "c50933ca2aa61e0fe2c43d46bb6b59cb" },"url":"https://libwebsockets.org/repo/libwebsockets", "f":3, "items": [ {"schema":"libjg2-1", "cid":"6f7989afd61d515cc4521caffeda7361", "oid":{ "oid": "e1a73c42096a9f94617a25440501d7adc4abbd9f", "alias": [ "refs/heads/main"]},"blobname": "lib/event-libs/libevent/libevent.c", "blob": "/*\n * libwebsockets - small server side websockets and web server implementation\n *\n * Copyright (C) 2010 - 2019 Andy Green \u003candy@warmcat.com\u003e\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \u0022Software\u0022), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \u0022AS IS\u0022, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n#include \u0022private-lib-core.h\u0022\n#include \u0022private-lib-event-libs-libevent.h\u0022\n\n#define pt_to_priv_event(_pt) ((struct lws_pt_eventlibs_libevent *)(_pt)-\u003eevlib_pt)\n#define wsi_to_priv_event(_w) ((struct lws_wsi_eventlibs_libevent *)(_w)-\u003eevlib_wsi)\n\nstatic void\nlws_event_hrtimer_cb(evutil_socket_t fd, short event, void *p)\n{\n\tstruct lws_context_per_thread *pt \u003d (struct lws_context_per_thread *)p;\n\tstruct lws_pt_eventlibs_libevent *ptpr \u003d pt_to_priv_event(pt);\n\tstruct timeval tv;\n\tlws_usec_t us;\n\n\tlws_pt_lock(pt, __func__);\n\tus \u003d __lws_sul_service_ripe(pt-\u003ept_sul_owner, LWS_COUNT_PT_SUL_OWNERS,\n\t\t\t\t lws_now_usecs());\n\tif (us) {\n#if defined(__APPLE__)\n\t\ttv.tv_sec \u003d (int)(us / LWS_US_PER_SEC);\n\t\ttv.tv_usec \u003d (int)(us - (tv.tv_sec * LWS_US_PER_SEC));\n#else\n\t\ttv.tv_sec \u003d (long)(us / LWS_US_PER_SEC);\n\t\ttv.tv_usec \u003d (long)(us - (tv.tv_sec * LWS_US_PER_SEC));\n#endif\n\t\tevtimer_add(ptpr-\u003ehrtimer, \u0026tv);\n\t}\n\tlws_pt_unlock(pt);\n}\n\nstatic void\nlws_event_idle_timer_cb(evutil_socket_t fd, short event, void *p)\n{\n\tstruct lws_context_per_thread *pt \u003d (struct lws_context_per_thread *)p;\n\tstruct lws_pt_eventlibs_libevent *ptpr \u003d pt_to_priv_event(pt);\n\tstruct timeval tv;\n\tlws_usec_t us;\n\n\tif (pt-\u003eis_destroyed)\n\t\treturn;\n\n\tlws_service_do_ripe_rxflow(pt);\n\n\t/*\n\t * is there anybody with pending stuff that needs service forcing?\n\t */\n\tif (!lws_service_adjust_timeout(pt-\u003econtext, 1, pt-\u003etid)) {\n\t\t/* -1 timeout means just do forced service */\n\t\t_lws_plat_service_forced_tsi(pt-\u003econtext, pt-\u003etid);\n\t\t/* still somebody left who wants forced service? */\n\t\tif (!lws_service_adjust_timeout(pt-\u003econtext, 1, pt-\u003etid)) {\n\t\t\t/* yes... come back again later */\n\n\t\t\ttv.tv_sec \u003d 0;\n\t\t\ttv.tv_usec \u003d 1000;\n\t\t\tevtimer_add(ptpr-\u003eidle_timer, \u0026tv);\n\n\t\t\treturn;\n\t\t}\n\t}\n\n\t/* account for hrtimer */\n\n\tlws_pt_lock(pt, __func__);\n\tus \u003d __lws_sul_service_ripe(pt-\u003ept_sul_owner, LWS_COUNT_PT_SUL_OWNERS,\n\t\t\t\t lws_now_usecs());\n\tif (us) {\n\t\ttv.tv_sec \u003d (suseconds_t)(us / LWS_US_PER_SEC);\n\t\ttv.tv_usec \u003d (suseconds_t)(us - (tv.tv_sec * LWS_US_PER_SEC));\n\t\tevtimer_add(ptpr-\u003ehrtimer, \u0026tv);\n\t}\n\tlws_pt_unlock(pt);\n\n\tif (pt-\u003edestroy_self)\n\t\tlws_context_destroy(pt-\u003econtext);\n}\n\nstatic void\nlws_event_cb(evutil_socket_t sock_fd, short revents, void *ctx)\n{\n\tstruct lws_signal_watcher_libevent *lws_io \u003d\n\t\t\t(struct lws_signal_watcher_libevent *)ctx;\n\tstruct lws_context *context \u003d lws_io-\u003econtext;\n\tstruct lws_context_per_thread *pt;\n\tstruct lws_pollfd eventfd;\n\tstruct timeval tv;\n\tstruct lws *wsi;\n\n\tif (revents \u0026 EV_TIMEOUT)\n\t\treturn;\n\n\t/* !!! EV_CLOSED doesn't exist in libevent2 */\n#if LIBEVENT_VERSION_NUMBER \u003c 0x02000000\n\tif (revents \u0026 EV_CLOSED) {\n\t\tevent_del(lws_io-\u003eevent.watcher);\n\t\tevent_free(lws_io-\u003eevent.watcher);\n\t\treturn;\n\t}\n#endif\n\n\teventfd.fd \u003d sock_fd;\n\teventfd.events \u003d 0;\n\teventfd.revents \u003d 0;\n\tif (revents \u0026 EV_READ) {\n\t\teventfd.events |\u003d LWS_POLLIN;\n\t\teventfd.revents |\u003d LWS_POLLIN;\n\t}\n\tif (revents \u0026 EV_WRITE) {\n\t\teventfd.events |\u003d LWS_POLLOUT;\n\t\teventfd.revents |\u003d LWS_POLLOUT;\n\t}\n\n\twsi \u003d wsi_from_fd(context, sock_fd);\n\tif (!wsi)\n\t\treturn;\n\n\tpt \u003d \u0026context-\u003ept[(int)wsi-\u003etsi];\n\tif (pt-\u003eis_destroyed)\n\t\treturn;\n\n\tlws_service_fd_tsi(context, \u0026eventfd, wsi-\u003etsi);\n\n\tif (pt-\u003edestroy_self) {\n\t\tlwsl_cx_notice(context, \u0022pt destroy self coming true\u0022);\n\t\tlws_context_destroy(pt-\u003econtext);\n\t\treturn;\n\t}\n\n\t/* set the idle timer for 1ms ahead */\n\n\ttv.tv_sec \u003d 0;\n\ttv.tv_usec \u003d 1000;\n\tevtimer_add(pt_to_priv_event(pt)-\u003eidle_timer, \u0026tv);\n}\n\nvoid\nlws_event_sigint_cb(evutil_socket_t sock_fd, short revents, void *ctx)\n{\n\tstruct lws_context_per_thread *pt \u003d ctx;\n\tstruct event *signal \u003d pt_to_priv_event(pt)-\u003ew_sigint.watcher;\n\n\tif (pt-\u003econtext-\u003eeventlib_signal_cb) {\n\t\tpt-\u003econtext-\u003eeventlib_signal_cb((void *)(lws_intptr_t)sock_fd,\n\t\t\t\t\t\tevent_get_signal(signal));\n\n\t\treturn;\n\t}\n\tif (!pt-\u003eevent_loop_foreign)\n\t\tevent_base_loopbreak(pt_to_priv_event(pt)-\u003eio_loop);\n}\n\nstatic int\nelops_listen_init_event(struct lws_dll2 *d, void *user)\n{\n\tstruct lws *wsi \u003d lws_container_of(d, struct lws, listen_list);\n\tstruct lws_context *context \u003d (struct lws_context *)user;\n\tstruct lws_context_per_thread *pt \u003d \u0026context-\u003ept[(int)wsi-\u003etsi];\n\tstruct lws_pt_eventlibs_libevent *ptpr \u003d pt_to_priv_event(pt);\n\tstruct lws_io_watcher_libevent *w_read \u003d\n\t\t\t\t\t\u0026(wsi_to_priv_event(wsi)-\u003ew_read);\n\n\tw_read-\u003econtext \u003d context;\n\tw_read-\u003ewatcher \u003d event_new(ptpr-\u003eio_loop, wsi-\u003edesc.sockfd,\n\t\t\t\t(EV_READ | EV_PERSIST), lws_event_cb, w_read);\n\tevent_add(w_read-\u003ewatcher, NULL);\n\tw_read-\u003eset \u003d 1;\n\n\treturn 0;\n}\n\nstatic int\nelops_init_pt_event(struct lws_context *context, void *_loop, int tsi)\n{\n\tstruct event_base *loop \u003d (struct event_base *)_loop;\n\tstruct lws_context_per_thread *pt \u003d \u0026context-\u003ept[tsi];\n\tstruct lws_pt_eventlibs_libevent *ptpr \u003d pt_to_priv_event(pt);\n\n\tlwsl_cx_info(context, \u0022loop %p\u0022, _loop);\n\n\tif (!loop)\n\t\tloop \u003d event_base_new();\n\telse\n\t\tcontext-\u003ept[tsi].event_loop_foreign \u003d 1;\n\n\tif (!loop) {\n\t\tlwsl_cx_err(context, \u0022creating event base failed\u0022);\n\n\t\treturn -1;\n\t}\n\n\tptpr-\u003eio_loop \u003d loop;\n\n\tlws_vhost_foreach_listen_wsi(context, context, elops_listen_init_event);\n\n\t/* static event loop objects */\n\n\tptpr-\u003ehrtimer \u003d event_new(loop, -1, EV_PERSIST,\n\t\t\t\t lws_event_hrtimer_cb, pt);\n\n\tptpr-\u003eidle_timer \u003d event_new(loop, -1, 0,\n\t\t\t\t\t lws_event_idle_timer_cb, pt);\n\t{\n\t\tstruct timeval tv;\n\t\ttv.tv_sec \u003d (long)0;\n\t\ttv.tv_usec \u003d (long)1000;\n\t\tevtimer_add(ptpr-\u003ehrtimer, \u0026tv);\n\t}\n\n\t/* Register the signal watcher unless it's a foreign loop */\n\n\tif (pt-\u003eevent_loop_foreign)\n\t\treturn 0;\n\n\tptpr-\u003ew_sigint.watcher \u003d evsignal_new(loop, SIGINT,\n\t\t\t\t\t\t lws_event_sigint_cb, pt);\n\tevent_add(ptpr-\u003ew_sigint.watcher, NULL);\n\n\treturn 0;\n}\n\nstatic int\nelops_init_context_event(struct lws_context *context,\n\t\t\t const struct lws_context_creation_info *info)\n{\n\tint n;\n\n\tcontext-\u003eeventlib_signal_cb \u003d info-\u003esignal_cb;\n\n\tfor (n \u003d 0; n \u003c context-\u003ecount_threads; n++)\n\t\tpt_to_priv_event(\u0026context-\u003ept[n])-\u003ew_sigint.context \u003d context;\n\n\treturn 0;\n}\n\nstatic int\nelops_accept_event(struct lws *wsi)\n{\n\tstruct lws_context *context \u003d lws_get_context(wsi);\n\tstruct lws_context_per_thread *pt;\n\tstruct lws_pt_eventlibs_libevent *ptpr;\n\tstruct lws_wsi_eventlibs_libevent *wpr \u003d wsi_to_priv_event(wsi);\n evutil_socket_t fd;\n\n\twpr-\u003ew_read.context \u003d context;\n\twpr-\u003ew_write.context \u003d context;\n\n\t// Initialize the event\n\tpt \u003d \u0026context-\u003ept[(int)wsi-\u003etsi];\n\tptpr \u003d pt_to_priv_event(pt);\n\n\tif (wsi-\u003erole_ops-\u003efile_handle)\n fd \u003d (evutil_socket_t)(ev_intptr_t) wsi-\u003edesc.filefd;\n\telse\n\t\tfd \u003d wsi-\u003edesc.sockfd;\n\n\twpr-\u003ew_read.watcher \u003d event_new(ptpr-\u003eio_loop, fd,\n\t\t\t(EV_READ | EV_PERSIST), lws_event_cb, \u0026wpr-\u003ew_read);\n\twpr-\u003ew_write.watcher \u003d event_new(ptpr-\u003eio_loop, fd,\n\t\t\t(EV_WRITE | EV_PERSIST), lws_event_cb, \u0026wpr-\u003ew_write);\n\n\treturn 0;\n}\n\nstatic void\nelops_io_event(struct lws *wsi, unsigned int flags)\n{\n\tstruct lws_context_per_thread *pt \u003d \u0026wsi-\u003ea.context-\u003ept[(int)wsi-\u003etsi];\n\tstruct lws_pt_eventlibs_libevent *ptpr \u003d pt_to_priv_event(pt);\n\tstruct lws_wsi_eventlibs_libevent *wpr \u003d wsi_to_priv_event(wsi);\n\n\tif (!ptpr-\u003eio_loop || wsi-\u003ea.context-\u003ebeing_destroyed ||\n\t pt-\u003eis_destroyed)\n\t\treturn;\n\n\tassert((flags \u0026 (LWS_EV_START | LWS_EV_STOP)) \u0026\u0026\n\t (flags \u0026 (LWS_EV_READ | LWS_EV_WRITE)));\n\n\tif (flags \u0026 LWS_EV_START) {\n\t\tif ((flags \u0026 LWS_EV_WRITE) \u0026\u0026 !wpr-\u003ew_write.set) {\n\t\t\tevent_add(wpr-\u003ew_write.watcher, NULL);\n\t\t\twpr-\u003ew_write.set \u003d 1;\n\t\t}\n\n\t\tif ((flags \u0026 LWS_EV_READ) \u0026\u0026 !wpr-\u003ew_read.set) {\n\t\t\tevent_add(wpr-\u003ew_read.watcher, NULL);\n\t\t\twpr-\u003ew_read.set \u003d 1;\n\t\t}\n\t} else {\n\t\tif ((flags \u0026 LWS_EV_WRITE) \u0026\u0026 wpr-\u003ew_write.set) {\n\t\t\tevent_del(wpr-\u003ew_write.watcher);\n\t\t\twpr-\u003ew_write.set \u003d 0;\n\t\t}\n\n\t\tif ((flags \u0026 LWS_EV_READ) \u0026\u0026 wpr-\u003ew_read.set) {\n\t\t\tevent_del(wpr-\u003ew_read.watcher);\n\t\t\twpr-\u003ew_read.set \u003d 0;\n\t\t}\n\t}\n}\n\nstatic void\nelops_run_pt_event(struct lws_context *context, int tsi)\n{\n\t/* Run / Dispatch the event_base loop */\n\tif (pt_to_priv_event(\u0026context-\u003ept[tsi])-\u003eio_loop)\n\t\tevent_base_dispatch(\n\t\t\tpt_to_priv_event(\u0026context-\u003ept[tsi])-\u003eio_loop);\n}\n\nstatic int\nelops_listen_destroy_event(struct lws_dll2 *d, void *user)\n{\n\tstruct lws *wsi \u003d lws_container_of(d, struct lws, listen_list);\n\tstruct lws_wsi_eventlibs_libevent *w \u003d wsi_to_priv_event(wsi);\n\n\tevent_free(w-\u003ew_read.watcher);\n\tw-\u003ew_read.watcher \u003d NULL;\n\tevent_free(w-\u003ew_write.watcher);\n\tw-\u003ew_write.watcher \u003d NULL;\n\n\treturn 0;\n}\n\nstatic void\nelops_destroy_pt_event(struct lws_context *context, int tsi)\n{\n\tstruct lws_context_per_thread *pt \u003d \u0026context-\u003ept[tsi];\n\tstruct lws_pt_eventlibs_libevent *ptpr \u003d pt_to_priv_event(pt);\n\n\tif (!ptpr-\u003eio_loop)\n\t\treturn;\n\n\tlws_vhost_foreach_listen_wsi(context, context, elops_listen_destroy_event);\n\n\tevent_free(ptpr-\u003ehrtimer);\n\tevent_free(ptpr-\u003eidle_timer);\n\n\tif (!pt-\u003eevent_loop_foreign) {\n\t\tevent_del(ptpr-\u003ew_sigint.watcher);\n\t\tevent_free(ptpr-\u003ew_sigint.watcher);\n\t\tevent_base_loopexit(ptpr-\u003eio_loop, NULL);\n\t//\tevent_base_free(pt-\u003eevent.io_loop);\n\t//\tpt-\u003eevent.io_loop \u003d NULL;\n\t\tlwsl_cx_notice(context, \u0022set to exit loop\u0022);\n\t}\n}\n\nstatic void\nelops_destroy_wsi_event(struct lws *wsi)\n{\n\tstruct lws_context_per_thread *pt;\n\tstruct lws_wsi_eventlibs_libevent *w;\n\n\tif (!wsi)\n\t\treturn;\n\n\tpt \u003d \u0026wsi-\u003ea.context-\u003ept[(int)wsi-\u003etsi];\n\tif (pt-\u003eis_destroyed)\n\t\treturn;\n\n\tw \u003d wsi_to_priv_event(wsi);\n\n\tif (w-\u003ew_read.watcher) {\n\t\tevent_free(w-\u003ew_read.watcher);\n\t\tw-\u003ew_read.watcher \u003d NULL;\n\t}\n\n\tif (w-\u003ew_write.watcher) {\n\t\tevent_free(w-\u003ew_write.watcher);\n\t\tw-\u003ew_write.watcher \u003d NULL;\n\t}\n}\n\nstatic int\nelops_wsi_logical_close_event(struct lws *wsi)\n{\n\telops_destroy_wsi_event(wsi);\n\n\treturn 0;\n}\n\nstatic int\nelops_init_vhost_listen_wsi_event(struct lws *wsi)\n{\n\tstruct lws_context_per_thread *pt;\n\tstruct lws_pt_eventlibs_libevent *ptpr;\n\tstruct lws_wsi_eventlibs_libevent *w;\n evutil_socket_t fd;\n\n\tif (!wsi) {\n\t\tassert(0);\n\t\treturn 0;\n\t}\n\n\tw \u003d wsi_to_priv_event(wsi);\n\n\tw-\u003ew_read.context \u003d wsi-\u003ea.context;\n\tw-\u003ew_write.context \u003d wsi-\u003ea.context;\n\n\tpt \u003d \u0026wsi-\u003ea.context-\u003ept[(int)wsi-\u003etsi];\n\tptpr \u003d pt_to_priv_event(pt);\n\n\tif (wsi-\u003erole_ops-\u003efile_handle)\n fd \u003d (evutil_socket_t) wsi-\u003edesc.filefd;\n\telse\n\t\tfd \u003d wsi-\u003edesc.sockfd;\n\n\tw-\u003ew_read.watcher \u003d event_new(ptpr-\u003eio_loop, fd, (EV_READ | EV_PERSIST),\n\t\t\t\t lws_event_cb, \u0026w-\u003ew_read);\n\tw-\u003ew_write.watcher \u003d event_new(ptpr-\u003eio_loop, fd,\n\t\t\t\t (EV_WRITE | EV_PERSIST),\n\t\t\t\t lws_event_cb, \u0026w-\u003ew_write);\n\n\telops_io_event(wsi, LWS_EV_START | LWS_EV_READ);\n\n\treturn 0;\n}\n\nstatic int\nelops_destroy_context2_event(struct lws_context *context)\n{\n\tstruct lws_context_per_thread *pt;\n\tstruct lws_pt_eventlibs_libevent *ptpr;\n\tint n, m;\n\n\tfor (n \u003d 0; n \u003c context-\u003ecount_threads; n++) {\n\t\tint budget \u003d 1000;\n\n\t\tpt \u003d \u0026context-\u003ept[n];\n\t\tptpr \u003d pt_to_priv_event(pt);\n\n\t\t/* only for internal loops... */\n\n\t\tif (pt-\u003eevent_loop_foreign || !ptpr-\u003eio_loop)\n\t\t\tcontinue;\n\n\t\tif (!context-\u003eevlib_finalize_destroy_after_int_loops_stop) {\n\t\t\tevent_base_loopexit(ptpr-\u003eio_loop, NULL);\n\t\t\tcontinue;\n\t\t}\n\t\twhile (budget-- \u0026\u0026\n\t\t (m \u003d event_base_loop(ptpr-\u003eio_loop, EVLOOP_NONBLOCK)))\n\t\t\t;\n\n\t\tlwsl_cx_info(context, \u0022event_base_free\u0022);\n\n\t\tevent_base_free(ptpr-\u003eio_loop);\n\t\tptpr-\u003eio_loop \u003d NULL;\n\t}\n\n\treturn 0;\n}\n\nstatic const struct lws_event_loop_ops event_loop_ops_event \u003d {\n\t/* name */\t\t\t\u0022libevent\u0022,\n\t/* init_context */\t\telops_init_context_event,\n\t/* destroy_context1 */\t\tNULL,\n\t/* destroy_context2 */\t\telops_destroy_context2_event,\n\t/* init_vhost_listen_wsi */\telops_init_vhost_listen_wsi_event,\n\t/* init_pt */\t\t\telops_init_pt_event,\n\t/* wsi_logical_close */\t\telops_wsi_logical_close_event,\n\t/* check_client_connect_ok */\tNULL,\n\t/* close_handle_manually */\tNULL,\n\t/* accept */\t\t\telops_accept_event,\n\t/* io */\t\t\telops_io_event,\n\t/* run_pt */\t\t\telops_run_pt_event,\n\t/* destroy_pt */\t\telops_destroy_pt_event,\n\t/* destroy wsi */\t\telops_destroy_wsi_event,\n\t/* foreign_thread */\t\tNULL,\n\n\t/* flags */\t\t\t0,\n\n\t/* evlib_size_ctx */\t0,\n\t/* evlib_size_pt */\tsizeof(struct lws_pt_eventlibs_libevent),\n\t/* evlib_size_vh */\t0,\n\t/* evlib_size_wsi */\tsizeof(struct lws_wsi_eventlibs_libevent),\n};\n\n#if defined(LWS_WITH_EVLIB_PLUGINS)\nLWS_VISIBLE\n#endif\nconst lws_plugin_evlib_t evlib_event \u003d {\n\t.hdr \u003d {\n\t\t\u0022libevent event loop\u0022,\n\t\t\u0022lws_evlib_plugin\u0022,\n\t\tLWS_BUILD_HASH,\n\t\tLWS_PLUGIN_API_MAGIC\n\t},\n\n\t.ops\t\u003d \u0026event_loop_ops_event\n};\n","s":{"c":1638758803,"u": 710}} ],"g": 4362,"chitpc": 0,"ehitpc": 0,"indexed":0 , "ab": 1, "si": 0, "db":0, "di":0, "sat":0, "lfc": "0000"}