Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
d091950
lws_switches_print_help
lws-team Mar 11, 2026
09733ad
mnemonic
lws-team Jan 28, 2026
b3462ed
genhash: lws_genhash_render
lws-team Jan 30, 2026
65dbd9f
dht: peer server
lws-team Jan 28, 2026
600be98
lws_gendtls
lws-team Feb 11, 2026
84ac686
mbedtls-fixes
lws-team Feb 22, 2026
fea5194
rtp
lws-team Feb 9, 2026
1e71fdf
mixer
lws-team Feb 10, 2026
5909858
LWS_WITH_LATENCY
lws-team Feb 23, 2026
cd2d53d
async-serving
lws-team Feb 28, 2026
57ae24c
layout-speaker
lws-team Feb 25, 2026
1579404
1080p
lws-team Feb 25, 2026
2a381ed
dht-conf
lws-team Feb 26, 2026
4729f89
plugins: document and enable inclusion
lws-team Feb 27, 2026
2ac8e53
authoritative_dns-signing
lws-team Feb 27, 2026
d18f5d8
authoritative-dns-server
lws-team Feb 27, 2026
1851733
async-dns-tcp-fallback
lws-team Feb 27, 2026
0ac63a5
async_dns: DNSSEC
lws-team Feb 28, 2026
2e45bb3
plugins: modernize to C99
lws-team Mar 1, 2026
2199103
fixes
lws-team Mar 2, 2026
42dbff9
lws_adapt: improve api
lws-team Mar 12, 2026
362bf38
gnutls: gencrypto-extra
lws-team Mar 1, 2026
c82bd2b
jws-alignment-with-gnutls
lws-team Mar 1, 2026
89ebcd4
cove-fixes-8
lws-team Mar 3, 2026
8aad73c
adopt: use correct sockaddr length
lws-team Mar 6, 2026
e2db10c
dht: deduplicate
lws-team Mar 3, 2026
9458a1e
dht-dnssec-plugin
lws-team Mar 7, 2026
5432e18
minimal-crypto-dnssec
lws-team Mar 11, 2026
18a19a5
help: provide --help for every app that takes commandline args
lws-team Mar 12, 2026
c73edb3
acme: dns-01 and refactor
lws-team Mar 11, 2026
158f27e
protocol_lws_dht_dnssec_monitor
lws-team Mar 11, 2026
82e9501
adns: multi server broadside
lws-team Mar 12, 2026
789f734
dht: dnssec: implement change notification
lws-team Mar 13, 2026
7bf89e0
dnssec: add dht backend
lws-team Mar 13, 2026
2a0eac5
crypto: improve help
lws-team Mar 14, 2026
064d6c8
gencrypto: jose: cose: support ED25519 and ED448
lws-team Mar 14, 2026
ad2cc07
sai-fixes
lws-team Mar 14, 2026
6f36ec2
Fix cookie storage on Windows
saghul Mar 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
21 changes: 13 additions & 8 deletions .sai.json
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@
"lws_system": {
"cmake": "-DLWS_SUPPRESS_DEPRECATED_API_WARNINGS=1 -DLWS_WITH_ACME=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DCMAKE_BUILD_TYPE=RELEASE -DLWS_WITH_GENCRYPTO=1 -DLWS_WITH_JOSE=1 -DLWS_WITH_SYS_ASYNC_DNS=1 -DLWS_WITH_SYS_NTPCLIENT=1"
},
"async_dnssec": {
"cmake": "-DLWS_SUPPRESS_DEPRECATED_API_WARNINGS=1 -DCMAKE_BUILD_TYPE=DEBUG -DLWS_WITH_GENCRYPTO=1 -DLWS_WITH_JOSE=1 -DLWS_WITH_SYS_ASYNC_DNS=1 -DLWS_WITH_SYS_ASYNC_DNS_DNSSEC=1 -DLWS_WITH_AUTHORITATIVE_DNS=1"
},

"secure-streams": {
"cmake": "-DLWS_WITH_SECURE_STREAMS=1 -DLWS_WITH_MINIMAL_EXAMPLES=1",
"platforms": "w11/x86_64-amd/msvc,netbsd/aarch64BE-bcm2837-a53/gcc"
Expand Down Expand Up @@ -254,18 +258,19 @@
# only applies to the coverity builder, and on pushes to "coverity" branch

"coverity": {
"cmake": "-DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_CGI=1 -DLWS_IPV6=1 -DLWS_WITH_HTTP_PROXY=1 -DLWS_WITH_RANGES=1 -DLWS_WITH_THREADPOOL=1 -DLWS_WITH_CBOR=1 -DLWS_WITH_JOSE=1 -DLWS_WITH_COSE=1 -DLWS_WITH_SYS_DHCP_CLIENT=1 -DLWS_WITH_FTS=1 -DLWS_WITH_STRUCT_SQLITE3=1 -DLWS_ROLE_DBUS=1 -DLWS_WITH_SYS_ASYNC_DNS=1 -DLWS_WITH_SYS_FAULT_INJECTION=1 -DLWS_WITH_TLS_JIT_TRUST=1 -DLWS_ROLE_MQTT=1 -DLWS_ROLE_RAW_PROXY=1 -DLWS_WITH_EVENT_LIBS=1 -DLWS_WITH_LIBUV=1 -DLWS_WITH_STRUCT_JSON=1 -DLWS_WITH_LWS_DSH=1 -DLWS_WITH_SECURE_STREAMS_PROXY_API=1",
"platforms": "none, coverity/x86_64/gcc",
"cpack": "export STAMP=`git log -1 --pretty=format:%h` && rm -f libwebsockets.tgz && tar czvf libwebsockets.tgz cov-int && script -q -c \"cat /etc/coverity/secrets.sh | lws-minimal-http-client-post-form https://scan.coverity.com:443/builds?project=warmcat%2Flibwebsockets --form file=@libwebsockets.tgz --form version=${STAMP} --form 'description=lws qa'\" /dev/null",
"branches": "coverity"
},
# awkward, we also want to test mbedtls, but coverity blocks on SSL build needing manual intervention
"coverity-mbedtls": {
"cmake": "-DLWS_WITH_MBEDTLS=1 -DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_CGI=1 -DLWS_IPV6=1 -DLWS_WITH_HTTP_PROXY=1 -DLWS_WITH_RANGES=1 -DLWS_WITH_THREADPOOL=1 -DLWS_WITH_CBOR=1 -DLWS_WITH_JOSE=1 -DLWS_WITH_COSE=1 -DLWS_WITH_SYS_DHCP_CLIENT=1 -DLWS_WITH_FTS=1 -DLWS_WITH_STRUCT_SQLITE3=1 -DLWS_ROLE_DBUS=1 -DLWS_WITH_SYS_ASYNC_DNS=1 -DLWS_WITH_SYS_FAULT_INJECTION=1 -DLWS_WITH_TLS_JIT_TRUST=1 -DLWS_ROLE_MQTT=1 -DLWS_ROLE_RAW_PROXY=1 -DLWS_WITH_EVENT_LIBS=1 -DLWS_WITH_LIBUV=1 -DLWS_WITH_STRUCT_JSON=1 -DLWS_WITH_LWS_DSH=1 -DLWS_WITH_SECURE_STREAMS_PROXY_API=1",
"cmake": "-DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_CGI=1 -DLWS_IPV6=1 -DLWS_WITH_HTTP_PROXY=1 -DLWS_WITH_RANGES=1 -DLWS_WITH_THREADPOOL=1 -DLWS_WITH_CBOR=1 -DLWS_WITH_JOSE=1 -DLWS_WITH_COSE=1 -DLWS_WITH_SYS_DHCP_CLIENT=1 -DLWS_WITH_FTS=1 -DLWS_WITH_STRUCT_SQLITE3=1 -DLWS_ROLE_DBUS=1 -DLWS_WITH_SYS_ASYNC_DNS=1 -DLWS_WITH_SYS_ASYNC_DNS_DNSSEC=1 -DLWS_WITH_WEBRTC=1 -DLWS_WITH_DHT=1 -DLWS_WITH_ASYNC_QUEUE=1 -DLWS_WITH_SYS_FAULT_INJECTION=1 -DLWS_WITH_TLS_JIT_TRUST=1 -DLWS_ROLE_MQTT=1 -DLWS_ROLE_RAW_PROXY=1 -DLWS_WITH_EVENT_LIBS=1 -DLWS_WITH_LIBUV=1 -DLWS_WITH_STRUCT_JSON=1 -DLWS_WITH_LWS_DSH=1 -DLWS_WITH_SECURE_STREAMS_PROXY_API=1 -DLWS_WITH_AUTHORITATIVE_DNS=1 -DLWS_WITH_DHT=1 -DLWS_WITH_DHT_BACKEND=1 -DLWS_WITH_PLUGINS=1",
"platforms": "none, coverity/x86_64/gcc",
"cpack": "export STAMP=`git log -1 --pretty=format:%h` && rm -f libwebsockets.tgz && tar czvf libwebsockets.tgz cov-int && script -q -c \"cat /etc/coverity/secrets.sh | lws-minimal-http-client-post-form https://scan.coverity.com:443/builds?project=warmcat%2Flibwebsockets --form file=@libwebsockets.tgz --form version=${STAMP} --form 'description=lws qa'\" /dev/null",
"branches": "coverity"
}
# ,
# awkward, we also want to test mbedtls, but coverity blocks on SSL build needing manual intervention
# "coverity-mbedtls": {
# "cmake": "-DLWS_WITH_MBEDTLS=1 -DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_CGI=1 -DLWS_IPV6=1 -DLWS_WITH_HTTP_PROXY=1 -DLWS_WITH_RANGES=1 -DLWS_WITH_THREADPOOL=1 -DLWS_WITH_CBOR=1 -DLWS_WITH_JOSE=1 -DLWS_WITH_COSE=1 -DLWS_WITH_SYS_DHCP_CLIENT=1 -DLWS_WITH_FTS=1 -DLWS_WITH_STRUCT_SQLITE3=1 -DLWS_ROLE_DBUS=1 -DLWS_WITH_SYS_ASYNC_DNS=1 -DLWS_WITH_SYS_ASYNC_DNS_DNSSEC=1 -DLWS_WITH_WEBRTC=1 -DLWS_WITH_DHT=1 -DLWS_WITH_ASYNC_QUEUE=1 -DLWS_WITH_SYS_FAULT_INJECTION=1 -DLWS_WITH_TLS_JIT_TRUST=1 -DLWS_ROLE_MQTT=1 -DLWS_ROLE_RAW_PROXY=1 -DLWS_WITH_EVENT_LIBS=1 -DLWS_WITH_LIBUV=1 -DLWS_WITH_STRUCT_JSON=1 -DLWS_WITH_LWS_DSH=1 -DLWS_WITH_SECURE_STREAMS_PROXY_API=1",
# "platforms": "none, coverity/x86_64/gcc",
# "cpack": "export STAMP=`git log -1 --pretty=format:%h` && rm -f libwebsockets.tgz && tar czvf libwebsockets.tgz cov-int && script -q -c \"cat /etc/coverity/secrets.sh | lws-minimal-http-client-post-form https://scan.coverity.com:443/builds?project=warmcat%2Flibwebsockets --form file=@libwebsockets.tgz --form version=${STAMP} --form 'description=lws qa'\" /dev/null",
# "branches": "coverity"
# }

}
}
Expand Down
38 changes: 38 additions & 0 deletions CMakeLists-implied-options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,31 @@ if (LWS_WITH_SECURE_STREAMS_PROXY_API)
set(LWS_WITH_SECURE_STREAMS 1)
endif()

if (LWS_WITH_DHT_BACKEND)
set(LWS_WITH_DHT 1)
endif()

if (LWS_WITH_DHT)
set(LWS_WITH_TRANSPORT_SEQUENCER 1)
endif()

if (LWS_WITH_TRANSPORT_SEQUENCER)
set(LWS_WITH_LWS_DSH 1)
endif()

if (LWS_WITH_WEBRTC)
set(LWS_WITH_UDP 1)
set(LWS_WITH_DTLS 1)
set(LWS_WITH_ALSA 1 CACHE BOOL "Enable alsa audio example" FORCE)
set(LWS_WITH_OPUS 1 CACHE BOOL "Enable opus audio codec" FORCE)
set(LWS_WITH_PLUGINS 1 CACHE BOOL "Enable plugins" FORCE)
set(LWS_WITH_GENCRYPTO 1)
set(LWS_WITH_JOSE 1)
set(LWS_WITH_NETWORK 1)
set(LWS_WITH_CLIENT 1)
endif()


if (NOT LWS_WITH_NETWORK)
set(LWS_ROLE_MQTT 0)
set(LWS_ROLE_H1 0)
Expand Down Expand Up @@ -400,6 +425,16 @@ if (LWS_WITH_LHP)
set(LWS_WITH_SECURE_STREAMS 1)
endif()

if (LWS_WITH_AUTHORITATIVE_DNS)
set(LWS_WITH_GENCRYPTO 1)
set(LWS_WITH_JOSE 1)
endif()

if (LWS_WITH_SYS_ASYNC_DNS_DNSSEC)
set(LWS_WITH_SYS_ASYNC_DNS 1)
set(LWS_WITH_GENCRYPTO 1)
endif()

# using any abstract protocol enables LWS_WITH_ABSTRACT

#if (LWS_WITH_SMTP)
Expand Down Expand Up @@ -453,3 +488,6 @@ if (WIN32 AND NOT LWS_EXT_PTHREAD_LIBRARIES)
set(LWS_WITH_SYS_SMD 0)
endif()

if (LWS_WITH_ASYNC_QUEUE)
set(LWS_ROLE_H1 1)
endif()
98 changes: 97 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@

cmake_minimum_required(VERSION 3.10...4.0)

set(CMAKE_EXPORT_COMPILE_COMMANDS 1)

if (PICO_SDK_PATH)
include(cmake/pico_sdk_import.cmake)
endif()
Expand Down Expand Up @@ -165,12 +167,17 @@ option(LWS_WITH_RANGES "Support http ranges (RFC7233)" OFF)
option(LWS_WITH_THREADPOOL "Managed worker thread pool support (relies on pthreads)" OFF)
option(LWS_WITH_HTTP_STREAM_COMPRESSION "Support HTTP stream compression" OFF)
option(LWS_WITH_HTTP_BROTLI "Also offer brotli http stream compression (requires LWS_WITH_HTTP_STREAM_COMPRESSION)" OFF)
option(LWS_WITH_ASYNC_QUEUE "HTTP file serving uses async io in a separate thread" OFF)
option(LWS_WITH_ACME "Enable support for ACME automatic cert acquisition + maintenance (letsencrypt etc)" OFF)
option(LWS_WITH_HUBBUB "Enable libhubbub rewriting support" OFF)
option(LWS_WITH_ALSA "Enable alsa audio example" OFF)
option(LWS_WITH_OPUS "Enable opus audio codec" OFF)
option(LWS_WITH_ALEXA "Enable Alexa example" OFF)
option(LWS_WITH_GTK "Enable gtk example" OFF)
option(LWS_WITH_FTS "Full Text Search support" OFF)
option(LWS_WITH_SYS_ASYNC_DNS "Nonblocking internal IPv4 + IPv6 DNS resolver" OFF)
option(LWS_WITH_SYS_ASYNC_DNS_DNSSEC "Include DNSSEC parsing/validation in async-dns (requires crypto)" OFF)
option(LWS_WITH_AUTHORITATIVE_DNS "Authoritative DNS zone signer / server" OFF)
option(LWS_WITH_SYS_NTPCLIENT "Build in tiny ntpclient good for tls date validation and run via lws_system" OFF)
option(LWS_WITH_SYS_DHCP_CLIENT "Build in tiny DHCP client" OFF)
option(LWS_WITH_HTTP_BASIC_AUTH "Support Basic Auth" ON)
Expand All @@ -180,10 +187,27 @@ option(LWS_WITH_SYS_STATE "lws_system state support" ON)
option(LWS_WITH_SYS_SMD "Lws System Message Distribution" ON)
option(LWS_WITH_SYS_FAULT_INJECTION "Enable fault injection support" OFF)
option(LWS_WITH_SYS_METRICS "Lws Metrics API" OFF)
option(LWS_WITH_LATENCY "Event loop latency tracking and monitoring (see ../READMEs/README.LWS_WITH_LATENCY.md)" OFF)
option(LWS_WITH_UPNG "Enable stateful PNG stream decoder" ON)
option(LWS_WITH_GZINFLATE "Enable internal minimal gzip inflator" ON)
option(LWS_WITH_JPEG "Enable stateful JPEG stream decoder" ON)
option(LWS_WITH_DLO "Enable Display List Objects" ON)
option(LWS_WITH_TRANSCODE "Enable video transcoding support (requires ffmpeg)" OFF)
option(LWS_WITH_V4L2 "Enable V4L2 support (Linux only)" OFF)
option(LWS_WITH_LIBV4L2 "Link against libv4l2 if available" OFF)

if (LWS_WITH_LIBV4L2)
find_library(LIBV4L2_LIBRARIES NAMES v4l2)
find_path(LIBV4L2_INCLUDE_DIRS NAMES libv4l2.h)
if (LIBV4L2_LIBRARIES AND LIBV4L2_INCLUDE_DIRS)
set(LWS_HAVE_LIBV4L2 1)
include_directories("${LIBV4L2_INCLUDE_DIRS}")
list(APPEND LIB_LIST_AT_END ${LIBV4L2_LIBRARIES})
list(APPEND LIB_LIST ${LIBV4L2_LIBRARIES})
else()
message(FATAL_ERROR "LWS_WITH_LIBV4L2 enabled but libv4l2 not found")
endif()
endif()

#
# Secure Streams
Expand Down Expand Up @@ -367,7 +391,15 @@ else()
endif()
option(LWS_WITH_MCUFONT_ENCODER "Build the ttf to mcufont encoder" OFF)
option(LWS_WITH_WAKE_LOGGING "Log each wake reason" OFF)
option(LWS_WITH_DHT "Include DHT APIs" OFF)
option(LWS_WITH_DHT "Include DHT frontend client APIs" OFF)
set(LWS_WITH_DHT_BACKEND_DEFAULT OFF)
if (LWS_WITH_DHT)
set(LWS_WITH_DHT_BACKEND_DEFAULT ON)
endif()
option(LWS_WITH_DHT_BACKEND "Include full DHT backend node functionality" ${LWS_WITH_DHT_BACKEND_DEFAULT})
option(LWS_WITH_TRANSPORT_SEQUENCER "Include Transport Sequencer APIs" OFF)
option(LWS_WITH_MNEMONIC "Include mnemonic key generation support" OFF)
option(LWS_WITH_DTLS "Compile with support for Generic DTLS" OFF)

#
# Compressed backtraces
Expand Down Expand Up @@ -545,6 +577,11 @@ set(LWS_LIBRARY_VERSION_MINOR ${CPACK_PACKAGE_VERSION_MINOR})
set(LWS_LIBRARY_VERSION_PATCH ${CPACK_PACKAGE_VERSION_PATCH_NUMBER})
set(LWS_LIBRARY_VERSION_PATCH_ELABORATED ${CPACK_PACKAGE_VERSION_PATCH})

if(NOT DEFINED CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type")
endif()

option(LWS_WITH_AV1_ENCODE "Enable AV1 encoding in webrtc mixer" ON)
if (NOT CMAKE_MODULE_PATH)
set(CMAKE_MODULE_PATH "")
endif()
Expand Down Expand Up @@ -745,6 +782,10 @@ endif()
# add libs here that need to be at the end of the link order
#

if (LWS_WITH_MNEMONIC AND NOT LWS_WITH_GENCRYPTO)
message(FATAL_ERROR "LWS_WITH_MNEMONIC requires LWS_WITH_GENCRYPTO")
endif()

if (LWS_EXT_PTHREAD_INCLUDE_DIR)
list(APPEND LIB_LIST_AT_END ${LWS_EXT_PTHREAD_LIBRARIES})
endif()
Expand Down Expand Up @@ -786,6 +827,59 @@ else()
set(LWS_HAVE_SYS_CAPABILITY_H OFF)
endif()

if (LWS_WITH_ALSA)
find_path(LWS_ALSA_INCLUDE_DIRS NAMES alsa/asoundlib.h)
find_library(LWS_ALSA_LIBRARIES NAMES asound)
if (LWS_ALSA_INCLUDE_DIRS AND LWS_ALSA_LIBRARIES)
set(LWS_HAVE_ALSA ON)
include_directories("${LWS_ALSA_INCLUDE_DIRS}")
list(APPEND LIB_LIST_AT_END ${LWS_ALSA_LIBRARIES})
else()
message(FATAL_ERROR "LWS_WITH_ALSA is set but alsa/asoundlib.h or libasound not found")
endif()
endif()

if (LWS_WITH_OPUS)
find_path(LWS_OPUS_INCLUDE_DIRS NAMES opus/opus.h)
find_library(LWS_OPUS_LIBRARIES NAMES opus)
if (LWS_OPUS_INCLUDE_DIRS AND LWS_OPUS_LIBRARIES)
set(LWS_HAVE_OPUS ON)
include_directories("${LWS_OPUS_INCLUDE_DIRS}")
list(APPEND LIB_LIST_AT_END ${LWS_OPUS_LIBRARIES})
else()
message(FATAL_ERROR "LWS_WITH_OPUS is set but opus/opus.h or libopus not found")
endif()
endif()

if (LWS_WITH_TRANSCODE)
find_package(PkgConfig)
if (PKG_CONFIG_FOUND)
pkg_check_modules(FFMPEG libavcodec libswscale libavutil)
pkg_check_modules(RAV1E rav1e)
endif()

if (FFMPEG_FOUND)
set(LWS_HAVE_FFMPEG 1)
include_directories(${FFMPEG_INCLUDE_DIRS})
list(APPEND LIB_LIST_AT_END ${FFMPEG_LIBRARIES})
else()
message(FATAL_ERROR "LWS_WITH_TRANSCODE is set but ffmpeg components (libavcodec, libswscale, libavutil) not found")
endif()

if (RAV1E_FOUND)
set(LWS_HAVE_RAV1E 1)
include_directories(${RAV1E_INCLUDE_DIRS})
list(APPEND LIB_LIST_AT_END ${RAV1E_LIBRARIES})
endif()
endif()

if (LWS_WITH_V4L2)
CHECK_INCLUDE_FILE(linux/videodev2.h LWS_HAVE_LINUX_VIDEODEV2_H)
if (NOT LWS_HAVE_LINUX_VIDEODEV2_H)
message(FATAL_ERROR "LWS_WITH_V4L2 is set but linux/videodev2.h not found")
endif()
endif()


if (LWS_WITH_ZLIB AND NOT LWS_WITH_BUNDLED_ZLIB)
if (LWS_WITH_MINIZ)
Expand Down Expand Up @@ -1228,6 +1322,8 @@ install(DIRECTORY include/libwebsockets
DESTINATION "${LWS_INSTALL_INCLUDE_DIR}" COMPONENT dev)
install(FILES ${PROJECT_BINARY_DIR}/include/libwebsockets.h ${PROJECT_BINARY_DIR}/include/lws_config.h
DESTINATION "${LWS_INSTALL_INCLUDE_DIR}" COMPONENT dev)
install(FILES ${PROJECT_SOURCE_DIR}/assets/libwebsockets-dht-nodes.txt
DESTINATION share/libwebsockets COMPONENT dev)

# Generate the config file for the installation tree.
get_filename_component(LWS_ABSOLUTE_INSTALL_CMAKE_DIR ${LWS_INSTALL_CMAKE_DIR} ABSOLUTE)
Expand Down
70 changes: 70 additions & 0 deletions READMEs/README.LWS_WITH_LATENCY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# cmake option: `LWS_WITH_LATENCY`

```
cmake .. -DLWS_WITH_LATENCY=1
```

## Function

Enabling this cmake build option causes:

- instrumentation to be built into lws that measures how long every service blocks the event loop (this works on all the event libs as well as the default event loop)
- builds a plugin `protocol_lws_latency` which allows realtime monitoring of the worst latencies

Notice that this measures how long the event loop is blocked for in your system with your user code. It doesn't measure packet arrival to handling interval.

## Building the plugins

You also need to enable `-DLWS_WITH_PLUGINS=1` to build the plugins, and to do `sudo make install` to install the plugins and the web assets.

## Setting up the monitoring plugin - code

- you will need to add a pvo for the plugin with name "lws-latency" and value "ok".
- you will need to add a mount to your existing vhost, or add a vhost bound to lo only and add the mount there, to serve the web assets / JS. The necessary files are installed into /usr/local/share/libwebsockets-test-server/lws-latency by default so the mount should set it's origin there. Typically the mountpoint would be `/latency` and it's a file type mountpoint. The default file there should be `index.html`

## Setting up the monitoring plugin - via lwsws

This is lwsws configuration to run the lws-latency UI plugin on lo without tls.

After starting `sudo lwsws` with this config, you should be able to browse to http://127.0.0.1/latency and get a live display of the current and worst latencies.

### /etc/lwsws/conf


```
{
"global": {
"uid": "48",
"gid": "48",
"interface": "lo",
"server-string": "lwsws",
"init-ssl": "no",
"timeout-secs": "50",
"rlimit-nofile": "10000",
"count-async-threads": 4
}
}
```

### /etc/lwsws/conf.d/lo

```
{
"vhosts": [{
"name": "lo",
"port": "80",
"disable-no-protocol-ws-upgrades": "on",
"enable-client-ssl": "on",
"ws-protocols": [{
"lws-latency": {
"status": "ok"
}
}],
"mounts": [{
"mountpoint": "/latency",
"origin": "file://_lws_ddir_/libwebsockets-test-server/lws-latency",
"default": "index.html"
}]
}
}
```
31 changes: 31 additions & 0 deletions READMEs/README.async-dns.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ Other features
- Uses CNAME resolution inside the same response if present, otherwise
recurses to resolve the CNAME (up to 3 deep)
- ipv6 pieces only built if cmake `LWS_IPV6` enabled
- **Multi-server support**: automatically parses multiple nameservers from `/etc/resolv.conf`.
- **Adaptive server selection**: tracks DNS server response latencies using exponential weighted moving averages.
- **Parallel broadsiding**: initially sends queries to all configured servers simultaneously to determine the fastest responder.
- **Round-robin fallback**: utilizes the fastest server for subsequent queries or round-robins between equally performant servers.

## Api

Expand Down Expand Up @@ -97,4 +101,31 @@ and restarts it. It allows this to happen for 3 CNAME deep.
At the end, either way, the cached result is set using the original
query name and the results from the last CNAME in the chain.

## DNSSEC Support

Async DNS supports DNSSEC validation of responses. This is optional and provides robust protection against DNS spoofing or injection of forged results.

To enable DNSSEC features, build with `-DLWS_WITH_SYS_ASYNC_DNS_DNSSEC=1` in CMake. This will automatically enable the `LWS_WITH_GENCRYPTO` required dependency.

Once enabled, clients can strictly enforce DNSSEC validation globally via the config struct or explicitly over context:
```c
lws_async_dns_dnssec_set_mode(context, LWS_ADNS_DNSSEC_REQUIRE);
```

When validation is set to `LWS_ADNS_DNSSEC_REQUIRE`, queries failing to authenticate computationally with upstream Trust Anchors (or those lacking RRSIG/DNSKEY records entirely) will be explicitly rejected by the resolver and not propagate to callbacks or connections. But some domains inherently lack DNSSEC. For situations where strict DNSSEC is globally mandated, but a small handful of known-unsigned destinations must be reached, clients can explicitly set the `LWS_ADNS_INDICATE_LACKS_DNSSEC` bitflag natively on integer `qtype` lookups. This allows the resolver to tolerate missing records explicitly for that singular lookup, while strictly required globally.

## Network configuration changes and failover

Since lws async DNS natively talks to the DNS servers over UDP, it doesn't automatically adapt when the OS routing table or network configuration changes (e.g., when a mobile device moves from WiFi to a cellular network and loses access to the previous local DNS server).

To handle this gracefully, there are three mechanisms:

1. **Reactive Failover**: The adaptive server selection tracks response latencies using `lws_adapt`. If all active DNS servers consecutively fail to respond or experience severe timeouts (e.g. >10s tracking averages), the lws async DNS system will infer the network configuration has changed and will automatically flush its active nameserver list. It then re-queries the system (e.g., via `GetNetworkParams` on Windows or `__system_property_get` on Android) to learn the new servers. This occurs automatically.
2. **File Monitoring (POSIX)**: On POSIX systems (Linux, macOS, etc.), lws async DNS automatically checks the modification time of `/etc/resolv.conf` before making new queries. If the file has changed since the last check, it transparently reloads the DNS servers.
3. **Explicit API**: Applications can explicitly tell lws to drop its currently tracked DNS servers and refresh its understanding of the network environment by calling the public API:

```c
lws_async_dns_server_reload(context);
```

This is particularly useful on Android, where native C code cannot easily hook onto Java `ConnectivityManager` link change broadcasts. Android applications can listen to `onLinkPropertiesChanged()` natively in Kotlin/Java and call a JNI function that executes `lws_async_dns_server_reload()` out-of-band to proactively trigger the failover.
Loading