Project homepage Mailing List  API Docs  Github Mirror 
{"schema":"libjg2-1", "vpath":"/git/", "avatar":"/git/avatar/", "alang":"en-US,en;q\u003d0.5", "gen_ut":1721660381, "reponame":"libwebsockets", "desc":"libwebsockets lightweight C networking library", "owner": { "name": "Andy Green", "email": "", "md5": "c50933ca2aa61e0fe2c43d46bb6b59cb" },"url":"", "f":3, "items": [ { "schema":"libjg2-1", "oid":{ "oid": "8674bf1585c0196f071eb6f0ae2184c9ca053301", "alias": [ "refs/heads/main"]},"tree": [ { "name": "cgi","mode": "16384", "size":0}, { "name": "dbus","mode": "16384", "size":0}, { "name": "h1","mode": "16384", "size":0}, { "name": "h2","mode": "16384", "size":0}, { "name": "http","mode": "16384", "size":0}, { "name": "listen","mode": "16384", "size":0}, { "name": "mqtt","mode": "16384", "size":0}, { "name": "netlink","mode": "16384", "size":0}, { "name": "pipe","mode": "16384", "size":0}, { "name": "raw-file","mode": "16384", "size":0}, { "name": "raw-proxy","mode": "16384", "size":0}, { "name": "raw-skt","mode": "16384", "size":0}, { "name": "ws","mode": "16384", "size":0}, { "name": "CMakeLists.txt","mode": "33188", "size":2554}, { "name": "","mode": "33188", "size":6123}, { "name": "private-lib-roles.h","mode": "33188", "size":14926}],"s":{"c":1721550424,"u": 641}} ,{"schema":"libjg2-1", "cid":"641abc1550dd1195e88da0c45759e1ef", "oid":{ "oid": "8674bf1585c0196f071eb6f0ae2184c9ca053301", "alias": [ "refs/heads/main"]},"blobname": "lib/roles/", "blob": "## Information for new role implementers\n\n### Introduction\n\nIn lws the \u0022role\u0022 is the job the wsi is doing in the system, eg,\nbeing an http1 or h2, or ws connection, or being a listen socket, etc.\n\nThis is different than, eg, a new ws protocol or a different callback\nfor an existing role. A new role is needed when you want to add support for\nsomething completely new, like a completely new wire protocol that\ndoesn't use http or ws.\n\nSo... what's the point of implementing the protocol inside the lws role framework?\n\nYou inherit all the well-maintained lws core functionality around:\n\n - connection lifecycle sequencing in a valgrind-clean way\n\n - client connection proxy support, for HTTP and Socks5\n\n - tls support working equally on mbedTLS and OpenSSL and derivatives without any code in the role\n\n - apis for cert lifecycle management and parsing\n\n - event loop support working on all the lws event loops (poll, libuv , ev, and event)\n\n - clean connection tracking and closing even on advanced event loops\n\n - user code follows the same simple callbacks on wsi\n\n - multi-vhost support\n\n - core multithreaded service support with usually no locking requirement on the role code\n\n - direct compatibility with all other lws roles + protocols in the same event loop\n\n - compatibility with higher-level stuff like lwsws as the server application\n\n### Code placement\n\nThe code specific to that role should live in `./lib/roles/**role name**`\n\nIf a role is asymmetic between a client and server side, like http is, it\nshould generally be implemented as a single role.\n\n### Allowing control over enabling roles\n\nAll roles should add a cmake define `LWS_ROLE_**role name**` and make its build\ndependent on it in CMakeLists.txt. Export the cmakedefine in `./cmake/`\nas well so user builds can understand if the role is available in the lws build it is\ntrying to bind to.\n\nIf the role is disabled in cmake, nothing in its directory is built.\n\n### Role ops struct\n\nThe role is defined by `struct lws_role_ops` in `lib/roles/private-lib-roles.h`,\neach role instantiates one of these and fills in the appropriate ops\ncallbacks to perform its job. By convention that lives in\n`./lib/roles/**role name**/ops-**role_name**.c`.\n\n### Private role declarations\n\nTruly private declarations for the role can go in the role directory as you like.\nHowever when the declarations must be accessible to other things in lws build, eg,\nthe role adds members to `struct lws` when enabled, they should be in the role\ndirectory in a file `private-lib-roles-myrole.h`.\n\nSearch for \u0022bring in role private declarations\u0022 in `./lib/roles/private-lib-roles.h\nand add your private role file there following the style used for the other roles,\neg,\n\n```\n#if defined(LWS_ROLE_WS)\n #include \u0022roles/ws/private-lib-roles-ws.h\u0022\n#else\n #define lwsi_role_ws(wsi) (0)\n#endif\n```\n\nIf the role is disabled at cmake, nothing from its private.h should be used anywhere.\n\n### Integrating role assets to lws\n\nIf your role needs special storage in lws objects, that's no problem. But to keep\nthings sane, there are some rules.\n\n - declare a \u0022container struct\u0022 in your private.h for everything, eg, the ws role wants\n to add storage in lws_vhost for enabled extensions, it declares in its private.h\n\n```\nstruct lws_vhost_role_ws {\n#if !defined(LWS_WITHOUT_EXTENSIONS)\n\tconst struct lws_extension *extensions;\n#endif\n};\n```\n\n - add your role content in one place in the lws struct, protected by `#if defined(LWS_ROLE_**role name**)`,\n eg, again for LWS_ROLE_WS\n\n```\n\tstruct lws_vhost {\n\n...\n\n#if defined(LWS_ROLE_WS)\n\tstruct lws_vhost_role_ws ws;\n#endif\n\n...\n```\n\n### Adding to lws available roles list\n\nEdit the NULL-terminated array `available_roles` at the top of `./lib/core/context.c` to include\na pointer to your new role's ops struct, following the style already there.\n\n```\nconst struct lws_role_ops * available_roles[] \u003d {\n#if defined(LWS_ROLE_H2)\n\t\u0026role_ops_h2,\n#endif\n...\n```\n\nThis makes lws aware that your role exists, and it can auto-generate some things like\nALPN lists, and call your role ops callbacks for things like hooking vhost creation.\n\n### Enabling role adoption\n\nThe primary way wsi get bound to a specific role is via the lws adoption api\n`lws_adopt_descriptor_vhost()`. Add flags as necessary in `./include/libwebsockets/lws-adopt.h`\n`enum lws_adoption_type` and follow the existing code in `lws_adopt_descriptor_vhost()`\nto bind a wsi with suitable flags to your role ops.\n\n### Implementation of the role\n\nAfter that plumbing-in is completed, the role ops you declare are \u0022live\u0022 on a wsi\nbound to them via the adoption api.\n\nThe core support for wsis in lws has some generic concepts\n\n - the wsi holds a pointer member `role_ops` that indicates which role ops the\n wsi is bound to\n\n - the wsi holds a generic uint32 `wsistate` that contains role flags and wsi state\n\n - role flags are provided (LWSIFR_CLIENT, LWSIFR_SERVER) to differentiate between\n client and server connections inside a wsi, along with helpers `lwsi_role_client(wsi)`\n and `lwsi_role_server(wsi)`.\n\n - lws provides around 30 generic states for the wsi starting from 'unconnected' through\n various proxy or tunnel states, to 'established', and then various states shutting\n down until 'dead socket'. The states have testable flags and helpers to discover if\n the wsi state is before establishment `lwsi_state_est(wsi)` and if in the state it is\n in, it can handle pollout `lwsi_state_can_handle_POLLOUT(wsi)`.\n\n - You set the initial binding, role flags and state using `lws_role_transition()`. Afterwards\n you can adjust the state using `lwsi_set_state()`.\n\n### Role ops compression\n\nSince the role ops struct is typically only sparsely filled, rather than have 20 function\npointers most of which may be NULL, there is a separate array of a union of function\npointers that is just long enough for functions that exist in the role, and a nybble index\ntable with a nybble for each possible op, either 0 indicating that the operation is not\nprovided in this role, or 1 - 15 indicating the position of the function pointer in the\narray.\n\n","s":{"c":1721550424,"u": 220}} ],"g": 1223,"chitpc": 0,"ehitpc": 0,"indexed":0 , "ab": 0, "si": 0, "db":0, "di":0, "sat":0, "lfc": "7d0a"}