Name |
Date |
Size |
#Lines |
LOC |
||
---|---|---|---|---|---|---|
.. | - | - | ||||
README.async-dns.md | D | 23-Nov-2023 | 4.3 KiB | 101 | 77 | |
README.build-windows.md | D | 23-Nov-2023 | 2.2 KiB | 76 | 46 | |
README.build.md | D | 23-Nov-2023 | 26.2 KiB | 742 | 543 | |
README.ci.md | D | 23-Nov-2023 | 911 | 30 | 18 | |
README.coding.md | D | 23-Nov-2023 | 53.2 KiB | 1,374 | 989 | |
README.content-security-policy.md | D | 23-Nov-2023 | 5.8 KiB | 149 | 112 | |
README.contributing.md | D | 23-Nov-2023 | 1.1 KiB | 42 | 25 | |
README.crypto-apis.md | D | 23-Nov-2023 | 7.7 KiB | 182 | 133 | |
README.detailed-latency.md | D | 23-Nov-2023 | 3.3 KiB | 118 | 93 | |
README.esp32.md | D | 23-Nov-2023 | 1.9 KiB | 38 | 23 | |
README.generic-sessions.md | D | 23-Nov-2023 | 12.9 KiB | 374 | 268 | |
README.generic-table.md | D | 23-Nov-2023 | 6.3 KiB | 220 | 153 | |
README.h2-long-poll.md | D | 23-Nov-2023 | 1.8 KiB | 56 | 39 | |
README.http-fallback.md | D | 23-Nov-2023 | 6.5 KiB | 173 | 124 | |
README.lws_dll.md | D | 23-Nov-2023 | 3.7 KiB | 131 | 88 | |
README.lws_retry.md | D | 23-Nov-2023 | 3.8 KiB | 99 | 72 | |
README.lws_sequencer.md | D | 23-Nov-2023 | 6.3 KiB | 150 | 116 | |
README.lws_struct.md | D | 23-Nov-2023 | 1.5 KiB | 39 | 26 | |
README.lws_sul.md | D | 23-Nov-2023 | 2.1 KiB | 63 | 47 | |
README.lws_system.md | D | 23-Nov-2023 | 7.7 KiB | 220 | 161 | |
README.lwsws.md | D | 23-Nov-2023 | 24.6 KiB | 703 | 530 | |
README.plugin-acme.md | D | 23-Nov-2023 | 5.9 KiB | 181 | 122 | |
README.plugin-sshd-base.md | D | 23-Nov-2023 | 7.9 KiB | 250 | 187 | |
README.porting.md | D | 23-Nov-2023 | 2.1 KiB | 61 | 39 | |
README.problems.md | D | 23-Nov-2023 | 3 KiB | 67 | 48 | |
README.release-policy.md | D | 23-Nov-2023 | 5.6 KiB | 127 | 91 | |
README.test-apps.md | D | 23-Nov-2023 | 14.5 KiB | 449 | 328 | |
README.udp.md | D | 23-Nov-2023 | 1.7 KiB | 51 | 38 | |
README.unix-domain-reverse-proxy.md | D | 23-Nov-2023 | 4.5 KiB | 102 | 72 | |
README.vulnerability-reporting.md | D | 23-Nov-2023 | 337 | 13 | 8 | |
mainpage.md | D | 23-Nov-2023 | 1,009 | 24 | 17 | |
release-checklist | D | 23-Nov-2023 | 1.4 KiB | 86 | 48 |
README.async-dns.md
1# Asynchronous DNS 2 3## Introduction 4 5Lws now features optional asynchronous, ie, nonblocking recursive DNS 6resolution done on the event loop, enable `-DLWS_WITH_SYS_ASYNC_DNS=1` 7at cmake to build it in. 8 9## Description 10 11The default libc name resolution is via libc `getaddrinfo()`, which is 12blocking, possibly for quite long periods (seconds). If you are 13taking care about latency, but want to create outgoing connections, 14you can't tolerate this exception from the rule that everything in 15lws is nonblocking. 16 17Lws' asynchronous DNS resolver creates a caching name resolver 18that directly queries the configured nameserver itself over UDP, 19from the event loop. 20 21It supports both ipv4 / A records and ipv6 / AAAA records (see later 22for a description about how). One server supported over UDP :53, 23and the nameserver is autodicovered on linux, windows, and freertos. 24 25Other features 26 27 - lws-style paranoid response parsing 28 - random unique tid generation to increase difficulty of poisoning 29 - it's really integrated with the lws event loop, it does not spawn 30 threads or use the libc resolver, and of course no blocking at all 31 - platform-specific server address capturing (from /etc/resolv.conf 32 on linux, windows apis on windows) 33 - LRU caching 34 - piggybacking (multiple requests before the first completes go on 35 a list on the first request, not spawn multiple requests) 36 - observes TTL in cache 37 - TTL and timeout use `lws_sul` timers on the event loop 38 - Uses CNAME resolution inside the same response if present, otherwise 39 recurses to resolve the CNAME (up to 3 deep) 40 - ipv6 pieces only built if cmake `LWS_IPV6` enabled 41 42## Api 43 44If enabled at cmake, the async DNS implementation is used automatically 45for lws client connections. It's also possible to call it directly, see 46the api-test-async-dns example for how. 47 48The Api follows that of `getaddrinfo()` but results are not created on 49the heap. Instead a single, const cached copy of the addrinfo struct 50chain is reference-counted, with `lws_async_dns_freeaddrinfo()` provided 51to deduct from the reference count. Cached items with a nonzero 52reference count can't be destroyed from the cache, so it's safe to keep 53a pointer to the results and iterate through them. 54 55## Dealing with IPv4 and IPv6 56 57DNS is a very old standard that has some quirks... one of them is that 58multiple queries are not supported in one packet, even though the protocol 59suggests it is. This creates problems on ipv6 enabled systems, where 60it may prefer to have AAAA results, but the server may only have A records. 61 62To square the circle, for ipv4 only systems (`LWS_IPV6=0`) the resolver 63requests only A records. For ipv6-capable systems, it always requests 64first A and then immediately afterwards AAAA records. 65 66To simplify the implementation, the tid b0 is used to differentiate 67between A (b0 = 0) and AAAA (b0 = 1) requests and responses using the 68same query body. 69 70The first response to come back is parsed, and a cache entry made... 71it leaves a note in the query about the address of the last `struct addrinfo` 72record. When the second response comes, a second allocation is made, 73but not added to the logical cache... instead it's chained on to the 74first cache entry and the `struct addrinfo` linked-list from the 75first cache entry is extended into the second one. At the time the 76second result arrives, the query is destroyed and the cached results 77provided on the result callback. 78 79## Recursion 80 81Where CNAMEs are returned, DNS servers may take two approaches... if the 82CNAME is also resolved by the same server and so it knows what it should 83resolve to, it may provide the CNAME resolution in the same response 84packet. 85 86In the case the CNAME is actually resolved by a different name server, 87the server with the CNAME does not have the information to hand to also 88resolve the CNAME in the same response. So it just leaves it for the 89client to sort out. 90 91The lws implementation can deal with both of these, first it "recurses" 92(it does not recurse on the process stack but uses its own manual stack) 93to look for results in the same packet that told it about the CNAME. If 94there are no results, it resets the query to look instead for the CNAME, 95and restarts it. It allows this to happen for 3 CNAME deep. 96 97At the end, either way, the cached result is set using the original 98query name and the results from the last CNAME in the chain. 99 100 101
README.build-windows.md
1# Some notes for the windows jungle 2 3This was how I compiled libwebsockets in windows March 2020. 4 5## OpenSSL 6 7### Installing prebuilt libs 8 9I used the 1.1.1d (the latest) libs from here, as recommended on the OpenSSL site 10 11[overbyte.eu](https:..wiki.overbyte.eu/wiki/index.php/ICS_Download#Download_OpenSSL_Binaries_.28required_for_SSL-enabled_components.29) 12 13I had to use procmon64 (windows' strace) to establish that these libraries are 14looking for a cert bundle at "C:\Program Files\Common Files\SSL\cert.pem"... it's not 15included in the zip file from the above, so... 16 17### Installing a cert bundle 18 19You can get a trusted cert bundle from here 20 21[drwetter/testssl cert bundle](https://raw.githubusercontent.com/drwetter/testssl.sh/3.1dev/etc/Microsoft.pem) 22 23Save it into `C:\Program Files\Common Files\SSL\cert.pem` where openssl will be able to see it. 24 25### Installing cmake 26 27CMake have a windows installer thing downloadable from here 28 29[cmake](https://cmake.org/download/) 30 31after that you can use `cmake` from the terminal OK. 32 33### Installing git 34 35Visit the canonical git site to download their windows installer thing 36 37[git](https://git-scm.com/download/win) 38 39after that `git` from the terminal is working. 40 41### Install the free "community" visual studio 42 43You can do this through "windows store" by searching for "visual studio" 44 45I installed as little as possible, we just want the C "C++" tools. 46 47It still wouldn't link without the "mt" helper tool from the 48huge windows SDK, so you have to install GB of that as well. 49 50### Building 51 52Somehow windows cmake seems slightly broken, some of the plugins and 53examples are conditional on `if (NOT WIN32)`, but it configures them 54anyway. For this reason (it seems "only", it worked when I commented the 55cmake entries for the related plugins) `-DLWS_WITH_MINIMAL_EXAMPLES=1` 56 57Instead I followed how appveyor builds the stuff in CI... clone libwebsockets then 58 59``` 60> git clone https://libwebsockets.org/repo/libwebsockets 61> cd libwebsockets 62> mkdir build 63> cd build 64> cmake .. 65> cmake --build . --config DEBUG 66``` 67 68Installing requires admin privs, I opened a second cmd window as admin and did it 69there. 70 71``` 72> cmake --install . --config DEBUG 73``` 74 75After that you can run the test apps OK. 76
README.build.md
1Notes about building lws 2======================== 3 4You can download and install lws using the [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager: 5``` 6git clone https://github.com/microsoft/vcpkg.git 7cd vcpkg 8./bootstrap-vcpkg.sh 9./vcpkg integrate install 10vcpkg install libwebsockets 11``` 12The lws port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg/) on the vcpkg repository. 13 14@section cm Introduction to CMake 15 16CMake is a multi-platform build tool that can generate build files for many 17different target platforms. See more info at http://www.cmake.org 18 19CMake also allows/recommends you to do "out of source"-builds, that is, 20the build files are separated from your sources, so there is no need to 21create elaborate clean scripts to get a clean source tree, instead you 22simply remove your build directory. 23 24Libwebsockets has been tested to build successfully on the following platforms 25with SSL support (for OpenSSL/wolfSSL/BoringSSL): 26 27- Windows (Visual Studio) 28- Windows (MinGW) 29- Linux (x86 and ARM) 30- OSX 31- NetBSD 32 33 34@section build1 Building the library and test apps 35 36The project settings used by CMake to generate the platform specific build 37files is called [CMakeLists.txt](../CMakeLists.txt). CMake then uses one of its "Generators" to 38output a Visual Studio project or Make file for instance. To see a list of 39the available generators for your platform, simply run the "cmake" command. 40 41Note that by default OpenSSL will be linked, if you don't want SSL support 42see below on how to toggle compile options. 43 44 45@section bu Building on Unix: 46 471. Install CMake 2.8 or greater: http://cmake.org/cmake/resources/software.html 48 (Most Unix distributions comes with a packaged version also) 49 502. Install OpenSSL. 51 523. Generate the build files (default is Make files): 53``` 54 $ cd /path/to/src 55 $ mkdir build 56 $ cd build 57 $ cmake .. 58``` 59 604. Finally you can build using the generated Makefile: 61``` 62 $ make && sudo make install 63``` 64**NOTE**: The `build/`` directory can have any name and be located anywhere 65 on your filesystem, and that the argument `..` given to cmake is simply 66 the source directory of **libwebsockets** containing the [CMakeLists.txt](../CMakeLists.txt) 67 project file. All examples in this file assumes you use ".." 68 69**NOTE2**: 70A common option you may want to give is to set the install path, same 71as --prefix= with autotools. It defaults to /usr/local. 72You can do this by, eg 73``` 74 $ cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr . 75``` 76 77**NOTE3**: 78On machines that want libraries in lib64, you can also add the 79following to the cmake line 80``` 81 -DLIB_SUFFIX=64 82``` 83 84**NOTE4**: 85If you are building against a non-distro OpenSSL (eg, in order to get 86access to ALPN support only in newer OpenSSL versions) the nice way to 87express that in one cmake command is eg, 88``` 89 $ cmake .. -DOPENSSL_ROOT_DIR=/usr/local/ssl \ 90 -DCMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE=/usr/local/ssl \ 91 -DLWS_WITH_HTTP2=1 92``` 93 94When you run the test apps using non-distro SSL, you have to force them 95to use your libs, not the distro ones 96``` 97 $ LD_LIBRARY_PATH=/usr/local/ssl/lib libwebsockets-test-server --ssl 98``` 99 100To get it to build on latest openssl (2016-04-10) it needed this approach 101``` 102 cmake .. -DLWS_WITH_HTTP2=1 -DLWS_OPENSSL_INCLUDE_DIRS=/usr/local/include/openssl -DLWS_OPENSSL_LIBRARIES="/usr/local/lib64/libssl.so;/usr/local/lib64/libcrypto.so" 103``` 104 105Mac users have reported 106 107``` 108 $ export OPENSSL_ROOT_DIR=/usr/local/Cellar/openssl/1.0.2k; cmake ..; make -j4 109``` 110 111worked for them when using "homebrew" OpenSSL 112 113**NOTE5**: 114To build with debug info and _DEBUG for lower priority debug messages 115compiled in, use 116``` 117 $ cmake .. -DCMAKE_BUILD_TYPE=DEBUG 118``` 119 120**NOTE6** 121To build on Solaris the linker needs to be informed to use lib socket 122and libnsl, and only builds in 64bit mode. 123 124```bash 125 $ cmake .. -DCMAKE_C_FLAGS=-m64 -DCMAKE_EXE_LINKER_FLAGS="-lsocket -lnsl" 126``` 127 128**NOTE7** 129 130Build and test flow against boringssl. Notice `LWS_WITH_GENHASH` is currently 131unavailable with boringssl due to their removing the necessary apis. 132 133Build current HEAD boringssl 134 135``` 136 $ cd /projects 137 $ git clone https://boringssl.googlesource.com/boringssl 138 $ cd boringssl 139 $ mkdir build 140 $ cd build 141 $ cmake .. -DBUILD_SHARED_LIBS=1 142 $ make -j8 143``` 144 145Build and test lws against it 146 147``` 148 $ cd /projects/libwebsockets/build 149 $ cmake .. -DOPENSSL_LIBRARIES="/projects/boringssl/build/ssl/libssl.so;\ 150 /projects/boringssl/build/crypto/libcrypto.so" \ 151 -DOPENSSL_INCLUDE_DIRS=/projects/boringssl/include \ 152 -DLWS_WITH_BORINGSSL=1 -DCMAKE_BUILD_TYPE=DEBUG 153 $ make -j8 && sudo make install 154 $ LD_PRELOAD="/projects/boringssl/build/ssl/libssl.so \ 155 /projects/boringssl/build/crypto/libcrypto.so" \ 156 /usr/local/bin/libwebsockets-test-server -s 157``` 158 1594. Finally you can build using the generated Makefile: 160 161```bash 162 $ make 163 ``` 164 165@section lcap Linux Capabilities 166 167On Linux, lws now lets you retain selected root capabilities when dropping 168privileges. If libcap-dev or similar package is installed providing 169sys/capabilities.h, and libcap or similar package is installed providing 170libcap.so, CMake will enable the capability features. 171 172The context creation info struct .caps[] and .count_caps members can then 173be set by user code to enable selected root capabilities to survive the 174transition to running under an unprivileged user. 175 176@section cmq Quirk of cmake 177 178When changing cmake options, for some reason the only way to get it to see the 179changes sometimes is delete the contents of your build directory and do the 180cmake from scratch. 181 182deleting build/CMakeCache.txt may be enough. 183 184 185@section cmw Building on Windows (Visual Studio) 186 1871. Install CMake 2.6 or greater: http://cmake.org/cmake/resources/software.html 188 1892. Install OpenSSL binaries. https://wiki.openssl.org/index.php/Binaries 190 191 (**NOTE**: Preferably in the default location to make it easier for CMake to find them) 192 193 **NOTE2**: 194 Be sure that OPENSSL_CONF environment variable is defined and points at 195 <OpenSSL install location>\bin\openssl.cfg 196 1973. Generate the Visual studio project by opening the Visual Studio cmd prompt: 198 199``` 200 cd <path to src> 201 md build 202 cd build 203 cmake -G "Visual Studio 10" .. 204``` 205 206 (**NOTE**: There is also a cmake-gui available on Windows if you prefer that) 207 208 **NOTE2**: 209 See this link to find out the version number corresponding to your Visual Studio edition: 210 http://superuser.com/a/194065 211 2124. Now you should have a generated Visual Studio Solution in your 213 `<path to src>/build` directory, which can be used to build. 214 2155. Some additional deps may be needed 216 217 - iphlpapi.lib 218 - psapi.lib 219 - userenv.lib 220 2216. If you're using libuv, you must make sure to compile libuv with the same multithread-dll / Mtd attributes as libwebsockets itself 222 223 224@section cmwmgw Building on Windows (MinGW) 225 2261. Install MinGW 227 228 For Fedora, it's, eg, `dnf install mingw64-gcc` 229 2302. Install current CMake package 231 232 For Fedora, it's `dnf install cmake` 233 2343. Instal mingw-built OpenSSL pieces 235 236 For Fedora, it's `mingw64-openssl.noarch mingw64-openssl-static.noarch` 237 238 mingw64-cmake as described below will auto-find the libs and includes 239 for build. But to execute the apps, they either need to go into the same 240 `/usr/x86_64-w64-mingw32/sys-root/mingw/bin/` as the dlls are installed to, 241 or the dlls have to be copied into the same dir as your app executable. 242 2434. Generate the build files (default is Make files) using MSYS shell. 244 245 For Fedora, they provide a `mingw64-cmake` wrapper in the package 246 `mingw64-filesystem`, with this you can run that instead of cmake directly 247 and don't have to get involved with setting the cmake generator. 248 249 Otherwise doing it by hand is like this: 250 251``` 252 $ cd /drive/path/to/src 253 $ mkdir build 254 $ cd build 255 $ cmake -G "MSYS Makefiles" -DCMAKE_INSTALL_PREFIX=C:/MinGW .. 256``` 257 258 To generate build files allowing to create libwebsockets binaries with debug information 259 set the CMAKE_BUILD_TYPE flag to DEBUG: 260``` 261 $ cmake -G "MSYS Makefiles" -DCMAKE_INSTALL_PREFIX=C:/MinGW -DCMAKE_BUILD_TYPE=DEBUG .. 262``` 2635. Finally you can build using the generated Makefile and get the results deployed into your MinGW installation: 264 265``` 266 $ make && make install 267``` 268 269@section distro Selecting CMake options useful for distros 270 271Distro packagers should select the CMake option "LWS_WITH_DISTRO_RECOMMENDED", 272which selects common additional options like support for various event libraries, 273plugins and lwsws. 274 275@section ssllib Choosing Your TLS Poison 276 277 - If you are really restricted on memory, code size, or don't care about TLS 278 speed, mbedTLS is a good choice: `cmake .. -DLWS_WITH_MBEDTLS=1` 279 280 - If cpu and memory is not super restricted and you care about TLS speed, 281 OpenSSL or a directly compatible variant like Boring SSL is a good choice. 282 283Just building lws against stock Fedora OpenSSL or stock Fedora mbedTLS, for 284SSL handhake mbedTLS takes ~36ms and OpenSSL takes ~1ms on the same x86_64 285build machine here, with everything else the same. Over the 144 connections of 286h2spec compliance testing for example, this ends up completing in 400ms for 287OpenSSL and 5.5sec for mbedTLS on x86_64. In other words mbedTLS is very slow 288compared to OpenSSL under the (fairly typical) conditions I tested it. 289 290This isn't an inefficiency in the mbedtls interface implementation, it's just 291mbedTLS doing the crypto much slower than OpenSSL, which has accelerated 292versions of common crypto operations it automatically uses for platforms 293supporting it. As of Oct 2017 mbedTLS itself has no such optimizations for any 294platform that I could find. It's just pure C running on the CPU. 295 296Lws supports both almost the same, so instead of taking my word for it you are 297invited to try it both ways and see which the results (including, eg, binary 298size and memory usage as well as speed) suggest you use. 299 300NOTE: one major difference with mbedTLS is it does not load the system trust 301store by default. That has advantages and disadvantages, but the disadvantage 302is you must provide the CA cert to lws built against mbedTLS for it to be able 303to validate it, ie, use -A with the test client. The minimal test clients 304have the CA cert for warmcat.com and libwebsockets.org and use it if they see 305they were built with mbedTLS. 306 307@section optee Building for OP-TEE 308 309OP-TEE is a "Secure World" Trusted Execution Environment. 310 311Although lws is only part of the necessary picture to have an https-enabled 312TA, it does support OP-TEE as a platform and if you provide the other 313pieces, does work very well. 314 315Select it in cmake with `-DLWS_PLAT_OPTEE=1` 316 317 318@section cmco Setting compile options 319 320To set compile time flags you can either use one of the CMake gui applications 321or do it via the command line. 322 323@subsection cmcocl Command line 324 325To list available options (omit the H if you don't want the help text): 326 327 cmake -LH .. 328 329Then to set an option and build (for example turn off SSL support): 330 331 cmake -DLWS_WITH_SSL=0 .. 332or 333 cmake -DLWS_WITH_SSL:BOOL=OFF .. 334 335@subsection cmcoug Unix GUI 336 337If you have a curses-enabled build you simply type: 338(not all packages include this, my debian install does not for example). 339 340 ccmake 341 342@subsection cmcowg Windows GUI 343 344On windows CMake comes with a gui application: 345 Start -> Programs -> CMake -> CMake (cmake-gui) 346 347 348@section wolf wolfSSL/CyaSSL replacement for OpenSSL 349 350wolfSSL/CyaSSL is a lightweight SSL library targeted at embedded systems: 351https://www.wolfssl.com/wolfSSL/Products-wolfssl.html 352 353It contains a OpenSSL compatibility layer which makes it possible to pretty 354much link to it instead of OpenSSL, giving a much smaller footprint. 355 356**NOTE**: wolfssl needs to be compiled using the `--enable-opensslextra` flag for 357this to work. 358 359@section wolf1 Compiling libwebsockets with wolfSSL 360 361``` 362 cmake .. -DLWS_WITH_WOLFSSL=1 \ 363 -DLWS_WOLFSSL_INCLUDE_DIRS=/path/to/wolfssl \ 364 -DLWS_WOLFSSL_LIBRARIES=/path/to/wolfssl/wolfssl.a .. 365``` 366 367**NOTE**: On windows use the .lib file extension for `LWS_WOLFSSL_LIBRARIES` instead. 368 369@section cya Compiling libwebsockets with CyaSSL 370 371``` 372 cmake .. -DLWS_WITH_CYASSL=1 \ 373 -DLWS_CYASSL_INCLUDE_DIRS=/path/to/cyassl \ 374 -DLWS_CYASSL_LIBRARIES=/path/to/wolfssl/cyassl.a .. 375``` 376 377**NOTE**: On windows use the .lib file extension for `LWS_CYASSL_LIBRARIES` instead. 378 379@section gzip Selecting GZIP or MINIZ 380 381By default lws supports gzip when compression is needed. But you can tell it to use 382MINIZ instead by using `-DLWS_WITH_MINIZ=1`. 383 384For native build cmake will try to find an existing libminiz.so or .a and build 385against that and the found includes automatically. 386 387For cross-build or building against local miniz, you need the following kind of 388cmake to tell it where to get miniz 389 390``` 391cmake .. -DLWS_WITH_MINIZ=1 -DLWS_WITH_ZIP_FOPS=1 -DMINIZ_INCLUDE_DIRS="/projects/miniz;/projects/miniz/build" -DMINIZ_LIBRARIES=/projects/miniz/build/libminiz.so.2.1.0 392``` 393 394@section esp32 Building for ESP32 395 396Building for ESP32 requires the ESP-IDF framework. It can be built under Linux, OSX or Windows (MSYS2). 397 3981. Install ESP-IDF, follow the getting started guide here - http://esp-idf.readthedocs.io/en/latest/get-started/ 3992. Set ESP-IDF to last known working version (assuming ESP-IDF is in `~/esp/esp-idf`) : 400``` 401 cd ~/esp/esp-idf 402 git checkout 0c50b65a34cd6b3954f7435193411a88adb49cb0 403 git submodule update --recursive 404``` 4053. Add `libwebsockets` as a submodule in the `components` folder of your ESP-IDF project: 406``` 407 git submodule add https://github.com/warmcat/libwebsockets.git components/libwebsockets 408``` 4094. If on Windows (MSYS2) you will need to install CMake in the MSYS2 environment: 410``` 411 pacman -S mingw-w64-i686-cmake 412``` 413If you're on Linux or OSX ensure CMake version is at least 3.7. 414 415@section extplugins Building plugins outside of lws itself 416 417The directory ./plugin-standalone/ shows how easy it is to create plugins 418outside of lws itself. First build lws itself with -DLWS_WITH_PLUGINS, 419then use the same flow to build the standalone plugin 420``` 421 cd ./plugin-standalone 422 mkdir build 423 cd build 424 cmake .. 425 make && sudo make install 426``` 427 428if you changed the default plugin directory when you built lws, you must 429also give the same arguments to cmake here (eg, 430` -DCMAKE_INSTALL_PREFIX:PATH=/usr/something/else...` ) 431 432Otherwise if you run lwsws or libwebsockets-test-server-v2.0, it will now 433find the additional plugin "libprotocol_example_standalone.so" 434``` 435 lwsts[21257]: Plugins: 436 lwsts[21257]: libprotocol_dumb_increment.so 437 lwsts[21257]: libprotocol_example_standalone.so 438 lwsts[21257]: libprotocol_lws_mirror.so 439 lwsts[21257]: libprotocol_lws_server_status.so 440 lwsts[21257]: libprotocol_lws_status.so 441``` 442If you have multiple vhosts, you must enable plugins at the vhost 443additionally, discovered plugins are not enabled automatically for security 444reasons. You do this using info->pvo or for lwsws, in the JSON config. 445 446 447@section http2rp Reproducing HTTP/2 tests 448 449Enable `-DLWS_WITH_HTTP2=1` in cmake to build with http/2 support enabled. 450 451You must have built and be running lws against a version of openssl that has 452ALPN. At the time of writing, recent distros have started upgrading to OpenSSL 4531.1+ that supports this already. You'll know it's right by seeing 454 455``` 456 lwsts[4752]: Compiled with OpenSSL support 457 lwsts[4752]: Using SSL mode 458 lwsts[4752]: HTTP2 / ALPN enabled 459``` 460at lws startup. 461 462Recent Firefox and Chrome also support HTTP/2 by ALPN, so these should just work 463with the test server running in -s / ssl mode. 464 465For testing with nghttp client: 466 467``` 468 $ nghttp -nvas https://localhost:7681/test.html 469``` 470 471Testing with h2spec (https://github.com/summerwind/h2spec) 472 473``` 474 $ h2spec -h 127.0.0.1 -p 7681 -t -k -v -o 1 475``` 476 477``` 478145 tests, 145 passed, 0 skipped, 0 failed 479 480``` 481 482@section coverage Automated Coverage Testing 483 484./test-apps/attack.sh contains scripted tests that are the basis 485of the automated test coverage assessment available for gcc and clang. 486 487To reproduce 488 489 $ cd build 490 $ cmake .. -DLWS_WITH_GCOV=1 -DCMAKE_BUILD_TYPE=DEBUG 491 $ ../scripts/build-gcov.sh 492 $ ../test-apps/attack.sh 493 $ ../scripts/gcov.sh 494... 495Lines executed:51.24% of 8279 496 497@section windowsprebuilt Using Windows binary builds on Appveyor 498 499The CI builds on Appveyor now produce usable binary outputs. Visit 500 501[lws on Appveyor](https://ci.appveyor.com/project/lws-team/libwebsockets) 502 503and select one of the builds, then click on ARTIFACTS at the top right. The zip file 504want to be unpacked into `C:\Program Files (x86)/libwebsockets`, after that, you should be able to run the test server, by running it from `bin/Release/libwebsockets-test-server.exe` and opening a browser on http://127.0.0.1:7681 505 506@section cross Cross compiling 507 508To enable cross-compiling **libwebsockets** using CMake you need to create 509a "Toolchain file" that you supply to CMake when generating your build files. 510CMake will then use the cross compilers and build paths specified in this file 511to look for dependencies and such. 512 513**Libwebsockets** includes an example toolchain file [cross-arm-linux-gnueabihf.cmake](../contrib/cross-arm-linux-gnueabihf.cmake) 514you can use as a starting point. 515 516The commandline to configure for cross with this would look like 517``` 518 $ cmake .. -DCMAKE_INSTALL_PREFIX:PATH=/usr/lib/my-cross-root \ 519 -DCMAKE_TOOLCHAIN_FILE=../contrib/cross-arm-linux-gnueabihf.cmake \ 520 -DLWS_WITHOUT_EXTENSIONS=1 -DLWS_WITH_SSL=0 \ 521 -DLWS_WITH_ZIP_FOPS=0 -DLWS_WITH_ZLIB=0 522``` 523The example shows how to build with no external cross lib dependencies, you 524need to provide the cross libraries otherwise. 525 526**NOTE**: start from an EMPTY build directory if you had a non-cross build in there 527 before the settings will be cached and your changes ignored. 528 Delete `build/CMakeCache.txt` at least before trying a new cmake config 529 to ensure you are really building the options you think you are. 530 531Additional information on cross compilation with CMake: 532 http://www.vtk.org/Wiki/CMake_Cross_Compiling 533 534@section cross_example Complex Cross compiling example 535 536Here are step by step instructions for cross-building the external projects needed for lws with lwsws + mbedtls as an example. 537 538In the example, my toolchain lives in `/projects/aist-tb/arm-tc` and is named `arm-linux-gnueabihf`. So you will need to adapt those to where your toolchain lives and its name where you see them here. 539 540Likewise I do all this in /tmp but it has no special meaning, you can adapt that to somewhere else. 541 542All "foreign" cross-built binaries are sent into `/tmp/cross` so they cannot be confused for 'native' x86_64 stuff on your host machine in /usr/[local/].... 543 544## Prepare the cmake toolchain file 545 5461) `cd /tmp` 547 5482) `wget -O mytoolchainfile https://raw.githubusercontent.com/warmcat/libwebsockets/master/contrib/cross-arm-linux-gnueabihf.cmake` 549 5503) Edit `/tmp/mytoolchainfile` adapting `CROSS_PATH`, `CMAKE_C_COMPILER` and `CMAKE_CXX_COMPILER` to reflect your toolchain install dir and path to your toolchain C and C++ compilers respectively. For my case: 551 552``` 553set(CROSS_PATH /projects/aist-tb/arm-tc/) 554set(CMAKE_C_COMPILER "${CROSS_PATH}/bin/arm-linux-gnueabihf-gcc") 555set(CMAKE_CXX_COMPILER "${CROSS_PATH}/bin/arm-linux-gnueabihf-g++") 556``` 557 558## 1/4: Building libuv cross: 559 5601) `export PATH=/projects/aist-tb/arm-tc/bin:$PATH` Notice there is a **/bin** on the end of the toolchain path 561 5622) `cd /tmp ; mkdir cross` we will put the cross-built libs in /tmp/cross 563 5643) `git clone https://github.com/libuv/libuv.git` get libuv 565 5664) `cd libuv` 567 5685) `./autogen.sh` 569 570``` 571+ libtoolize --copy 572libtoolize: putting auxiliary files in '.'. 573libtoolize: copying file './ltmain.sh' 574libtoolize: putting macros in AC_CONFIG_MACRO_DIRS, 'm4'. 575libtoolize: copying file 'm4/libtool.m4' 576libtoolize: copying file 'm4/ltoptions.m4' 577libtoolize: copying file 'm4/ltsugar.m4' 578libtoolize: copying file 'm4/ltversion.m4' 579libtoolize: copying file 'm4/lt~obsolete.m4' 580+ aclocal -I m4 581+ autoconf 582+ automake --add-missing --copy 583configure.ac:38: installing './ar-lib' 584configure.ac:25: installing './compile' 585configure.ac:22: installing './config.guess' 586configure.ac:22: installing './config.sub' 587configure.ac:21: installing './install-sh' 588configure.ac:21: installing './missing' 589Makefile.am: installing './depcomp' 590``` 591If it has problems, you will need to install `automake`, `libtool` etc. 592 5936) `./configure --host=arm-linux-gnueabihf --prefix=/tmp/cross` 594 5957) `make && make install` this will install to `/tmp/cross/...` 596 5978) `file /tmp/cross/lib/libuv.so.1.0.0` Check it's really built for ARM 598``` 599/tmp/cross/lib/libuv.so.1.0.0: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, BuildID[sha1]=cdde0bc945e51db6001a9485349c035baaec2b46, with debug_info, not stripped 600``` 601 602## 2/4: Building zlib cross 603 6041) `cd /tmp` 605 6062) `git clone https://github.com/madler/zlib.git` 607 6083) `CC=arm-linux-gnueabihf-gcc ./configure --prefix=/tmp/cross` 609``` 610Checking for shared library support... 611Building shared library libz.so.1.2.11 with arm-linux-gnueabihf-gcc. 612Checking for size_t... Yes. 613Checking for off64_t... Yes. 614Checking for fseeko... Yes. 615Checking for strerror... Yes. 616Checking for unistd.h... Yes. 617Checking for stdarg.h... Yes. 618Checking whether to use vs[n]printf() or s[n]printf()... using vs[n]printf(). 619Checking for vsnprintf() in stdio.h... Yes. 620Checking for return value of vsnprintf()... Yes. 621Checking for attribute(visibility) support... Yes. 622``` 623 6244) `make && make install` 625``` 626arm-linux-gnueabihf-gcc -O3 -D_LARGEFILE64_SOURCE=1 -DHAVE_HIDDEN -I. -c -o example.o test/example.c 627... 628rm -f /tmp/cross/include/zlib.h /tmp/cross/include/zconf.h 629cp zlib.h zconf.h /tmp/cross/include 630chmod 644 /tmp/cross/include/zlib.h /tmp/cross/include/zconf.h 631``` 632 6335) `file /tmp/cross/lib/libz.so.1.2.11` This is just to confirm we built an ARM lib as expected 634``` 635/tmp/cross/lib/libz.so.1.2.11: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, BuildID[sha1]=6f8ffef84389b1417d2fd1da1bd0c90f748f300d, with debug_info, not stripped 636``` 637 638## 3/4: Building mbedtls cross 639 6401) `cd /tmp` 641 6422) `git clone https://github.com/ARMmbed/mbedtls.git` 643 6443) `cd mbedtls ; mkdir build ; cd build` 645 6463) `cmake .. -DCMAKE_TOOLCHAIN_FILE=/tmp/mytoolchainfile -DCMAKE_INSTALL_PREFIX:PATH=/tmp/cross -DCMAKE_BUILD_TYPE=RELEASE -DUSE_SHARED_MBEDTLS_LIBRARY=1` mbedtls also uses cmake, so you can simply reuse the toolchain file you used for libwebsockets. That is why you shouldn't put project-specific options in the toolchain file, it should just describe the toolchain. 647 6484) `make && make install` 649 6505) `file /tmp/cross/lib/libmbedcrypto.so.2.6.0` 651``` 652/tmp/cross/lib/libmbedcrypto.so.2.6.0: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, BuildID[sha1]=bcca195e78bd4fd2fb37f36ab7d72d477d609d87, with debug_info, not stripped 653``` 654 655## 4/4: Building libwebsockets with everything 656 6571) `cd /tmp` 658 6592) `git clone ssh://git@github.com/warmcat/libwebsockets` 660 6613) `cd libwebsockets ; mkdir build ; cd build` 662 6634) (this is all one line on the commandline) 664``` 665cmake .. -DCMAKE_TOOLCHAIN_FILE=/tmp/mytoolchainfile \ 666-DCMAKE_INSTALL_PREFIX:PATH=/tmp/cross \ 667-DLWS_WITH_LWSWS=1 \ 668-DLWS_WITH_MBEDTLS=1 \ 669-DLWS_MBEDTLS_LIBRARIES="/tmp/cross/lib/libmbedcrypto.so;/tmp/cross/lib/libmbedtls.so;/tmp/cross/lib/libmbedx509.so" \ 670-DLWS_MBEDTLS_INCLUDE_DIRS=/tmp/cross/include \ 671-DLWS_LIBUV_LIBRARIES=/tmp/cross/lib/libuv.so \ 672-DLWS_LIBUV_INCLUDE_DIRS=/tmp/cross/include \ 673-DLWS_ZLIB_LIBRARIES=/tmp/cross/lib/libz.so \ 674-DLWS_ZLIB_INCLUDE_DIRS=/tmp/cross/include 675``` 676 6773) `make && make install` 678 6794) `file /tmp/cross/lib/libwebsockets.so.11` 680``` 681/tmp/cross/lib/libwebsockets.so.11: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, BuildID[sha1]=81e59c6534f8e9629a9fc9065c6e955ce96ca690, with debug_info, not stripped 682``` 683 6845) `arm-linux-gnueabihf-objdump -p /tmp/cross/lib/libwebsockets.so.11 | grep NEEDED` Confirm that the lws library was linked against everything we expect (libm / libc are provided by your toolchain) 685``` 686 NEEDED libz.so.1 687 NEEDED libmbedcrypto.so.0 688 NEEDED libmbedtls.so.10 689 NEEDED libmbedx509.so.0 690 NEEDED libuv.so.1 691 NEEDED libm.so.6 692 NEEDED libc.so.6 693``` 694 695You will also find the lws test apps in `/tmp/cross/bin`... to run lws on the target you will need to copy the related things from /tmp/cross... all the .so from /tmp/cross/lib and anything from /tmp/cross/bin you want. 696 697@section mem Memory efficiency 698 699Embedded server-only configuration without extensions (ie, no compression 700on websocket connections), but with full v13 websocket features and http 701server, built on ARM Cortex-A9: 702 703Update at 8dac94d (2013-02-18) 704``` 705 $ ./configure --without-client --without-extensions --disable-debug --without-daemonize 706 707 Context Creation, 1024 fd limit[2]: 16720 (includes 12 bytes per fd) 708 Per-connection [3]: 72 bytes, +1328 during headers 709 710 .text .rodata .data .bss 711 11512 2784 288 4 712``` 713This shows the impact of the major configuration with/without options at 71413ba5bbc633ea962d46d using Ubuntu ARM on a PandaBoard ES. 715 716These are accounting for static allocations from the library elf, there are 717additional dynamic allocations via malloc. These are a bit old now but give 718the right idea for relative "expense" of features. 719 720Static allocations, ARM9 721 722| | .text | .rodata | .data | .bss | 723|--------------------------------|---------|---------|-------|------| 724| All (no without) | 35024 | 9940 | 336 | 4104 | 725| without client | 25684 | 7144 | 336 | 4104 | 726| without client, exts | 21652 | 6288 | 288 | 4104 | 727| without client, exts, debug[1] | 19756 | 3768 | 288 | 4104 | 728| without server | 30304 | 8160 | 336 | 4104 | 729| without server, exts | 25382 | 7204 | 288 | 4104 | 730| without server, exts, debug[1] | 23712 | 4256 | 288 | 4104 | 731 732[1] `--disable-debug` only removes messages below `lwsl_notice`. Since that is 733the default logging level the impact is not noticeable, error, warn and notice 734logs are all still there. 735 736[2] `1024` fd per process is the default limit (set by ulimit) in at least Fedora 737and Ubuntu. You can make significant savings tailoring this to actual expected 738peak fds, ie, at a limit of `20`, context creation allocation reduces to `4432 + 739240 = 4672`) 740 741[3] known header content is freed after connection establishment 742
README.ci.md
1## Need for CI 2 3Generally if we're adding something that's supposed to work ongoing, the stuff 4should be exercised in CI (at least Travis). 5 6If there are few users for a particular feature, experience has shown that 7refactors or other upheaval can easily break it into a state of uselessness 8without anyone noticing until later. 9 10Therefore here's a description of how to add something to the CI tests... this 11is certainly a nonproductive PITA and I have never been thanked for the work 12involved. But if the promise of the various features working is going to 13remain alive, it's necessary to include CI test where possible with new 14nontrivial code. 15 16## Integration points 17 18### cmake 19 20`.travis.yml` maps the various test activities to CMake options needed. 21 22### including dependent packages into travis 23 24See `./scripts/travis_install.sh` 25 26### performing prepared test actions 27 28See `./scripts/travis_control.sh` 29 30
README.coding.md
1Notes about coding with lws 2=========================== 3 4@section era Old lws and lws v2.0 5 6Originally lws only supported the "manual" method of handling everything in the 7user callback found in test-server.c / test-server-http.c. 8 9Since v2.0, the need for most or all of this manual boilerplate has been 10eliminated: the protocols[0] http stuff is provided by a generic lib export 11`lws_callback_http_dummy()`. You can serve parts of your filesystem at part of 12the URL space using mounts, the dummy http callback will do the right thing. 13 14It's much preferred to use the "automated" v2.0 type scheme, because it's less 15code and it's easier to support. 16 17The minimal examples all use the modern, recommended way. 18 19If you just need generic serving capability, without the need to integrate lws 20to some other app, consider not writing any server code at all, and instead use 21the generic server `lwsws`, and writing your special user code in a standalone 22"plugin". The server is configured for mounts etc using JSON, see 23./READMEs/README.lwsws.md. 24 25Although the "plugins" are dynamically loaded if you use lwsws or lws built 26with libuv, actually they may perfectly well be statically included if that 27suits your situation better, eg, ESP32 test server, where the platform does 28not support processes or dynamic loading, just #includes the plugins 29one after the other and gets the same benefit from the same code. 30 31Isolating and collating the protocol code in one place also makes it very easy 32to maintain and understand. 33 34So it if highly recommended you put your protocol-specific code into the 35form of a "plugin" at the source level, even if you have no immediate plan to 36use it dynamically-loaded. 37 38@section writeable Only send data when socket writeable 39 40You should only send data on a websocket connection from the user callback 41`LWS_CALLBACK_SERVER_WRITEABLE` (or `LWS_CALLBACK_CLIENT_WRITEABLE` for 42clients). 43 44If you want to send something, do NOT just send it but request a callback 45when the socket is writeable using 46 47 - `lws_callback_on_writable(wsi)` for a specific `wsi`, or 48 49 - `lws_callback_on_writable_all_protocol(protocol)` for all connections 50using that protocol to get a callback when next writeable. 51 52Usually you will get called back immediately next time around the service 53loop, but if your peer is slow or temporarily inactive the callback will be 54delayed accordingly. Generating what to write and sending it should be done 55in the ...WRITEABLE callback. 56 57See the test server code for an example of how to do this. 58 59Otherwise evolved libs like libuv get this wrong, they will allow you to "send" 60anything you want but it only uses up your local memory (and costs you 61memcpys) until the socket can actually accept it. It is much better to regulate 62your send action by the downstream peer readiness to take new data in the first 63place, avoiding all the wasted buffering. 64 65Libwebsockets' concept is that the downstream peer is truly the boss, if he, 66or our connection to him, cannot handle anything new, we should not generate 67anything new for him. This is how unix shell piping works, you may have 68`cat a.txt | grep xyz > remote", but actually that does not cat anything from 69a.txt while remote cannot accept anything new. 70 71@section oneper Only one lws_write per WRITEABLE callback 72 73From v2.5, lws strictly enforces only one lws_write() per WRITEABLE callback. 74 75You will receive a message about "Illegal back-to-back write of ... detected" 76if there is a second lws_write() before returning to the event loop. 77 78This is because with http/2, the state of the network connection carrying a 79wsi is unrelated to any state of the wsi. The situation on http/1 where a 80new request implied a new tcp connection and new SSL buffer, so you could 81assume some window for writes is no longer true. Any lws_write() can fail 82and be buffered for completion by lws; it will be auto-completed by the 83event loop. 84 85Note that if you are handling your own http responses, writing the headers 86needs to be done with a separate lws_write() from writing any payload. That 87means after writing the headers you must call `lws_callback_on_writable(wsi)` 88and send any payload from the writable callback. 89 90@section otherwr Do not rely on only your own WRITEABLE requests appearing 91 92Libwebsockets may generate additional `LWS_CALLBACK_CLIENT_WRITEABLE` events 93if it met network conditions where it had to buffer your send data internally. 94 95So your code for `LWS_CALLBACK_CLIENT_WRITEABLE` needs to own the decision 96about what to send, it can't assume that just because the writeable callback 97came something is ready to send. 98 99It's quite possible you get an 'extra' writeable callback at any time and 100just need to `return 0` and wait for the expected callback later. 101 102@section dae Daemonization 103 104There's a helper api `lws_daemonize` built by default that does everything you 105need to daemonize well, including creating a lock file. If you're making 106what's basically a daemon, just call this early in your init to fork to a 107headless background process and exit the starting process. 108 109Notice stdout, stderr, stdin are all redirected to /dev/null to enforce your 110daemon is headless, so you'll need to sort out alternative logging, by, eg, 111syslog via `lws_set_log_level(..., lwsl_emit_syslog)`. 112 113@section conns Maximum number of connections 114 115The maximum number of connections the library can deal with is decided when 116it starts by querying the OS to find out how many file descriptors it is 117allowed to open (1024 on Fedora for example). It then allocates arrays that 118allow up to that many connections, minus whatever other file descriptors are 119in use by the user code. 120 121If you want to restrict that allocation, or increase it, you can use ulimit or 122similar to change the available number of file descriptors, and when restarted 123**libwebsockets** will adapt accordingly. 124 125@section peer_limits optional LWS_WITH_PEER_LIMITS 126 127If you select `LWS_WITH_PEER_LIMITS` at cmake, then lws will track peer IPs 128and monitor how many connections and ah resources they are trying to use 129at one time. You can choose to limit these at context creation time, using 130`info.ip_limit_ah` and `info.ip_limit_wsi`. 131 132Note that although the ah limit is 'soft', ie, the connection will just wait 133until the IP is under the ah limit again before attaching a new ah, the 134wsi limit is 'hard', lws will drop any additional connections from the 135IP until it's under the limit again. 136 137If you use these limits, you should consider multiple clients may simultaneously 138try to access the site through NAT, etc. So the limits should err on the side 139of being generous, while still making it impossible for one IP to exhaust 140all the server resources. 141 142@section evtloop Libwebsockets is singlethreaded 143 144Libwebsockets works in a serialized event loop, in a single thread. It supports 145the default poll() backend, and libuv, libev, and libevent event loop 146libraries that also take this locking-free, nonblocking event loop approach that 147is not threadsafe. There are several advantages to this technique, but one 148disadvantage, it doesn't integrate easily if there are multiple threads that 149want to use libwebsockets. 150 151However integration to multithreaded apps is possible if you follow some guidelines. 152 1531) Aside from two APIs, directly calling lws apis from other threads is not allowed. 154 1552) If you want to keep a list of live wsi, you need to use lifecycle callbacks on 156the protocol in the service thread to manage the list, with your own locking. 157Typically you use an ESTABLISHED callback to add ws wsi to your list and a CLOSED 158callback to remove them. 159 1603) LWS regulates your write activity by being able to let you know when you may 161write more on a connection. That reflects the reality that you cannot succeed to 162send data to a peer that has no room for it, so you should not generate or buffer 163write data until you know the peer connection can take more. 164 165Other libraries pretend that the guy doing the writing is the boss who decides 166what happens, and absorb as much as you want to write to local buffering. That does 167not scale to a lot of connections, because it will exhaust your memory and waste 168time copying data around in memory needlessly. 169 170The truth is the receiver, along with the network between you, is the boss who 171decides what will happen. If he stops accepting data, no data will move. LWS is 172designed to reflect that. 173 174If you have something to send, you call `lws_callback_on_writable()` on the 175connection, and when it is writeable, you will get a `LWS_CALLBACK_SERVER_WRITEABLE` 176callback, where you should generate the data to send and send it with `lws_write()`. 177 178You cannot send data using `lws_write()` outside of the WRITEABLE callback. 179 1804) For multithreaded apps, this corresponds to a need to be able to provoke the 181`lws_callback_on_writable()` action and to wake the service thread from its event 182loop wait (sleeping in `poll()` or `epoll()` or whatever). The rules above 183mean directly sending data on the connection from another thread is out of the 184question. 185 186Therefore the two apis mentioned above that may be used from another thread are 187 188 - For LWS using the default poll() event loop, `lws_callback_on_writable()` 189 190 - For LWS using libuv/libev/libevent event loop, `lws_cancel_service()` 191 192If you are using the default poll() event loop, one "foreign thread" at a time may 193call `lws_callback_on_writable()` directly for a wsi. You need to use your own 194locking around that to serialize multiple thread access to it. 195 196If you implement LWS_CALLBACK_GET_THREAD_ID in protocols[0], then LWS will detect 197when it has been called from a foreign thread and automatically use 198`lws_cancel_service()` to additionally wake the service loop from its wait. 199 200For libuv/libev/libevent event loop, they cannot handle being called from other 201threads. So there is a slightly different scheme, you may call `lws_cancel_service()` 202to force the event loop to end immediately. This then broadcasts a callback (in the 203service thread context) `LWS_CALLBACK_EVENT_WAIT_CANCELLED`, to all protocols on all 204vhosts, where you can perform your own locking and walk a list of wsi that need 205`lws_callback_on_writable()` calling on them. 206 207`lws_cancel_service()` is very cheap to call. 208 2095) The obverse of this truism about the receiver being the boss is the case where 210we are receiving. If we get into a situation we actually can't usefully 211receive any more, perhaps because we are passing the data on and the guy we want 212to send to can't receive any more, then we should "turn off RX" by using the 213RX flow control API, `lws_rx_flow_control(wsi, 0)`. When something happens where we 214can accept more RX, (eg, we learn our onward connection is writeable) we can call 215it again to re-enable it on the incoming wsi. 216 217LWS stops calling back about RX immediately you use flow control to disable RX, it 218buffers the data internally if necessary. So you will only see RX when you can 219handle it. When flow control is disabled, LWS stops taking new data in... this makes 220the situation known to the sender by TCP "backpressure", the tx window fills and the 221sender finds he cannot write any more to the connection. 222 223See the mirror protocol implementations for example code. 224 225If you need to service other socket or file descriptors as well as the 226websocket ones, you can combine them together with the websocket ones 227in one poll loop, see "External Polling Loop support" below, and 228still do it all in one thread / process context. If the need is less 229architectural, you can also create RAW mode client and serving sockets; this 230is how the lws plugin for the ssh server works. 231 232@section anonprot Working without a protocol name 233 234Websockets allows connections to negotiate without a protocol name... 235in that case by default it will bind to the first protocol in your 236vhost protocols[] array. 237 238You can tell the vhost to use a different protocol by attaching a 239pvo (per-vhost option) to the 240 241``` 242/* 243 * this sets a per-vhost, per-protocol option name:value pair 244 * the effect is to set this protocol to be the default one for the vhost, 245 * ie, selected if no Protocol: header is sent with the ws upgrade. 246 */ 247 248static const struct lws_protocol_vhost_options pvo_opt = { 249 NULL, 250 NULL, 251 "default", 252 "1" 253}; 254 255static const struct lws_protocol_vhost_options pvo = { 256 NULL, 257 &pvo_opt, 258 "my-protocol", 259 "" 260}; 261 262... 263 264 context_info.pvo = &pvo; 265... 266 267``` 268 269Will select "my-protocol" from your protocol list (even if it came 270in by plugin) as being the target of client connections that don't 271specify a protocol. 272 273@section closing Closing connections from the user side 274 275When you want to close a connection, you do it by returning `-1` from a 276callback for that connection. 277 278You can provoke a callback by calling `lws_callback_on_writable` on 279the wsi, then notice in the callback you want to close it and just return -1. 280But usually, the decision to close is made in a callback already and returning 281-1 is simple. 282 283If the socket knows the connection is dead, because the peer closed or there 284was an affirmitive network error like a FIN coming, then **libwebsockets** will 285take care of closing the connection automatically. 286 287If you have a silently dead connection, it's possible to enter a state where 288the send pipe on the connection is choked but no ack will ever come, so the 289dead connection will never become writeable. To cover that, you can use TCP 290keepalives (see later in this document) or pings. 291 292@section gzip Serving from inside a zip file 293 294Lws now supports serving gzipped files from inside a zip container. Thanks to 295Per Bothner for contributing the code. 296 297This has the advtantage that if the client can accept GZIP encoding, lws can 298simply send the gzip-compressed file from inside the zip file with no further 299processing, saving time and bandwidth. 300 301In the case the client can't understand gzip compression, lws automatically 302decompressed the file and sends it normally. 303 304Clients with limited storage and RAM will find this useful; the memory needed 305for the inflate case is constrained so that only one input buffer at a time 306is ever in memory. 307 308To use this feature, ensure LWS_WITH_ZIP_FOPS is enabled at CMake. 309 310`libwebsockets-test-server-v2.0` includes a mount using this technology 311already, run that test server and navigate to http://localhost:7681/ziptest/candide.html 312 313This will serve the book Candide in html, together with two jpgs, all from 314inside a .zip file in /usr/[local/]share-libwebsockets-test-server/candide.zip 315 316Usage is otherwise automatic, if you arrange a mount that points to the zipfile, 317eg, "/ziptest" -> "mypath/test.zip", then URLs like `/ziptest/index.html` will be 318servied from `index.html` inside `mypath/test.zip` 319 320@section frags Fragmented messages 321 322To support fragmented messages you need to check for the final 323frame of a message with `lws_is_final_fragment`. This 324check can be combined with `libwebsockets_remaining_packet_payload` 325to gather the whole contents of a message, eg: 326 327``` 328 case LWS_CALLBACK_RECEIVE: 329 { 330 Client * const client = (Client *)user; 331 const size_t remaining = lws_remaining_packet_payload(wsi); 332 333 if (!remaining && lws_is_final_fragment(wsi)) { 334 if (client->HasFragments()) { 335 client->AppendMessageFragment(in, len, 0); 336 in = (void *)client->GetMessage(); 337 len = client->GetMessageLength(); 338 } 339 340 client->ProcessMessage((char *)in, len, wsi); 341 client->ResetMessage(); 342 } else 343 client->AppendMessageFragment(in, len, remaining); 344 } 345 break; 346``` 347 348The test app libwebsockets-test-fraggle sources also show how to 349deal with fragmented messages. 350 351 352@section debuglog Debug Logging 353 354Also using `lws_set_log_level` api you may provide a custom callback to actually 355emit the log string. By default, this points to an internal emit function 356that sends to stderr. Setting it to `NULL` leaves it as it is instead. 357 358A helper function `lwsl_emit_syslog()` is exported from the library to simplify 359logging to syslog. You still need to use `setlogmask`, `openlog` and `closelog` 360in your user code. 361 362The logging apis are made available for user code. 363 364- `lwsl_err(...)` 365- `lwsl_warn(...)` 366- `lwsl_notice(...)` 367- `lwsl_info(...)` 368- `lwsl_debug(...)` 369 370The difference between notice and info is that notice will be logged by default 371whereas info is ignored by default. 372 373If you are not building with _DEBUG defined, ie, without this 374 375``` 376 $ cmake .. -DCMAKE_BUILD_TYPE=DEBUG 377``` 378 379then log levels below notice do not actually get compiled in. 380 381@section asan Building with ASAN 382 383Under GCC you can select for the build to be instrumented with the Address 384Sanitizer, using `cmake .. -DCMAKE_BUILD_TYPE=DEBUG -DLWS_WITH_ASAN=1`. LWS is routinely run during development with valgrind, but ASAN is capable of finding different issues at runtime, like operations which are not strictly defined in the C 385standard and depend on platform behaviours. 386 387Run your application like this 388 389``` 390 $ sudo ASAN_OPTIONS=verbosity=2:halt_on_error=1 /usr/local/bin/lwsws 391``` 392 393and attach gdb to catch the place it halts. 394 395@section extpoll External Polling Loop support 396 397**libwebsockets** maintains an internal `poll()` array for all of its 398sockets, but you can instead integrate the sockets into an 399external polling array. That's needed if **libwebsockets** will 400cooperate with an existing poll array maintained by another 401server. 402 403Three callbacks `LWS_CALLBACK_ADD_POLL_FD`, `LWS_CALLBACK_DEL_POLL_FD` 404and `LWS_CALLBACK_CHANGE_MODE_POLL_FD` appear in the callback for protocol 0 405and allow interface code to manage socket descriptors in other poll loops. 406 407You can pass all pollfds that need service to `lws_service_fd()`, even 408if the socket or file does not belong to **libwebsockets** it is safe. 409 410If **libwebsocket** handled it, it zeros the pollfd `revents` field before returning. 411So you can let **libwebsockets** try and if `pollfd->revents` is nonzero on return, 412you know it needs handling by your code. 413 414Also note that when integrating a foreign event loop like libev or libuv where 415it doesn't natively use poll() semantics, and you must return a fake pollfd 416reflecting the real event: 417 418 - be sure you set .events to .revents value as well in the synthesized pollfd 419 420 - check the built-in support for the event loop if possible (eg, ./lib/libuv.c) 421 to see how it interfaces to lws 422 423 - use LWS_POLLHUP / LWS_POLLIN / LWS_POLLOUT from libwebsockets.h to avoid 424 losing windows compatibility 425 426You also need to take care about "forced service" somehow... these are cases 427where the network event was consumed, incoming data was all read, for example, 428but the work arising from it was not completed. There will not be any more 429network event to trigger the remaining work, Eg, we read compressed data, but 430we did not use up all the decompressed data before returning to the event loop 431because we had to write some of it. 432 433Lws provides an API to determine if anyone is waiting for forced service, 434`lws_service_adjust_timeout(context, 1, tsi)`, normally tsi is 0. If it returns 4350, then at least one connection has pending work you can get done by calling 436`lws_service_tsi(context, -1, tsi)`, again normally tsi is 0. 437 438For eg, the default poll() event loop, or libuv/ev/event, lws does this 439checking for you and handles it automatically. But in the external polling 440loop case, you must do it explicitly. Handling it after every normal service 441triggered by the external poll fd should be enough, since the situations needing 442it are initially triggered by actual network events. 443 444An example of handling it is shown in the test-server code specific to 445external polling. 446 447@section cpp Using with in c++ apps 448 449The library is ready for use by C++ apps. You can get started quickly by 450copying the test server 451 452``` 453 $ cp test-apps/test-server.c test.cpp 454``` 455 456and building it in C++ like this 457 458``` 459 $ g++ -DINSTALL_DATADIR=\"/usr/share\" -ocpptest test.cpp -lwebsockets 460``` 461 462`INSTALL_DATADIR` is only needed because the test server uses it as shipped, if 463you remove the references to it in your app you don't need to define it on 464the g++ line either. 465 466 467@section headerinfo Availability of header information 468 469HTTP Header information is managed by a pool of "ah" structs. These are a 470limited resource so there is pressure to free the headers and return the ah to 471the pool for reuse. 472 473For that reason header information on HTTP connections that get upgraded to 474websockets is lost after the ESTABLISHED callback. Anything important that 475isn't processed by user code before then should be copied out for later. 476 477For HTTP connections that don't upgrade, header info remains available the 478whole time. 479 480@section http2compat Code Requirements for HTTP/2 compatibility 481 482Websocket connections only work over http/1, so there is nothing special to do 483when you want to enable -DLWS_WITH_HTTP2=1. 484 485The internal http apis already follow these requirements and are compatible with 486http/2 already. So if you use stuff like mounts and serve stuff out of the 487filesystem, there's also nothing special to do. 488 489However if you are getting your hands dirty with writing response headers, or 490writing bulk data over http/2, you need to observe these rules so that it will 491work over both http/1.x and http/2 the same. 492 4931) LWS_PRE requirement applies on ALL lws_write(). For http/1, you don't have 494to take care of LWS_PRE for http data, since it is just sent straight out. 495For http/2, it will write up to LWS_PRE bytes behind the buffer start to create 496the http/2 frame header. 497 498This has implications if you treated the input buffer to lws_write() as const... 499it isn't any more with http/2, up to 9 bytes behind the buffer will be trashed. 500 5012) Headers are encoded using a sophisticated scheme in http/2. The existing 502header access apis are already made compatible for incoming headers, 503for outgoing headers you must: 504 505 - observe the LWS_PRE buffer requirement mentioned above 506 507 - Use `lws_add_http_header_status()` to add the transaction status (200 etc) 508 509 - use lws apis `lws_add_http_header_by_name()` and `lws_add_http_header_by_token()` 510 to put the headers into the buffer (these will translate what is actually 511 written to the buffer depending on if the connection is in http/2 mode or not) 512 513 - use the `lws api lws_finalize_http_header()` api after adding the last 514 response header 515 516 - write the header using lws_write(..., `LWS_WRITE_HTTP_HEADERS`); 517 518 3) http/2 introduces per-stream transmit credit... how much more you can send 519 on a stream is decided by the peer. You start off with some amount, as the 520 stream sends stuff lws will reduce your credit accordingly, when it reaches 521 zero, you must not send anything further until lws receives "more credit" for 522 that stream the peer. Lws will suppress writable callbacks if you hit 0 until 523 more credit for the stream appears, and lws built-in file serving (via mounts 524 etc) already takes care of observing the tx credit restrictions. However if 525 you write your own code that wants to send http data, you must consult the 526 `lws_get_peer_write_allowance()` api to find out the state of your tx credit. 527 For http/1, it will always return (size_t)-1, ie, no limit. 528 529 This is orthogonal to the question of how much space your local side's kernel 530 will make to buffer your send data on that connection. So although the result 531 from `lws_get_peer_write_allowance()` is "how much you can send" logically, 532 and may be megabytes if the peer allows it, you should restrict what you send 533 at one time to whatever your machine will generally accept in one go, and 534 further reduce that amount if `lws_get_peer_write_allowance()` returns 535 something smaller. If it returns 0, you should not consume or send anything 536 and return having asked for callback on writable, it will only come back when 537 more tx credit has arrived for your stream. 538 539 4) Header names with captital letters are illegal in http/2. Header names in 540 http/1 are case insensitive. So if you generate headers by name, change all 541 your header name strings to lower-case to be compatible both ways. 542 543 5) Chunked Transfer-encoding is illegal in http/2, http/2 peers will actively 544 reject it. Lws takes care of removing the header and converting CGIs that 545 emit chunked into unchunked automatically for http/2 connections. 546 547If you follow these rules, your code will automatically work with both http/1.x 548and http/2. 549 550@section ka TCP Keepalive 551 552It is possible for a connection which is not being used to send to die 553silently somewhere between the peer and the side not sending. In this case 554by default TCP will just not report anything and you will never get any more 555incoming data or sign the link is dead until you try to send. 556 557To deal with getting a notification of that situation, you can choose to 558enable TCP keepalives on all **libwebsockets** sockets, when you create the 559context. 560 561To enable keepalive, set the ka_time member of the context creation parameter 562struct to a nonzero value (in seconds) at context creation time. You should 563also fill ka_probes and ka_interval in that case. 564 565With keepalive enabled, the TCP layer will send control packets that should 566stimulate a response from the peer without affecting link traffic. If the 567response is not coming, the socket will announce an error at `poll()` forcing 568a close. 569 570Note that BSDs don't support keepalive time / probes / interval per-socket 571like Linux does. On those systems you can enable keepalive by a nonzero 572value in `ka_time`, but the systemwide kernel settings for the time / probes/ 573interval are used, regardless of what nonzero value is in `ka_time`. 574 575 576@section sslopt Optimizing SSL connections 577 578There's a member `ssl_cipher_list` in the `lws_context_creation_info` struct 579which allows the user code to restrict the possible cipher selection at 580context-creation time. 581 582You might want to look into that to stop the ssl peers selecting a cipher which 583is too computationally expensive. To use it, point it to a string like 584 585 `"RC4-MD5:RC4-SHA:AES128-SHA:AES256-SHA:HIGH:!DSS:!aNULL"` 586 587if left `NULL`, then the "DEFAULT" set of ciphers are all possible to select. 588 589You can also set it to `"ALL"` to allow everything (including insecure ciphers). 590 591 592@section sslcerts Passing your own cert information direct to SSL_CTX 593 594For most users it's enough to pass the SSL certificate and key information by 595giving filepaths to the info.ssl_cert_filepath and info.ssl_private_key_filepath 596members when creating the vhost. 597 598If you want to control that from your own code instead, you can do so by leaving 599the related info members NULL, and setting the info.options flag 600LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX at vhost creation time. That will create 601the vhost SSL_CTX without any certificate, and allow you to use the callback 602LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS to add your certificate to 603the SSL_CTX directly. The vhost SSL_CTX * is in the user parameter in that 604callback. 605 606@section clientasync Async nature of client connections 607 608When you call `lws_client_connect_info(..)` and get a `wsi` back, it does not 609mean your connection is active. It just means it started trying to connect. 610 611Your client connection is actually active only when you receive 612`LWS_CALLBACK_CLIENT_ESTABLISHED` for it. 613 614There's a 5 second timeout for the connection, and it may give up or die for 615other reasons, if any of that happens you'll get a 616`LWS_CALLBACK_CLIENT_CONNECTION_ERROR` callback on protocol 0 instead for the 617`wsi`. 618 619After attempting the connection and getting back a non-`NULL` `wsi` you should 620loop calling `lws_service()` until one of the above callbacks occurs. 621 622As usual, see [test-client.c](../test-apps/test-client.c) for example code. 623 624Notice that the client connection api tries to progress the connection 625somewhat before returning. That means it's possible to get callbacks like 626CONNECTION_ERROR on the new connection before your user code had a chance to 627get the wsi returned to identify it (in fact if the connection did fail early, 628NULL will be returned instead of the wsi anyway). 629 630To avoid that problem, you can fill in `pwsi` in the client connection info 631struct to point to a struct lws that get filled in early by the client 632connection api with the related wsi. You can then check for that in the 633callback to confirm the identity of the failing client connection. 634 635 636@section fileapi Lws platform-independent file access apis 637 638lws now exposes his internal platform file abstraction in a way that can be 639both used by user code to make it platform-agnostic, and be overridden or 640subclassed by user code. This allows things like handling the URI "directory 641space" as a virtual filesystem that may or may not be backed by a regular 642filesystem. One example use is serving files from inside large compressed 643archive storage without having to unpack anything except the file being 644requested. 645 646The test server shows how to use it, basically the platform-specific part of 647lws prepares a file operations structure that lives in the lws context. 648 649The user code can get a pointer to the file operations struct 650 651``` 652 LWS_VISIBLE LWS_EXTERN struct lws_plat_file_ops * 653 `lws_get_fops`(struct lws_context *context); 654``` 655 656and then can use helpers to also leverage these platform-independent 657file handling apis 658 659``` 660 lws_fop_fd_t 661 `lws_plat_file_open`(struct lws_plat_file_ops *fops, const char *filename, 662 lws_fop_flags_t *flags) 663 int 664 `lws_plat_file_close`(lws_fop_fd_t fop_fd) 665 666 unsigned long 667 `lws_plat_file_seek_cur`(lws_fop_fd_t fop_fd, lws_fileofs_t offset) 668 669 int 670 `lws_plat_file_read`(lws_fop_fd_t fop_fd, lws_filepos_t *amount, 671 uint8_t *buf, lws_filepos_t len) 672 673 int 674 `lws_plat_file_write`(lws_fop_fd_t fop_fd, lws_filepos_t *amount, 675 uint8_t *buf, lws_filepos_t len ) 676``` 677 678Generic helpers are provided which provide access to generic fops information or 679call through to the above fops 680 681``` 682lws_filepos_t 683lws_vfs_tell(lws_fop_fd_t fop_fd); 684 685lws_filepos_t 686lws_vfs_get_length(lws_fop_fd_t fop_fd); 687 688uint32_t 689lws_vfs_get_mod_time(lws_fop_fd_t fop_fd); 690 691lws_fileofs_t 692lws_vfs_file_seek_set(lws_fop_fd_t fop_fd, lws_fileofs_t offset); 693 694lws_fileofs_t 695lws_vfs_file_seek_end(lws_fop_fd_t fop_fd, lws_fileofs_t offset); 696``` 697 698 699The user code can also override or subclass the file operations, to either 700wrap or replace them. An example is shown in test server. 701 702### Changes from v2.1 and before fops 703 704There are several changes: 705 7061) Pre-2.2 fops directly used platform file descriptors. Current fops returns and accepts a wrapper type lws_fop_fd_t which is a pointer to a malloc'd struct containing information specific to the filesystem implementation. 707 7082) Pre-2.2 fops bound the fops to a wsi. This is completely removed, you just give a pointer to the fops struct that applies to this file when you open it. Afterwards, the operations in the fops just need the lws_fop_fd_t returned from the open. 709 7103) Everything is wrapped in typedefs. See lws-plat-unix.c for examples of how to implement. 711 7124) Position in the file, File Length, and a copy of Flags left after open are now generically held in the fop_fd. 713VFS implementation must set and manage this generic information now. See the implementations in lws-plat-unix.c for 714examples. 715 7165) The file length is no longer set at a pointer provided by the open() fop. The api `lws_vfs_get_length()` is provided to 717get the file length after open. 718 7196) If your file namespace is virtual, ie, is not reachable by platform fops directly, you must set LWS_FOP_FLAG_VIRTUAL 720on the flags during open. 721 7227) There is an optional `mod_time` uint32_t member in the generic fop_fd. If you are able to set it during open, you 723should indicate it by setting `LWS_FOP_FLAG_MOD_TIME_VALID` on the flags. 724 725@section rawfd RAW file descriptor polling 726 727LWS allows you to include generic platform file descriptors in the lws service / poll / event loop. 728 729Open your fd normally and then 730 731``` 732 lws_sock_file_fd_type u; 733 734 u.filefd = your_open_file_fd; 735 736 if (!lws_adopt_descriptor_vhost(vhost, 0, u, 737 "protocol-name-to-bind-to", 738 optional_wsi_parent_or_NULL)) { 739 // failed 740 } 741 742 // OK 743``` 744 745A wsi is created for the file fd that acts like other wsi, you will get these 746callbacks on the named protocol 747 748``` 749 LWS_CALLBACK_RAW_ADOPT_FILE 750 LWS_CALLBACK_RAW_RX_FILE 751 LWS_CALLBACK_RAW_WRITEABLE_FILE 752 LWS_CALLBACK_RAW_CLOSE_FILE 753``` 754 755starting with LWS_CALLBACK_RAW_ADOPT_FILE. 756 757The minimal example `raw/minimal-raw-file` demonstrates how to use it. 758 759`protocol-lws-raw-test` plugin also provides a method for testing this with 760`libwebsockets-test-server-v2.0`: 761 762The plugin creates a FIFO on your system called "/tmp/lws-test-raw" 763 764You can feed it data through the FIFO like this 765 766``` 767 $ sudo sh -c "echo hello > /tmp/lws-test-raw" 768``` 769 770This plugin simply prints the data. But it does it through the lws event 771loop / service poll. 772 773@section rawsrvsocket RAW server socket descriptor polling 774 775You can also enable your vhost to accept RAW socket connections, in addition to 776HTTP[s] and WS[s]. If the first bytes written on the connection are not a 777valid HTTP method, then the connection switches to RAW mode. 778 779This is disabled by default, you enable it by setting the `.options` flag 780LWS_SERVER_OPTION_FALLBACK_TO_APPLY_LISTEN_ACCEPT_CONFIG, and setting 781`.listen_accept_role` to `"raw-skt"` when creating the vhost. 782 783RAW mode socket connections receive the following callbacks 784 785``` 786 LWS_CALLBACK_RAW_ADOPT 787 LWS_CALLBACK_RAW_RX 788 LWS_CALLBACK_RAW_WRITEABLE 789 LWS_CALLBACK_RAW_CLOSE 790``` 791 792You can control which protocol on your vhost handles these RAW mode 793incoming connections by setting the vhost info struct's `.listen_accept_protocol` 794to the vhost protocol name to use. 795 796`protocol-lws-raw-test` plugin provides a method for testing this with 797`libwebsockets-test-server-v2.0`: 798 799Run libwebsockets-test-server-v2.0 and connect to it by telnet, eg 800 801``` 802 $ telnet 127.0.0.1 7681 803``` 804 805type something that isn't a valid HTTP method and enter, before the 806connection times out. The connection will switch to RAW mode using this 807protocol, and pass the unused rx as a raw RX callback. 808 809The test protocol echos back what was typed on telnet to telnet. 810 811@section rawclientsocket RAW client socket descriptor polling 812 813You can now also open RAW socket connections in client mode. 814 815Follow the usual method for creating a client connection, but set the 816`info.method` to "RAW". When the connection is made, the wsi will be 817converted to RAW mode and operate using the same callbacks as the 818server RAW sockets described above. 819 820The libwebsockets-test-client supports this using raw:// URLS. To 821test, open a netcat listener in one window 822 823``` 824 $ nc -l 9999 825``` 826 827and in another window, connect to it using the test client 828 829``` 830 $ libwebsockets-test-client raw://127.0.0.1:9999 831``` 832 833The connection should succeed, and text typed in the netcat window (including a CRLF) 834will be received in the client. 835 836@section rawudp RAW UDP socket integration 837 838Lws provides an api to create, optionally bind, and adopt a RAW UDP 839socket (RAW here means an uninterpreted normal UDP socket, not a 840"raw socket"). 841 842``` 843LWS_VISIBLE LWS_EXTERN struct lws * 844lws_create_adopt_udp(struct lws_vhost *vhost, int port, int flags, 845 const char *protocol_name, struct lws *parent_wsi); 846``` 847 848`flags` should be `LWS_CAUDP_BIND` if the socket will receive packets. 849 850The callbacks `LWS_CALLBACK_RAW_ADOPT`, `LWS_CALLBACK_RAW_CLOSE`, 851`LWS_CALLBACK_RAW_RX` and `LWS_CALLBACK_RAW_WRITEABLE` apply to the 852wsi. But UDP is different than TCP in some fundamental ways. 853 854For receiving on a UDP connection, data becomes available at 855`LWS_CALLBACK_RAW_RX` as usual, but because there is no specific 856connection with UDP, it is necessary to also get the source address of 857the data separately, using `struct lws_udp * lws_get_udp(wsi)`. 858You should take a copy of the `struct lws_udp` itself (not the 859pointer) and save it for when you want to write back to that peer. 860 861Writing is also a bit different for UDP. By default, the system has no 862idea about the receiver state and so asking for a `callback_on_writable()` 863always believes that the socket is writeable... the callback will 864happen next time around the event loop. 865 866With UDP, there is no single "connection". You need to write with sendto() and 867direct the packets to a specific destination. To return packets to a 868peer who sent something earlier and you copied his `struct lws_udp`, you 869use the .sa and .salen members as the last two parameters of the sendto(). 870 871The kernel may not accept to buffer / write everything you wanted to send. 872So you are responsible to watch the result of sendto() and resend the 873unsent part next time (which may involve adding new protocol headers to 874the remainder depending on what you are doing). 875 876@section ecdh ECDH Support 877 878ECDH Certs are now supported. Enable the CMake option 879 880 cmake .. -DLWS_SSL_SERVER_WITH_ECDH_CERT=1 881 882**and** the info->options flag 883 884 LWS_SERVER_OPTION_SSL_ECDH 885 886to build in support and select it at runtime. 887 888@section sslinfo SSL info callbacks 889 890OpenSSL allows you to receive callbacks for various events defined in a 891bitmask in openssl/ssl.h. The events include stuff like TLS Alerts. 892 893By default, lws doesn't register for these callbacks. 894 895However if you set the info.ssl_info_event_mask to nonzero (ie, set some 896of the bits in it like `SSL_CB_ALERT` at vhost creation time, then 897connections to that vhost will call back using LWS_CALLBACK_SSL_INFO 898for the wsi, and the `in` parameter will be pointing to a struct of 899related args: 900 901``` 902struct lws_ssl_info { 903 int where; 904 int ret; 905}; 906``` 907 908The default callback handler in lws has a handler for LWS_CALLBACK_SSL_INFO 909which prints the related information, You can test it using the switch 910-S -s on `libwebsockets-test-server-v2.0`. 911 912Returning nonzero from the callback will close the wsi. 913 914@section smp SMP / Multithreaded service 915 916SMP support is integrated into LWS without any internal threading. It's 917very simple to use, libwebsockets-test-server-pthread shows how to do it, 918use -j n argument there to control the number of service threads up to 32. 919 920Two new members are added to the info struct 921 922 unsigned int count_threads; 923 unsigned int fd_limit_per_thread; 924 925leave them at the default 0 to get the normal singlethreaded service loop. 926 927Set count_threads to n to tell lws you will have n simultaneous service threads 928operating on the context. 929 930There is still a single listen socket on one port, no matter how many 931service threads. 932 933When a connection is made, it is accepted by the service thread with the least 934connections active to perform load balancing. 935 936The user code is responsible for spawning n threads running the service loop 937associated to a specific tsi (Thread Service Index, 0 .. n - 1). See 938the libwebsockets-test-server-pthread for how to do. 939 940If you leave fd_limit_per_thread at 0, then the process limit of fds is shared 941between the service threads; if you process was allowed 1024 fds overall then 942each thread is limited to 1024 / n. 943 944You can set fd_limit_per_thread to a nonzero number to control this manually, eg 945the overall supported fd limit is less than the process allowance. 946 947You can control the context basic data allocation for multithreading from Cmake 948using -DLWS_MAX_SMP=, if not given it's set to 1. The serv_buf allocation 949for the threads (currently 4096) is made at runtime only for active threads. 950 951Because lws will limit the requested number of actual threads supported 952according to LWS_MAX_SMP, there is an api lws_get_count_threads(context) to 953discover how many threads were actually allowed when the context was created. 954 955See the test-server-pthreads.c sample for how to use. 956 957@section smplocking SMP Locking Helpers 958 959Lws provide a set of pthread mutex helpers that reduce to no code or 960variable footprint in the case that LWS_MAX_SMP == 1. 961 962Define your user mutex like this 963 964``` 965 lws_pthread_mutex(name); 966``` 967 968If LWS_MAX_SMP > 1, this produces `pthread_mutex_t name;`. In the case 969LWS_MAX_SMP == 1, it produces nothing. 970 971Likewise these helpers for init, destroy, lock and unlock 972 973 974``` 975 void lws_pthread_mutex_init(pthread_mutex_t *lock) 976 void lws_pthread_mutex_destroy(pthread_mutex_t *lock) 977 void lws_pthread_mutex_lock(pthread_mutex_t *lock) 978 void lws_pthread_mutex_unlock(pthread_mutex_t *lock) 979``` 980 981resolve to nothing if LWS_MAX_SMP == 1, otherwise produce the equivalent 982pthread api. 983 984pthreads is required in lws only if LWS_MAX_SMP > 1. 985 986 987@section libevuv libev / libuv / libevent support 988 989You can select either or both 990 991 -DLWS_WITH_LIBEV=1 992 -DLWS_WITH_LIBUV=1 993 -DLWS_WITH_LIBEVENT=1 994 995at cmake configure-time. The user application may use one of the 996context init options flags 997 998 LWS_SERVER_OPTION_LIBEV 999 LWS_SERVER_OPTION_LIBUV 1000 LWS_SERVER_OPTION_LIBEVENT 1001 1002to indicate it will use one of the event libraries at runtime. 1003 1004libev and libevent headers conflict, they both define critical constants like 1005EV_READ to different values. Attempts to discuss clearing that up with both 1006libevent and libev did not get anywhere useful. Therefore CMakeLists.txt will 1007error out if you enable both LWS_WITH_LIBEV and LWS_WITH_LIBEVENT. 1008 1009In addition depending on libev / compiler version, building anything with libev 1010apis using gcc may blow strict alias warnings (which are elevated to errors in 1011lws). I did some googling at found these threads related to it, the issue goes 1012back at least to 2010 on and off 1013 1014https://github.com/redis/hiredis/issues/434 1015https://bugs.gentoo.org/show_bug.cgi?id=615532 1016http://lists.schmorp.de/pipermail/libev/2010q1/000916.html 1017http://lists.schmorp.de/pipermail/libev/2010q1/000920.html 1018http://lists.schmorp.de/pipermail/libev/2010q1/000923.html 1019 1020We worked around this problem by disabling -Werror on the parts of lws that 1021use libev. FWIW as of Dec 2019 using Fedora 31 libev 4.27.1 and its gcc 9.2.1 1022doesn't seem to trigger the problem even without the workaround. 1023 1024For these reasons and the response I got trying to raise these issues with 1025them, if you have a choice about event loop, I would gently encourage you 1026to avoid libev. Where lws uses an event loop itself, eg in lwsws, we use 1027libuv. 1028 1029@section extopts Extension option control from user code 1030 1031User code may set per-connection extension options now, using a new api 1032`lws_set_extension_option()`. 1033 1034This should be called from the ESTABLISHED callback like this 1035``` 1036 lws_set_extension_option(wsi, "permessage-deflate", 1037 "rx_buf_size", "12"); /* 1 << 12 */ 1038``` 1039 1040If the extension is not active (missing or not negotiated for the 1041connection, or extensions are disabled on the library) the call is 1042just returns -1. Otherwise the connection's extension has its 1043named option changed. 1044 1045The extension may decide to alter or disallow the change, in the 1046example above permessage-deflate restricts the size of his rx 1047output buffer also considering the protocol's rx_buf_size member. 1048 1049 1050@section httpsclient Client connections as HTTP[S] rather than WS[S] 1051 1052You may open a generic http client connection using the same 1053struct lws_client_connect_info used to create client ws[s] 1054connections. 1055 1056To stay in http[s], set the optional info member "method" to 1057point to the string "GET" instead of the default NULL. 1058 1059After the server headers are processed, when payload from the 1060server is available the callback LWS_CALLBACK_RECEIVE_CLIENT_HTTP 1061will be made. 1062 1063You can choose whether to process the data immediately, or 1064queue a callback when an outgoing socket is writeable to provide 1065flow control, and process the data in the writable callback. 1066 1067Either way you use the api `lws_http_client_read()` to access the 1068data, eg 1069 1070``` 1071 case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: 1072 { 1073 char buffer[1024 + LWS_PRE]; 1074 char *px = buffer + LWS_PRE; 1075 int lenx = sizeof(buffer) - LWS_PRE; 1076 1077 lwsl_notice("LWS_CALLBACK_RECEIVE_CLIENT_HTTP\n"); 1078 1079 /* 1080 * Often you need to flow control this by something 1081 * else being writable. In that case call the api 1082 * to get a callback when writable here, and do the 1083 * pending client read in the writeable callback of 1084 * the output. 1085 */ 1086 if (lws_http_client_read(wsi, &px, &lenx) < 0) 1087 return -1; 1088 while (lenx--) 1089 putchar(*px++); 1090 } 1091 break; 1092``` 1093 1094Notice that if you will use SSL client connections on a vhost, you must 1095prepare the client SSL context for the vhost after creating the vhost, since 1096this is not normally done if the vhost was set up to listen / serve. Call 1097the api lws_init_vhost_client_ssl() to also allow client SSL on the vhost. 1098 1099@section clipipe Pipelining Client Requests to same host 1100 1101If you are opening more client requests to the same host and port, you 1102can give the flag LCCSCF_PIPELINE on `info.ssl_connection` to indicate 1103you wish to pipeline them. 1104 1105Without the flag, the client connections will occur concurrently using a 1106socket and tls wrapper if requested for each connection individually. 1107That is fast, but resource-intensive. 1108 1109With the flag, lws will queue subsequent client connections on the first 1110connection to the same host and port. When it has confirmed from the 1111first connection that pipelining / keep-alive is supported by the server, 1112it lets the queued client pipeline connections send their headers ahead 1113of time to create a pipeline of requests on the server side. 1114 1115In this way only one tcp connection and tls wrapper is required to transfer 1116all the transactions sequentially. It takes a little longer but it 1117can make a significant difference to resources on both sides. 1118 1119If lws learns from the first response header that keepalive is not possible, 1120then it marks itself with that information and detaches any queued clients 1121to make their own individual connections as a fallback. 1122 1123Lws can also intelligently combine multiple ongoing client connections to 1124the same host and port into a single http/2 connection with multiple 1125streams if the server supports it. 1126 1127Unlike http/1 pipelining, with http/2 the client connections all occur 1128simultaneously using h2 stream multiplexing inside the one tcp + tls 1129connection. 1130 1131You can turn off the h2 client support either by not building lws with 1132`-DLWS_WITH_HTTP2=1` or giving the `LCCSCF_NOT_H2` flag in the client 1133connection info struct `ssl_connection` member. 1134 1135@section vhosts Using lws vhosts 1136 1137If you set LWS_SERVER_OPTION_EXPLICIT_VHOSTS options flag when you create 1138your context, it won't create a default vhost using the info struct 1139members for compatibility. Instead you can call lws_create_vhost() 1140afterwards to attach one or more vhosts manually. 1141 1142``` 1143 LWS_VISIBLE struct lws_vhost * 1144 lws_create_vhost(struct lws_context *context, 1145 struct lws_context_creation_info *info); 1146``` 1147 1148lws_create_vhost() uses the same info struct as lws_create_context(), 1149it ignores members related to context and uses the ones meaningful 1150for vhost (marked with VH in libwebsockets.h). 1151 1152``` 1153 struct lws_context_creation_info { 1154 int port; /* VH */ 1155 const char *iface; /* VH */ 1156 const struct lws_protocols *protocols; /* VH */ 1157 const struct lws_extension *extensions; /* VH */ 1158 ... 1159``` 1160 1161When you attach the vhost, if the vhost's port already has a listen socket 1162then both vhosts share it and use SNI (is SSL in use) or the Host: header 1163from the client to select the right one. Or if no other vhost already 1164listening the a new listen socket is created. 1165 1166There are some new members but mainly it's stuff you used to set at 1167context creation time. 1168 1169 1170@section sni How lws matches hostname or SNI to a vhost 1171 1172LWS first strips any trailing :port number. 1173 1174Then it tries to find an exact name match for a vhost listening on the correct 1175port, ie, if SNI or the Host: header provided abc.com:1234, it will match on a 1176vhost named abc.com that is listening on port 1234. 1177 1178If there is no exact match, lws will consider wildcard matches, for example 1179if cats.abc.com:1234 is provided by the client by SNI or Host: header, it will 1180accept a vhost "abc.com" listening on port 1234. If there was a better, exact, 1181match, it will have been chosen in preference to this. 1182 1183Connections with SSL will still have the client go on to check the 1184certificate allows wildcards and error out if not. 1185 1186 1187 1188@section mounts Using lws mounts on a vhost 1189 1190The last argument to lws_create_vhost() lets you associate a linked 1191list of lws_http_mount structures with that vhost's URL 'namespace', in 1192a similar way that unix lets you mount filesystems into areas of your / 1193filesystem how you like and deal with the contents transparently. 1194 1195``` 1196 struct lws_http_mount { 1197 struct lws_http_mount *mount_next; 1198 const char *mountpoint; /* mountpoint in http pathspace, eg, "/" */ 1199 const char *origin; /* path to be mounted, eg, "/var/www/warmcat.com" */ 1200 const char *def; /* default target, eg, "index.html" */ 1201 1202 struct lws_protocol_vhost_options *cgienv; 1203 1204 int cgi_timeout; 1205 int cache_max_age; 1206 1207 unsigned int cache_reusable:1; 1208 unsigned int cache_revalidate:1; 1209 unsigned int cache_intermediaries:1; 1210 1211 unsigned char origin_protocol; 1212 unsigned char mountpoint_len; 1213 }; 1214``` 1215 1216The last mount structure should have a NULL mount_next, otherwise it should 1217point to the 'next' mount structure in your list. 1218 1219Both the mount structures and the strings must persist until the context is 1220destroyed, since they are not copied but used in place. 1221 1222`.origin_protocol` should be one of 1223 1224``` 1225 enum { 1226 LWSMPRO_HTTP, 1227 LWSMPRO_HTTPS, 1228 LWSMPRO_FILE, 1229 LWSMPRO_CGI, 1230 LWSMPRO_REDIR_HTTP, 1231 LWSMPRO_REDIR_HTTPS, 1232 LWSMPRO_CALLBACK, 1233 }; 1234``` 1235 1236 - LWSMPRO_FILE is used for mapping url namespace to a filesystem directory and 1237serve it automatically. 1238 1239 - LWSMPRO_CGI associates the url namespace with the given CGI executable, which 1240runs when the URL is accessed and the output provided to the client. 1241 1242 - LWSMPRO_REDIR_HTTP and LWSMPRO_REDIR_HTTPS auto-redirect clients to the given 1243origin URL. 1244 1245 - LWSMPRO_CALLBACK causes the http connection to attach to the callback 1246associated with the named protocol (which may be a plugin). 1247 1248 1249@section mountcallback Operation of LWSMPRO_CALLBACK mounts 1250 1251The feature provided by CALLBACK type mounts is binding a part of the URL 1252namespace to a named protocol callback handler. 1253 1254This allows protocol plugins to handle areas of the URL namespace. For example 1255in test-server-v2.0.c, the URL area "/formtest" is associated with the plugin 1256providing "protocol-post-demo" like this 1257 1258``` 1259 static const struct lws_http_mount mount_post = { 1260 NULL, /* linked-list pointer to next*/ 1261 "/formtest", /* mountpoint in URL namespace on this vhost */ 1262 "protocol-post-demo", /* handler */ 1263 NULL, /* default filename if none given */ 1264 NULL, 1265 0, 1266 0, 1267 0, 1268 0, 1269 0, 1270 LWSMPRO_CALLBACK, /* origin points to a callback */ 1271 9, /* strlen("/formtest"), ie length of the mountpoint */ 1272 }; 1273``` 1274 1275Client access to /formtest[anything] will be passed to the callback registered 1276with the named protocol, which in this case is provided by a protocol plugin. 1277 1278Access by all methods, eg, GET and POST are handled by the callback. 1279 1280protocol-post-demo deals with accepting and responding to the html form that 1281is in the test server HTML. 1282 1283When a connection accesses a URL related to a CALLBACK type mount, the 1284connection protocol is changed until the next access on the connection to a 1285URL outside the same CALLBACK mount area. User space on the connection is 1286arranged to be the size of the new protocol user space allocation as given in 1287the protocol struct. 1288 1289This allocation is only deleted / replaced when the connection accesses a 1290URL region with a different protocol (or the default protocols[0] if no 1291CALLBACK area matches it). 1292 1293This "binding connection to a protocol" lifecycle in managed by 1294`LWS_CALLBACK_HTTP_BIND_PROTOCOL` and `LWS_CALLBACK_HTTP_DROP_PROTOCOL`. 1295Because of HTTP/1.1 connection pipelining, one connection may perform 1296many transactions, each of which may map to different URLs and need 1297binding to different protocols. So these messages are used to 1298create the binding of the wsi to your protocol including any 1299allocations, and to destroy the binding, at which point you should 1300destroy any related allocations. 1301 1302@section BINDTODEV SO_BIND_TO_DEVICE 1303 1304The .bind_iface flag in the context / vhost creation struct lets you 1305declare that you want all traffic for listen and transport on that 1306vhost to be strictly bound to the network interface named in .iface. 1307 1308This Linux-only feature requires SO_BIND_TO_DEVICE, which in turn 1309requires CAP_NET_RAW capability... root has this capability. 1310 1311However this feature needs to apply the binding also to accepted 1312sockets during normal operation, which implies the server must run 1313the whole time as root. 1314 1315You can avoid this by using the Linux capabilities feature to have 1316the unprivileged user inherit just the CAP_NET_RAW capability. 1317 1318You can confirm this with the test server 1319 1320 1321``` 1322 $ sudo /usr/local/bin/libwebsockets-test-server -u agreen -i eno1 -k 1323``` 1324 1325The part that ensures the capability is inherited by the unprivileged 1326user is 1327 1328``` 1329#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP) 1330 info.caps[0] = CAP_NET_RAW; 1331 info.count_caps = 1; 1332#endif 1333``` 1334 1335 1336@section dim Dimming webpage when connection lost 1337 1338The lws test plugins' html provides useful feedback on the webpage about if it 1339is still connected to the server, by greying out the page if not. You can 1340also add this to your own html easily 1341 1342 - include lws-common.js from your HEAD section 1343 1344 \<script src="/lws-common.js">\</script> 1345 1346 - dim the page during initialization, in a script section on your page 1347 1348 lws_gray_out(true,{'zindex':'499'}); 1349 1350 - in your ws onOpen(), remove the dimming 1351 1352 lws_gray_out(false); 1353 1354 - in your ws onClose(), reapply the dimming 1355 1356 lws_gray_out(true,{'zindex':'499'}); 1357 1358@section errstyle Styling http error pages 1359 1360In the code, http errors should be handled by `lws_return_http_status()`. 1361 1362There are basically two ways... the vhost can be told to redirect to an "error 1363page" URL in response to specifically a 404... this is controlled by the 1364context / vhost info struct (`struct lws_context_creation_info`) member 1365`.error_document_404`... if non-null the client is redirected to this string. 1366 1367If it wasn't redirected, then the response code html is synthesized containing 1368the user-selected text message and attempts to pull in `/error.css` for styling. 1369 1370If this file exists, it can be used to style the error page. See 1371https://libwebsockets.org/git/badrepo for an example of what can be done ( 1372and https://libwebsockets.org/error.css for the corresponding css). 1373 1374
README.content-security-policy.md
1## Using Content Security Policy (CSP) 2 3### What is it? 4 5Modern browsers have recently implemented a new feature providing 6a sort of "selinux for your web page". If the server sends some 7new headers describing the security policy for the content, then 8the browser strictly enforces it. 9 10### Why would we want to do that? 11 12Scripting on webpages is pretty universal, sometimes the scripts 13come from third parties, and sometimes attackers find a way to 14inject scripts into the DOM, eg, through scripts in content. 15 16CSP lets the origin server define what is legitimate for the page it 17served and everything else is denied. 18 19The CSP for warmcat.com and libwebsockets.org looks like this, 20I removed a handful of whitelisted image sources like travis 21status etc for clarity... 22 23``` 24"content-security-policy": "default-src 'none'; img-src 'self' data:; script-src 'self'; font-src 'self'; style-src 'self'; connect-src 'self'; frame-ancestors 'none'; base-uri 'none';", 25"x-content-type-options": "nosniff", 26"x-xss-protection": "1; mode=block", 27"x-frame-options": "deny", 28"referrer-policy": "no-referrer" 29``` 30 31The result of this is the browser won't let the site content be iframed, and it 32will reject any inline styles or inline scripts. Fonts, css, ajax, ws and 33images are only allowed to come from 'self', ie, the server that served the 34page. You may inject your script, or deceptive styles: it won't run or be shown. 35 36Because inline scripts are banned, the usual methods for XSS are dead; 37the attacker can't even load js from another server. So these rules 38provide a very significant increase in client security. 39 40### Implications of strict CSP 41 42Halfhearted CSP isn't worth much. The only useful approach is to start 43with `default-src 'none'` which disables everything, and then whitelist the 44minimum needed for the pages to operate. 45 46"Minimum needed for the pages to operate" doesn't mean defeat the protections 47necessary so everything in the HTML can stay the same... it means adapt the 48pages to want the minimum and then enable the minimum. 49 50The main point is segregation of styles and script away from the content, in 51files referenced in the document `<head>` section, along these lines: 52 53``` 54<head> 55 <meta charset=utf-8 http-equiv="Content-Language" content="en"/> 56 <link rel="stylesheet" type="text/css" href="test.css"/> 57 <script type='text/javascript' src="/lws-common.js"></script> 58 <script type='text/javascript' src='test.js'></script> 59 <title>Minimal Websocket test app</title> 60</head> 61``` 62 63#### Inline styles must die 64 65All styling must go in one or more `.css` file(s) best served by the same 66server... while you can whitelist other sources in the CSP if you have to, 67unless you control that server as well, you are allowing whoever gains 68access to that server access to your users. 69 70Inline styles are no longer allowed (eg, "style='font-size:120%'" in the 71HTML)... they must be replaced by reference to one or more CSS class, which 72in this case includes "font-size:120%". This has always been the best 73practice anyway, and your pages will be cleaner and more maintainable. 74 75#### Inline scripts must die 76 77Inline scripts need to be placed in a `.js` file and loaded in the page head 78section, again it should only be from the server that provided the page. 79 80Then, any kind of inline script, yours or injected or whatever, will be 81completely rejected by the browser. 82 83#### onXXX must be replaced by eventListener 84 85Inline `onclick()` etc are kinds of inline scripting and are banned. 86 87Modern browsers have offered a different system called ["EventListener" for 88a while](https://developer.mozilla.org/en-US/docs/Web/API/EventListener) 89which allows binding of events to DOM elements in JS. 90 91A bunch of different named events are possible to listen on, commonly the 92`.js` file will ask for one or both of 93 94``` 95window.addEventListener("load", function() { 96... 97}, false); 98 99document.addEventListener("DOMContentLoaded", function() { 100... 101}, false); 102``` 103 104These give the JS a way to trigger when either everything on the page has 105been "loaded" or the DOM has been populated from the initial HTML. These 106can set up other event listeners on the DOM objects and aftwards the 107events will drive what happens on the page from user interaction and / or 108timers etc. 109 110If you have `onclick` in your HTML today, you would replace it with an id 111for the HTML element, then eg in the DOMContentLoaded event listener, 112apply 113 114``` 115 document.getElementById("my-id").addEventListener("click", function() { 116 ... 117 }, false); 118``` 119 120ie the .js file becomes the only place with the "business logic" of the 121elements mentioned in the HTML, applied at runtime. 122 123#### Do you really need external sources? 124 125Do your scripts and fonts really need to come from external sources? 126If your caching policy is liberal, they are not actually that expensive 127to serve once and then the user is using his local copy for the next 128days. 129 130Some external sources are marked as anti-privacy in modern browsers, meaning 131they track your users, in turn meaning if your site refers to them, you 132will lose your green padlock in the browser. If the content license allows 133it, hosting them on "self", ie, the same server that provided the HTML, 134will remove that problem. 135 136Bringing in scripts from external sources is actually quite scary from the 137security perspective. If someone hacks the `ajax.googleapis.com` site to serve 138a hostile, modified jquery, half the Internet will instantly 139become malicious. However if you serve it yourself, unless your server 140was specifically targeted you know it will continue to serve what you 141expect. 142 143Since these scripts are usually sent with cache control headers for local 144caching duration of 1 year, the cost of serving them yourself under the same 145conditions is small but your susceptibility to attack is reduced to only taking 146care of your own server. And there is a privacy benefit that google is not 147informed of your users' IPs and activities on your site. 148 149
README.contributing.md
1## Contributing to lws 2 3### How to contribute 4 5Sending a patch with a bug report is very welcome. 6 7For nontrivial problems, it's probably best to discuss on the mailing list, 8or on github if you prefer, how to best solve it. 9 10However your contribution is coming is fine: 11 12 - paste a `git diff` 13 14 - send a patch series by mail or mailing list 15 16 - paste in a github issue 17 18 - github PR 19 20are all OK. 21 22### Coding Standards 23 24Code should look roughly like the existing code, which follows linux kernel 25coding style. 26 27If there are non-functional problems I will clean them out when I apply the 28patch. 29 30If there are functional problems (eg broken error paths etc) if they are 31small compared to the working part I will also clean them. If there are 32larger problems, or consequences to the patch will have to discuss how to 33solve them with a retry. 34 35### Funding specific work 36 37If there is a feature you wish was supported in lws, consider paying for the 38work to be done. The maintainer is a consultant and if we can agree the 39task, you can quickly get a high quality result that does just what you need, 40maintained ongoing along with the rest of lws. 41 42
README.crypto-apis.md
1# Lws Crypto Apis 2 3## Overview 4 5 6 7Lws provides a "generic" crypto layer on top of both OpenSSL and 8compatible tls library, and mbedtls. Using this layer, your code 9can work without any changes on both types of tls library crypto 10backends... it's as simple as rebuilding lws with `-DLWS_WITH_MBEDTLS=0` 11or `=1` at cmake. 12 13The generic layer can be used directly (as in, eg, the sshd plugin), 14or via another layer on top, which processes JOSE JSON objects using 15JWS (JSON Web Signatures), JWK (JSON Web Keys), and JWE (JSON Web 16Encryption). 17 18The `JW` apis use the generic apis (`lws_genrsa_`, etc) to get the crypto tasks 19done, so anything they can do you can also get done using the generic apis. 20The main difference is that with the generic apis, you must instantiate the 21correct types and use type-specfic apis. With the `JW` apis, there is only 22one interface for all operations, with the details hidden in the api and 23controlled by the JSON objects. 24 25Because of this, the `JW` apis are often preferred because they give you 26"crypto agility" cheaply... to change your crypto to another supported algorithm 27once it's working, you literally just change your JSON defining the keys and 28JWE or JWS algorithm. (It's up to you to define your policy for which 29combinations are acceptable by querying the parsed JW structs). 30 31## Crypto supported in generic layer 32 33### Generic Hash 34 35 - SHA1 36 - SHA256 37 - SHA384 38 - SHA512 39 40### Generic HMAC 41 42 - SHA256 43 - SHA384 44 - SHA512 45 46### Generic AES 47 48 - CBC 49 - CFB128 50 - CFB8 51 - CTR 52 - ECB 53 - OFB 54 - XTS 55 - GCM 56 - KW (Key Wrap) 57 58### Generic RSA 59 60 - PKCS 1.5 61 - OAEP / PSS 62 63### Generic EC 64 65 - ECDH 66 - ECDSA 67 - P256 / P384 / P521 (sic) curves 68 69## Using the generic layer 70 71All the necessary includes are part of `libwebsockets.h`. 72 73Enable `-DLWS_WITH_GENCRYPTO=1` at cmake. 74 75|api|header|Functionality| 76|---|---|---| 77|genhash|[./include/libwebsockets/lws-genhash.h](https://libwebsockets.org/git/libwebsockets/tree/include/libwebsockets/lws-genhash.h)|Provides SHA1 + SHA2 hashes and hmac| 78|genrsa|[./include/libwebsockets/lws-genrsa.h](https://libwebsockets.org/git/libwebsockets/tree/include/libwebsockets/lws-genrsa.h)|Provides RSA encryption, decryption, signing, verification, key generation and creation| 79|genaes|[./include/libwebsockets/lws-genaes.h](https://libwebsockets.org/git/libwebsockets/tree/include/libwebsockets/lws-genaes.h)|Provides AES in all common variants for encryption and decryption| 80|genec|[./include/libwebsockets/lws-genec.h](https://libwebsockets.org/git/libwebsockets/tree/include/libwebsockets/lws-genec.h)|Provides Elliptic Curve for encryption, decryption, signing, verification, key generation and creation| 81|x509|[./include/libwebsockets/lws-x509.h](https://libwebsockets.org/git/libwebsockets/tree/include/libwebsockets/lws-x509.h)|Apis for X.509 Certificate loading, parsing, and stack verification, plus JWK key extraction from PEM X.509 certificate / private key| 82 83Unit tests for these apis, which serve as usage examples, can be found in [./minimal-examples/api-tests/api-test-gencrypto](https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/api-tests/api-test-gencrypto) 84 85### Keys in the generic layer 86 87The necessary types and defines are brought in by `libwebsockets.h`. 88 89Keys are represented only by an array of `struct lws_jwk_elements`... the 90length of the array is defined by the cipher... it's one of 91 92|key elements count|definition| 93|---|---| 94|`LWS_COUNT_OCT_KEY_ELEMENTS`|1| 95|`LWS_COUNT_RSA_KEY_ELEMENTS`|8| 96|`LWS_COUNT_EC_KEY_ELEMENTS`|4| 97|`LWS_COUNT_AES_KEY_ELEMENTS`|1| 98 99`struct lws_jwk_elements` is a simple pointer / length combination used to 100store arbitrary octets that make up the key element's binary representation. 101 102## Using the JOSE layer 103 104The JOSE (JWK / JWS / JWE) stuff is a crypto-agile JSON-based layer 105that uses the gencrypto support underneath. 106 107"Crypto Agility" means the JSON structs include information about the 108algorithms and ciphers used in that particular object, making it easy to 109upgrade system crypto strength or cycle keys over time while supporting a 110transitional period where the old and new keys or algorithms + ciphers 111are also valid. 112 113Uniquely lws generic support means the JOSE stuff also has "tls library 114agility", code written to the lws generic or JOSE apis is completely unchanged 115even if the underlying tls library changes between OpenSSL and mbedtls, meaning 116sharing code between server and client sides is painless. 117 118All the necessary includes are part of `libwebsockets.h`. 119 120Enable `-DLWS_WITH_JOSE=1` at CMake. 121 122|api|header|Functionality| 123|---|---|---| 124|JOSE|[./include/libwebsockets/lws-jose.h](https://libwebsockets.org/git/libwebsockets/tree/include/libwebsockets/lws-jose.h)|Provides crypto agility for JWS / JWE| 125|JWE|[./include/libwebsockets/lws-jwe.h](https://libwebsockets.org/git/libwebsockets/tree/include/libwebsockets/lws-jwe.h)|Provides Encryption and Decryption services for RFC7516 JWE JSON| 126|JWS|[./include/libwebsockets/lws-jws.h](https://libwebsockets.org/git/libwebsockets/tree/include/libwebsockets/lws-jws.h)|Provides signature and verifcation services for RFC7515 JWS JSON| 127|JWK|[./include/libwebsockets/lws-jwk.h](https://libwebsockets.org/git/libwebsockets/tree/include/libwebsockets/lws-jwk.h)|Provides signature and verifcation services for RFC7517 JWK JSON, both "keys" arrays and singletons| 128 129Minimal examples are provided in the form of commandline tools for JWK / JWS / JWE / x509 handling: 130 131 - [JWK minimal example](https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/crypto/minimal-crypto-jwk) 132 - [JWS minimal example](https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/crypto/minimal-crypto-jws) 133 - [JWE minimal example](https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/crypto/minimal-crypto-jwe) 134 - [X509 minimal example](https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/crypto/minimal-crypto-x509) 135 136Unit tests for these apis, which serve as usage examples, can be found in [./minimal-examples/api-tests/api-test-jose](https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/api-tests/api-test-jose) 137 138## Crypto supported in the JOSE layer 139 140The JOSE RFCs define specific short names for different algorithms 141 142### JWS 143 144|JSOE name|Hash|Signature| 145---|---|--- 146|RS256, RS384, RS512|SHA256/384/512|RSA 147|ES256, ES384, ES521|SHA256/384/512|EC 148 149### JWE 150 151|Key Encryption|Payload authentication + crypt| 152|---|---| 153|`RSAES-PKCS1-v1.5` 2048b & 4096b|`AES_128_CBC_HMAC_SHA_256`| 154|`RSAES-PKCS1-v1.5` 2048b|`AES_192_CBC_HMAC_SHA_384`| 155|`RSAES-PKCS1-v1.5` 2048b|`AES_256_CBC_HMAC_SHA_512`| 156|`RSAES-OAEP`|`AES_256_GCM`| 157|`AES128KW`, `AES192KW`, `AES256KW`|`AES_128_CBC_HMAC_SHA_256`| 158|`AES128KW`, `AES192KW`, `AES256KW`|`AES_192_CBC_HMAC_SHA_384`| 159|`AES128KW`, `AES192KW`, `AES256KW`|`AES_256_CBC_HMAC_SHA_512`| 160|`ECDH-ES` (P-256/384/521 key)|`AES_128/192/256_GCM`| 161|`ECDH-ES+A128/192/256KW` (P-256/384/521 key)|`AES_128/192/256_GCM`| 162 163### Keys in the JOSE layer 164 165Keys in the JOSE layer use a `struct lws_jwk`, this contains two arrays of 166`struct lws_jwk_elements` sized for the worst case (currently RSA). One 167array contains the key elements as described for the generic case, and the 168other contains various nonencrypted key metadata taken from JWK JSON. 169 170|metadata index|function| 171|---|---| 172|`JWK_META_KTY`|Key type, eg, "EC"| 173|`JWK_META_KID`|Arbitrary ID string| 174|`JWK_META_USE`|What the public key may be used to validate, "enc" or "sig"| 175|`JWK_META_KEY_OPS`|Which operations the key is authorized for, eg, "encrypt"| 176|`JWK_META_X5C`|Optional X.509 cert version of the key| 177|`JWK_META_ALG`|Optional overall crypto algorithm the key is intended for use with| 178 179`lws_jwk_destroy()` should be called when the jwk is going out of scope... this 180takes care to zero down any key element data in the jwk. 181 182
README.detailed-latency.md
1# lws detailed latency 2 3 4 5## Introduction 6 7lws has the capability to make detailed latency measurements and 8report them in realtime to a specified callback. 9 10A default callback is provided that renders the data as text in 11space-separated format suitable for gnuplot, to a specified file. 12 13## Configuring 14 15Enable `LWS_WITH_DETAILED_LATENCY` at cmake. 16 17Create your context with something similar to this 18 19``` 20#if defined(LWS_WITH_DETAILED_LATENCY) 21 info.detailed_latency_cb = lws_det_lat_plot_cb; 22 info.detailed_latency_filepath = "/tmp/lws-latency-results"; 23#endif 24``` 25 26`lws_det_lat_plot_cb` is provided by lws as a convenience to convert 27the stuct data provided at the callback interface to space-separated 28text data that is easy to process with shell commands and gnuplot. 29 30## `lws_det_lat_plot_cb` format 31 32``` 33728239173547 N 23062 0 0 23062 0 0 0 34728239192554 C 18879 0 0 18879 0 0 0 35728239217894 T 25309 0 0 25309 0 0 0 36728239234998 r 0 0 0 0 271 172 256 37728239250611 r 0 0 0 0 69 934 4096 38728239255679 w 19 122 18 159 20 80 80 39728239275718 w 20 117 15 152 18 80 80 40728239295578 w 10 73 7 90 7 80 80 41728239315567 w 9 67 5 81 7 80 80 42728239335745 w 23 133 9 165 14 80 80 43... 44``` 45 46Each event is shown in 9 columns 47 48 - unix time in us 49 - event type 50 - N = Name resolution 51 - C = TCP Connection 52 - T = TLS negotiation server 53 - t = TLS negotiation client 54 - r = Read 55 - w = Write 56 - us duration, for w time client spent waiting to write 57 - us duration, for w time data spent in transit to proxy 58 - us duration, for w time proxy waited to send data 59 - as a convenience, sum of last 3 columns above 60 - us duration, time spent in callback 61 - last 2 are actual / requested size in bytes 62 63## Processing captured data with ministat 64 65Eg, to summarize overall latencies on all captured writes 66 67``` 68 $ cat /tmp/lws-latency-results | grep " w " | cut -d' ' -f6 | ministat 69... 70 N Min Max Median Avg Stddev 71x 1000 43 273 141 132.672 32.471693 72``` 73 74## Processing captured data with gnuplot 75 76### Gnuplot plotting script 77 78Create a gnuplot script, eg myscript.gp 79 80``` 81reset 82set term pngcairo enhanced nocrop font "OpenSans, 12" size 800,600#output terminal and file 83set output "lws-latency.png" 84#set yrange [0:10000] 85#to put an empty boundary around the 86#data inside an autoscaled graph. 87set offset graph 0.05,0.05,0.05,0.0 88set style fill transparent solid 0.5 #fillstyle 89set tics out nomirror 90set xlabel "event" 91set ylabel "latency (us)" 92set format x "" 93set title "Write latency" 94set key invert reverse Right inside nobox 95set key autotitle columnheader 96set style data histogram 97set style histogram rowstacked 98set style fill solid border -1 99set boxwidth 0.75 100set style fill solid 1.00 noborder 101set tic scale 0 102set grid ytics lc rgb "#505050" 103unset border 104unset xtics 105 106plot '/tmp/1' \ 107 using ($3 + $4 + $5):xtic(1) w boxes lt rgbcolor "blue" title 'prox wr wait', \ 108 '' using ($3 + $4):xtic(1) w boxes lt rgbcolor "green" title 'txfr to prox', \ 109 '' using 3:xtic(1) w boxes lt rgbcolor "red" title 'cli wri wait' 110``` 111 112### gnuplot invocation 113 114``` 115 $ cat /tmp/lws-latency-results | grep " w " \>/tmp/1 ; gnuplot myscript.gp && eog lws-latency.png 116``` 117 118
README.esp32.md
1ESP32 Support 2============= 3 4See \ref esp32 for details on how to build lws as a component in an ESP-IDF project. 5 6Lws provides a "factory" application 7 8https://github.com/warmcat/lws-esp32-factory 9 10and a test application which implements the generic lws server test apps 11 12https://github.com/warmcat/lws-esp32-test-server-demos 13 14The behaviours of the generic factory are are quite rich, and cover uploading SSL certs through factory and user configuration, AP selection and passphrase entry, and managing a switch to allow the user to force entry to user setup mode at boot subsequently. 15 16The factory app comes with partitioning for a 1MB factory partition containing that app and data, and a single 2.9MB OTA partition containing the main app. 17 18The factory app is able to do OTA updates for both the factory and OTA partition slots; updating the factory slot first writes the new image to the OTA slot and copies it into place at the next boot, after which the user can reload the OTA slot. 19 20State|Image|AP SSID|Port|URL|Mode 21---|---|---|---|---|--- 22Factory Reset or Uninitialized|Factory|AP: ESP_012345|80|http://192.168.4.1|factory.html - to set certificates and serial 23User configuration|Factory|AP: config-model-serial|443|https://192.168.4.1|index.html - user set up his AP information 24Operation|OTA|Station only|443|https://model-serial.local|OTA application 25 26## Basic Auth 27 28The lws-esp32-test-server-demos app also demos basic auth. 29 30On a normal platform this is done by binding a mount to a text file somewhere in the filesystem, which 31contains user:password information one per line. 32 33On ESP32 there is not necessarily any generic VFS in use. So instead, the basic auth lookup is bound to 34a given nvs domain, where the username is the key and the password the value. main/main.c in the test 35demos app shows how to both make the mount use basic auth, and how to set a user:password combination 36using nvs. 37 38
README.generic-sessions.md
1Notes about generic-sessions Plugin 2=================================== 3 4@section gseb Enabling lwsgs for build 5 6Enable at CMake with -DLWS_WITH_GENERIC_SESSIONS=1 7 8This also needs sqlite3 (libsqlite3-dev or similar package) 9 10 11@section gsi lwsgs Introduction 12 13The generic-sessions protocol plugin provides cookie-based login 14authentication for lws web and ws connections. 15 16The plugin handles everything about generic account registration, 17email verification, lost password, account deletion, and other generic account 18management. 19 20Other code, in another eg, ws protocol handler, only needs very high-level 21state information from generic-sessions, ie, which user the client is 22authenticated as. Everything underneath is managed in generic-sessions. 23 24 25 - random 20-byte session id managed in a cookie 26 27 - all information related to the session held at the server, nothing managed clientside 28 29 - sqlite3 used at the server to manage active sessions and users 30 31 - defaults to creating anonymous sessions with no user associated 32 33 - admin account (with user-selectable username) is defined in config with a SHA-1 of the password; rest of the accounts are in sqlite3 34 35 - user account passwords stored as salted SHA-1 with additional confounder 36 only stored in the JSON config, not the database 37 38 - login, logout, register account + email verification built-in with examples 39 40 - in a mount, some file suffixes (ie, .js) can be associated with a protocol for the purposes of rewriting symbolnames. These are read-only copies of logged-in server state. 41 42 - When your page fetches .js or other rewritten files from that mount, "$lwsgs_user" and so on are rewritten on the fly using chunked transfer encoding 43 44 - Eliminates server-side scripting with a few rewritten symbols and 45 javascript on client side 46 47 - 32-bit bitfield for authentication sectoring, mounts can provide a mask on the loggin-in session's associated server-side bitfield that must be set for access. 48 49 - No code (just config) required for, eg, private URL namespace that requires login to access. 50 51 52@section gsin Lwsgs Integration to HTML 53 54Only three steps are needed to integrate lwsgs in your HTML. 55 561) lwsgs HTML UI is bundled with the javascript it uses in `lwsgs.js`, so 57import that script file in your head section 58 592) define an empty div of id "lwsgs" somewhere 60 613) Call lwsgs_initial() in your page 62 63That's it. An example is below 64 65``` 66 <html> 67 <head> 68 <script src="lwsgs.js"></script> 69 <style> 70 .body { font-size: 12 } 71 .gstitle { font-size: 18 } 72 </style> 73 </head> 74 <body style="background-image:url(seats.jpg)"> 75 <table style="width:100%;transition: max-height 2s;"> 76 <tr> 77 <td style="vertical-align:top;text-align:left;width=200px"> 78 <img src="lwsgs-logo.png"> 79 </td> 80 <td style="vertical-align:top;float:right"> 81 <div id=lwsgs style="text-align:right;background-color: rgba(255, 255, 255, 0.8);"></div> 82 </td> 83 </tr> 84 </table> 85 </form> 86 87 <script>lwsgs_initial();</script> 88 89 </body> 90 </html> 91``` 92 93@section gsof Lwsgs Overall Flow@ 94 95When the protocol is initialized, it gets per-vhost information from the config, such 96as where the sqlite3 databases are to be stored. The admin username and sha-1 of the 97admin password are also taken from here. 98 99In the mounts using protocol-generic-sessions, a cookie is maintained against any requests; if no cookie was active on the initial request a new session is 100created with no attached user. 101 102So there should always be an active session after any transactions with the server. 103 104In the example html going to the mount /lwsgs loads a login / register page as the default. 105 106The <form> in the login page contains 'next url' hidden inputs that let the html 'program' where the form handler will go after a successful admin login, a successful user login and a failed login. 107 108After a successful login, the sqlite record at the server for the current session is updated to have the logged-in username associated with it. 109 110 111 112@section gsconf Lwsgs Configuration 113 114"auth-mask" defines the authorization sector bits that must be enabled on the session to gain access. 115 116"auth-mask" 0 is the default. 117 118 - b0 is set if you are logged in as a user at all. 119 - b1 is set if you are logged in with the user configured to be admin 120 - b2 is set if the account has been verified (the account configured for admin is always verified) 121 - b3 is set if your session just did the forgot password flow successfully 122 123``` 124 { 125 # things in here can always be served 126 "mountpoint": "/lwsgs", 127 "origin": "file:///usr/share/libwebsockets-test-server/generic-sessions", 128 "origin": "callback://protocol-lws-messageboard", 129 "default": "generic-sessions-login-example.html", 130 "auth-mask": "0", 131 "interpret": { 132 ".js": "protocol-lws-messageboard" 133 } 134 }, { 135 # things in here can only be served if logged in as a user 136 "mountpoint": "/lwsgs/needauth", 137 "origin": "file:///usr/share/libwebsockets-test-server/generic-sessions/needauth", 138 "origin": "callback://protocol-lws-messageboard", 139 "default": "generic-sessions-login-example.html", 140 "auth-mask": "5", # logged in as a verified user 141 "interpret": { 142 ".js": "protocol-lws-messageboard" 143 } 144 }, { 145 # things in here can only be served if logged in as admin 146 "mountpoint": "/lwsgs/needadmin", 147 "origin": "file:///usr/share/libwebsockets-test-server/generic-sessions/needadmin", 148 "origin": "callback://protocol-lws-messageboard", 149 "default": "generic-sessions-login-example.html", 150 "auth-mask": "7", # b2 = verified (by email / or admin), b1 = admin, b0 = logged in with any user name 151 "interpret": { 152 ".js": "protocol-lws-messageboard" 153 } 154 } 155``` 156Note that the name of the real application protocol that uses generic-sessions 157is used, not generic-sessions itself. 158 159The vhost configures the storage dir, admin credentials and session cookie lifetimes: 160 161``` 162 "ws-protocols": [{ 163 "protocol-generic-sessions": { 164 "status": "ok", 165 "admin-user": "admin", 166 167 # create the pw hash like this (for the example pw, "jipdocesExunt" ) 168 # $ echo -n "jipdocesExunt" | sha1sum 169 # 046ce9a9cca769e85798133be06ef30c9c0122c9 - 170 # 171 # Obviously ** change this password hash to a secret one before deploying ** 172 # 173 "admin-password-sha1": "046ce9a9cca769e85798133be06ef30c9c0122c9", 174 "session-db": "/var/www/sessions/lws.sqlite3", 175 "timeout-idle-secs": "600", 176 "timeout-anon-idle-secs": "1200", 177 "timeout-absolute-secs": "6000", 178 # the confounder is part of the salted password hashes. If this config 179 # file is in a 0700 root:root dir, an attacker with apache credentials 180 # will have to get the confounder out of the process image to even try 181 # to guess the password hashes. 182 "confounder": "Change to <=31 chars of junk", 183 184 "email-from": "noreply@example.com", 185 "email-smtp-ip": "127.0.0.1", 186 "email-expire": "3600", 187 "email-helo": "myhost.com", 188 "email-contact-person": "Set Me <real-person@email.com>", 189 "email-confirm-url-base": "http://localhost:7681/lwsgs" 190 } 191``` 192 193The email- related settings control generation of automatic emails for 194registration and forgotten password. 195 196 - `email-from`: The email address automatic emails are sent from 197 198 - `email-smtp-ip`: Normally 127.0.0.1, if you have a suitable server on port 199 25 on your lan you can use this instead here. 200 201 - `email-expire`: Seconds that links sent in email will work before being 202 deleted 203 204 - `email-helo`: HELO to use when communicating with your SMTP server 205 206 - `email-contact-person`: mentioned in the automatic emails as a human who can 207 answer questions 208 209 - `email-confirm-url-base`: the URL to start links with in the emails, so the 210 recipient can get back to the web server 211 212The real protocol that makes use of generic-sessions must also be listed and 213any configuration it needs given 214 215``` 216 "protocol-lws-messageboard": { 217 "status": "ok", 218 "message-db": "/var/www/sessions/messageboard.sqlite3" 219 }, 220``` 221 222Notice the real application uses his own sqlite db, no details about how 223generic-sessions works or how it stores data are available to it. 224 225 226@section gspwc Lwsgs Password Confounder 227 228You can also define a per-vhost confounder shown in the example above, used 229when aggregating the password with the salt when it is hashed. Any attacker 230will also need to get the confounder along with the database, which you can 231make harder by making the config dir only eneterable / readable by root. 232 233 234@section gsprep Lwsgs Preparing the db directory 235 236You will have to prepare the db directory so it's suitable for the lwsws user to use, 237that usually means apache, eg 238 239``` 240 # mkdir -p /var/www/sessions 241 # chown root:apache /var/www/sessions 242 # chmod 770 /var/www/sessions 243``` 244 245@section gsrmail Lwsgs Email configuration 246 247lwsgs will can send emails by talking to an SMTP server on localhost:25. That 248will usually be sendmail or postfix, you should confirm that works first by 249itself using the `mail` application to send on it. 250 251lwsgs has been tested on stock Fedora sendmail and postfix. 252 253 254@section gsap Lwsgs Integration with another protocol 255 256lwsgs is designed to provide sessions and accounts in a standalone and generic way. 257 258But it's not useful by itself, there will always be the actual application who wants 259to make use of generic-sessions features. 260 261We provide the "messageboard" plugin as an example of how to integrate with 262your actual application protocol. 263 264The basic approach is the 'real' protocol handler (usually a plugin itself) 265subclasses the generic-sessions plugin and calls through to it by default. 266 267The "real" protocol handler entirely deals with ws-related stuff itself, since 268generic-sessions does not use ws. But for 269 270 - LWS_CALLBACK_HTTP 271 - LWS_CALLBACK_HTTP_BODY 272 - LWS_CALLBACK_HTTP_BODY_COMPLETION 273 - LWS_CALLBACK_HTTP_DROP_PROTOCOL 274 275the "real" protocol handler checks if it recognizes the activity (eg, his own 276POST form URL) and if not, passes stuff through to the generic-sessions protocol callback to handle it. To simplify matters the real protocol can just pass 277through any unhandled messages to generic-sessions. 278 279The "real" protocol can get a pointer to generic-sessions protocol on the 280same vhost using 281 282``` 283 vhd->gsp = lws_vhost_name_to_protocol(vhd->vh, "protocol-generic-sessions"); 284``` 285 286The "real" protocol must also arrange generic-sessions per_session_data in his 287own per-session allocation. To allow keeping generic-sessions opaque, the 288real protocol must allocate that space at runtime, using the pss size 289the generic-sessions protocol struct exposes 290 291``` 292 struct per_session_data__myapp { 293 void *pss_gs; 294 ... 295 296 pss->pss_gs = malloc(vhd->gsp->per_session_data_size); 297``` 298 299The allocation reserved for generic-sessions is then used as user_space when 300the real protocol calls through to the generic-sessions callback 301 302``` 303 vhd->gsp->callback(wsi, reason, &pss->pss_gs, in, len); 304``` 305 306In that way the "real" protocol can subclass generic-sessions functionality. 307 308 309To ease management of these secondary allocations, there are callbacks that 310occur when a wsi binds to a protocol and when the binding is dropped. These 311should be used to malloc and free and kind of per-connection 312secondary allocations. 313 314``` 315 case LWS_CALLBACK_HTTP_BIND_PROTOCOL: 316 if (!pss || pss->pss_gs) 317 break; 318 319 pss->pss_gs = malloc(vhd->gsp->per_session_data_size); 320 if (!pss->pss_gs) 321 return -1; 322 323 memset(pss->pss_gs, 0, vhd->gsp->per_session_data_size); 324 break; 325 326 case LWS_CALLBACK_HTTP_DROP_PROTOCOL: 327 if (vhd->gsp->callback(wsi, reason, pss ? pss->pss_gs : NULL, in, len)) 328 return -1; 329 330 if (pss->pss_gs) { 331 free(pss->pss_gs); 332 pss->pss_gs = NULL; 333 } 334 break; 335``` 336 337 338#section gsapsib Getting session-specific information from another protocol 339 340At least at the time when someone tries to upgrade an http(s) connection to 341ws(s) with your real protocol, it is necessary to confirm the cookie the http(s) 342connection has with generic-sessions and find out his username and other info. 343 344Generic sessions lets another protocol check it again by calling his callback, 345and lws itself provides a generic session info struct to pass the related data 346 347``` 348 struct lws_session_info { 349 char username[32]; 350 char email[100]; 351 char ip[72]; 352 unsigned int mask; 353 char session[42]; 354 }; 355 356 struct lws_session_info sinfo; 357 ... 358 vhd->gsp->callback(wsi, LWS_CALLBACK_SESSION_INFO, 359 &pss->pss_gs, &sinfo, 0); 360``` 361 362After the call to generic-sessions, the results can be 363 364 - all the strings will be zero-length and .mask zero, there is no usable cookie 365 366 - only .ip and .session are set: the cookie is OK but no user logged in 367 368 - all the strings contain information about the logged-in user 369 370the real protocol can use this to reject attempts to open ws connections from 371http connections that are not authenticated; afterwards there's no need to 372check the ws connection auth status again. 373 374
README.generic-table.md
1Notes about generic-table 2========================= 3 4@section gtint What is generic-table? 5 6Generic-table is a JSON schema and client-side JS file that makes it easy to 7display live, table structured HTML over a ws link. 8 9An example plugin and index.html using it are provided, but lwsgt itself doesn't 10have its own plugin, it's just a JSON schema and client-side JS that other 11plugins can use to simplify displaying live, table-based data without having 12to reinvent the wheel each time. 13 14The ws protocol sends JSON describing the table, and then JSON updating the table 15contents when it chooses, the brower table is updated automatically, live. 16 17\image html lwsgt-overview.png 18 19 - Example protocol plugin (displays directory contents): https://github.com/warmcat/libwebsockets/tree/master/plugins/generic-table/protocol_table_dirlisting.c 20 21 - Example HTML: https://github.com/warmcat/libwebsockets/tree/master/plugins/generic-table/assets/index.html 22 23 - lwsgt.js (client-side table rendering / ws link management): https://github.com/warmcat/libwebsockets/tree/master/plugins/generic-table/assets/lwsgt.js 24 25 26@section gteb Enabling for build 27 28Enable the demo plugin at CMake with -DLWS_WITH_PLUGINS=1 29 30 31@section gtinth Integrating with your html 32 33 - In your HEAD section, include lwsgt.js 34 35``` 36 <script src="lwsgt.js"></script> 37``` 38 39 - Also in your HEAD section, style the lwsgt CSS, eg 40 41``` 42 <style> 43 .lwsgt_title { font-size: 24; text-align:center } 44 .lwsgt_breadcrumbs { font-size: 18; text-align:left } 45 .lwsgt_table { font-size: 14; padding:12px; margin: 12px; align:center } 46 .lwsgt_hdr { font-size: 18; text-align:center; 47 background-color: rgba(40, 40, 40, 0.8); color: white } 48 .lwsgt_tr { padding: 10px } 49 .lwsgt_td { padding: 3px } 50 </style> 51``` 52 53You can skip this but the result will be less beautiful until some CSS is 54provided. 55 56 - In your body section, declare a div with an id (can be whatever you want) 57 58``` 59 <tr><td><div id="lwsgt1" class="group1"></div></td></tr> 60``` 61 62lwsgt JS will put its content there. 63 64 - Finally in a <script> at the end of your page, instantiate lwsgt and 65provide a custom callback for clickable links 66 67``` 68 <script> 69 var v1 = new lwsgt_initial("Dir listing demo", 70 "protocol-lws-table-dirlisting", 71 "lwsgt1", "lwsgt_dir_click", "v1"); 72 73 function lwsgt_dir_click(gt, u, col, row) 74 { 75 if (u[0] == '=') { /* change directory */ 76 window[gt].lwsgt_ws.send(u.substring(1, u.length)); 77 return; 78 } 79 var win = window.open(u, '_blank'); 80 win.focus(); 81 } 82 83 </script> 84``` 85 86In the callback, you can recover the ws object by `window[gt].lwsgt_ws`. 87 88 89@section gtc Lwsgt constructor 90 91To instantiate the ws link and lwsgt instance, your HTML must call a lwsgt 92constructor for each region on the page managed by lwsgt. 93 94`var myvar = new lwsgt_initial(title, ws_protocol, div_id, click_cb, myvar);` 95 96All of the arguments are strings. 97 98| Parameter | Description | 99|-----------------|---------------------------------------------------------| 100| title | Title string to go above the table | 101| ws_protocol | Protocol name string to use when making ws connection | 102| div_id | HTML id of div to fill with content | 103| click_cb | Callback function name string to handle clickable links | 104| myvar | Name of var used to hold this instantiation globally | 105 106Note "myvar" is needed so it can be passed to the click handling callback. 107 108 109@section gtclick Lwsgt click handling function 110 111When a clickable link produced by lwsgt is clicked, the function named in the 112click_cb parameter to lwsgt_initial is called. 113 114That function is expected to take four parameters, eg 115 116`function lwsgt_dir_click(gt, u, col, row)` 117 118| Parameter | Description | 119|------- ---|-----------------------------------------------------------| 120| gt | Name of global var holding this lwsgt context (ie, myvar) | 121| u | Link "url" string | 122| col | Table column number link is from | 123| row | Table row number link is from | 124 125 126 127@section gtgj Generic-table JSON 128 129### Column layout 130 131When the ws connection is established, the protocol should send a JSON message 132describing the table columns. For example 133 134``` 135 "cols": [ 136 { "name": "Date" }, 137 { "name": "Size", "align": "right" }, 138 { "name": "Icon" }, 139 { "name": "Name", "href": "uri"}, 140 { "name": "uri", "hide": "1" } 141 ] 142 } 143``` 144 145 - This describes 5 columns 146 147 - Only four columns (not "uri") should be visible 148 149 - "Name" should be presented as a clickable link using "uri" as the 150 destination, when a "uri" field is presented. 151 152 - "Size" field should be presented aligned to the right 153 154 ### Breadcrumbs 155 156 When a view is hierarchical, it's useful to provide a "path" with links back 157 in the "path", known as "breadcrumbs". 158 159 Elements before the last one should provide a "url" member as well as the 160 displayable name, which is used to create the link destination. 161 162 The last element, being the current displayed page should not have a url 163 member and be displayed without link style. 164 165 166 ``` 167 "breadcrumbs":[{"name":"top", "url": "/" }, {"name":"mydir"}] 168 ``` 169 170 ### Table data 171 172 The actual file data consists of an array of rows, containing the columns 173 mentioned in the original "cols" section. 174 175 ``` 176 "data":[ 177 { 178 "Icon":" ", 179 "Date":"2015-Feb-06 03:08:35 +0000", 180 "Size":"1406", 181 "uri":"./serve//favicon.ico", 182 "Name":"favicon.ico" 183 } 184 ] 185 186 ``` 187 188 @section gtdirl Setting up protocol-lws-table-dirlisting 189 190 The example protocol needs two mounts, one to provide the index.html, js and 191 the protocol itself 192 193 ``` 194 { 195 "mountpoint": "/dirtest", 196 "origin": "file:///usr/share/libwebsockets-test-server/generic-table", 197 "origin": "callback://protocol-lws-table-dirlisting", 198 "default": "index.html", 199 "pmo": [{ 200 "dir": "/usr/share/libwebsockets-test-server" 201 }] 202 }, 203``` 204 205The protocol wants a per-mount option (PMO) to tell it the base directory it 206is serving from, named "dir". 207 208The other mount is there to simply serve items that get clicked on from the 209table in a secure way 210 211``` 212 { 213 "mountpoint": "/dirtest/serve", 214 "origin": "file:///usr/share/libwebsockets-test-server", 215 "default": "index.html" 216 }, 217``` 218 219This last bit is not related to using lwsgt itself. 220
README.h2-long-poll.md
1# h2 long poll in lws 2 3lws server and client can support "immortal" streams that are 4not subject to normal timeouts under a special condition. These 5are read-only (to the client). 6 7Network connections that contain at least one immortal stream 8are themselves not subject to timeouts until the last immortal 9stream they are carrying closes. 10 11Because of this, it's recommended there is some other way of 12confirming that the client is still active. 13 14## Setting up lws server for h2 long poll 15 16Vhosts that wish to allow clients to serve these immortal 17streams need to set the info.options flag `LWS_SERVER_OPTION_VH_H2_HALF_CLOSED_LONG_POLL` 18at vhost creation time. The JSON config equivalent is to set 19 20``` 21"h2-half-closed-long-poll": "1" 22``` 23 24on the vhost. That's all that is needed. 25 26Streams continue to act normally for timeout with the exception 27client streams are allowed to signal they are half-closing by 28sending a zero-length DATA frame with END_STREAM set. These 29streams are allowed to exist outside of any timeout and data 30can be sent on them at will in the server -> client direction. 31 32## Setting client streams for long poll 33 34An API is provided to allow established h2 client streams to 35transition to immortal mode and send the END_STREAM to the server 36to indicate it. 37 38``` 39int 40lws_h2_client_stream_long_poll_rxonly(struct lws *wsi); 41``` 42 43## Example applications 44 45You can confirm the long poll flow simply using example applications. 46Build and run `http-server/minimal-http-server-h2-long-poll` in one 47terminal. 48 49In another, build the usual `http-client/minimal-http-client` example 50and run it with the flags `-l --long-poll` 51 52The client will connect to the server and transition to the immortal mode. 53The server sends a timestamp every minute to the client, and that will 54stay up without timeouts. 55 56
README.http-fallback.md
1# Http fallback and raw proxying 2 3Lws has several interesting options and features that can be applied to get 4some special behaviours... this article discusses them and how they work. 5 6## Overview of normal vhost selection 7 8Lws supports multiple http or https vhosts sharing a listening socket on the 9same port. 10 11For unencrypted http, the Host: header is used to select which vhost the 12connection should bind to, by comparing what is given there against the 13names the server was configured with for the various vhosts. If no match, it 14selects the first configured vhost. 15 16For TLS, it has an extension called SNI (Server Name Indication) which tells 17the server early in the TLS handshake the host name the connection is aimed at. 18That allows lws to select the vhost early, and use vhost-specific TLS certs 19so everything is happy. Again, if there is no match the connection proceeds 20using the first configured vhost and its certs. 21 22## Http(s) fallback options 23 24What happens if you try to connect, eg, an ssh client to the http server port 25(this is not an idle question...)? Obviously the http server part or the tls 26part of lws will fail the connection and close it. (We will look at that flow 27in a moment in detail for both unencrypted and tls listeners.) 28 29However if the first configured vhost for the port was created with the 30vhost creation info struct `.options` flag `LWS_SERVER_OPTION_FALLBACK_TO_APPLY_LISTEN_ACCEPT_CONFIG`, 31then instead of the error, the connection transitions to whatever role was 32given in the vhost creation info struct `.listen_accept_role` and `.listen_accept_protocol`. 33 34With lejp-conf / lwsws, the options can be applied to the first vhost using: 35 36``` 37 "listen-accept-role": "the-role-name", 38 "listen-accept-protocol": "the-protocol-name", 39 "fallback-listen-accept": "1" 40``` 41 42See `./minimal-examples/raw/minimal-raw-fallback-http-server` for examples of 43all the options in use via commandline flags. 44 45So long as the first packet for the protocol doesn't look like GET, POST, or 46a valid tls packet if connection to an https vhost, this allows the one listen 47socket to handle both http(s) and a second protocol, as we will see, like ssh. 48 49Notice there is a restriction that no vhost selection processing is possible, 50neither for tls listeners nor plain http ones... the packet belonging to a 51different protocol will not send any Host: header nor tls SNI. 52 53Therefore although the flags and settings are applied to the first configured 54vhost, actually their effect is global for a given listen port. If enabled, 55all vhosts on the same listen port will do the fallback action. 56 57### Plain http flow 58 59 60 61Normally, if the first received packet does not contain a valid HTTP method, 62then the connection is dropped. Which is what you want from an http server. 63 64However if enabled, the connection can transition to the defined secondary 65role / protocol. 66 67|Flag|lejp-conf / lwsws|Function| 68|---|---|---| 69|`LWS_SERVER_OPTION_FALLBACK_TO_APPLY_LISTEN_ACCEPT_CONFIG`|`"fallback-listen-accept": "1"`|Enable fallback processing| 70 71### TLS https flow 72 73 74 75If the port is listening with tls, the point that a packet from a different 76protocol will fail is earlier, when the tls tunnel is being set up. 77 78|Flag|lejp-conf / lwsws|Function| 79|---|---|---| 80|`LWS_SERVER_OPTION_FALLBACK_TO_APPLY_LISTEN_ACCEPT_CONFIG`|`"fallback-listen-accept": "1"`|Enable fallback processing| 81|`LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS`|`"redirect-http": "1"`|Treat invalid tls packet as http, issue http redirect to https://| 82|`LWS_SERVER_OPTION_ALLOW_HTTP_ON_HTTPS_LISTENER`|`"allow-http-on-https": "1"`|Accept unencrypted http connections on this tls port (dangerous)| 83 84The latter two options are higher priority than, and defeat, the first one. 85 86### Non-http listener 87 88 89 90It's also possible to skip the fallback processing and just force the first 91vhost on the port to use the specified role and protocol in the first place. 92 93|Flag|lejp-conf / lwsws|Function| 94|---|---|---| 95|LWS_SERVER_OPTION_ADOPT_APPLY_LISTEN_ACCEPT_CONFIG|`"apply-listen-accept": "1"`|Force vhost to use listen-accept-role / listen-accept-protocol| 96 97## Using http(s) fallback with raw-proxy 98 99If enabled for build with `cmake .. -DLWS_ROLE_RAW_PROXY=1 -DLWS_WITH_PLUGINS=1` 100then lws includes ready-to-use support for raw tcp proxying. 101 102This can be used standalone on the first vhost on a port, but most intriguingly 103it can be specified as the fallback for http(s)... 104 105See `./minimal-examples/raw/minimal-raw-proxy-fallback.c` for a working example. 106 107### fallback with raw-proxy in code 108 109On the first vhost for the port, specify the required "onward" pvo to configure 110the raw-proxy protocol...you can adjust the "ipv4:127.0.0.1:22" to whatever you 111want... 112 113``` 114 static struct lws_protocol_vhost_options pvo1 = { 115 NULL, 116 NULL, 117 "onward", /* pvo name */ 118 "ipv4:127.0.0.1:22" /* pvo value */ 119 }; 120 121 static const struct lws_protocol_vhost_options pvo = { 122 NULL, /* "next" pvo linked-list */ 123 &pvo1, /* "child" pvo linked-list */ 124 "raw-proxy", /* protocol name we belong to on this vhost */ 125 "" /* ignored */ 126 }; 127``` 128 129... and set up the fallback enable and bindings... 130 131``` 132 info.options |= LWS_SERVER_OPTION_FALLBACK_TO_APPLY_LISTEN_ACCEPT_CONFIG; 133 info.listen_accept_role = "raw_proxy"; 134 info.listen_accept_proxy = "raw_proxy"; 135 info.pvo = &pvo; 136``` 137 138### fallback with raw-proxy in JSON conf 139 140On the first vhost for the port, enable the raw-proxy protocol on the vhost and 141set the pvo config 142 143``` 144 "ws-protocols": [{ 145 "raw-proxy": { 146 "status": "ok", 147 "onward": "ipv4:127.0.0.1:22" 148 } 149 }], 150``` 151 152Enable the fallback behaviour on the vhost and the role / protocol binding 153 154``` 155 "listen-accept-role": "raw-proxy", 156 "listen-accept-protocol": "raw-proxy", 157 "fallback-listen-accept": "1" 158``` 159 160### Testing 161 162With this configured, the listen port will function normally for http or https 163depending on how it was set up. 164 165But if you try to connect to it with an ssh client, that will also work fine. 166 167The libwebsockets.org server is set up in this way, you can confirm it by 168visiting `https://libwebsockets.org` on port 443 as usual, but also trying 169`ssh -p 443 invalid@libwebsockets.org`... you will get permission denied from 170your ssh client. With valid credentials in fact that works perfectly for 171ssh, scp, git-over-ssh etc all on port 443... 172 173
README.lws_dll.md
1# lws_dll Doubly-linked list 2 3## Introduction 4 5Lws supports two kinds of doubly-linked list, `lws_dll` and `lws_dll2`. 6 7Unless memory is at a big premium, or it has to work on lws < v3.2, it's 8best to simply use `lws_dll2`. 9 10 11 12## How to use 13 14The basics are the same for lws_dll and lws_dll2. 15 16The list objects point only to themselves, and you use the `lws_container_of` 17macro to get a pointer to your struct that contains the list object. Doing 18it this way 19 20 - the list object does not have to be the first thing in your struct 21 22 - your struct can contain multiple list objects and appear on lists belonging 23 to multiple owners simultaenously, 24 25### lws_dll Minimal example 26 27``` 28struct mystruct { 29 .... 30 lws_dll list; 31 ... 32}; 33 34lws_dll owner; 35``` 36 37Adding a mystruct to the owner list (...add_tail() works the same way but adds 38to the other end of the list) 39 40``` 41 struct mystruct *p; 42 43 ... 44 45 lws_dll_add_head(&p->list, &owner); 46``` 47 48Removing the list object from its owner 49 50``` 51 lws_dll2_remove(&p->list, &owner); 52``` 53 54If you have a `struct lws_dll *d` pointing to `list` in struct mystruct, you can 55convert it to a `struct mystruct *p` ike this 56 57``` 58 struct mystruct *p = lws_container_of(d, struct lws_dll, list); 59``` 60 61### lws_dll2 Minimal example 62 63 64``` 65struct mystruct { 66 .... 67 lws_dll2 list; 68 ... 69}; 70 71lws_dll2_owner owner; 72``` 73 74Adding a mystruct to the owner list (...add_tail() works the same way but adds 75to the other end of the list) 76 77``` 78 struct mystruct *p; 79 80 ... 81 82 lws_dll2_add_head(&p->list, &owner); 83``` 84 85Removing the list object from its owner (notice compared to lws_dll, it doesn't 86need to be told the owner) 87 88``` 89 lws_dll2_remove(&p->list); 90``` 91 92If you have a `struct lws_dll2 *d` pointing to `list` in struct mystruct, you 93can convert it to a `struct mystruct *p` ike this 94 95``` 96 struct mystruct *p = lws_container_of(d, struct lws_dll2, list); 97``` 98 99## Summary Comparing lws_dll and lws_dll2 100 101 - both offer a doubly-linked list object, and (since v3.2) track both the 102 head and tail in an "list owner" object 103 104 - both are initalized by memsetting to 0 105 106 - for `lws_dll`, it reuses an `lws_dll` as the "owner", for `lws_dll2`, there's a 107 specific `lws_dll2_owner` structure for that 108 109 - `lws_dll2_owner` also keeps count of the number of list elements 110 111 - `lws_dll2` knows which owner's list it is participating on. So it can remove 112 itself and update the owner without the caller needing to know its owner. 113 In the case there are several potential owners list objects may be on, this 114 is very convenient. 115 116 - `lws_dll` is simpler and has a smaller footprint (two pointers per entry vs 117 three). But you have to know the exact list owner to perform operations on 118 it. 119 120## apis 121 122|function|lws_dll|lws_dll2| 123|---|---|---| 124|add entry at head|`void lws_dll_add_head(struct lws_dll *d, struct lws_dll *phead)`|`void lws_dll2_add_head(struct lws_dll2 *d, struct lws_dll2_owner *owner)`| 125|add entry at tail|`void lws_dll_add_tail(struct lws_dll *d, struct lws_dll *phead);`|`void lws_dll2_add_tail(struct lws_dll2 *d, struct lws_dll2_owner *owner)`| 126|remove entry from its owning list|`void lws_dll_remove_track_tail(struct lws_dll *d, struct lws_dll *phead)`|`void lws_dll2_add_tail(struct lws_dll2 *d, struct lws_dll2_owner *owner)`| 127|get owner|(not supported)|`struct lws_dll2_owner * lws_dll2_owner(const struct lws_dll2 *d)`| 128|check if item is detached from any list|`lws_dll_is_detached(struct lws_dll *d, struct lws_dll *phead)|int lws_dll2_is_detached(const struct lws_dll2 *d)`| 129|iterate through items on list|`int lws_dll_foreach_safe(struct lws_dll *phead, void *user, int (*cb)(struct lws_dll *d, void *user))|int lws_dll2_foreach_safe(struct lws_dll2_owner *owner, void *user, int (*cb)(struct lws_dll2 *d, void *user))`| 130 131
README.lws_retry.md
1# `lws_retry_bo_t` client connection management 2 3This struct sets the policy for delays between retries, and for 4how long a connection may be 'idle' before it first tries to 5ping / pong on it to confirm it's up, or drops the connection 6if still idle. 7 8## Retry rate limiting 9 10You can define a table of ms-resolution delays indexed by which 11connection attempt number is ongoing, this is pointed to by 12`.retry_ms_table` with `.retry_ms_table_count` containing the 13count of table entries. 14 15`.conceal_count` is the number of retries that should be allowed 16before informing the parent that the connection has failed. If it's 17greater than the number of entries in the table, the last entry is 18reused for the additional attempts. 19 20`.jitter_percent` controls how much additional random delay is 21added to the actual interval to be used... this stops a lot of 22devices all synchronizing when they try to connect after a single 23trigger event and DDoS-ing the server. 24 25The struct and apis are provided for user implementations, lws does 26not offer reconnection itself. 27 28## Connection validity management 29 30Lws has a sophisticated idea of connection validity and the need to 31reconfirm that a connection is still operable if proof of validity 32has not been seen for some time. It concerns itself only with network 33connections rather than streams, for example, it only checks h2 34network connections rather than the individual streams inside (which 35is consistent with h2 PING frames only working at the network stream 36level itself). 37 38Connections may fail in a variety of ways, these include that no traffic 39at all is passing, or, eg, incoming traffic may be received but no 40outbound traffic is making it to the network, and vice versa. In the 41case that tx is not failing at any point but just isn't getting sent, 42endpoints can potentially kid themselves that since "they are sending" 43and they are seeing RX, the combination means the connection is valid. 44This can potentially continue for a long time if the peer is not 45performing keepalives. 46 47"Connection validity" is proven when one side sends something and later 48receives a response that can only have been generated by the peer 49receiving what was just sent. This can happen for some kinds of user 50transactions on any stream using the connection, or by sending PING / 51PONG protocol packets where the PONG is only returned for a received PING. 52 53To ensure that the generated traffic is only sent when necessary, user 54code can report for any stream that it has observed a transaction amounting 55to a proof of connection validity using an api. This resets the timer for 56the associated network connection before the validity is considered 57expired. 58 59`.secs_since_valid_ping` in the retry struct sets the number of seconds since 60the last validity after which lws will issue a protocol-specific PING of some 61kind on the connection. `.secs_since_valid_hangup` specifies how long lws 62will allow the connection to go without a confirmation of validity before 63simply hanging up on it. 64 65## Defaults 66 67The context defaults to having a 5m valid ping interval and 5m10s hangup interval, 68ie, it'll send a ping at 5m idle if the protocol supports it, and if no response 69validating the connection arrives in another 10s, hang up the connection. 70 71User code can set this in the context creation info and can individually set the 72retry policy per vhost for server connections. Client connections can set it 73per connection in the client creation info `.retry_and_idle_policy`. 74 75## Checking for h2 and ws 76 77Check using paired minimal examples with the -v flag on one or both sides to get a 78small validity check period set of 3s / 10s 79 80Also give, eg, -d1039 to see info level debug logging 81 82### h2 83 84``` 85$ lws-minimal-http-server-h2-long-poll -v 86 87$ lws-minimal-http-client -l -v 88``` 89 90### ws 91 92``` 93$ lws-minimal-ws-server-h2 -s -v 94 95$ lws-minimal-ws-client-ping -n --server 127.0.0.1 --port 7681 -v 96``` 97 98 99
README.lws_sequencer.md
1# `struct lws_sequencer` introduction 2 3Often a single network action like a client GET is just part of a 4larger series of actions, perhaps involving different connections. 5 6Since lws operates inside an event loop, if the outer sequencing 7doesn't, it can be awkward to synchronize these steps with what's 8happening on the network with a particular connection on the event 9loop thread. 10 11 12 13`struct lws_sequencer` provides a generic way to stage multi-step 14operations from inside the event loop. Because it participates 15in the event loop similar to a wsi, it always operates from the 16service thread context and can access structures that share the 17service thread without locking. It can also provide its own 18higher-level timeout handling. 19 20Naturally you can have many of them running in the same event 21loop operating independently. 22 23Sequencers themselves bind to a pt (per-thread) service thread, 24by default there's only one of these and it's the same as saying 25they bind to an `lws_context`. The sequencer callback may create 26wsi which in turn are bound to a vhost, but the sequencer itself 27is above all that. 28 29## Sequencer timeouts 30 31The sequencer additionally maintains its own second-resolution timeout 32checked by lws for the step being sequenced... this is independent of 33any lws wsi timeouts which tend to be set and reset for very short-term 34timeout protection inside one transaction. 35 36The sequencer timeout operates separately and above any wsi timeout, and 37is typically only reset by the sequencer callback when it receives an 38event indicating a step completed or failed, or it sets up the next sequence 39step. 40 41If the sequencer timeout expires, then the sequencer receives a queued 42`LWSSEQ_TIMED_OUT` message informing it, and it can take corrective action 43or schedule a retry of the step. This message is queued and sent normally 44under the service thread context and in order of receipt. 45 46Unlike lws timeouts which force the wsi to close, the sequencer timeout 47only sends the message. This allows the timeout to be used to, eg, wait 48out a retry cooloff period and then start the retry when the 49`LWSSEQ_TIMED_OUT` is received, according to the state of the sequencer. 50 51## Creating an `struct lws_sequencer` 52 53``` 54typedef struct lws_seq_info { 55 struct lws_context *context; /* lws_context for seq */ 56 int tsi; /* thread service idx */ 57 size_t user_size; /* size of user alloc */ 58 void **puser; /* place ptr to user */ 59 lws_seq_event_cb cb; /* seq callback */ 60 const char *name; /* seq name */ 61 const lws_retry_bo_t *retry; /* retry policy */ 62} lws_seq_info_t; 63``` 64 65``` 66struct lws_sequencer * 67lws_sequencer_create(lws_seq_info_t *info); 68``` 69 70When created, in lws the sequencer objects are bound to a 'per-thread', 71which is by default the same as to say bound to the `lws_context`. You 72can tag them with an opaque user data pointer, and they are also bound to 73a user-specified callback which handles sequencer events 74 75``` 76typedef int (*lws_seq_event_cb)(struct lws_sequencer *seq, void *user_data, 77 lws_seq_events_t event, void *data); 78``` 79 80`struct lws_sequencer` objects are private to lws and opaque to the user. A small 81set of apis lets you perform operations on the pointer returned by the 82create api. 83 84## Queueing events on a sequencer 85 86Each sequencer object can be passed "events", which are held on a per-sequencer 87queue and handled strictly in the order they arrived on subsequent event loops. 88`LWSSEQ_CREATED` and `LWSSEQ_DESTROYED` events are produced by lws reflecting 89the sequencer's lifecycle, but otherwise the event indexes have a user-defined 90meaning and are queued on the sequencer by user code for eventual consumption 91by user code in the sequencer callback. 92 93Pending events are removed from the sequencer queues and sent to the sequencer 94callback from inside the event loop at a rate of one per event loop wait. 95 96## Destroying sequencers 97 98`struct lws_sequencer` objects are cleaned up during context destruction if they are 99still around. 100 101Normally the sequencer callback receives a queued message that 102informs it that it's either failed at the current step, or succeeded and that 103was the last step, and requests that it should be destroyed by returning 104`LWSSEQ_RET_DESTROY` from the sequencer callback. 105 106## Lifecycle considerations 107 108Sequencers may spawn additional assets like client wsi as part of the sequenced 109actions... the lifecycle of the sequencer and the assets overlap but do not 110necessarily depend on each other... that is a wsi created by the sequencer may 111outlive the sequencer. 112 113It's important therefore to detach assets from the sequencer and the sequencer 114from the assets when each step is over and the asset is "out of scope" for the 115sequencer. It doesn't necessarily mean closing the assets, just making sure 116pointers are invalidated. For example, if a client wsi held a pointer to the 117sequencer as its `.user_data`, when the wsi is out of scope for the sequencer 118it can set it to NULL, eg, `lws_set_wsi_user(wsi, NULL);`. 119 120Under some conditions wsi may want to hang around a bit to see if there is a 121subsequent client wsi transaction they can be reused on. They will clean 122themselves up when they time out. 123 124## Watching wsi lifecycle from a sequencer 125 126When a sequencer is creating a wsi as part of its sequence, it will be very 127interested in lifecycle events. At client wsi creation time, the sequencer 128callback can set info->seq to itself in order to receive lifecycle messages 129about its wsi. 130 131|message|meaning| 132|---|---| 133|`LWSSEQ_WSI_CONNECTED`|The wsi has become connected| 134|`LWSSEQ_WSI_CONN_FAIL`|The wsi has failed to connect| 135|`LWSSEQ_WSI_CONN_CLOSE`|The wsi had been connected, but has now closed| 136 137By receiving these, the sequencer can understand when it should attempt 138reconnections or that it cannot progress the sequence. 139 140When dealing with wsi that were created by the sequencer, they may close at 141any time, eg, be closed by the remote peer or an intermediary. The 142`LWSSEQ_WSI_CONN_CLOSE` message may have been queued but since they are 143strictly handled in the order they arrived, before it was 144handled an earlier message may want to cause some api to be called on 145the now-free()-d wsi. To detect this situation safely, there is a 146sequencer api `lws_sequencer_check_wsi()` which peeks the message 147buffer and returns nonzero if it later contains an `LWSSEQ_WSI_CONN_CLOSE` 148already. 149 150
README.lws_struct.md
1# lws_struct 2 3## Overview 4 5lws_struct provides a lightweight method for serializing and deserializing C 6structs to and from JSON, and to and from sqlite3. 7 8 9 10 - you provide a metadata array describing struct members one-time, then call 11 generic apis to serialize and deserialize 12 13 - supports flat structs, single child struct pointers, and unbounded arrays / 14 linked-lists of child objects automatically using [lws_dll2 linked-lists](./README.lws_dll.md) 15 16 - supports boolean and C types char, int, long, long long in explicitly signed 17 and unsigned forms 18 19 - supports both char * type string members where the unbounded content is 20 separate and pointed to, and fixed length char array[] type members where 21 the content is part of the struct 22 23 - huge linear strings are supported by storing to a temp lwsac of chained chunks, 24 which is written into a single linear chunk in the main lwsac once the 25 total string length is known 26 27 - deserialization allocates into an [lwsac](../lib/misc/lwsac/README.md), so everything is inside as few 28 heap allocations as possible while still able to expand to handle arbitrary 29 array or strins sizes 30 31 - when deserialized structs are finished with, a single call to free the 32 lwsac frees the whole thing without having to walk it 33 34 - stateful serializaton and deserialization allows as-you-get packets incremental 35 parsing and production of chunks of as-you-can-send incremental serialization 36 output cleanly 37 38## Examples 39
README.lws_sul.md
1# `lws_sul` scheduler api 2 3Since v3.2 lws no longer requires periodic checking for timeouts and 4other events. A new system was refactored in where future events are 5scheduled on to a single, unified, sorted linked-list in time order, 6with everything at us resolution. 7 8This makes it very cheap to know when the next scheduled event is 9coming and restrict the poll wait to match, or for event libraries 10set a timer to wake at the earliest event when returning to the 11event loop. 12 13Everything that was checked periodically was converted to use `lws_sul` 14and schedule its own later event. The end result is when lws is idle, 15it will stay asleep in the poll wait until a network event or the next 16scheduled `lws_sul` event happens, which is optimal for power. 17 18# Side effect for older code 19 20If your older code uses `lws_service_fd()`, it used to be necessary 21to call this with a NULL pollfd periodically to indicate you wanted 22to let the background checks happen. `lws_sul` eliminates the whole 23concept of periodic checking and NULL is no longer a valid pollfd 24value for this and related apis. 25 26# Using `lws_sul` in user code 27 28See `minimal-http-client-multi` for an example of using the `lws_sul` 29scheduler from your own code; it uses it to spread out connection 30attempts so they are staggered in time. You must create an 31`lws_sorted_usec_list_t` object somewhere, eg, in you own existing object. 32 33``` 34static lws_sorted_usec_list_t sul_stagger; 35``` 36 37Create your own callback for the event... the argument points to the sul object 38used when the callback was scheduled. You can use pointer arithmetic to translate 39that to your own struct when the `lws_sorted_usec_list_t` was a member of the 40same struct. 41 42``` 43static void 44stagger_cb(lws_sorted_usec_list_t *sul) 45{ 46... 47} 48``` 49 50When you want to schedule the callback, use `lws_sul_schedule()`... this will call 51it 10ms in the future 52 53``` 54 lws_sul_schedule(context, 0, &sul_stagger, stagger_cb, 10 * LWS_US_PER_MS); 55``` 56 57In the case you destroy your object and need to cancel the scheduled callback, use 58 59``` 60 lws_sul_schedule(context, 0, &sul_stagger, NULL, LWS_SET_TIMER_USEC_CANCEL); 61``` 62 63
README.lws_system.md
1# `lws_system` 2 3See `include/libwebsockets/lws-system.h` for function and object prototypes. 4 5## System integration api 6 7`lws_system` allows you to set a `system_ops` struct at context creation time, 8which can write up some function callbacks for system integration. The goal 9is the user code calls these by getting the ops struct pointer from the 10context using `lws_system_get_ops(context)` and so does not spread system 11dependencies around the user code, making it directly usable on completely 12different platforms. 13 14``` 15typedef struct lws_system_ops { 16 int (*reboot)(void); 17 int (*set_clock)(lws_usec_t us); 18 int (*attach)(struct lws_context *context, int tsi, lws_attach_cb_t cb, 19 lws_system_states_t state, void *opaque, 20 struct lws_attach_item **get); 21} lws_system_ops_t; 22``` 23 24|Item|Meaning| 25|---|---| 26|`(*reboot)()`|Reboot the system| 27|`(*set_clock)()`|Set the system clock| 28|`(*attach)()`|Request an event loop callback from another thread context| 29 30### `reboot` 31 32Reboots the device 33 34### `set_clock` 35 36Set the system clock to us-resolution Unix time in seconds 37 38### `attach` 39 40Request a callback from the event loop from a foreign thread. This is used, for 41example, for foreign threads to set up their event loop activity in their 42callback, and eg, exit once it is done, with their event loop activity able to 43continue wholly from the lws event loop thread and stack context. 44 45## Foreign thread `attach` architecture 46 47When lws is started, it should define an `lws_system_ops_t` at context creation 48time which defines its `.attach` handler. In the `.attach` handler 49implementation, it should perform platform-specific locking around a call to 50`__lws_system_attach()`, a public lws api that actually queues the callback 51request and does the main work. The platform-specific wrapper is just there to 52do the locking so multiple calls from different threads to the `.attach()` 53operation can't conflict. 54 55User code can indicate it wants a callback from the lws event loop like this: 56 57``` 58lws_system_get_ops(context)->attach(context, tsi, cb, state, opaque, NULL) 59``` 60 61`context` is a pointer to the lws_context, `tsi` is normally 0, `cb` is the user 62callback in the form 63 64``` 65void (*lws_attach_cb_t)(struct lws_context *context, int tsi, void *opaque); 66``` 67 68`state` is the `lws_system` state we should have reached before performing the 69callback (usually, `LWS_SYSTATE_OPERATIONAL`), and `opaque` is a user pointer that 70will be passed into the callback. 71 72`cb` will normally want to create scheduled events and set up lws network-related 73activity from the event loop thread and stack context. 74 75Once the event loop callback has been booked by calling this api, the thread and 76its stack context that booked it may be freed. It will be called back and can 77continue operations from the lws event loop thread and stack context. For that 78reason, if `opaque` is needed it will usually point to something on the heap, 79since the stack context active at the time the callback was booked may be long 80dead by the time of the callback. 81 82See ./lib/system/README.md for more details. 83 84## `lws_system` blobs 85 86"Blobs" are arbitrary binary objects that have a total length. Lws lets you set 87them in two ways 88 89 - "directly", by pointing to them, which has no heap implication 90 91 - "heap", by adding one or more arbitrary chunk to a chained heap object 92 93In the "heap" case, it can be incrementally defined and the blob doesn't all 94have to be declared at once. 95 96For read, the same api allows you to read all or part of the blob into a user 97buffer. 98 99The following kinds of blob are defined 100 101|Item|Meaning| 102|---|---| 103|`LWS_SYSBLOB_TYPE_AUTH`|Auth-related blob 1, typically a registration token| 104|`LWS_SYSBLOB_TYPE_AUTH + 1`|Auth-related blob 2, typically an auth token| 105|`LWS_SYSBLOB_TYPE_CLIENT_CERT_DER`|Client cert public part| 106|`LWS_SYSBLOB_TYPE_CLIENT_KEY_DER`|Client cert key part| 107|`LWS_SYSBLOB_TYPE_DEVICE_SERIAL`|Arbitrary device serial number| 108|`LWS_SYSBLOB_TYPE_DEVICE_FW_VERSION`|Arbitrary firmware version| 109|`LWS_SYSBLOB_TYPE_DEVICE_TYPE`|Arbitrary Device Type identifier| 110|`LWS_SYSBLOB_TYPE_NTP_SERVER`|String with the ntp server address (defaults to pool.ntp.org)| 111 112### Blob handle api 113 114Returns an object representing the blob for a particular type (listed above) 115 116``` 117lws_system_blob_t * 118lws_system_get_blob(struct lws_context *context, lws_system_blob_item_t type, 119 int idx); 120``` 121 122### Blob Setting apis 123 124Sets the blob to point length `len` at `ptr`. No heap allocation is used. 125 126``` 127void 128lws_system_blob_direct_set(lws_system_blob_t *b, const uint8_t *ptr, size_t len); 129``` 130 131Allocates and copied `len` bytes from `buf` into heap and chains it on the end of 132any existing. 133 134``` 135int 136lws_system_blob_heap_append(lws_system_blob_t *b, const uint8_t *buf, size_t len) 137``` 138 139Remove any content from the blob, freeing it if it was on the heap 140 141``` 142void 143lws_system_blob_heap_empty(lws_system_blob_t *b) 144``` 145 146### Blob getting apis 147 148Get the total size of the blob (ie, if on the heap, the aggreate size of all the 149chunks that were appeneded) 150 151``` 152size_t 153lws_system_blob_get_size(lws_system_blob_t *b) 154``` 155 156Copy part or all of the blob starting at offset ofs into a user buffer at buf. 157`*len` should be the length of the user buffer on entry, on exit it's set to 158the used extent of `buf`. This works the same whether the bob is a direct pointer 159or on the heap. 160 161``` 162int 163lws_system_blob_get(lws_system_blob_t *b, uint8_t *buf, size_t *len, size_t ofs) 164``` 165 166If you know that the blob was handled as a single direct pointer, or a single 167allocation, you can get a pointer to it without copying using this. 168 169``` 170int 171lws_system_blob_get_single_ptr(lws_system_blob_t *b, const uint8_t **ptr) 172``` 173 174### Blob destroy api 175 176Deallocates any heap allocation for the blob 177 178``` 179void 180lws_system_blob_destroy(lws_system_blob_t *b) 181``` 182 183 184## System state and notifiers 185 186Lws implements a state in the context that reflects the readiness of the system 187for various steps leading up to normal operation. By default it acts in a 188backwards-compatible way and directly reaches the OPERATIONAL state just after 189the context is created. 190 191However other pieces of lws, and user, code may define notification handlers 192that get called back when the state changes incrementally, and may veto or delay 193the changes until work necessary for the new state has completed asynchronously. 194 195The generic states defined are: 196 197|State|Meaning| 198|---|---| 199|`LWS_SYSTATE_CONTEXT_CREATED`|The context was just created.| 200|`LWS_SYSTATE_INITIALIZED`|The vhost protocols have been initialized| 201|`LWS_SYSTATE_IFACE_COLDPLUG`|Existing network interfaces have been iterated| 202|`LWS_SYSTATE_DHCP`|Network identity is available| 203|`LWS_SYSTATE_TIME_VALID`|The system knows the time| 204|`LWS_SYSTATE_POLICY_VALID`|If the system needs information about how to act from the net, it has it| 205|`LWS_SYSTATE_REGISTERED`|The device has a registered identity| 206|`LWS_SYSTATE_AUTH1`|The device identity has produced a time-limited access token| 207|`LWS_SYSTATE_AUTH2`|Optional second access token for different services| 208|`LWS_SYSTATE_OPERATIONAL`|The system is ready for user code to work normally| 209|`LWS_SYSTATE_POLICY_INVALID`|All connections are being dropped because policy information is changing. It will transition back to `LWS_SYSTATE_INITIALIZED` and onward to `OPERATIONAL` again afterwards with the new policy| 210 211### Inserting a notifier 212 213You should create an object `lws_system_notify_link_t` in non-const memory and zero it down. 214Set the `notify_cb` member and the `name` member and then register it using either 215`lws_system_reg_notifier()` or the `.register_notifier_list` 216member of the context creation info struct to make sure it will exist early 217enough to see all events. The context creation info method takes a list of 218pointers to notify_link structs ending with a NULL entry. 219 220
README.lwsws.md
1Notes about lwsws 2================= 3 4@section lwsws Libwebsockets Web Server 5 6lwsws is an implementation of a very lightweight, ws-capable generic web 7server, which uses libwebsockets to implement everything underneath. 8 9If you are basically implementing a standalone server with lws, you can avoid 10reinventing the wheel and use a debugged server including lws. 11 12 13@section lwswsb Build 14 15Just enable -DLWS_WITH_LWSWS=1 at cmake-time. 16 17It enables libuv and plugin support automatically. 18 19NOTICE on Ubuntu, the default libuv package is called "libuv-0.10". This is ancient. 20 21You should replace this with libuv1 and libuv1-dev before proceeding. 22 23@section lwswsc Lwsws Configuration 24 25lwsws uses JSON config files, they're pure JSON except: 26 27 - '#' may be used to turn the rest of the line into a comment. 28 29 - There's also a single substitution, if a string contains "_lws_ddir_", then that is 30replaced with the LWS install data directory path, eg, "/usr/share" or whatever was 31set when LWS was built + installed. That lets you refer to installed paths without 32having to change the config if your install path was different. 33 34There is a single file intended for global settings 35 36/etc/lwsws/conf 37``` 38 # these are the server global settings 39 # stuff related to vhosts should go in one 40 # file per vhost in ../conf.d/ 41 42 { 43 "global": { 44 "username": "apache", 45 "groupname": "apache", 46 "count-threads": "1", 47 "server-string": "myserver v1", # returned in http headers 48 "ws-pingpong-secs": "200", # confirm idle established ws connections this often 49 "init-ssl": "yes" 50 } 51 } 52``` 53and a config directory intended to take one file per vhost 54 55/etc/lwsws/conf.d/warmcat.com 56``` 57 { 58 "vhosts": [{ 59 "name": "warmcat.com", 60 "port": "443", 61 "interface": "eth0", # optional 62 "host-ssl-key": "/etc/pki/tls/private/warmcat.com.key", # if given enable ssl 63 "host-ssl-cert": "/etc/pki/tls/certs/warmcat.com.crt", 64 "host-ssl-ca": "/etc/pki/tls/certs/warmcat.com.cer", 65 "mounts": [{ # autoserve 66 "mountpoint": "/", 67 "origin": "file:///var/www/warmcat.com", 68 "default": "index.html" 69 }] 70 }] 71 } 72``` 73To get started quickly, an example config reproducing the old test server 74on port 7681, non-SSL is provided. To set it up 75``` 76 # mkdir -p /etc/lwsws/conf.d /var/log/lwsws 77 # cp ./lwsws/etc-lwsws-conf-EXAMPLE /etc/lwsws/conf 78 # cp ./lwsws/etc-lwsws-conf.d-localhost-EXAMPLE /etc/lwsws/conf.d/test-server 79 # sudo lwsws 80``` 81 82@section lwswsacme Using Letsencrypt or other ACME providers 83 84Lws supports automatic provisioning and renewal of TLS certificates. 85 86See ./READMEs/README.plugin-acme.md for examples of how to set it up on an lwsws vhost. 87 88@section lwsogo Other Global Options 89 90 - `reject-service-keywords` allows you to return an HTTP error code and message of your choice 91if a keyword is found in the user agent 92 93``` 94 "reject-service-keywords": [{ 95 "scumbot": "404 Not Found" 96 }] 97``` 98 99 - `timeout-secs` lets you set the global timeout for various network-related 100 operations in lws, in seconds. It defaults to 5. 101 102@section lwswsv Lwsws Vhosts 103 104One server can run many vhosts, where SSL is in use SNI is used to match 105the connection to a vhost and its vhost-specific SSL keys during SSL 106negotiation. 107 108Listing multiple vhosts looks something like this 109``` 110 { 111 "vhosts": [ { 112 "name": "localhost", 113 "port": "443", 114 "host-ssl-key": "/etc/pki/tls/private/libwebsockets.org.key", 115 "host-ssl-cert": "/etc/pki/tls/certs/libwebsockets.org.crt", 116 "host-ssl-ca": "/etc/pki/tls/certs/libwebsockets.org.cer", 117 "mounts": [{ 118 "mountpoint": "/", 119 "origin": "file:///var/www/libwebsockets.org", 120 "default": "index.html" 121 }, { 122 "mountpoint": "/testserver", 123 "origin": "file:///usr/local/share/libwebsockets-test-server", 124 "default": "test.html" 125 }], 126 # which protocols are enabled for this vhost, and optional 127 # vhost-specific config options for the protocol 128 # 129 "ws-protocols": [{ 130 "warmcat,timezoom": { 131 "status": "ok" 132 } 133 }] 134 }, 135 { 136 "name": "localhost", 137 "port": "7681", 138 "host-ssl-key": "/etc/pki/tls/private/libwebsockets.org.key", 139 "host-ssl-cert": "/etc/pki/tls/certs/libwebsockets.org.crt", 140 "host-ssl-ca": "/etc/pki/tls/certs/libwebsockets.org.cer", 141 "mounts": [{ 142 "mountpoint": "/", 143 "origin": ">https://localhost" 144 }] 145 }, 146 { 147 "name": "localhost", 148 "port": "80", 149 "mounts": [{ 150 "mountpoint": "/", 151 "origin": ">https://localhost" 152 }] 153 } 154 155 ] 156 } 157``` 158 159That sets up three vhosts all called "localhost" on ports 443 and 7681 with SSL, and port 80 without SSL but with a forced redirect to https://localhost 160 161 162@section lwswsvn Lwsws Vhost name and port sharing 163 164The vhost name field is used to match on incoming SNI or Host: header, so it 165must always be the host name used to reach the vhost externally. 166 167 - Vhosts may have the same name and different ports, these will each create a 168listening socket on the appropriate port. 169 170 - Vhosts may also have the same port and different name: these will be treated as 171true vhosts on one listening socket and the active vhost decided at SSL 172negotiation time (via SNI) or if no SSL, then after the Host: header from 173the client has been parsed. 174 175 176@section lwswspr Lwsws Protocols 177 178Vhosts by default have available the union of any initial protocols from context creation time, and 179any protocols exposed by plugins. 180 181Vhosts can select which plugins they want to offer and give them per-vhost settings using this syntax 182``` 183 "ws-protocols": [{ 184 "warmcat-timezoom": { 185 "status": "ok" 186 } 187 }] 188``` 189 190The "x":"y" parameters like "status":"ok" are made available to the protocol during its per-vhost 191LWS_CALLBACK_PROTOCOL_INIT (in is a pointer to a linked list of struct lws_protocol_vhost_options 192containing the name and value pointers). 193 194To indicate that a protocol should be used when no Protocol: header is sent 195by the client, you can use "default": "1" 196``` 197 "ws-protocols": [{ 198 "warmcat-timezoom": { 199 "status": "ok", 200 "default": "1" 201 } 202 }] 203``` 204 205Similarly, if your vhost is serving a raw protocol, you can mark the protocol 206to be selected using "raw": "1" 207``` 208 "ws-protocols": [{ 209 "warmcat-timezoom": { 210 "status": "ok", 211 "raw": "1" 212 } 213 }] 214``` 215 216See also "apply-listen-accept" below. 217 218@section lwswsovo Lwsws Other vhost options 219 220 - If the three options `host-ssl-cert`, `host-ssl-ca` and `host-ssl-key` are given, then the vhost supports SSL. 221 222 Each vhost may have its own certs, SNI is used during the initial connection negotiation to figure out which certs to use by the server name it's asking for from the request DNS name. 223 224 - `keeplive-timeout` (in secs) defaults to 60 for lwsws, it may be set as a vhost option 225 226 - `interface` lets you specify which network interface to listen on, if not given listens on all. If the network interface is not usable (eg, ethernet cable out) it will be logged at startup with such vhost not listening, and lws will poll for it and bind a listen socket to the interface if and when it becomes available. 227 228 - "`unix-socket`": "1" causes the unix socket specified in the interface option to be used instead of an INET socket 229 230 - "`unix-socket-perms`": "user:group" allows you to control the unix permissons on the listening unix socket. It's always get to `0600` mode, but you can control the user and group for the socket fd at creation time. This allows you to use unix user and groups to control who may open the other end of the unix socket on the local system. 231 232 - "`sts`": "1" causes lwsws to send a Strict Transport Security header with responses that informs the client he should never accept to connect to this address using http. This is needed to get the A+ security rating from SSL Labs for your server. 233 234 - "`access-log`": "filepath" sets where apache-compatible access logs will be written 235 236 - `"enable-client-ssl"`: `"1"` enables the vhost's client SSL context, you will need this if you plan to create client conections on the vhost that will use SSL. You don't need it if you only want http / ws client connections. 237 238 - "`ciphers`": "<cipher list>" OPENSSL only: sets the allowed list of TLS <= 1.2 ciphers and key exchange protocols for the serving SSL_CTX on the vhost. The default list is restricted to only those providing PFS (Perfect Forward Secrecy) on the author's Fedora system. 239 240 If you need to allow weaker ciphers, you can provide an alternative list here per-vhost. 241 242 - "`client-ssl-ciphers`": "<cipher list>" OPENSSL only: sets the allowed list of <= TLS1.2 ciphers and key exchange protocols for the client SSL_CTX on the vhost 243 244 - "`tls13-ciphers`": "<cipher list>" OPENSSL 1.1.1+ only: sets allowed list of TLS1.3+ ciphers and key exchange protocols for the client SSL_CTX on the vhost. The default is to allow all. 245 246 - "`client-tls13-ciphers`": "<cipher list>" OPENSSL 1.1.1+ only: sets the allowed list of TLS1.3+ ciphers and key exchange protocols for the client SSL_CTX on the vhost. The default is to allow all. 247 248 - "`ecdh-curve`": "<curve name>" The default ecdh curve is "prime256v1", but you can override it here, per-vhost 249 250 - "`noipv6`": "on" Disable ipv6 completely for this vhost 251 252 - "`ipv6only`": "on" Only allow ipv6 on this vhost / "off" only allow ipv4 on this vhost 253 254 - "`ssl-option-set`": "<decimal>" Sets the SSL option flag value for the vhost. 255 It may be used multiple times and OR's the flags together. 256 257 The values are derived from /usr/include/openssl/ssl.h 258``` 259 # define SSL_OP_NO_TLSv1_1 0x10000000L 260``` 261 262 would equate to 263 264``` 265 "`ssl-option-set`": "268435456" 266 ``` 267 - "`ssl-option-clear'": "<decimal>" Clears the SSL option flag value for the vhost. 268 It may be used multiple times and OR's the flags together. 269 270 - "`ssl-client-option-set`" and "`ssl-client-option-clear`" work the same way for the vhost Client SSL context 271 272 - "`headers':: [{ "header1": "h1value", "header2": "h2value" }] 273 274allows you to set arbitrary headers on every file served by the vhost 275 276recommended vhost headers for good client security are 277 278``` 279 "headers": [{ 280 "Content-Security-Policy": "script-src 'self'", 281 "X-Content-Type-Options": "nosniff", 282 "X-XSS-Protection": "1; mode=block", 283 "X-Frame-Options": "SAMEORIGIN" 284 }] 285 286``` 287 288 - "`apply-listen-accept`": "on" This vhost only serves a non-http protocol, specified in "listen-accept-role" and "listen-accept-protocol" 289 290@section lwswsm Lwsws Mounts 291 292Where mounts are given in the vhost definition, then directory contents may 293be auto-served if it matches the mountpoint. 294 295Mount protocols are used to control what kind of translation happens 296 297 - file:// serve the uri using the remainder of the url past the mountpoint based on the origin directory. 298 299 Eg, with this mountpoint 300``` 301 { 302 "mountpoint": "/", 303 "origin": "file:///var/www/mysite.com", 304 "default": "/" 305 } 306``` 307 The uri /file.jpg would serve /var/www/mysite.com/file.jpg, since / matched. 308 309 - ^http:// or ^https:// these cause any url matching the mountpoint to issue a redirect to the origin url 310 311 - cgi:// this causes any matching url to be given to the named cgi, eg 312``` 313 { 314 "mountpoint": "/git", 315 "origin": "cgi:///var/www/cgi-bin/cgit", 316 "default": "/" 317 }, { 318 "mountpoint": "/cgit-data", 319 "origin": "file:///usr/share/cgit", 320 "default": "/" 321 }, 322``` 323 would cause the url /git/myrepo to pass "myrepo" to the cgi /var/www/cgi-bin/cgit and send the results to the client. 324 325 - http:// or https:// these perform reverse proxying, serving the remote origin content from the mountpoint. Eg 326 327``` 328 { 329 "mountpoint": "/proxytest", 330 "origin": "https://libwebsockets.org" 331 } 332``` 333 334This will cause your local url `/proxytest` to serve content fetched from libwebsockets.org over ssl; whether it's served from your server using ssl is unrelated and depends how you configured your local server. Notice if you will use the proxying feature, `LWS_WITH_HTTP_PROXY` is required to be enabled at cmake, and for `https` proxy origins, your lwsws configuration must include `"init-ssl": "1"` and the vhost with the proxy mount must have `"enable-client-ssl": "1"`, even if you are not using ssl to serve. 335 336`/proxytest/abc`, or `/proxytest/abc?def=ghi` etc map to the origin + the part past `/proxytest`, so links and img src urls etc work as do all urls under the origin path. 337 338In addition link and src urls in the document are rewritten so / or the origin url part are rewritten to the mountpoint part. 339 340 341@section lwswsomo Lwsws Other mount options 342 3431) Some protocols may want "per-mount options" in name:value format. You can 344provide them using "pmo" 345 346 { 347 "mountpoint": "/stuff", 348 "origin": "callback://myprotocol", 349 "pmo": [{ 350 "myname": "myvalue" 351 }] 352 } 353 3542) When using a cgi:// protocol origin at a mountpoint, you may also give cgi environment variables specific to the mountpoint like this 355``` 356 { 357 "mountpoint": "/git", 358 "origin": "cgi:///var/www/cgi-bin/cgit", 359 "default": "/", 360 "cgi-env": [{ 361 "CGIT_CONFIG": "/etc/cgitrc/libwebsockets.org" 362 }] 363 } 364``` 365 This allows you to customize one cgi depending on the mountpoint (and / or vhost). 366 3673) It's also possible to set the cgi timeout (in secs) per cgi:// mount, like this 368``` 369 "cgi-timeout": "30" 370``` 3714) `callback://` protocol may be used when defining a mount to associate a 372named protocol callback with the URL namespace area. For example 373``` 374 { 375 "mountpoint": "/formtest", 376 "origin": "callback://protocol-post-demo" 377 } 378``` 379All handling of client access to /formtest[anything] will be passed to the 380callback registered to the protocol "protocol-post-demo". 381 382This is useful for handling POST http body content or general non-cgi http 383payload generation inside a plugin. 384 385See the related notes in README.coding.md 386 3875) Cache policy of the files in the mount can also be set. If no 388options are given, the content is marked uncacheable. 389``` 390 { 391 "mountpoint": "/", 392 "origin": "file:///var/www/mysite.com", 393 "cache-max-age": "60", # seconds 394 "cache-reuse": "1", # allow reuse at client at all 395 "cache-revalidate": "1", # check it with server each time 396 "cache-intermediaries": "1" # allow intermediary caches to hold 397 } 398``` 399 4006) You can also define a list of additional mimetypes per-mount 401``` 402 "extra-mimetypes": { 403 ".zip": "application/zip", 404 ".doc": "text/evil" 405 } 406``` 407 408Normally a file suffix MUST match one of the canned mimetypes or one of the extra 409mimetypes, or the file is not served. This adds a little bit of security because 410even if there is a bug somewhere and the mount dirs are circumvented, lws will not 411serve, eg, /etc/passwd. 412 413If you provide an extra mimetype entry 414 415 "*": "" 416 417Then any file is served, if the mimetype was not known then it is served without a 418Content-Type: header. 419 4207) A mount can be protected by HTTP Basic Auth. This only makes sense when using 421https, since otherwise the password can be sniffed. 422 423You can add a `basic-auth` entry on an http mount like this 424 425``` 426{ 427 "mountpoint": "/basic-auth", 428 "origin": "file://_lws_ddir_/libwebsockets-test-server/private", 429 "basic-auth": "/var/www/balogins-private" 430} 431``` 432 433Before serving anything, lws will signal to the browser that a username / password 434combination is required, and it will pop up a dialog. When the user has filled it 435in, lwsws checks the user:password string against the text file named in the `basic-auth` 436entry. 437 438The file should contain user:pass one per line 439 440``` 441testuser:testpass 442myuser:hispass 443``` 444 445The file should be readable by lwsws, and for a little bit of extra security not 446have a file suffix, so lws would reject to serve it even if it could find it on 447a mount. 448 449After successful authentication, `WSI_TOKEN_HTTP_AUTHORIZATION` contains the 450authenticated username. 451 452In the case you want to also protect being able to connect to a ws protocol on 453a particular vhost by requiring the http part can authenticate using Basic 454Auth before the ws upgrade, this is also possible. In this case, the 455"basic-auth": and filepath to the credentials file is passed as a pvo in the 456"ws-protocols" section of the vhost definition. 457 458@section lwswscc Requiring a Client Cert on a vhost 459 460You can make a vhost insist to get a client certificate from the peer before 461allowing the connection with 462 463``` 464 "client-cert-required": "1" 465``` 466 467the connection will only proceed if the client certificate was signed by the 468same CA as the server has been told to trust. 469 470@section rawconf Configuring Fallback and Raw vhosts 471 472Lws supports some unusual modes for vhost listen sockets, which may be 473configured entirely using the JSON per-vhost config language in the related 474vhost configuration section. 475 476There are three main uses for them 477 4781) A vhost bound to a specific role and protocol, not http. This binds all 479incoming connections on the vhost listen socket to the "raw-proxy" role and 480protocol "myprotocol". 481 482``` 483 "listen-accept-role": "raw-proxy", 484 "listen-accept-protocol": "myprotocol", 485 "apply-listen-accept": "1" 486``` 487 4882) A vhost that wants to treat noncompliant connections for http or https as 489 belonging to a secondary fallback role and protocol. This causes non-https 490 connections to an https listener to stop being treated as https, to lose the 491 tls wrapper, and bind to role "raw-proxy" and protocol "myprotocol". For 492 example, connect a browser on your external IP :443 as usual and it serves 493 as normal, but if you have configured the raw-proxy to portforward 494 127.0.0.1:22, then connecting your ssh client to your external port 443 will 495 instead proxy your sshd over :443 with no http or tls getting in the way. 496 497``` 498 "listen-accept-role": "raw-proxy", 499 "listen-accept-protocol": "myprotocol", 500 "fallback-listen-accept": "1", 501 "allow-non-tls": "1" 502``` 503 5043) A vhost wants to either redirect stray http traffic back to https, or to 505 actually serve http on an https listen socket (this is not recommended 506 since it allows anyone to drop the security assurances of https by 507 accident or design). 508 509``` 510 "allow-non-tls": "1", 511 "redirect-http": "1", 512``` 513 514...or, 515 516``` 517 "allow-non-tls": "1", 518 "allow-http-on-https": "1", 519``` 520 521@section lwswspl Lwsws Plugins 522 523Protcols and extensions may also be provided from "plugins", these are 524lightweight dynamic libraries. They are scanned for at init time, and 525any protocols and extensions found are added to the list given at context 526creation time. 527 528Protocols receive init (LWS_CALLBACK_PROTOCOL_INIT) and destruction 529(LWS_CALLBACK_PROTOCOL_DESTROY) callbacks per-vhost, and there are arrangements 530they can make per-vhost allocations and get hold of the correct pointer from 531the wsi at the callback. 532 533This allows a protocol to choose to strictly segregate data on a per-vhost 534basis, and also allows the plugin to handle its own initialization and 535context storage. 536 537To help that happen conveniently, there are some new apis 538 539 - lws_vhost_get(wsi) 540 - lws_protocol_get(wsi) 541 - lws_callback_on_writable_all_protocol_vhost(vhost, protocol) 542 - lws_protocol_vh_priv_zalloc(vhost, protocol, size) 543 - lws_protocol_vh_priv_get(vhost, protocol) 544 545dumb increment, mirror and status protocol plugins are provided as examples. 546 547 548@section lwswsplaplp Additional plugin search paths 549 550Packages that have their own lws plugins can install them in their own 551preferred dir and ask lwsws to scan there by using a config fragment 552like this, in its own conf.d/ file managed by the other package 553``` 554 { 555 "global": { 556 "plugin-dir": "/usr/local/share/coherent-timeline/plugins" 557 } 558 } 559``` 560 561@section lwswsssp lws-server-status plugin 562 563One provided protocol can be used to monitor the server status. 564 565Enable the protocol like this on a vhost's ws-protocols section 566``` 567 "lws-server-status": { 568 "status": "ok", 569 "update-ms": "5000" 570 } 571``` 572`"update-ms"` is used to control how often updated JSON is sent on a ws link. 573 574And map the provided HTML into the vhost in the mounts section 575``` 576 { 577 "mountpoint": "/server-status", 578 "origin": "file:///usr/local/share/libwebsockets-test-server/server-status", 579 "default": "server-status.html" 580 } 581``` 582You might choose to put it on its own vhost which has "interface": "lo", so it's not 583externally visible, or use the Basic Auth support to require authentication to 584access it. 585 586`"hide-vhosts": "{0 | 1}"` lets you control if information about your vhosts is included. 587Since this includes mounts, you might not want to leak that information, mount names, 588etc. 589 590`"filespath":"{path}"` lets you give a server filepath which is read and sent to the browser 591on each refresh. For example, you can provide server temperature information on most 592Linux systems by giving an appropriate path down /sys. 593 594This may be given multiple times. 595 596 597@section lwswsreload Lwsws Configuration Reload 598 599You may send lwsws a `HUP` signal, by, eg 600 601``` 602$ sudo killall -HUP lwsws 603``` 604 605This causes lwsws to "deprecate" the existing lwsws process, and remove and close all of 606its listen sockets, but otherwise allowing it to continue to run, until all 607of its open connections close. 608 609When a deprecated lwsws process has no open connections left, it is destroyed 610automatically. 611 612After sending the SIGHUP to the main lwsws process, a new lwsws process, which can 613pick up the newly-available listen sockets, and use the current configuration 614files, is automatically started. 615 616The new configuration may differ from the original one in arbitrary ways, the new 617context is created from scratch each time without reference to the original one. 618 619Notes 620 6211) Protocols that provide a "shared world" like mirror will have as many "worlds" 622as there are lwsws processes still active. People connected to a deprecated lwsws 623process remain connected to the existing peers. 624 625But any new connections will apply to the new lwsws process, which does not share 626per-vhost "shared world" data with the deprecated process. That means no new 627connections on the deprecated context, ie a "shrinking world" for those guys, and a 628"growing world" for people who connect after the SIGHUP. 629 6302) The new lwsws process owes nothing to the previous one. It starts with fresh 631plugins, fresh configuration, fresh root privileges if that how you start it. 632 633The plugins may have been updated in arbitrary ways including struct size changes 634etc, and lwsws or lws may also have been updated arbitrarily. 635 6363) A root parent process is left up that is not able to do anything except 637respond to SIGHUP or SIGTERM. Actual serving and network listening etc happens 638in child processes which use the privileges set in the lwsws config files. 639 640@section lwswssysd Lwsws Integration with Systemd 641 642lwsws needs a service file like this as `/usr/lib/systemd/system/lwsws.service` 643``` 644[Unit] 645Description=Libwebsockets Web Server 646After=syslog.target 647 648[Service] 649ExecStart=/usr/local/bin/lwsws 650ExecReload=/usr/bin/killall -s SIGHUP lwsws ; sleep 1 ; /usr/local/bin/lwsws 651StandardError=null 652 653[Install] 654WantedBy=multi-user.target 655``` 656 657You can find this prepared in `./lwsws/usr-lib-systemd-system-lwsws.service` 658 659 660@section lwswslr Lwsws Integration with logrotate 661 662For correct operation with logrotate, `/etc/logrotate.d/lwsws` (if that's 663where we're putting the logs) should contain 664``` 665 /var/log/lwsws/*log { 666 copytruncate 667 missingok 668 notifempty 669 delaycompress 670 } 671``` 672You can find this prepared in `/lwsws/etc-logrotate.d-lwsws` 673 674Prepare the log directory like this 675 676``` 677 sudo mkdir /var/log/lwsws 678 sudo chmod 700 /var/log/lwsws 679``` 680 681@section lwswsgdb Debugging lwsws with gdb 682 683Hopefully you won't need to debug lwsws itself, but you may want to debug your plugins. start lwsws like this to have everything running under gdb 684 685``` 686sudo gdb -ex "set follow-fork-mode child" -ex "run" --args /usr/local/bin/lwsws 687 688``` 689 690this will give nice backtraces in lwsws itself and in plugins, if they were built with symbols. 691 692@section lwswsvgd Running lwsws under valgrind 693 694You can just run lwsws under valgrind as usual and get valid results. However the results / analysis part of valgrind runs 695after the plugins have removed themselves, this means valgrind backtraces into plugin code is opaque, without 696source-level info because the dynamic library is gone. 697 698There's a simple workaround, use LD_PRELOAD=<plugin.so> before running lwsws, this has the loader bring the plugin 699in before executing lwsws as if it was a direct dependency. That means it's still mapped until the whole process 700exits after valgtind has done its thing. 701 702 703
README.plugin-acme.md
1lws-acme-client Plugin 2====================== 3 4## Introduction 5 6lws-acme-client is a protcol plugin for libwebsockets that implements an 7ACME client able to communicate with let's encrypt and other certificate 8providers. 9 10It implements `tls-sni-01` challenge, and is able to provision tls certificates 11"from thin air" that are accepted by all the major browsers. It also manages 12re-requesting the certificate when it only has two weeks left to run. 13 14It works with both the OpenSSL and mbedTLS backends. 15 16## Overview for use 17 18You need to: 19 20 - Provide name resolution to the IP with your server, ie, myserver.com needs to 21 resolve to the IP that hosts your server 22 23 - Enable port forwarding / external firewall access to your port, usually 443 24 25 - Enable the "lws-acme-client" plugin on the vhosts you want it to manage 26 certs for 27 28 - Add per-vhost options describing what should be in the certificate 29 30After that the plugin will sort everything else out. 31 32## Example lwsws setup 33 34``` 35 "vhosts": [ { 36 "name": "home.warmcat.com", 37 "port": "443", 38 "host-ssl-cert": "/etc/lwsws/acme/home.warmcat.com.crt.pem", 39 "host-ssl-key": "/etc/lwsws/acme/home.warmcat.com.key.pem", 40 "ignore-missing-cert": "1", 41 "access-log": "/var/log/lwsws/test-access-log", 42 "ws-protocols": [{ 43 "lws-acme-client": { 44 "auth-path": "/etc/lwsws/acme/auth.jwk", 45 "cert-path": "/etc/lwsws/acme/home.warmcat.com.crt.pem", 46 "key-path": "/etc/lwsws/acme/home.warmcat.com.key.pem", 47 "directory-url": "https://acme-staging.api.letsencrypt.org/directory", 48 "country": "TW", 49 "state": "Taipei", 50 "locality": "Xiaobitan", 51 "organization": "Crash Barrier Ltd", 52 "common-name": "home.warmcat.com", 53 "email": "andy@warmcat.com" 54 }, 55 ... 56``` 57 58## Required PVOs 59 60Notice that the `"host-ssl-cert"` and `"host-ssl-key"` entries have the same 61meaning as usual, they point to your certificate and private key. However 62because the ACME plugin can provision these, you should also mark the vhost with 63`"ignore-missing-cert" : "1"`, so lwsws will ignore what will initially be 64missing certificate / keys on that vhost, and will set about creating the 65necessary certs and keys instead of erroring out. 66 67You must make sure the directories mentioned here exist, lws doesn't create them 68for you. They should be 0700 root:root, even if you drop lws privileges. 69 70If you are implementing support in code, this corresponds to making sure the 71vhost creating `info.options` has the `LWS_SERVER_OPTION_IGNORE_MISSING_CERT` 72bit set. 73 74Similarly, in code, the each of the per-vhost options shown above can be 75provided in a linked-list of structs at vhost creation time. See 76`./test-apps/test-server-v2.0.c` for example code for providing pvos. 77 78### auth-path 79 80This is where the plugin will store the auth keys it generated. 81 82### cert-path 83 84Where the plugin will store the certificate file. Should match `host-ssl-cert` 85that the vhost wants to use. 86 87The path should include at least one 0700 root:root directory. 88 89### key-path 90 91Where the plugin will store the certificate keys. Again it should match 92`host-ssl-key` the vhost is trying to use. 93 94The path should include at least one 0700 root:root directory. 95 96### directory-url 97 98This defines the URL of the certification server you will get your 99certificates from. For let's encrypt, they have a "practice" one 100 101 - `https://acme-staging.api.letsencrypt.org/directory` 102 103and they have a "real" one 104 105 - `https://acme-v01.api.letsencrypt.org/directory` 106 107the main difference is the CA certificate for the real one is in most browsers 108already, but the staging one's CA certificate isn't. The staging server will 109also let you abuse it more in terms of repeated testing etc. 110 111It's recommended you confirm expected operation with the staging directory-url, 112and then switch to the "real" URL. 113 114### common-name 115 116Your server DNS name, like "libwebsockets.org". The remote ACME server will 117use this to find your server to perform the SNI challenges. 118 119### email 120 121The contact email address for the certificate. 122 123## Optional PVOs 124 125These are not included in the cert by letsencrypt 126 127### country 128 129Two-letter country code for the certificate 130 131### state 132 133State "or province" for the certificate 134 135### locality 136 137Locality for the certificate 138 139### organization 140 141Your company name 142 143## Security / Key storage considerations 144 145The `lws-acme-client` plugin is able to provision and update your certificate 146and keys in an entirely root-only storage environment, even though lws runs 147as a different uid / gid with no privileges to access the storage dir. 148 149It does this by opening and holding two WRONLY fds on "update paths" inside the 150root directory structure for each cert and key it manages; these are the normal 151cert and key paths with `.upd` appended. If during the time the server is up 152the certs become within two weeks of expiry, the `lws-acme-client` plugin will 153negotiate new certs and write them to the file descriptors. 154 155Next time the server starts, if it sees `.upd` cert and keys, it will back up 156the old ones and copy them into place as the new ones, before dropping privs. 157 158To also handle the long-uptime server case, lws will update the vhost with the 159new certs using in-memory temporary copies of the cert and key after updating 160the cert. 161 162In this way the cert and key live in root-only storage but the vhost is kept up 163to date dynamically with any cert changes as well. 164 165## Multiple vhosts using same cert 166 167In the case you have multiple vhosts using of the same cert, just attach 168the `lws-acme-client` plugin to one instance. When the cert updates, all the 169vhosts are informed and vhosts using the same filepath to access the cert will 170be able to update their cert. 171 172## Implementation point 173 174You will need to remove the auth keys when switching from OpenSSL to 175mbedTLS. They will be regenerated automatically. It's the file at this 176path: 177 178``` 179"auth-path": "/etc/lwsws/acme/auth.jwk", 180``` 181
README.plugin-sshd-base.md
1ssh-base Plugin 2================ 3 4## Introduction 5 6lws-ssh-base is a protcol plugin for libwebsockets that implements a 7generic, abstract, ssh server. 8 9 - very small footprint in code and memory, takes up small part of ESP32 10 11 - written with security in mind: valgrind and Coverity -clean 12 13 - binds to one or more vhosts, that controls listen port(s) 14 15 - all IO and settings abstracted through a single "ops" struct from user code 16 17 - each instance on a vhost has its own "ops" struct, defining server keys, 18 auth method and functions to implement IO and other operations 19 20 - The plugin has no built-in behaviours like check ~/.ssh/authorized_keys, 21 treat auth usernames as system usernames, or spawn the user's shell. 22 Everything potentially dangerous is left to the user ops code to decide 23 how to handle. It's NOT like sshd where running it implies it will accept 24 existing keys for any system user, will spawn a shell, etc, unless you 25 implement those parts in the ops callbacks. 26 27 - The plugin requires extra code around it in the form of the ops struct 28 handlers. So it's role is something like an abstract base class for an ssh 29 server. All the crypto, protocol sequencing and state machine are inside, 30 but all the IO except the network connection is outside. 31 32 - Built as part of libwebsockets, like all plugins may be dynamically loaded 33 at runtime or built statically. Test app `libwebsockets-test-sshd` provided 34 35 - Uses hash and RSA functions from either mbedTLS or OpenSSL automatically, 36 according to which library libwebsockets was built for 37 38To maintain its small size, it implements a single "best of breed" crypto for 39the following functions: 40 41|Function|Crypto| 42|---|---| 43|KEX|curve25519-sha256@libssh.org| 44|Server host key|ssh-rsa (4096b)| 45|Encryption|chacha20-poly1305@openssh.com| 46|Compression|None| 47 48## License 49 50lws-ssh-base is Free Software, available under libwebsockets' MIT license. 51 52The crypto parts are available elsewhere under a BSD license. But for 53simplicity the whole plugin is under MIT. 54 55## Generating your own keys 56 57``` 58 $ ssh-keygen -t rsa -b 4096 -f mykeys 59``` 60 61will ask for a passphrase and generate the private key in `mykeys` and the 62public key in `mykeys.pub`. If you already have a suitable RSA key you use 63with ssh, you can just use that directly. 64 65lws installs a test keypair in /usr[/local]/share/libwebsockets-test-server 66that the test apps will accept. 67 68## Example code 69 701) There's a working example app `libwebsockets-test-sshd` included that 71spawns a bash shell when an ssh client authenticates. The username used on 72the remote ssh has no meaning, it spawns the shell under the credentials of 73"lws-test-sshd" was run under. It accepts the lws ssh test key which is 74installed into /usr[/local]/share/libwebsockets-test-server. 75 76Start the server like this (it wants root only because the server key is stored 77in /etc) 78 79``` 80 $ sudo libwebsockets-test-sshd 81``` 82 83Connect to it using the test private key like this 84 85``` 86 $ ssh -p 2200 -i /usr/local/share/libwebsockets-test-server/lws-ssh-test-keys anyuser@127.0.0.1 87``` 88 892) There's also a working example plugin `lws-sshd-demo` that "subclasses" the 90abstract `lws-ssh-base` plugin to make a protocol which can be used from, 91eg, lwsws. For an lwsws vhost that listens on port 2222 and responds with 92the lws-sshd-demo ssh server, the related config is: 93 94``` 95 { 96 "name": "sshd", 97 "port": "2222", 98 "onlyraw": "1", 99 "ws-protocols": [{ 100 "lws-ssh-base": { 101 "status": "ok", 102 "ops-from": "lws-sshd-demo" 103 }, 104 "lws-sshd-demo": { 105 "status": "ok", 106 "raw": "1" 107 } 108 }] 109 } 110``` 111 112 113 114## Integration to other apps 115 116### Step 0: Build and install libwebsockets 117 118For the `libwebsockets-test-sshd` example, you will need CMake options 119`LWS_WITH_CGI`, since it uses lws helpers to spawn a shell. 120 121lws-ssh-base itself doesn't require CGI support in libwebsockets. 122 123### Step 1: make the code available in your app 124 125Include `lws-plugin-ssh-base` in your app, either as a runtime plugin or by using 126the lws static include scheme. 127 128To bring in the whole of the ssh-base plugin 129into your app in one step, statically, just include 130`plugins/ssh-base/include/lws-plugin-sshd-static-build-includes.h`, you can see 131an example of this in `./test-apps/test-sshd.c`. 132 133### Step 2: define your `struct lws_ssh_ops` 134 135`plugins/ssh-base/include/lws-plugin-ssh.h` defines 136`struct lws_ssh_ops` which is used for all customization and integration 137of the plugin per vhost. Eg, 138 139``` 140static const struct lws_ssh_ops ssh_ops = { 141 .channel_create = ssh_ops_channel_create, 142 .channel_destroy = ssh_ops_channel_destroy, 143 .tx_waiting = ssh_ops_tx_waiting, 144 .tx = ssh_ops_tx, 145 .rx = ssh_ops_rx, 146 .get_server_key = ssh_ops_get_server_key, 147 .set_server_key = ssh_ops_set_server_key, 148 .set_env = ssh_ops_set_env, 149 .pty_req = ssh_ops_pty_req, 150 .child_process_io = ssh_ops_child_process_io, 151 .child_process_terminated = ssh_ops_child_process_terminated, 152 .exec = ssh_ops_exec, 153 .shell = ssh_ops_shell, 154 .is_pubkey_authorized = ssh_ops_is_pubkey_authorized, 155 .banner = ssh_ops_banner, 156 .disconnect_reason = ssh_ops_disconnect_reason, 157 .server_string = "SSH-2.0-Libwebsockets", 158 .api_version = 1, 159}; 160``` 161The `ssh_ops_...()` functions are your implementations for the operations 162needed by the plugin for your purposes. 163 164### Step 3: enable `lws-ssh-base` protocol to a vhost and configure using pvo 165 166A pointer to your struct lws_ssh_ops is passed into the vhost instance of the 167protocol using per-vhost options 168 169``` 170static const struct lws_protocol_vhost_options pvo_ssh_ops = { 171 NULL, 172 NULL, 173 "ops", 174 (void *)&ssh_ops 175}; 176 177static const struct lws_protocol_vhost_options pvo_ssh = { 178 NULL, 179 &pvo_ssh_ops, 180 "lws-sshd-base", 181 "" /* ignored, just matches the protocol name above */ 182}; 183 184... 185 info.port = 22; 186 info.options = LWS_SERVER_OPTION_ONLY_RAW; 187 info.vhost_name = "sshd"; 188 info.protocols = protocols_sshd; 189 info.pvo = &pvo_ssh; 190 191 vh_sshd = lws_create_vhost(context, &info); 192``` 193 194There are two possible pvos supported, "ops", shown above, directly passes the 195ops structure in using the value on the "ops" pvo. 196 197To support other protocols that want to provide ops to lws-ssh-base themselves 198for a particular vhost, you can also provide a pvo `"ops-from"` whose value is 199the name of the protocol also enabled on this vhost, whose protocol ".user" 200pointer points to the ops struct lws-ssh-base should use. 201 202## Integration to other plugins 203 204A worked example of using the abstract `lws-ssh-base` plugin from another 205plugin that provides the ops struct is in `./plugins/protocol_lws_sshd_demo`. 206 207The key points to note 208 209 - the plugin sets the ops struct for the vhost instantiation of `lws-ssh-base` 210 by passing a pointer to the ops struct in its `lws_protocols` struct `user` 211 member. 212 213 - the config for the vhost tells `lws-ssh-base` to pick up the ops struct 214 pointer using an "ops-from" pvo that indicates the protocol name. 215 216``` 217 "lws-ssh-base": { 218 "status": "ok", 219 "ops-from": "lws-sshd-demo" 220 }, 221``` 222 223 - the config for the vhost tells lws this vhost only serves RAW (ie, no http) 224 225``` 226 { 227 "name": "sshd", 228 "port": "2222", 229 "onlyraw": "1", 230 ... 231``` 232 233 - the config for the vhost marks the protocol that uses `lws-ssh-base`, not 234 `lws-ssh-base` itself, as the protocol to be served for raw connections 235 236``` 237 "lws-sshd-demo": { 238 "status": "ok", 239 "raw": "1" 240 ... 241``` 242 243## Notes 244 245You can have the vhost it binds to listen on a nonstandard port. The ssh 246commandline app cane be told to connect to a non-22 port with 247`ssh -p portnum user@hostname` 248 249 250
README.porting.md
1# Guidance for porting to new platform 2 3Where differences existed between the initial POSIX platform for lws and other 4supported platforms like Windows, `lws_plat_...()` apis were added to move 5handling to platform-specific code in `./lib/plat/`. 6 7Depending o which platform is built, different platform-specific implementations 8of these `lws_plat...()` apis get built. 9 10## 1) Prepare the cmake cross-build file if necessary 11 12CMake isolates its settings for cross-build into a separate file, which can be 13used to different cmake projects for the same platform as well. 14 15Find a similar examples already in `./contrib/cross-*` and copy and adapt it 16as needed, 17 18All settings related to toolchain should go in there. For cross-toolchain, 19the convention is to pass the path to its installed directory in `CROSS_PATH` 20environment variable. 21 22## 2) Copy the closest platform dir in ./lib/plat 23 24Wholesale copy the closest existing platform dir to `/lib/plat/myplatform` and 25rename the files. 26 27Remove stuff specific to the original platform. 28 29## 3) Add a flag in CMakeLists.txt 30 31Cut and paste a flag to select your platform, preferably `LWS_PLAT_MYPLATFORM` or so 32 33## 4) Add a section to force-select and deselect other cmake options based on platform flag 34 35Some options on by default may not make sense on your platform, and others off 36by default may be mandatory. After the options() section in CMakeLists.txt, you 37can use this kind of structure 38 39``` 40 if (LWS_PLAT_MYPLATFORM) 41 set(LWS_WITH_XXXX 0) 42 endif() 43``` 44 45to enforce implicit requirements of your platform. Optional stuff should be set by 46running cmake commandline as usual. 47 48## 5) Add building your platform files into CMakeLists.txt 49 50Add entries in CMakeLists.txt for building stuff in `./lib/plat/myplatform` when 51`LWS_PLAT_MYPLATFORM` is enabled. 52 53## 6) Adapt your copied ./lib/plat/myplatform/ files 54 55You can now do test builds using the cross-build file, your platform flag in 56cmake, and your copied ./lib/plat content... this last part since it was 57copied from another platform will initially be a plentiful source of errors. 58 59You can iteratively build and adapt the platform files. 60 61
README.problems.md
1Debugging problems 2================== 3 4Check it's still a problem with latest lws 5------------------------------------------ 6 7Older versions of lws don't attract any new work after they are released 8(see [the release policy](https://libwebsockets.org/git/libwebsockets/tree/READMEs/README.release-policy.md) for details); 9for a while they will get backported bugfixes but that's it. 10 11All new work and bugfixes happen on master branch. 12 13Old, old versions may be convenient for you to use for some reason. But unless 14you pay for support or have contributed work to lws so we feel we owe you some 15consideration, nobody else has any reason to particularly care about solving 16issues on ancient versions. Whereas if the problem exists on master, and can be 17reproduced by developers, it usually gets attention, often immediately. 18 19If the problem doesn't exist on master, you can either use master or check also 20the -stable branch of the last released version to see if it was already solved 21there. 22 23Library is a component 24---------------------- 25 26As a library, lws is always just a component in a bigger application. 27 28When users have a problem involving lws, what is happening in the bigger 29application is usually critical to understand what is going on (and where the 30solution lies). Sometimes access to the remote peer like server or client is also 31necessary to provoke the symptom. Sometimes, the problem is in lws, but 32sometimes the problem is not in lws but in these other pieces. 33 34Many users are able to share their sources, but others decide not to, for 35presumed "commercial advantage" or whatever. (In any event, it can be painful 36looking through large chunks of someone else's sources for problems when that 37is not the library author's responsibility.) 38 39This makes answering questions like "what is wrong with my code I am not 40going to show you?" or even "what is wrong with my code?" very difficult. 41 42Even if it's clear there is a problem somewhere, it cannot be understood or 43reproduced by anyone else if it needs user code that isn't provided. 44 45The biggest question is, "is this an lws problem actually"? To solve that 46the best solution is to strip out all or as much user code as possible, 47and see if the problem is still coming. 48 49 50Use the test apps / minimal examples as sanity checks 51----------------------------------------------------- 52 53The test server and client, and any more specifically relevant minimal example 54 are extremely useful for sanity checks and debugging guidance. 55 56 - **test apps work on your platform**, then either 57 - your user code is broken, align it to how the test apps work, or, 58 - something from your code is required to show an lws problem, provide a 59 minimal patch on a test app so it can be reproduced 60 61 - **test apps break on your platform**, but work on, eg, x86_64, either 62 - toolchain or platform-specific (eg, OS) issue, or 63 - lws platform support issue 64 65 - **test apps break everywhere** 66 - sounds like lws problem, info to reproduce and / or a patch is appreciated 67
README.release-policy.md
1# lws release policy 2 3## How should users consume lws? 4 5The one definitively wrong way to consume lws (or anything else) is "import" some 6version of it into your proprietary tree and think you will stick with that 7forever, perhaps piling cryptic fixes or hacks on top until quite quickly, 8nobody dare think about updating it. 9 10The stable releases go on to a branch like v4.0-stable as described below, over 11time these attract dozens or even hundreds of minor or major fix patches 12backported from master. So you should not consume tags like v4.0.0 but build 13into your planning that you will need to follow v4.0-stable in order to stay on 14top of known bugs. 15 16And we only backport fixes to the last stable release, although we will make 17exceptions for important fixes. So after a while, trying to stick with one 18old versions means nobody is providing security fixes on it any more. So you 19should build into your planning that you will follow lws release upgrades. 20 21If you find problems and create fixes, please upstream them, simplifying your 22life so you can just directly consume the upstream tree with no private changes. 23 24## Master branch 25 26Master branch is the default and all new work happens there. It's unstable and 27subject to history rewrites, patches moving about and being squashed etc. In 28terms of it working, it is subject to passing CI tests including a battery of 29runtime tests, so if it is passing CI as it usually is then it's probably in 30usable shape. See "Why no history on master" below for why it's managed like 31that. 32 33 34 35If you have patches (you are a hero) they should be targeted at master. 36 37To follow such a branch, `git pull` is the wrong tool... the starting point 38of what you currently have may no longer exist remotely due to rearranging the 39patches there. Instead use a flow like this: 40 41``` 42 $ git fetch https://libwebsockets.org/repo/libwebsockets +master:m && git reset --hard m 43``` 44 45This fetches current remote master into local branch `m`, and then forces your 46local checkout to exactly match `m`. This replaces your checked-out tree 47including any of your local changes, so stash those first, or use stgit or so 48to pop them before updating your basis against lws master. 49 50## Stable branches 51 52Master is very useful for coordinating development, and integrating WIP, 53but for distros or integration into large user projects some stability is often 54more desirable than the latest development work. 55 56Periodically, when master seems in good shape and various new developments seem 57to be working, it's copied out into a versioned stable branch, like `v3.0-stable`. 58 59 60 61The initial copy is tagged with, eg, `v3.0.0`. 62 63(At that time, master's logical version is set to "...99", eg, `v3.0.99` so 64version comparisons show that version of master is "later" than any other 65v3.0 version, which will never reach 99 point releases itself, but "earlier" 66than, eg, v3.1.) 67 68## Backport policy 69 70Work continues on master, and as part of that usually bugs are reported and / or 71fixes found that may apply not just to current master, but the version of master 72that was copied to form the last -stable branch. 73 74In that case, the patch may be backported to the last stable branch to also fix 75the bug there. In the case of refactors or major internal improvements, these 76typically do not get backported. 77 78This applies only to fixes and public API-neutral internal changes to lws... if 79new features were backported or API changes allowed, then there would be 80multiple apis under the same version name and library soname, which is 81madness. 82 83When new stable releases are made, the soname is bumped reflecting the API is 84different than that of previous versions. 85 86 87 88If there is something you need in a later lws version that is not backported, 89you need to either backport it yourself or use a later lws version. 90Using a more recent version of lws (and contributing fixes and changes so you 91yourself can get them easily as well as contributing for others) is almost 92always the correct way. 93 94## Stable point releases 95 96Periodically fix patches pile up on the -stable branch and are tagged out as 97"point releases". So if the original stable release was "v3.0.0", the point 98release may be "v3.0.1". 99 100 101 102## Critical fixes 103 104Sometimes a bug is found and fixed that had been hiding for a few versions. 105If the bug has some security dimension or is otherwise important, we may 106backport it to a few recent releases, not just the last one. This is pretty 107uncommon though. 108 109 110 111## Why no history on master 112 113Git is a wonderful tool that can be understood to have two main modes of operation, 114merge and rebase that are mutually exclusive. Most devs only use merge / pull, 115but rebase / fetch is much more flexible. Running master via rebases allows me to 116dispense with feature branches during development and enables tracking multiple 117in-progress patches in-tree by updating them in place. If this doesn't make 118sense or seems heretical to you, it's OK I don't need devsplain'ing about it, 119just sit back and enjoy the clean, rapid development results. 120 121Since stable branches don't allow new features, they are run as traditional trees 122with a history, like a one-way pile of patches on top of the original release. If 123CI shows something is messed up with the latest patch, I will edit it in-place if 124it has only been out for a few hours, but there is no re-ordering or other history 125manipulation. 126 127
README.test-apps.md
1Overview of lws test apps 2========================= 3 4Are you building a client? You just need to look at the test client 5[libwebsockets-test-client](../test-apps/test-client.c). 6 7If you are building a standalone server, there are three choices, in order of 8preferability. 9 101) lwsws + protocol plugins 11 12Lws provides a generic web server app that can be configured with JSON 13config files. https://libwebsockets.org itself uses this method. 14 15With lwsws handling the serving part, you only need to write an lws protocol 16plugin. See [plugin-standalone](../plugin-standalone) for an example of how 17to do that outside lws itself, using lws public apis. 18 19 $ cmake .. -DLWS_WITH_LWSWS=1 20 21See [README.lwsws.md](../READMEs/README.lwsws.md) for information on how to configure 22lwsws. 23 24NOTE this method implies libuv is used by lws, to provide crossplatform 25implementations of timers, dynamic lib loading etc for plugins and lwsws. 26 272) Using plugins in code 28 29This method lets you configure web serving in code, instead of using lwsws. 30 31Plugins are still used, but you have a choice whether to dynamically load 32them or statically include them. In this example, they are dynamically 33loaded. 34 35 $ cmake .. -DLWS_WITH_PLUGINS=1 36 37See, eg, the [test-server](../test-apps/test-server.c) 38 393) protocols in the server app 40 41This is the original way lws implemented servers, plugins and libuv are not 42required, but without plugins separating the protocol code directly, the 43combined code is all squidged together and is much less maintainable. 44 45This method is still supported in lws but all ongoing and future work is 46being done in protocol plugins only. 47 48You can simply include the plugin contents and have it buit statically into 49your server, just define this before including the plugin source 50 51``` 52#define LWS_PLUGIN_STATIC 53``` 54 55This gets you most of the advantages without needing dynamic loading + 56libuv. 57 58 59Notes about lws test apps 60========================= 61 62@section tsb Testing server with a browser 63 64If you run [libwebsockets-test-server](../test-apps/test-server.c) and point your browser 65(eg, Chrome) to 66 67 http://127.0.0.1:7681 68 69It will fetch a script in the form of `test.html`, and then run the 70script in there on the browser to open a websocket connection. 71Incrementing numbers should appear in the browser display. 72 73By default the test server logs to both stderr and syslog, you can control 74what is logged using `-d <log level>`, see later. 75 76 77@section tsd Running test server as a Daemon 78 79You can use the -D option on the test server to have it fork into the 80background and return immediately. In this daemonized mode all stderr is 81disabled and logging goes only to syslog, eg, `/var/log/messages` or similar. 82 83The server maintains a lockfile at `/tmp/.lwsts-lock` that contains the pid 84of the master process, and deletes this file when the master process 85terminates. 86 87To stop the daemon, do 88``` 89 $ kill \`cat /tmp/.lwsts-lock\` 90``` 91If it finds a stale lock (the pid mentioned in the file does not exist 92any more) it will delete the lock and create a new one during startup. 93 94If the lock is valid, the daemon will exit with a note on stderr that 95it was already running. 96 97@section clicert Testing Client Certs 98 99Here is a very quick way to create a CA, and a client and server cert from it, 100for testing. 101 102``` 103$ cp -rp ./scripts/client-ca /tmp 104$ cd /tmp/client-ca 105$ ./create-ca.sh 106$ ./create-server-cert.sh server 107$ ./create-client-cert.sh client 108``` 109 110The last step wants an export password, you will need this password again to 111import the p12 format certificate into your browser. 112 113This will get you the following 114 115|name|function| 116|----|--------| 117|ca.pem|Your Certificate Authority cert| 118|ca.key|Private key for the CA cert| 119|client.pem|Client certificate, signed by your CA| 120|client.key|Client private key| 121|client.p12|combined client.pem + client.key in p12 format for browsers| 122|server.pem|Server cert, signed by your CA| 123|server.key|Server private key| 124 125You can confirm yourself the client and server certs are signed by the CA. 126 127``` 128 $ openssl verify -verbose -trusted ca.pem server.pem 129 $ openssl verify -verbose -trusted ca.pem client.pem 130``` 131 132Import the client.p12 file into your browser. In FFOX57 it's 133 134 - preferences 135 - Privacy & Security 136 - Certificates | View Certificates 137 - Certificate Manager | Your Certificates | Import... 138 - Enter the password you gave when creating client1.p12 139 - Click OK. 140 141You can then run the test server like this: 142 143``` 144 $ libwebsockets-test-server -s -A ca.pem -K server.key -C server.pem -v 145``` 146 147When you connect your browser to https://localhost:7681 after accepting the 148selfsigned server cert, your browser will pop up a prompt to send the server 149your client cert (the -v switch enables this). The server will only accept 150a client cert that has been signed by ca.pem. 151 152@section sssl Using SSL on the server side 153 154To test it using SSL/WSS, just run the test server with 155``` 156 $ libwebsockets-test-server --ssl 157``` 158and use the URL 159``` 160 https://127.0.0.1:7681 161``` 162The connection will be entirely encrypted using some generated 163certificates that your browser will not accept, since they are 164not signed by any real Certificate Authority. Just accept the 165certificates in the browser and the connection will proceed 166in first https and then websocket wss, acting exactly the 167same. 168 169[test-server.c](../test-apps/test-server.c) is all that is needed to use libwebsockets for 170serving both the script html over http and websockets. 171 172@section lwstsdynvhost Dynamic Vhosts 173 174You can send libwebsockets-test-server or libwebsockets-test-server-v2.0 a SIGUSR1 175to toggle the creation and destruction of an identical second vhost on port + 1. 176 177This is intended as a test and demonstration for how to bring up and remove 178vhosts dynamically. 179 180@section unixskt Testing Unix Socket Server support 181 182Start the test server with -U and the path to create the unix domain socket 183 184``` 185 $ libwebsockets-test-server -U /tmp/uds 186``` 187 188On exit, lws will delete the socket inode. 189 190To test the client side, eg 191 192``` 193 $ nc -C -U /tmp/uds -i 30 194``` 195 196and type 197 198`GET / HTTP/1.1` 199 200followed by two ENTER. The contents of test.html should be returned. 201 202@section wscl Testing websocket client support 203 204If you run the test server as described above, you can also 205connect to it using the test client as well as a browser. 206 207``` 208 $ libwebsockets-test-client localhost 209``` 210 211will by default connect to the test server on localhost:7681 212and print the dumb increment number from the server at the 213same time as drawing random circles in the mirror protocol; 214if you connect to the test server using a browser at the 215same time you will be able to see the circles being drawn. 216 217The test client supports SSL too, use 218 219``` 220 $ libwebsockets-test-client localhost --ssl -s 221``` 222 223the -s tells it to accept the default self-signed cert from the server, 224otherwise it will strictly fail the connection if there is no CA cert to 225validate the server's certificate. 226 227 228@section choosingts Choosing between test server variations 229 230If you will be doing standalone serving with lws, ideally you should avoid 231making your own server at all, and use lwsws with your own protocol plugins. 232 233The second best option is follow test-server-v2.0.c, which uses a mount to 234autoserve a directory, and lws protocol plugins for ws, without needing any 235user callback code (other than what's needed in the protocol plugin). 236 237For those two options libuv is needed to support the protocol plugins, if 238that's not possible then the other variations with their own protocol code 239should be considered. 240 241@section tassl Testing SSL on the client side 242 243To test SSL/WSS client action, just run the client test with 244``` 245 $ libwebsockets-test-client localhost --ssl 246``` 247By default the client test applet is set to accept self-signed 248certificates used by the test server, this is indicated by the 249`use_ssl` var being set to `2`. Set it to `1` to reject any server 250certificate that it doesn't have a trusted CA cert for. 251 252 253@section taping Using the websocket ping utility 254 255libwebsockets-test-ping connects as a client to a remote 256websocket server and pings it like the 257normal unix ping utility. 258``` 259 $ libwebsockets-test-ping localhost 260 handshake OK for protocol lws-mirror-protocol 261 Websocket PING localhost.localdomain (127.0.0.1) 64 bytes of data. 262 64 bytes from localhost: req=1 time=0.1ms 263 64 bytes from localhost: req=2 time=0.1ms 264 64 bytes from localhost: req=3 time=0.1ms 265 64 bytes from localhost: req=4 time=0.2ms 266 64 bytes from localhost: req=5 time=0.1ms 267 64 bytes from localhost: req=6 time=0.2ms 268 64 bytes from localhost: req=7 time=0.2ms 269 64 bytes from localhost: req=8 time=0.1ms 270 ^C 271 --- localhost.localdomain websocket ping statistics --- 272 8 packets transmitted, 8 received, 0% packet loss, time 7458ms 273 rtt min/avg/max = 0.110/0.185/0.218 ms 274 $ 275``` 276By default it sends 64 byte payload packets using the 04 277PING packet opcode type. You can change the payload size 278using the `-s=` flag, up to a maximum of 125 mandated by the 27904 standard. 280 281Using the lws-mirror protocol that is provided by the test 282server, libwebsockets-test-ping can also use larger payload 283sizes up to 4096 is BINARY packets; lws-mirror will copy 284them back to the client and they appear as a PONG. Use the 285`-m` flag to select this operation. 286 287The default interval between pings is 1s, you can use the -i= 288flag to set this, including fractions like `-i=0.01` for 10ms 289interval. 290 291Before you can even use the PING opcode that is part of the 292standard, you must complete a handshake with a specified 293protocol. By default lws-mirror-protocol is used which is 294supported by the test server. But if you are using it on 295another server, you can specify the protocol to handshake with 296by `--protocol=protocolname` 297 298 299@section ta fraggle Fraggle test app 300 301By default it runs in server mode 302``` 303 $ libwebsockets-test-fraggle 304 libwebsockets test fraggle 305 (C) Copyright 2010-2011 Andy Green <andy@warmcat.com> licensed under MIT 306 Compiled with SSL support, not using it 307 Listening on port 7681 308 server sees client connect 309 accepted v06 connection 310 Spamming 360 random fragments 311 Spamming session over, len = 371913. sum = 0x2D3C0AE 312 Spamming 895 random fragments 313 Spamming session over, len = 875970. sum = 0x6A74DA1 314 ... 315``` 316You need to run a second session in client mode, you have to 317give the `-c` switch and the server address at least: 318``` 319 $ libwebsockets-test-fraggle -c localhost 320 libwebsockets test fraggle 321 (C) Copyright 2010-2011 Andy Green <andy@warmcat.com> licensed under MIT 322 Client mode 323 Connecting to localhost:7681 324 denied deflate-stream extension 325 handshake OK for protocol fraggle-protocol 326 client connects to server 327 EOM received 371913 correctly from 360 fragments 328 EOM received 875970 correctly from 895 fragments 329 EOM received 247140 correctly from 258 fragments 330 EOM received 695451 correctly from 692 fragments 331 ... 332``` 333The fraggle test sends a random number up to 1024 fragmented websocket frames 334each of a random size between 1 and 2001 bytes in a single message, then sends 335a checksum and starts sending a new randomly sized and fragmented message. 336 337The fraggle test client receives the same message fragments and computes the 338same checksum using websocket framing to see when the message has ended. It 339then accepts the server checksum message and compares that to its checksum. 340 341 342@section taproxy proxy support 343 344The http_proxy environment variable is respected by the client 345connection code for both `ws://` and `wss://`. It doesn't support 346authentication. 347 348You use it like this 349``` 350 $ export http_proxy=myproxy.com:3128 351 $ libwebsockets-test-client someserver.com 352``` 353 354@section talog debug logging 355 356By default logging of severity "notice", "warn" or "err" is enabled to stderr. 357 358Again by default other logging is compiled in but disabled from printing. 359 360By default debug logs below "notice" in severity are not compiled in. To get 361them included, add this option in CMAKE 362 363``` 364 $ cmake .. -DCMAKE_BUILD_TYPE=DEBUG 365``` 366 367If you want to see more detailed debug logs, you can control a bitfield to 368select which logs types may print using the `lws_set_log_level()` api, in the 369test apps you can use `-d <number>` to control this. The types of logging 370available are (OR together the numbers to select multiple) 371 372 - 1 ERR 373 - 2 WARN 374 - 4 NOTICE 375 - 8 INFO 376 - 16 DEBUG 377 - 32 PARSER 378 - 64 HEADER 379 - 128 EXTENSION 380 - 256 CLIENT 381 - 512 LATENCY 382 383 384@section ws13 Websocket version supported 385 386The final IETF standard is supported for both client and server, protocol 387version 13. 388 389 390@section latency Latency Tracking 391 392Since libwebsockets runs using `poll()` and a single threaded approach, any 393unexpected latency coming from system calls would be bad news. There's now 394a latency tracking scheme that can be built in with `-DLWS_WITH_LATENCY=1` at 395cmake, logging the time taken for system calls to complete and if 396the whole action did complete that time or was deferred. 397 398You can see the detailed data by enabling logging level 512 (eg, `-d 519` on 399the test server to see that and the usual logs), however even without that 400the "worst" latency is kept and reported to the logs with NOTICE severity 401when the context is destroyed. 402 403Some care is needed interpreting them, if the action completed the first figure 404(in us) is the time taken for the whole action, which may have retried through 405the poll loop many times and will depend on network roundtrip times. High 406figures here don't indicate a problem. The figure in us reported after "lat" 407in the logging is the time taken by this particular attempt. High figures 408here may indicate a problem, or if you system is loaded with another app at 409that time, such as the browser, it may simply indicate the OS gave preferential 410treatment to the other app during that call. 411 412 413@section autobahn Autobahn Test Suite 414 415Lws can be tested against the autobahn websocket fuzzer in both client and 416server modes 417 4181) pip install autobahntestsuite 419 4202) From your build dir: 421 422``` 423 $ cmake .. -DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_MINIMAL_EXAMPLES=1 && make 424``` 425 4263) ../scripts/autobahn-test.sh 427 4284) In a browser go to the directory you ran wstest in (eg, /projects/libwebsockets) 429 430file:///projects/libwebsockets/build/reports/clients/index.html 431 432to see the results 433 434 435@section autobahnnotes Autobahn Test Notes 436 4371) Two of the tests make no sense for Libwebsockets to support and we fail them. 438 439 - Tests 2.10 + 2.11: sends multiple pings on one connection. Lws policy is to 440only allow one active ping in flight on each connection, the rest are dropped. 441The autobahn test itself admits this is not part of the standard, just someone's 442random opinion about how they think a ws server should act. So we will fail 443this by design and it is no problem about RFC6455 compliance. 444 4452) Currently two parts of autobahn are broken and we skip them 446 447https://github.com/crossbario/autobahn-testsuite/issues/71 448 449
README.udp.md
1## Using UDP in lws 2 3UDP is supported in lws... the quickest way is to use the api 4`lws_create_adopt_udp()` which returns a wsi bound to the provided 5vhost, protocol, `lws_retry` struct, dns address and port. 6 7The wsi can be treated normally and `lws_write()` used to write on 8it. 9 10## Implementing UDP retries 11 12Retries are important in udp but there's no standardized ack method 13unlike tcp. Lws allows you to bind an `lws_retry` struct describing 14the policy to the udp wsi, but since one UDP socket may have many 15transactions in flight, the `lws_sul` and `uint16_t` to count the 16retries must live in the user's transaction object like this 17 18``` 19... 20 lws_sorted_usec_list_t sul; 21 uint16_t retry; 22... 23``` 24 25in the `LWS_CALLBACK_RAW_WRITEABLE` callback, before doing the write, 26set up the retry like this 27 28``` 29 if (lws_dll2_is_detached(&transaction->sul_write.list) && 30 lws_retry_sul_schedule_retry_wsi(wsi, &transaction->sul_write, 31 transaction_retry_write_cb, 32 &transaction->retry_count_write)) { 33 /* we have reached the end of our concealed retries */ 34 lwsl_warn("%s: concealed retries done, failing\n", __func__); 35 goto retry_conn; 36 } 37``` 38 39This manages the retry counter in the transaction object, guards against it wrapping, 40selects the timeout using the policy bound to the wsi, and sets the `lws_sul` in the 41transaction object to call the given callback if the sul time expires. 42 43In the callback, it should simply call `lws_callback_on_writable()` for the udp wsi. 44 45## Simulating packetloss 46 47lws now allows you to set the amount of simulated packetloss on udp rx and tx in 48the context creation info struct, using `.udp_loss_sim_tx_pc` and `.udp_loss_sim_rx_pc`, 49the values are percentages between 0 and 100. 0, the default, means no packetloss. 50 51
README.unix-domain-reverse-proxy.md
1## Unix Domain Sockets Reverse Proxy 2 3### Introduction 4 5lws is able to use a mount to place reverse proxies into the URL space. 6 7These are particularly useful when using Unix Domain Sockets, basically 8files in the server filesystem, to communicate between lws and a separate 9server process and integrate the result into a coherent URL namespace on 10the lws side. It's also possible to proxy using tcp sockets. 11 12 13 14This has the advantage that the actual web server that forwards the 15data from the unix socket owner is in a different process than the server 16that serves on the unix socket. If it has problems, they do not affect 17the actual public-facing web server. The unix domain socket server may 18be in a completely different language than the web server. 19 20Compared to CGI, there are no forks to make a connection to the unix 21domain socket server. 22 23### Mount origin format 24 25Unix Domain Sockets are effectively "files" in the server filesystem, and 26are defined by their filepath. The "server" side that is to be proxied opens 27the socket and listens on it, which creates a file in the server filesystem. 28The socket understands either http or https protocol. 29 30Lws can be told to act as a proxy for that at a mountpoint in the lws vhost 31url space. 32 33If your mount is expressed in C code, then the mount type is LWSMPRO_HTTP or 34LWSMPRO_HTTPS depending on the protocol the unix socket understands, and the 35origin address has the form `+/path/to/unix/socket:/path/inside/mount`. 36 37The + at the start indicates it is a local unix socket we are proxying, and 38the ':' acts as a delimiter for the socket path, since unlike other addresses 39the unix socket path can contain '/' itself. 40 41### Connectivity rules and translations 42 43Onward proxy connections from lws to the Unix Domain Socket happen using 44http/1.1. That implies `transfer-encoding: chunking` in the case that the 45length of the output is not known beforehand. 46 47Lws takes care of stripping any chunking (which is illegal in h2) and 48translating between h1 and h2 header formats if the return connection is 49actually in http/2. 50 51The h1 onward proxy connection translates the following headers from the return 52connection, which may be h1 or h2: 53 54Header|Function 55---|--- 56host|Which vhost 57etag|Information on any etag the client has cached for this URI 58if-modified-since|Information on the freshness of any etag the client has cached for this URI 59accept-language|Which languages the return path client prefers 60accept-encoding|Which compression encodings the client can accept 61cache-control|Information from the return path client about cache acceptability 62x-forwarded-for|The IP address of the return path client 63 64This implies that the proxied connection can 65 66 - return 301 etc to say the return path client's etag is still valid 67 68 - choose to compress using an acceptable content-encoding 69 70The following headers are translated from the headers replied via the onward 71connection (always h1) back to the return path (which may be h1 or h2) 72 73Header|Function 74---|--- 75content-length|If present, an assertion of how much payload is expected 76content-type|The mimetype of the payload 77etag|The canonical etag for the content at this URI 78accept-language|This is returned to the return path client because there is no easy way for the return path client to know what it sent originally. It allows clientside selection of i18n. 79content-encoding|Any compression format on the payload (selected from what the client sent in accept-encoding, if anything) 80cache-control|The onward server's response about cacheability of its payload 81 82### h1 -> h2 conversion 83 84Chunked encoding that may have been used on the outgoing proxy client connection 85is removed for h2 return connections (chunked encoding is illegal for h2). 86 87Headers are converted to all lower-case and hpack format for h2 return connections. 88 89Header and payload proxying is staged according to when the return connection 90(which may be an h2 child stream) is writable. 91 92### Behaviour if unix domain socket server unavailable 93 94If the server that listens on the unix domain socket is down or being restarted, 95lws understands that it couldn't connect to it and returns a clean 503 response 96`HTTP_STATUS_SERVICE_UNAVAILABLE` along with a brief human-readable explanation. 97 98The generated status page produced will try to bring in a stylesheet 99`/error.css`. This allows you to produce a styled error pages with logos, 100graphics etc. See [this](https://libwebsockets.org/git/badrepo) for an example of what you can do with it. 101 102
README.vulnerability-reporting.md
1## Vulnerability Reporting 2 3If you become aware of an issue with lws that has a security 4dimension for users, please contact `andy@warmcat.com` by 5direct email. 6 7## Procedure for announcing vulnerability fixes 8 9The problem and fixed versions will be announced on the 10libwebsockets mailing list and a note added to the master 11README.md. 12 13