1*1c60b9acSAndroid Build Coastguard Worker## Information for new role implementers 2*1c60b9acSAndroid Build Coastguard Worker 3*1c60b9acSAndroid Build Coastguard Worker### Introduction 4*1c60b9acSAndroid Build Coastguard Worker 5*1c60b9acSAndroid Build Coastguard WorkerIn lws the "role" is the job the wsi is doing in the system, eg, 6*1c60b9acSAndroid Build Coastguard Workerbeing an http1 or h2, or ws connection, or being a listen socket, etc. 7*1c60b9acSAndroid Build Coastguard Worker 8*1c60b9acSAndroid Build Coastguard WorkerThis is different than, eg, a new ws protocol or a different callback 9*1c60b9acSAndroid Build Coastguard Workerfor an existing role. A new role is needed when you want to add support for 10*1c60b9acSAndroid Build Coastguard Workersomething completely new, like a completely new wire protocol that 11*1c60b9acSAndroid Build Coastguard Workerdoesn't use http or ws. 12*1c60b9acSAndroid Build Coastguard Worker 13*1c60b9acSAndroid Build Coastguard WorkerSo... what's the point of implementing the protocol inside the lws role framework? 14*1c60b9acSAndroid Build Coastguard Worker 15*1c60b9acSAndroid Build Coastguard WorkerYou inherit all the well-maintained lws core functionality around: 16*1c60b9acSAndroid Build Coastguard Worker 17*1c60b9acSAndroid Build Coastguard Worker - connection lifecycle sequencing in a valgrind-clean way 18*1c60b9acSAndroid Build Coastguard Worker 19*1c60b9acSAndroid Build Coastguard Worker - client connection proxy support, for HTTP and Socks5 20*1c60b9acSAndroid Build Coastguard Worker 21*1c60b9acSAndroid Build Coastguard Worker - tls support working equally on mbedTLS and OpenSSL and derivatives without any code in the role 22*1c60b9acSAndroid Build Coastguard Worker 23*1c60b9acSAndroid Build Coastguard Worker - apis for cert lifecycle management and parsing 24*1c60b9acSAndroid Build Coastguard Worker 25*1c60b9acSAndroid Build Coastguard Worker - event loop support working on all the lws event loops (poll, libuv , ev, and event) 26*1c60b9acSAndroid Build Coastguard Worker 27*1c60b9acSAndroid Build Coastguard Worker - clean connection tracking and closing even on advanced event loops 28*1c60b9acSAndroid Build Coastguard Worker 29*1c60b9acSAndroid Build Coastguard Worker - user code follows the same simple callbacks on wsi 30*1c60b9acSAndroid Build Coastguard Worker 31*1c60b9acSAndroid Build Coastguard Worker - multi-vhost support 32*1c60b9acSAndroid Build Coastguard Worker 33*1c60b9acSAndroid Build Coastguard Worker - core multithreaded service support with usually no locking requirement on the role code 34*1c60b9acSAndroid Build Coastguard Worker 35*1c60b9acSAndroid Build Coastguard Worker - direct compatibility with all other lws roles + protocols in the same event loop 36*1c60b9acSAndroid Build Coastguard Worker 37*1c60b9acSAndroid Build Coastguard Worker - compatibility with higher-level stuff like lwsws as the server application 38*1c60b9acSAndroid Build Coastguard Worker 39*1c60b9acSAndroid Build Coastguard Worker### Code placement 40*1c60b9acSAndroid Build Coastguard Worker 41*1c60b9acSAndroid Build Coastguard WorkerThe code specific to that role should live in `./lib/roles/**role name**` 42*1c60b9acSAndroid Build Coastguard Worker 43*1c60b9acSAndroid Build Coastguard WorkerIf a role is asymmetic between a client and server side, like http is, it 44*1c60b9acSAndroid Build Coastguard Workershould generally be implemented as a single role. 45*1c60b9acSAndroid Build Coastguard Worker 46*1c60b9acSAndroid Build Coastguard Worker### Allowing control over enabling roles 47*1c60b9acSAndroid Build Coastguard Worker 48*1c60b9acSAndroid Build Coastguard WorkerAll roles should add a cmake define `LWS_ROLE_**role name**` and make its build 49*1c60b9acSAndroid Build Coastguard Workerdependent on it in CMakeLists.txt. Export the cmakedefine in `./cmake/lws_config.h.in` 50*1c60b9acSAndroid Build Coastguard Workeras well so user builds can understand if the role is available in the lws build it is 51*1c60b9acSAndroid Build Coastguard Workertrying to bind to. 52*1c60b9acSAndroid Build Coastguard Worker 53*1c60b9acSAndroid Build Coastguard WorkerIf the role is disabled in cmake, nothing in its directory is built. 54*1c60b9acSAndroid Build Coastguard Worker 55*1c60b9acSAndroid Build Coastguard Worker### Role ops struct 56*1c60b9acSAndroid Build Coastguard Worker 57*1c60b9acSAndroid Build Coastguard WorkerThe role is defined by `struct lws_role_ops` in `lib/roles/private-lib-roles.h`, 58*1c60b9acSAndroid Build Coastguard Workereach role instantiates one of these and fills in the appropriate ops 59*1c60b9acSAndroid Build Coastguard Workercallbacks to perform its job. By convention that lives in 60*1c60b9acSAndroid Build Coastguard Worker`./lib/roles/**role name**/ops-**role_name**.c`. 61*1c60b9acSAndroid Build Coastguard Worker 62*1c60b9acSAndroid Build Coastguard Worker### Private role declarations 63*1c60b9acSAndroid Build Coastguard Worker 64*1c60b9acSAndroid Build Coastguard WorkerTruly private declarations for the role can go in the role directory as you like. 65*1c60b9acSAndroid Build Coastguard WorkerHowever when the declarations must be accessible to other things in lws build, eg, 66*1c60b9acSAndroid Build Coastguard Workerthe role adds members to `struct lws` when enabled, they should be in the role 67*1c60b9acSAndroid Build Coastguard Workerdirectory in a file `private-lib-roles-myrole.h`. 68*1c60b9acSAndroid Build Coastguard Worker 69*1c60b9acSAndroid Build Coastguard WorkerSearch for "bring in role private declarations" in `./lib/roles/private-lib-roles.h 70*1c60b9acSAndroid Build Coastguard Workerand add your private role file there following the style used for the other roles, 71*1c60b9acSAndroid Build Coastguard Workereg, 72*1c60b9acSAndroid Build Coastguard Worker 73*1c60b9acSAndroid Build Coastguard Worker``` 74*1c60b9acSAndroid Build Coastguard Worker#if defined(LWS_ROLE_WS) 75*1c60b9acSAndroid Build Coastguard Worker #include "roles/ws/private-lib-roles-ws.h" 76*1c60b9acSAndroid Build Coastguard Worker#else 77*1c60b9acSAndroid Build Coastguard Worker #define lwsi_role_ws(wsi) (0) 78*1c60b9acSAndroid Build Coastguard Worker#endif 79*1c60b9acSAndroid Build Coastguard Worker``` 80*1c60b9acSAndroid Build Coastguard Worker 81*1c60b9acSAndroid Build Coastguard WorkerIf the role is disabled at cmake, nothing from its private.h should be used anywhere. 82*1c60b9acSAndroid Build Coastguard Worker 83*1c60b9acSAndroid Build Coastguard Worker### Integrating role assets to lws 84*1c60b9acSAndroid Build Coastguard Worker 85*1c60b9acSAndroid Build Coastguard WorkerIf your role needs special storage in lws objects, that's no problem. But to keep 86*1c60b9acSAndroid Build Coastguard Workerthings sane, there are some rules. 87*1c60b9acSAndroid Build Coastguard Worker 88*1c60b9acSAndroid Build Coastguard Worker - declare a "container struct" in your private.h for everything, eg, the ws role wants 89*1c60b9acSAndroid Build Coastguard Worker to add storage in lws_vhost for enabled extensions, it declares in its private.h 90*1c60b9acSAndroid Build Coastguard Worker 91*1c60b9acSAndroid Build Coastguard Worker``` 92*1c60b9acSAndroid Build Coastguard Workerstruct lws_vhost_role_ws { 93*1c60b9acSAndroid Build Coastguard Worker#if !defined(LWS_WITHOUT_EXTENSIONS) 94*1c60b9acSAndroid Build Coastguard Worker const struct lws_extension *extensions; 95*1c60b9acSAndroid Build Coastguard Worker#endif 96*1c60b9acSAndroid Build Coastguard Worker}; 97*1c60b9acSAndroid Build Coastguard Worker``` 98*1c60b9acSAndroid Build Coastguard Worker 99*1c60b9acSAndroid Build Coastguard Worker - add your role content in one place in the lws struct, protected by `#if defined(LWS_ROLE_**role name**)`, 100*1c60b9acSAndroid Build Coastguard Worker eg, again for LWS_ROLE_WS 101*1c60b9acSAndroid Build Coastguard Worker 102*1c60b9acSAndroid Build Coastguard Worker``` 103*1c60b9acSAndroid Build Coastguard Worker struct lws_vhost { 104*1c60b9acSAndroid Build Coastguard Worker 105*1c60b9acSAndroid Build Coastguard Worker... 106*1c60b9acSAndroid Build Coastguard Worker 107*1c60b9acSAndroid Build Coastguard Worker#if defined(LWS_ROLE_WS) 108*1c60b9acSAndroid Build Coastguard Worker struct lws_vhost_role_ws ws; 109*1c60b9acSAndroid Build Coastguard Worker#endif 110*1c60b9acSAndroid Build Coastguard Worker 111*1c60b9acSAndroid Build Coastguard Worker... 112*1c60b9acSAndroid Build Coastguard Worker``` 113*1c60b9acSAndroid Build Coastguard Worker 114*1c60b9acSAndroid Build Coastguard Worker### Adding to lws available roles list 115*1c60b9acSAndroid Build Coastguard Worker 116*1c60b9acSAndroid Build Coastguard WorkerEdit the NULL-terminated array `available_roles` at the top of `./lib/core/context.c` to include 117*1c60b9acSAndroid Build Coastguard Workera pointer to your new role's ops struct, following the style already there. 118*1c60b9acSAndroid Build Coastguard Worker 119*1c60b9acSAndroid Build Coastguard Worker``` 120*1c60b9acSAndroid Build Coastguard Workerconst struct lws_role_ops * available_roles[] = { 121*1c60b9acSAndroid Build Coastguard Worker#if defined(LWS_ROLE_H2) 122*1c60b9acSAndroid Build Coastguard Worker &role_ops_h2, 123*1c60b9acSAndroid Build Coastguard Worker#endif 124*1c60b9acSAndroid Build Coastguard Worker... 125*1c60b9acSAndroid Build Coastguard Worker``` 126*1c60b9acSAndroid Build Coastguard Worker 127*1c60b9acSAndroid Build Coastguard WorkerThis makes lws aware that your role exists, and it can auto-generate some things like 128*1c60b9acSAndroid Build Coastguard WorkerALPN lists, and call your role ops callbacks for things like hooking vhost creation. 129*1c60b9acSAndroid Build Coastguard Worker 130*1c60b9acSAndroid Build Coastguard Worker### Enabling role adoption 131*1c60b9acSAndroid Build Coastguard Worker 132*1c60b9acSAndroid Build Coastguard WorkerThe primary way wsi get bound to a specific role is via the lws adoption api 133*1c60b9acSAndroid Build Coastguard Worker`lws_adopt_descriptor_vhost()`. Add flags as necessary in `./include/libwebsockets/lws-adopt.h` 134*1c60b9acSAndroid Build Coastguard Worker`enum lws_adoption_type` and follow the existing code in `lws_adopt_descriptor_vhost()` 135*1c60b9acSAndroid Build Coastguard Workerto bind a wsi with suitable flags to your role ops. 136*1c60b9acSAndroid Build Coastguard Worker 137*1c60b9acSAndroid Build Coastguard Worker### Implementation of the role 138*1c60b9acSAndroid Build Coastguard Worker 139*1c60b9acSAndroid Build Coastguard WorkerAfter that plumbing-in is completed, the role ops you declare are "live" on a wsi 140*1c60b9acSAndroid Build Coastguard Workerbound to them via the adoption api. 141*1c60b9acSAndroid Build Coastguard Worker 142*1c60b9acSAndroid Build Coastguard WorkerThe core support for wsis in lws has some generic concepts 143*1c60b9acSAndroid Build Coastguard Worker 144*1c60b9acSAndroid Build Coastguard Worker - the wsi holds a pointer member `role_ops` that indicates which role ops the 145*1c60b9acSAndroid Build Coastguard Worker wsi is bound to 146*1c60b9acSAndroid Build Coastguard Worker 147*1c60b9acSAndroid Build Coastguard Worker - the wsi holds a generic uint32 `wsistate` that contains role flags and wsi state 148*1c60b9acSAndroid Build Coastguard Worker 149*1c60b9acSAndroid Build Coastguard Worker - role flags are provided (LWSIFR_CLIENT, LWSIFR_SERVER) to differentiate between 150*1c60b9acSAndroid Build Coastguard Worker client and server connections inside a wsi, along with helpers `lwsi_role_client(wsi)` 151*1c60b9acSAndroid Build Coastguard Worker and `lwsi_role_server(wsi)`. 152*1c60b9acSAndroid Build Coastguard Worker 153*1c60b9acSAndroid Build Coastguard Worker - lws provides around 30 generic states for the wsi starting from 'unconnected' through 154*1c60b9acSAndroid Build Coastguard Worker various proxy or tunnel states, to 'established', and then various states shutting 155*1c60b9acSAndroid Build Coastguard Worker down until 'dead socket'. The states have testable flags and helpers to discover if 156*1c60b9acSAndroid Build Coastguard Worker the wsi state is before establishment `lwsi_state_est(wsi)` and if in the state it is 157*1c60b9acSAndroid Build Coastguard Worker in, it can handle pollout `lwsi_state_can_handle_POLLOUT(wsi)`. 158*1c60b9acSAndroid Build Coastguard Worker 159*1c60b9acSAndroid Build Coastguard Worker - You set the initial binding, role flags and state using `lws_role_transition()`. Afterwards 160*1c60b9acSAndroid Build Coastguard Worker you can adjust the state using `lwsi_set_state()`. 161*1c60b9acSAndroid Build Coastguard Worker 162*1c60b9acSAndroid Build Coastguard Worker### Role ops compression 163*1c60b9acSAndroid Build Coastguard Worker 164*1c60b9acSAndroid Build Coastguard WorkerSince the role ops struct is typically only sparsely filled, rather than have 20 function 165*1c60b9acSAndroid Build Coastguard Workerpointers most of which may be NULL, there is a separate array of a union of function 166*1c60b9acSAndroid Build Coastguard Workerpointers that is just long enough for functions that exist in the role, and a nybble index 167*1c60b9acSAndroid Build Coastguard Workertable with a nybble for each possible op, either 0 indicating that the operation is not 168*1c60b9acSAndroid Build Coastguard Workerprovided in this role, or 1 - 15 indicating the position of the function pointer in the 169*1c60b9acSAndroid Build Coastguard Workerarray. 170*1c60b9acSAndroid Build Coastguard Worker 171