1*1c60b9acSAndroid Build Coastguard Worker## Information for new event lib implementers 2*1c60b9acSAndroid Build Coastguard Worker 3*1c60b9acSAndroid Build Coastguard Worker### Introduction 4*1c60b9acSAndroid Build Coastguard Worker 5*1c60b9acSAndroid Build Coastguard WorkerBy default lws has built-in support for POSIX poll() as the event loop on unix, 6*1c60b9acSAndroid Build Coastguard Workerand native WSA on windows. 7*1c60b9acSAndroid Build Coastguard Worker 8*1c60b9acSAndroid Build Coastguard WorkerTo get access to epoll() or other platform specific better poll waits, or to 9*1c60b9acSAndroid Build Coastguard Workerintegrate with existing applications already using a specific event loop, it can 10*1c60b9acSAndroid Build Coastguard Workerbe desirable for lws to use another external event library, like libuv, glib, 11*1c60b9acSAndroid Build Coastguard Workerlibevent, libev, or sdevent. 12*1c60b9acSAndroid Build Coastguard Worker 13*1c60b9acSAndroid Build Coastguard WorkerLws supports wholesale replacement of its wait selectable at runtime, either by 14*1c60b9acSAndroid Build Coastguard Workerbuilding support for one or more event lib into the libwebsockets library, or by 15*1c60b9acSAndroid Build Coastguard Workerbuilding runtime-loadable plugins. CMake symbol `LWS_WITH_EVLIB_PLUGINS` 16*1c60b9acSAndroid Build Coastguard Workerdecides if the support is built as plugins or included into the lws lib. 17*1c60b9acSAndroid Build Coastguard Worker 18*1c60b9acSAndroid Build Coastguard WorkerDue to their history libevent and libev have conflicting defines in the same 19*1c60b9acSAndroid Build Coastguard Workernamespace and cannot be built together if included into the lib, however when 20*1c60b9acSAndroid Build Coastguard Workerbuilt as plugins they are built separately without problems. 21*1c60b9acSAndroid Build Coastguard WorkerSee ./READMEs/README.event-libs.md for more details. 22*1c60b9acSAndroid Build Coastguard Worker 23*1c60b9acSAndroid Build Coastguard WorkerDespite it may be more work, lws event lib implementations must support 24*1c60b9acSAndroid Build Coastguard Worker"foreign" loops cleanly, that is integration with an already-existing loop and 25*1c60b9acSAndroid Build Coastguard Workerthe ability to destroy the lws_context without stopping or leaving the foreign 26*1c60b9acSAndroid Build Coastguard Workerloop in any different state than when lws found it. For most loops this is 27*1c60b9acSAndroid Build Coastguard Workerfairly simple, but with libuv async close, it required refcounting lws libuv 28*1c60b9acSAndroid Build Coastguard Workerhandles and deferring the actual destroy until they were all really closed. 29*1c60b9acSAndroid Build Coastguard Worker 30*1c60b9acSAndroid Build Coastguard Worker### Code placement 31*1c60b9acSAndroid Build Coastguard Worker 32*1c60b9acSAndroid Build Coastguard WorkerThe code specific to the event library should live in `./lib/event-libs/**lib name**` 33*1c60b9acSAndroid Build Coastguard Worker 34*1c60b9acSAndroid Build Coastguard Worker### Allowing control over enabling event libs 35*1c60b9acSAndroid Build Coastguard Worker 36*1c60b9acSAndroid Build Coastguard WorkerAll event libs should add a cmake define `LWS_WITH_**lib name**` and make its 37*1c60b9acSAndroid Build Coastguard Workerbuild dependent on it in CMakeLists.txt. Export the cmakedefine in 38*1c60b9acSAndroid Build Coastguard Worker`./cmake/lws_config.h.in` as well so user builds can understand if the event 39*1c60b9acSAndroid Build Coastguard Workerlib is available in the lws build it is trying to bind to. 40*1c60b9acSAndroid Build Coastguard Worker 41*1c60b9acSAndroid Build Coastguard WorkerIf the event lib is disabled in cmake, nothing in its directory is built or 42*1c60b9acSAndroid Build Coastguard Workerreferenced. 43*1c60b9acSAndroid Build Coastguard Worker 44*1c60b9acSAndroid Build Coastguard Worker### Event loop ops struct 45*1c60b9acSAndroid Build Coastguard Worker 46*1c60b9acSAndroid Build Coastguard WorkerThe event lib support is defined by `struct lws_event_loop_ops` in 47*1c60b9acSAndroid Build Coastguard Worker`lib/event-libs/private-lib-event-libs.h`, 48*1c60b9acSAndroid Build Coastguard Workereach event lib support instantiates one of these and fills in the appropriate 49*1c60b9acSAndroid Build Coastguard Workerops callbacks to perform its job. By convention that lives in 50*1c60b9acSAndroid Build Coastguard Worker`./lib/event-libs/**lib name**/**lib_name**.c`. 51*1c60b9acSAndroid Build Coastguard Worker 52*1c60b9acSAndroid Build Coastguard WorkerThe ops struct must be public, not static, and must be named using `**lib_name**`, 53*1c60b9acSAndroid Build Coastguard Workereg 54*1c60b9acSAndroid Build Coastguard Worker 55*1c60b9acSAndroid Build Coastguard Worker``` 56*1c60b9acSAndroid Build Coastguard Worker``` 57*1c60b9acSAndroid Build Coastguard Worker 58*1c60b9acSAndroid Build Coastguard Worker### Private event lib declarations 59*1c60b9acSAndroid Build Coastguard Worker 60*1c60b9acSAndroid Build Coastguard WorkerTruly private declarations for the event lib support that are only referenced by 61*1c60b9acSAndroid Build Coastguard Workerthat code can go in the event-libs directory as you like. The convention is 62*1c60b9acSAndroid Build Coastguard Workerthey should be in the event lib support directory in a file 63*1c60b9acSAndroid Build Coastguard Worker`private-lib-event-libs-**lib name**.h`. 64*1c60b9acSAndroid Build Coastguard Worker 65*1c60b9acSAndroid Build Coastguard Worker### Integration with lws 66*1c60b9acSAndroid Build Coastguard Worker 67*1c60b9acSAndroid Build Coastguard WorkerThere are a couple of places to add refererences in ./lib/core/context.c, in a 68*1c60b9acSAndroid Build Coastguard Workertable of context creation time server option flags mapped to the **lib_name**, 69*1c60b9acSAndroid Build Coastguard Workerused for plugin mode, like this... 70*1c60b9acSAndroid Build Coastguard Worker 71*1c60b9acSAndroid Build Coastguard Worker``` 72*1c60b9acSAndroid Build Coastguard Worker#if defined(LWS_WITH_EVLIB_PLUGINS) && defined(LWS_WITH_EVENT_LIBS) 73*1c60b9acSAndroid Build Coastguard Workerstatic const struct lws_evlib_map { 74*1c60b9acSAndroid Build Coastguard Worker uint64_t flag; 75*1c60b9acSAndroid Build Coastguard Worker const char *name; 76*1c60b9acSAndroid Build Coastguard Worker} map[] = { 77*1c60b9acSAndroid Build Coastguard Worker { LWS_SERVER_OPTION_LIBUV, "evlib_uv" }, 78*1c60b9acSAndroid Build Coastguard Worker { LWS_SERVER_OPTION_LIBEVENT, "evlib_event" }, 79*1c60b9acSAndroid Build Coastguard Worker { LWS_SERVER_OPTION_GLIB, "evlib_glib" }, 80*1c60b9acSAndroid Build Coastguard Worker { LWS_SERVER_OPTION_LIBEV, "evlib_ev" }, 81*1c60b9acSAndroid Build Coastguard Worker}; 82*1c60b9acSAndroid Build Coastguard Worker``` 83*1c60b9acSAndroid Build Coastguard Worker 84*1c60b9acSAndroid Build Coastguard Workerand for backwards compatibility add a stanza to the built-in checks like this 85*1c60b9acSAndroid Build Coastguard Worker 86*1c60b9acSAndroid Build Coastguard Worker``` 87*1c60b9acSAndroid Build Coastguard Worker#if defined(LWS_WITH_LIBUV) 88*1c60b9acSAndroid Build Coastguard Worker if (lws_check_opt(info->options, LWS_SERVER_OPTION_LIBUV)) { 89*1c60b9acSAndroid Build Coastguard Worker extern const lws_plugin_evlib_t evlib_uv; 90*1c60b9acSAndroid Build Coastguard Worker plev = &evlib_uv; 91*1c60b9acSAndroid Build Coastguard Worker } 92*1c60b9acSAndroid Build Coastguard Worker#endif 93*1c60b9acSAndroid Build Coastguard Worker``` 94*1c60b9acSAndroid Build Coastguard Worker 95*1c60b9acSAndroid Build Coastguard WorkerBoth entries are the way the main libs hook up to the selected event lib ops 96*1c60b9acSAndroid Build Coastguard Workerstruct at runtime. 97*1c60b9acSAndroid Build Coastguard Worker 98*1c60b9acSAndroid Build Coastguard Worker### Integrating event lib assets to lws 99*1c60b9acSAndroid Build Coastguard Worker 100*1c60b9acSAndroid Build Coastguard WorkerDeclare "container structs" in your private....h for anything you need at 101*1c60b9acSAndroid Build Coastguard Workerwsi, pt, vhost and context levels, eg, the libuv event lib support need to 102*1c60b9acSAndroid Build Coastguard Workeradd its own assets in the perthread struct, it declares in its private....h 103*1c60b9acSAndroid Build Coastguard Worker 104*1c60b9acSAndroid Build Coastguard Worker``` 105*1c60b9acSAndroid Build Coastguard Workerstruct lws_pt_eventlibs_libuv { 106*1c60b9acSAndroid Build Coastguard Worker uv_loop_t *io_loop; 107*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt; 108*1c60b9acSAndroid Build Coastguard Worker uv_signal_t signals[8]; 109*1c60b9acSAndroid Build Coastguard Worker uv_timer_t sultimer; 110*1c60b9acSAndroid Build Coastguard Worker uv_idle_t idle; 111*1c60b9acSAndroid Build Coastguard Worker struct lws_signal_watcher_libuv w_sigint; 112*1c60b9acSAndroid Build Coastguard Worker}; 113*1c60b9acSAndroid Build Coastguard Worker``` 114*1c60b9acSAndroid Build Coastguard Worker 115*1c60b9acSAndroid Build Coastguard Workerthis is completely private and opaque, but in the ops struct there are provided 116*1c60b9acSAndroid Build Coastguard Workerfour entries to export the sizes of these event-lib specific objects 117*1c60b9acSAndroid Build Coastguard Worker 118*1c60b9acSAndroid Build Coastguard Worker``` 119*1c60b9acSAndroid Build Coastguard Worker... 120*1c60b9acSAndroid Build Coastguard Worker /* evlib_size_ctx */ sizeof(struct lws_context_eventlibs_libuv), 121*1c60b9acSAndroid Build Coastguard Worker /* evlib_size_pt */ sizeof(struct lws_pt_eventlibs_libuv), 122*1c60b9acSAndroid Build Coastguard Worker /* evlib_size_vh */ 0, 123*1c60b9acSAndroid Build Coastguard Worker /* evlib_size_wsi */ sizeof(struct lws_io_watcher_libuv), 124*1c60b9acSAndroid Build Coastguard Worker}; 125*1c60b9acSAndroid Build Coastguard Worker``` 126*1c60b9acSAndroid Build Coastguard Worker 127*1c60b9acSAndroid Build Coastguard WorkerIf the particular event lib doesn't need to have a private footprint in an 128*1c60b9acSAndroid Build Coastguard Workerobject, it can just set the size it needs there to 0. 129*1c60b9acSAndroid Build Coastguard Worker 130*1c60b9acSAndroid Build Coastguard WorkerWhen the context, pts, vhosts or wsis are created in lws, they over-allocate 131*1c60b9acSAndroid Build Coastguard Workerto also allow for the event lib object, and set a pointer in the lws object 132*1c60b9acSAndroid Build Coastguard Workerbeing created to point at the over-allocation. For example for the wsi 133*1c60b9acSAndroid Build Coastguard Worker 134*1c60b9acSAndroid Build Coastguard Worker``` 135*1c60b9acSAndroid Build Coastguard Worker#if defined(LWS_WITH_EVENT_LIBS) 136*1c60b9acSAndroid Build Coastguard Worker void *evlib_wsi; /* overallocated */ 137*1c60b9acSAndroid Build Coastguard Worker#endif 138*1c60b9acSAndroid Build Coastguard Worker``` 139*1c60b9acSAndroid Build Coastguard Worker 140*1c60b9acSAndroid Build Coastguard Workerand similarly there are `evlib_pt` and so on for those objects, usable by the 141*1c60b9acSAndroid Build Coastguard Workerevent lib and opaque to everyone else. Once the event lib is selected at 142*1c60b9acSAndroid Build Coastguard Workerruntime, all of these objects are guaranteed to have the right size object at 143*1c60b9acSAndroid Build Coastguard Worker`wsi->evlib_wsi` initialized to zeroes. 144*1c60b9acSAndroid Build Coastguard Worker 145*1c60b9acSAndroid Build Coastguard Worker### Enabling event lib adoption 146*1c60b9acSAndroid Build Coastguard Worker 147*1c60b9acSAndroid Build Coastguard WorkerYou need to add a `LWS_SERVER_OPTION...` flag as necessary in `./lib/libwebsockets.h` 148*1c60b9acSAndroid Build Coastguard Worker`enum lws_context_options`, and follow the existing code in `lws_create_context()` 149*1c60b9acSAndroid Build Coastguard Workerto convert the flag into binding your ops struct to the context. 150*1c60b9acSAndroid Build Coastguard Worker 151*1c60b9acSAndroid Build Coastguard Worker### Implementation of the event lib bindings 152*1c60b9acSAndroid Build Coastguard Worker 153*1c60b9acSAndroid Build Coastguard WorkerStudy eg libuv implementation, using the available ops in the struct lws_event_loop_ops 154*1c60b9acSAndroid Build Coastguard Workeras a guide. 155*1c60b9acSAndroid Build Coastguard Worker 156*1c60b9acSAndroid Build Coastguard Worker### Destruction 157*1c60b9acSAndroid Build Coastguard Worker 158*1c60b9acSAndroid Build Coastguard WorkerEnding the event loop is generally a bit tricky, because if the event loop is 159*1c60b9acSAndroid Build Coastguard Workerinternal to the lws context, you cannot destroy it while the event loop is 160*1c60b9acSAndroid Build Coastguard Workerrunning. 161*1c60b9acSAndroid Build Coastguard Worker 162*1c60b9acSAndroid Build Coastguard WorkerDon't add special exports... we tried that, it's a huge mess. The same user 163*1c60b9acSAndroid Build Coastguard Workercode should be able work with any of the event loops including poll. 164*1c60b9acSAndroid Build Coastguard Worker 165*1c60b9acSAndroid Build Coastguard WorkerThe solution we found was hide the different processing necessary for the 166*1c60b9acSAndroid Build Coastguard Workerdifferent cases in `lws_destroy_context()`. To help with that there are event 167*1c60b9acSAndroid Build Coastguard Workerlib ops available that will be called at two different places in the context 168*1c60b9acSAndroid Build Coastguard Workerdestroy processing. 169*1c60b9acSAndroid Build Coastguard Worker 170