libwebsockets Documentation

Canonical libwebsockets.org networking library

RAW Doc

File: README.md

Libwebsockets

Libwebsockets is a simple-to-use, MIT-license, pure C library providing client and server
for http/1, http/2, http/3, websockets, webtransport, MQTT and
other protocols in a security-minded, lightweight, configurable, scalable and flexible way.
It's easy to build and cross-build via cmake and is suitable for tasks from embedded RTOS
through mass cloud serving.

It supports a lot of lightweight ancilliary implementations for things like JSON,
CBOR, JOSE, COSE, and supports OpenSSL and MbedTLS v2/3/4 out of the box for everything.
It's very gregarious when it comes to event loop sharing, supporting libuv, libevent, libev,
sdevent, glib and uloop, as well as custom event libs.

100+ independent minimal examples for various scenarios, CC0-licensed
(public domain) for cut-and-paste, allow you to get started quickly.

There are a lot of READMEs on a variety of topics.
Doxygen API docs

We do a huge amount of CI testing per push

V5.0 now available... please upgrade to this as there are many
security fixes only available on v5.0 and main.

** NEW features available on v5.0 **

  • Support for SChannel (windows native TLS, no need for OpenSSL build!), GnuTLS, openHiTLS and BearSSL added
  • QUIC + H3 + Webtransport implementation, using aws-lc, wolfssl, boringssl, libressl, gnutls, and schannel (OpenSSL is h1/h2 -only; mbedtls can do it via a patch)
  • WebRTC mixing (like your own zoom)
  • HLS serving
LWS version Platform Protocols Default TLS
<= 4.5 non-FreeRTOS any OpenSSL
<= 4.5 FreeRTOS any mbedTLS
5.0+ Windows any schannel
5.0+ *nix h1, h2 OpenSSL
5.0+ *nix quic/h3 GnuTLS
5.0+ FreeRTOS any mbedTLS

quic/h3 is enabled for build by default... necessitating GnuTLS instead of OpenSSL to make quic/h3 work.

TLS Library Server TLS Client TLS QUIC Transport (TLS 1.3) WSS / HTTPS MQTT over TLS ALPN (HTTP/2) DTLS (WebRTC) Session Cache JIT Trust GenCrypto
GnuTLS Yes Yes Yes Yes Yes Yes Yes Yes No Yes
OpenSSL Yes Yes No* Yes Yes Yes Yes Yes Yes Yes
LibreSSL Yes Yes Yes Yes Yes Yes Yes Yes No Yes
AWS-LC Yes Yes Yes Yes Yes Yes Yes Yes No Yes
BoringSSL Yes Yes Yes Yes Yes Yes Yes Yes No Yes
wolfSSL Yes Yes Yes Yes Yes Yes Yes Yes No Yes
mbedTLS Yes Yes Needs patch Yes Yes Yes Yes Yes Yes Yes
SChannel Yes Yes Yes Yes Yes Yes Yes Yes No Yes
BearSSL Yes Yes No Yes Yes Yes No Yes Yes Yes
openHiTLS Yes Yes No Yes Yes Yes Yes (not SRTP) Yes Yes Yes

* Note: 1) Upstream OpenSSL does not provide the necessary QUIC TLS API (SSL_set_quic_method) to act as a cryptographic engine for LWS's QUIC transport. If you need QUIC/HTTP3 support, we recommend using BoringSSL or GnuTLS.
* *Note: 2) openHiTLS does not provide the necessary QUIC TLS API *

  • DHT support built-in: -DLWS_WITH_DHT=1

File: contrib/abi/README.md

ABI Compatility Tracking

This directory contains files that can be used to generate an ABI compatibility
timeline for libwebsockets. This gives users an idea of where the library has
changed and can be used by the developers to see when incompatible changes have
been introduced and either increase the library SO version or fix the changes.

The tools used are the abi-* family available at https://github.com/lvc/ and
some example output is here: http://abi-laboratory.pro/tracker/timeline/libuv/

The tools download existing source tarballs and git repository to generate this
data, so past versions are compared and in-development code can be compared as
well.

Although the application is not being included here, FYI the license is dual
LGPL2 / GPL2 at your choice.

Installation

The abi monitoring stuff is now packaged in, eg, fedora, which is a lot
easier than using the helper script.

text
# dnf install abi-tracker vtable-dumper

Otherwise, the author provides an "easy way" to install the various tools he provides:

    git clone https://github.com/lvc/installer
	cd installer
	make prefix=/usr/local target=abi-tracker

It will also list any dependencies that you need to install through normal
means.  (Although in the case of needing "elfutils-libelf-devel", it may
crash during install of vtable-dumper without giving a nice list)


Generating the output
---------------------

Use the `lws-abi-update.sh` script to download the source files, build them and
generate the output html. The output can be deployed to a directory on a web
server for example. Modify the commented line in lws-abi-update.sh to do this.

As it is configured, lws-abi-update.sh will only download new source - ones
that it hasn't built before - so is suitable for use with a cron job.


Viewing the output
------------------

The best place to start looking at the data is the `timeline/libwebsockets`
directory. If your path is on a web server, navigate there, otherwise you could
try:

    lynx timeline/libwebsockets/

---

## File: contrib/mcufont/README.md

# origin

This is part of the MIT-licensed mcufont project which can be found here

https://github.com/mcufont/mcufont

That project is great but it's not actively maintained[1][2] and most work
on it was done back in 2013.

The decoder part was rewritten for lws as `./lib/misc/dlo/dlo-font-mcufont.c`.
This directory contains the ttf-> mcufont encoder, which is a C++
commandline tool for development.

[1] https://github.com/mcufont/mcufont/issues/11
[2] https://github.com/mcufont/mcufont/issues/26

## Building

Install `freetype-dev` or similar package on your build host.

Enable lws cmake option `-DLWS_WITH_MCUFONT_ENCODER=1` to get it built, but
since it is for development it is not packaged with the rest of lws by make
install.

It produces an executable for your build host in `./bin/lws-mcufont-encoder`
or similar as part of the normal lws cmake build process then.

## Modifications vs upstream

1) The rledecoder is rewritten to decode statefully, emitting a rasterized
line at a time and only taking in more input when required to issue the
next pixel that is needed for the current line.  This implementation is
integrated into lws dlo stuff down ./lib/misc/dlo.

2) The mcufont decoder type headers are distributed as part of the lws
public headers, but are not imported with libwebsockets.h inclusion, you
should `#include <libwebsockets/mf_rlefont.h>` if you need them (you
normally won't need them, since the dlo stuff will bring it in for its
own usage).

3) Only the encoder part is brought into lws ./conftrib/mcufont; the
encoder can be built by selecting lws cmake option `-DLWS_WITH_MCUFONT_ENCODER=1`

4) The encoder part is modified to issue a single table blob file,
instead of the C typed structs and arrays requiring fonts to be
selected and managed only at build-time; it's at least possible to
download or otherwise manage fonts then after build-time.

The blob starts with a 64-byte header with a magic, versioning, flags and
a map of where the other regions can be found in the file... the overall
layout is like:

[64-byte header]
[font name string]
[font short name string]
[Dictionary Data area]
[Dictionary Offset area]
[Unicode range tables]
[offset table for range]
[data table for range]

text
File offsets are measured from the first byte of the blob / file.

Dictionary and glyph offset tables contain 16-bit offsets which apply to the first
byte of the Dictionary Data area and the Glyph data table respectively.

The header part is laid out like:

0000 4D 43 55 46 4-byte magic "MCUF"
0004 XX XX XX XX 4-byte MSB Flags + Version
0008 XX XX XX XX 4-byte MSB file offset: 00-terminated string: full_name
000C XX XX XX XX 4-byte MSB file offset: 00-terminated string: short_name
0010 XX XX XX XX 4-byte MSB file offset: Dictionary Data area (8b)
0014 XX XX XX XX 4-byte MSB count: extent of Dictionary Data area
0018 XX XX XX XX 4-byte MSB file offset: Dictionary Offsets (16b) into Data area
001C XX XX XX XX 4-byte MSB count: rle dictionary
0020 XX XX XX XX 4-byte MSB count: ref dictionary + rle dictionary
0024 XX XX XX XX 4-byte MSB file offset: Char Range Tables
0028 XX XX XX XX 4-byte MSB count: Char Range Tables
002C XX XX XX XX 4-byte MSB unicode fallback char
0030 XX XX 2-byte MSB width
0032 XX XX 2-byte MSB height
0034 XX XX 2-byte MSB min_x_advance
0036 XX XX 2-byte MSB max_x_advance
0038 XX XX 2-byte MSB signed baseline_x
003A XX XX 2-byte MSB baseline_y
003C XX XX 2-byte MSB line_height
003E 00 00 2-byte Reserved

text
Char range tables comprise for each range:

+0000 XX XX XX XX 4-byte MSB unicode index start
+0004 XX XX XX XX 4-byte MSB count of indexes covered
+0008 XX XX XX XX 4-byte MSB file offset: start of 16-bit glyph offsets table
+000C XX XX XX XX 4-byte MSB file offset: start of data above offsets point into

text
---

## File: lib/core-net/README.md

# Implementation background

## Client connection Queueing

By default lws treats each client connection as completely separate, and each is
made from scratch with its own network connection independently.

If the user code sets the `LCCSCF_PIPELINE` bit on `info.ssl_connection` when
creating the client connection though, lws attempts to optimize multiple client
connections to the same place by sharing any existing connection and its tls
tunnel where possible.

There are two basic approaches, for h1 additional connections of the same type
and endpoint basically queue on a leader and happen sequentially.

For muxed protocols like h2, they may also queue if the initial connection is
not up yet, but subsequently the will all join the existing connection
simultaneously "broadside".

## h1 queueing

The initial wsi to start the network connection becomes the "leader" that
subsequent connection attempts will queue against.  Each vhost has a dll2_owner
`wsi->dll_cli_active_conns_owner` that "leaders" who are actually making network
connections themselves can register on as "active client connections".

Other client wsi being created who find there is already a leader on the active
client connection list for the vhost, can join their dll2 wsi->dll2_cli_txn_queue
to the leader's wsi->dll2_cli_txn_queue_owner to "queue" on the leader.

The user code does not know which wsi was first or is queued, it just waits for
stuff to happen the same either way.

When the "leader" wsi connects, it performs its client transaction as normal,
and at the end arrives at `lws_http_transaction_completed_client()`.  Here, it
calls through to the lws_mux `_lws_generic_transaction_completed_active_conn()`
helper.  This helper sees if anything else is queued, and if so, migrates assets
like the SSL *, the socket fd, and any remaining queue from the original leader
to the head of the list, which replaces the old leader as the "active client
connection" any subsequent connects would queue on.

It has to be done this way so that user code which may know each client wsi by
its wsi, or have marked it with an opaque_user_data pointer, is getting its
specific request handled by the wsi it expects it to be handled by.

A side effect of this, and in order to be able to handle POSTs cleanly, lws
does not attempt to send the headers for the next queued child before the
previous child has finished.

The process of moving the SSL context and fd etc between the queued wsi continues
until the queue is all handled.

## muxed protocol queueing and stream binding

h2 connections act the same as h1 before the initial connection has been made,
but once it is made all the queued connections join the network connection as
child mux streams immediately, "broadside", binding the stream to the existing
network connection.

---

## File: lib/drivers/button/README.md

# LWS GPIO Button class drivers

Lws provides an GPIO button controller class, this centralizes handling a set of
up to 31 buttons for resource efficiency.  Each controller has two OS timers,
one for interrupt to bottom-half event triggering and another that runs at 5ms
intervals only when one or more button is down.

Each button has its own active level control and sophisticated state tracking;
each button can apply its own classification regime, to allow for different
physical button characteristics, if not overridden a default one is provided.

Both the controller and individual buttons specify names that are used in the
JSON events produced when the buttons perform actions.

## Button electronic to logical event processing

Buttons are monitored using GPIO interrupts since this is very cheap in the
usual case no interaction is ongoing.  There is assumed to be one interrupt
per GPIO, but they are pointed at the same ISR, with an opaque pointer to an
internal struct passed per-interrupt to differentiate them and bind them to a
particular button.

The interrupt is set for notification of the active-going edge, usually if
the button is pulled-up, that's the downgoing edge only.  This avoids any
ambiguity about the interrupt meaning, although oscillation is common around
the transition region when the signal is becoming inactive too.

An OS timer is used to schedule a bottom-half handler outside of interrupt
context.

To combat commonly-seen partial charging of the actual and parasitic network
around the button causing drift and oscillation, the bottom-half briefly drives
the button signal to the active level, forcing a more deterministic charge level
if it reached the point the interrupt was triggered.  This removes much of the
unpredictable behaviour in the us range.  It would be better done in the ISR
but many OS apis cannot perform GPIO operations in interrupt context.

The bottom-half makes sure a monitoring timer is enabled, by refcount.  This
is the engine of the rest of the classification while any button is down.  The
monitoring timer happens per OS tick or 5ms, whichever is longer.

## Declaring button controllers

An array of button map elements if provided first mapping at least GPIOs to
button names, and also optionally the classification regime for that button.

Then the button controller definition which points back to the button map.

static const lws_button_map_t bcm[] = {
{
.gpio = GPIO_NUM_0,
.smd_interaction_name = "user"
},
};

static const lws_button_controller_t bc = {
.smd_bc_name = "bc",
.gpio_ops = &lws_gpio_plat,
.button_map = &bcm[0],
.active_state_bitmap = 0,
.count_buttons = LWS_ARRAY_SIZE(bcm),
};

text
struct lws_button_state *bcs;

bcs = lws_button_controller_create(context, &bc);
if (!bcs) {
	lwsl_err("%s: could not create buttons\n", __func__);
	goto spin;
}
text
That is all that is needed for init, button events will be issued on lws_smd
when buttons are pressed.

### Regime settings

The classification regime is designed to reflect both the user interaction
style and the characteristics of a particular type of button.

Member|Default|Meaning
---|---|---
ms_min_down|20ms|Down events shorter than this are ignored
ms_min_down_longpress|300ms|Down events longer than this are reported as a long-click
ms_up_settle|20ms|After the first indication a button is no longer down, the button is ignored for this interval
ms_doubleclick_grace|120ms|The time allowed after a click to see if a second, double-click, is forthcoming
ms_repeat_down|0 / disabled|If held down, interval at which to issue `stilldown` events
flags|LWSBTNRGMFLAG_CLASSIFY_DOUBLECLICK|Control which classifications can apply

### lws_smd System Message Distribution Events

The button controller emits system messages of class `LWSSMDCL_INTERACTION`,
using a JSON formatted payload

{
"type": "button",
"src": "controller-name/button-name",
"event": "event-name"
}

text
For example, `{"type":"button","src":"bc/user","event":"doubleclick"}`

JSON is used because it is maintainable, extensible, self-documenting and does
not require a central, fragile-against-versioning specification of mappings.
Using button names allows the same code to adapt to different hardware or
button mappings.  Button events may be synthesized for test or other purposes
cleanly and clearly.

All the events are somewhat filtered, too short glitches from EMI or whatever
are not reported.  "up" and "down" events are reported for the buttons in case
the intention is the duration of the press is meaningful to the user code, but
more typically the user code wants to consume a higher-level classification of
the interaction, eg, that it can be understood as a single "double-click" event. 

Event name|Meaning
---|---
down|The button passes a filter for being down, useful for duration-based response
stilldown|The regime can be configured to issue "repeat" notifications at intervals
up|The button has come up, useful for duration-based response
click|The button activity resulted in a classification as a single-click
longclick|The button activity resulted in a classification as a long-click
doubleclick|The button activity resulted in a classification as a double-click

Since double-click detection requires delaying click reporting until it becomes
clear a second click isn't coming, it is enabled as a possible classification in
the regime structure and the regime structure chosen per-button.

Typically user code is interested in, eg, a high level classification of what
the button is doing, eg, a "click" event on a specific button.  Rather than
perform a JSON parse, these events can be processed as strings cheaply using
`lws_json_simple_strcmp()`, it's dumb enough to be cheap but smart enough to
understand enough JSON semantics to be accurate, while retaining the ability to
change and extend the JSON, eg
text
if (!lws_json_simple_strcmp(buf, len, "\"src\":", "bc/user")) {
	if (!lws_json_simple_strcmp(buf, len, "\"event\":", "click")) {
		...
	}
	...
}
text
### Relationship between up / down and classification

Classification|Sequencing
---|---
click|down-up-click (it's classified when it went up and cannot be a longclick)
longclick|down-longclick-up (it's classified while still down)
doubleclick|down-up-down-doubleclick-up (classified as soon as second click down long enough)

If the regime is configured for it, any "down" may be followed by one or more
"stilldown" at intervals if the button is down long enough

---

## File: lib/drivers/display/README.md

# lws_display

lws provides a generic "display" object that is independent of the connection
to the display, i2c and spi implementations are provided.

Its purpose is to provide basic blit, backlight binding to lws_pwm, backlight /
power management and display info like pixels wide and high in a generic way.

The generic display object `lws_display_t` can be included at the top of a
specific display implementation object, eg, binding it to additional members
to define the actual IO operations to be used, eg, i2c or spi.

When the display is instantiated, it allocates an additional structure on heap
that contains dynamic information about display state, `lws_display_state_t`.

## Power state machine

lws_display objects have convenient power state management using a single lws
sul event loop timer that is managed automatically.

State|Meaning
---|---
OFF|The display is in sleep and not showing anything
BECOMING_ACTIVE|The display was asked to come out of sleep and is waiting for .latency_wake_ms befor proceeding to ACTIVE.  The backlight if any is off.  After the delay, the backlight is sequenced up to `.bl_active` using `.bl_transition` sequencer
ACTIVE|The backlight is ON and the dim timer is running
AUTODIMMED|The dim timer was not told the display was active for `.autodim_ms`, we are at `.bl_dim` brightness.  After `.off_ms` we will transition to OFF 

The lws_pwm sequencers are used to provide customizable, smooth transitions for
the backlight, which may be nonlinear.

## Active notification

Calling `lws_display_state_active(&lds)` on eg, user interaction causes the
display state to transition to ACTIVE smoothly, taking care of waking the display
and waiting out a display-specific wake period, and sequencing the backlight
transition to active level as specified in the display structure.

---

## File: lib/drivers/led/README.md

# lws_led gpio and pwm class drivers

Lws provides an abstract led controller class that can bind an array of LEDs
to gpio and pwm controllers, and automatically handled pwm sequencers.

Lumience intensity is corrected for IEC curves to match perceptual intensity,
and the correction can be overridden per led for curve adaptation matching.

Intensity is normalized to a 16-bit scale, when controlled by a GPIO b15 is
significant and the rest ignored.  When controlled by PWM, as many bits from
b15 down are significant as the PWM arrangements can represent.

The PWM sequencers use arbitrary function generation callbacks on a normalized
16-bit phase space, they can choose how much to interpolate and how much to put
in a table, a 64-sample, 16-bit sine function is provided along with 16-bit
linear sawtooth.

Changing the sequencer is subject to a third transition function sequencer, this
can for example mix the transition linearly over, eg, 500ms so the leds look
very smooth.

## Defining an led controller

An array of inidividual LED information is provided first, and referenced by
the LED controller definintion.  Leds are named so code does not introduce
dependencies on specific implementations.

static const lws_led_gpio_map_t lgm[] = {
{
.name = "alert",
.gpio = GPIO_NUM_25,
.pwm_ops = &pwm_ops,
.active_level = 1,
},
};

static const lws_led_gpio_controller_t lgc = {
.led_ops = lws_led_gpio_ops,
.gpio_ops = &lws_gpio_plat,
.led_map = &lgm[0],
.count_leds = LWS_ARRAY_SIZE(lgm)
};

text
struct lws_led_state *lls;

lls = lgc.led_ops.create(&lgc.led_ops);
if (!lls) {
	lwsl_err("%s: could not create led\n", __func__);
	goto spin;
}
text
For GPIO control, the active level of the GPIO to light the LED may be set.

Each LED may bind to a pwm controller, in which case setting the intensity
programs the pwm controller corresponding to the GPIO.

## Setting the intensity directly
text
lgc.led_ops.intensity(&lgc.led_ops, "alert", 0);
text
## Defining Sequencer

Some common sequencers are provided out of the box, you can also define your
own arbitrary ones.

The main point is sequencers have a function that returns an intensity for each
of 65536 phase steps in its cycle.  For example, this is the linear function
that is included

lws_led_intensity_t
lws_led_func_linear(lws_led_seq_phase_t n)
{
return (lws_led_intensity_t)n;
}

text
It simply returns an intensity between 0 - 65535 matching the phase angle of
0 - 65535 that it was given, so it's a sawtooth ramp.

An interpolated sine function is also provided that returns an intensity
between 0 - 65535 reflecting one cycle of sine wave for the phase angle of 0 -
65535.

These functions are packaged into sequencer structures like this

const lws_led_sequence_def_t lws_pwmseq_sine_endless_fast = {
.func = lws_led_func_sine,
.ledphase_offset = 0, /* already at 0 amp at 0 phase */
.ledphase_total = LWS_SEQ_LEDPHASE_TOTAL_ENDLESS,
.ms = 750
};

text
This "endless" sequencer cycles through the sine function at 750ms per cycle.
Non-endless sequencers have a specific start and end in the phase space, eg

const lws_led_sequence_def_t lws_pwmseq_sine_up = {
.func = lws_led_func_sine,
.ledphase_offset = 0, /* already at 0 amp at 0 phase /
.ledphase_total = LWS_LED_FUNC_PHASE / 2, /
180 degree ./^ */
.ms = 300
};

text
... this one traverses 180 degrees of the sine wave starting from 0 and ending
at full intensity, over 300ms.

A commonly-used, provided one is like this, as used in the next section

const lws_led_sequence_def_t lws_pwmseq_linear_wipe = {
.func = lws_led_func_linear,
.ledphase_offset = 0,
.ledphase_total = LWS_LED_FUNC_PHASE - 1,
.ms = 300
};

text
## Setting the intensity using sequencer transitions

The main api for high level sequenced control is

int
lws_led_transition(struct lws_led_state *lcs, const char *name,
const lws_led_sequence_def_t *next,
const lws_led_sequence_def_t *trans);

text
This fades from the current sequence to a new sequence, using `trans` sequencer
intensity as the mix factor.  `trans` is typically `lws_pwmseq_linear_wipe`,
fading between the current and new linearly over 300ms.  At the end of the
`trans` sequence, the new sequence simply replaces the current one and the
transition is completed.

Sequencers use a single 30Hz OS timer while any sequence is active.

exported sequencer symbol|description
---|---
lws_pwmseq_sine_endless_slow|continuous 100% sine, 1.5s cycle 
lws_pwmseq_sine_endless_fast|continuous 100% sine, 0.75s cycle 
lws_pwmseq_linear_wipe|single 0 - 100% ramp over 0.3s
lws_pwmseq_sine_up|single 0 - 100% using sine curve over 0.3s
lws_pwmseq_sine_down|single 100% - 0 using sine curve over 0.3s
lws_pwmseq_static_on|100% static
lws_pwmseq_static_half|50% static
lws_pwmseq_static_off|0% static

---

## File: lib/drivers/README.md

# lws meta-drivers

Although drivers in lws (enabled in cmake by `LWS_WITH_DRIVERS`) provide
actual drivers for some devices like I2C OLED controllers, their main job is
to conceal from user code the underlying OS APIs being used to interface
to the SoC hardware assets.

CMake already allows lws to be platform-agnostic for build, the plat adaptations
allow lws to be platform-agnostic within itself for runtime.  The lws
drivers intend to extend that agnosticism to user code.

Using this technique on supported OSes frees the user code from dependencies
on the underlying OS choice... for example, although ESP32 is very good, it
comes with a highly specific set of apis in esp-idf that mean your code is
locked in to esp-idf if you follow them.  Esp-idf uses freertos apis for things
like OS timers, again if you follow those you are locked into freertos, the
end result is your work is non-portable to other platforms and completely
dependent on esp.

LWS drivers provide a thin wrapper to eliminate the OS dependencies while
still taking advantage of the work, drivers and maintenance of the underlying
OS layer without duplicating them, but bringing the flexibility to retarget
your work to other scenarios... for example, there is a generic gpio object
subclassed for specific implementations, an i2c object which may be subclassed
to use OS drivers or bitbang using the generic gpio object, buttons on top of
generic gpio, led class that can use generic gpio or pwm interchangeably,
platform-specific gpio, i2c, pwm implementations that can be used at the generic
level are defined to use underlying OS native apis and drivers.

## Building on the next layer up

At these generic objects like buttons or led controllers, there is a stable
codebase used by multiple implementations and the intention is to provide
best-of-breed features there generically, like

 - sophisticated button press debounce and classification

 - high quality transitions and log-response compensation and mixing for led pwm

 - display dimming timers, blanking timers, generic interaction detection to unblank

which are automatically available on top of any implementation that is ported to
lws drivers.

---

## File: lib/event-libs/README.md

## Information for new event lib implementers

### Introduction

By default lws has built-in support for POSIX poll() as the event loop on unix,
and native WSA on windows.

To get access to epoll() or other platform specific better poll waits, or to
integrate with existing applications already using a specific event loop, it can
be desirable for lws to use another external event library, like libuv, glib,
libevent, libev, or sdevent.

Lws supports wholesale replacement of its wait selectable at runtime, either by
building support for one or more event lib into the libwebsockets library, or by
building runtime-loadable plugins.  CMake symbol `LWS_WITH_EVLIB_PLUGINS`
decides if the support is built as plugins or included into the lws lib.

Due to their history libevent and libev have conflicting defines in the same
namespace and cannot be built together if included into the lib, however when
built as plugins they are built separately without problems.
See ./READMEs/README.event-libs.md for more details.

Despite it may be more work, lws event lib implementations must support
"foreign" loops cleanly, that is integration with an already-existing loop and
the ability to destroy the lws_context without stopping or leaving the foreign
loop in any different state than when lws found it.  For most loops this is
fairly simple, but with libuv async close, it required refcounting lws libuv
handles and deferring the actual destroy until they were all really closed.

### Code placement

The code specific to the event library should live in `./lib/event-libs/**lib name**`

### Allowing control over enabling event libs

All event libs should add a cmake define `LWS_WITH_**lib name**` and make its
build dependent on it in CMakeLists.txt.  Export the cmakedefine in
`./cmake/lws_config.h.in` as well so user builds can understand if the event
lib is available in the lws build it is trying to bind to.

If the event lib is disabled in cmake, nothing in its directory is built or
referenced.

### Event loop ops struct

The event lib support is defined by `struct lws_event_loop_ops` in
`lib/event-libs/private-lib-event-libs.h`,
each event lib support instantiates one of these and fills in the appropriate
ops callbacks to perform its job.  By convention that lives in
`./lib/event-libs/**lib name**/**lib_name**.c`.

The ops struct must be public, not static, and must be named using `**lib_name**`,
eg
text
### Private event lib declarations

Truly private declarations for the event lib support that are only referenced by
that code can go in the event-libs directory as you like.  The convention is
they should be in the event lib support directory in a file
`private-lib-event-libs-**lib name**.h`.

### Integration with lws

There are a couple of places to add refererences in ./lib/core/context.c, in a
table of context creation time server option flags mapped to the **lib_name**,
used for plugin mode, like this...

#if defined(LWS_WITH_EVLIB_PLUGINS) && defined(LWS_WITH_EVENT_LIBS)
static const struct lws_evlib_map {
uint64_t flag;
const char *name;
} map[] = {
{ LWS_SERVER_OPTION_LIBUV, "evlib_uv" },
{ LWS_SERVER_OPTION_LIBEVENT, "evlib_event" },
{ LWS_SERVER_OPTION_GLIB, "evlib_glib" },
{ LWS_SERVER_OPTION_LIBEV, "evlib_ev" },
};

text
and for backwards compatibility add a stanza to the built-in checks like this

#if defined(LWS_WITH_LIBUV)
if (lws_check_opt(info->options, LWS_SERVER_OPTION_LIBUV)) {
extern const lws_plugin_evlib_t evlib_uv;
plev = &evlib_uv;
}
#endif

text
Both entries are the way the main libs hook up to the selected event lib ops
struct at runtime.

### Integrating event lib assets to lws

Declare "container structs" in your private....h for anything you need at
wsi, pt, vhost and context levels, eg, the libuv event lib support need to
add its own assets in the perthread struct, it declares in its private....h

struct lws_pt_eventlibs_libuv {
uv_loop_t *io_loop;
struct lws_context_per_thread *pt;
uv_signal_t signals[8];
uv_timer_t sultimer;
uv_idle_t idle;
struct lws_signal_watcher_libuv w_sigint;
};

text
this is completely private and opaque, but in the ops struct there are provided
four entries to export the sizes of these event-lib specific objects

...
/* evlib_size_ctx / sizeof(struct lws_context_eventlibs_libuv),
/
evlib_size_pt / sizeof(struct lws_pt_eventlibs_libuv),
/
evlib_size_vh / 0,
/
evlib_size_wsi */ sizeof(struct lws_io_watcher_libuv),
};

text
If the particular event lib doesn't need to have a private footprint in an
object, it can just set the size it needs there to 0.

When the context, pts, vhosts or wsis are created in lws, they over-allocate
to also allow for the event lib object, and set a pointer in the lws object
being created to point at the over-allocation.  For example for the wsi

#if defined(LWS_WITH_EVENT_LIBS)
void evlib_wsi; / overallocated */
#endif

text
and similarly there are `evlib_pt` and so on for those objects, usable by the
event lib and opaque to everyone else.  Once the event lib is selected at
runtime, all of these objects are guaranteed to have the right size object at
`wsi->evlib_wsi` initialized to zeroes.

### Enabling event lib adoption

You need to add a `LWS_SERVER_OPTION...` flag as necessary in `./lib/libwebsockets.h`
`enum lws_context_options`, and follow the existing code in `lws_create_context()`
to convert the flag into binding your ops struct to the context.

### Implementation of the event lib bindings

Study eg libuv implementation, using the available ops in the struct lws_event_loop_ops
as a guide.

### Destruction

Ending the event loop is generally a bit tricky, because if the event loop is
internal to the lws context, you cannot destroy it while the event loop is
running.

Don't add special exports... we tried that, it's a huge mess.  The same user
code should be able work with any of the event loops including poll.

The solution we found was hide the different processing necessary for the
different cases in `lws_destroy_context()`.  To help with that there are event
lib ops available that will be called at two different places in the context
destroy processing.

---

## File: lib/jose/README.md

# JOSE support

JOSE is a set of web standards aimed at encapsulating crypto
operations flexibly inside JSON objects.

Lws provides lightweight apis to performs operations on JWK, JWS and JWE
independent of the tls backend in use.  The JSON parsing is handled by the lws
lejp stream parser.

|Part|RFC|Function|
|---|---|---|
|JWS|[RFC7515](https://tools.ietf.org/html/rfc7515)|JSON Web Signatures|
|JWE|[RFC7516](https://tools.ietf.org/html/rfc7516)|JSON Web Encryption|
|JWK|[RFC7517](https://tools.ietf.org/html/rfc7517)|JSON Web Keys|
|JWA|[RFC7518](https://tools.ietf.org/html/rfc7518)|JSON Web Algorithms|

JWA is a set of recommendations for which combinations of algorithms
are deemed desirable and secure, which implies what must be done for
useful implementations of JWS, JWE and JWK.

## Supported algorithms

### Supported keys

 - All RFC7517 / JWK forms: octet, RSA and EC

 - singleton and keys[] arrays of keys supported

### Symmetric ciphers

 - All common AES varaiants: CBC, CFB128, CFB8, CTR, EVB, OFB, KW and XTS

### Asymmetric ciphers

 - RSA

 - EC (P-256, P-384 and P-521 JWA curves)

### Payload auth and crypt

 - AES_128_CBC_HMAC_SHA_256
 - AES_192_CBC_HMAC_SHA_384
 - AES_256_CBC_HMAC_SHA_512
 - AES_128_GCM

For the required and recommended asymmetric algorithms, support currently
looks like this

|JWK kty|JWA|lws|
|---|---|---|
|EC|Recommended+|yes|
|RSA|Required|yes|
|oct|Required|yes|

|JWE alg|JWA|lws|
|---|---|---|
|RSA1_5|Recommended-|yes|
|RSA-OAEP|Recommended+|no|
|ECDH-ES|Recommended+|no|

|JWS alg|JWA|lws|
|---|---|---|
|HS256|Required|yes|
|RS256|Recommended+|yes|
|ES256|Recommended|yes|

## Minimal Example tools

[JWK](https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/crypto/minimal-crypto-jwk)

[JWS](https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/crypto/minimal-crypto-jws)

[JWE](https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/crypto/minimal-crypto-jwe)

## API tests

See `./minimal-examples/api-tests/api-test-jose/` for example test code.
The tests are built and confirmed during CI.