Quellcode durchsuchen

libwebsockets 4.1.3 used, library build system reworked (wip)

Arnis Lielturks vor 5 Jahren
Ursprung
Commit
decd645582
100 geänderte Dateien mit 2433 neuen und 9609 gelöschten Zeilen
  1. 0 7
      CMake/Modules/UrhoCommon.cmake
  2. 2 1
      Source/Samples/55_WebsocketsSceneReplication/SceneReplication.cpp
  3. 64 0
      Source/ThirdParty/libwebsockets/.gitignore
  4. 3 0
      Source/ThirdParty/libwebsockets/.mailmap
  5. 198 0
      Source/ThirdParty/libwebsockets/.sai.json
  6. 99 740
      Source/ThirdParty/libwebsockets/CMakeLists.txt
  7. 0 100
      Source/ThirdParty/libwebsockets/READMEs/README.async-dns.md
  8. 0 77
      Source/ThirdParty/libwebsockets/READMEs/README.build-android.md
  9. 0 214
      Source/ThirdParty/libwebsockets/READMEs/README.build-windows.md
  10. 0 741
      Source/ThirdParty/libwebsockets/READMEs/README.build.md
  11. 0 88
      Source/ThirdParty/libwebsockets/READMEs/README.captive-portal-detection.md
  12. 0 29
      Source/ThirdParty/libwebsockets/READMEs/README.ci.md
  13. 0 41
      Source/ThirdParty/libwebsockets/READMEs/README.cmake.md
  14. 0 1373
      Source/ThirdParty/libwebsockets/READMEs/README.coding.md
  15. 0 148
      Source/ThirdParty/libwebsockets/READMEs/README.content-security-policy.md
  16. 0 41
      Source/ThirdParty/libwebsockets/READMEs/README.contributing.md
  17. 0 181
      Source/ThirdParty/libwebsockets/READMEs/README.crypto-apis.md
  18. 0 67
      Source/ThirdParty/libwebsockets/READMEs/README.ctest.md
  19. 0 63
      Source/ThirdParty/libwebsockets/READMEs/README.debugging.md
  20. 0 117
      Source/ThirdParty/libwebsockets/READMEs/README.detailed-latency.md
  21. 0 37
      Source/ThirdParty/libwebsockets/READMEs/README.esp32.md
  22. 0 80
      Source/ThirdParty/libwebsockets/READMEs/README.event-libs.md
  23. 0 55
      Source/ThirdParty/libwebsockets/READMEs/README.h2-long-poll.md
  24. 0 172
      Source/ThirdParty/libwebsockets/READMEs/README.http-fallback.md
  25. 0 176
      Source/ThirdParty/libwebsockets/READMEs/README.jwt.md
  26. 0 43
      Source/ThirdParty/libwebsockets/READMEs/README.lifecycle.md
  27. 0 130
      Source/ThirdParty/libwebsockets/READMEs/README.lws_dll.md
  28. 0 105
      Source/ThirdParty/libwebsockets/READMEs/README.lws_plugins.md
  29. 0 98
      Source/ThirdParty/libwebsockets/READMEs/README.lws_retry.md
  30. 0 149
      Source/ThirdParty/libwebsockets/READMEs/README.lws_sequencer.md
  31. 0 38
      Source/ThirdParty/libwebsockets/READMEs/README.lws_struct.md
  32. 0 99
      Source/ThirdParty/libwebsockets/READMEs/README.lws_sul.md
  33. 0 219
      Source/ThirdParty/libwebsockets/READMEs/README.lws_system.md
  34. 0 702
      Source/ThirdParty/libwebsockets/READMEs/README.lwsws.md
  35. 0 180
      Source/ThirdParty/libwebsockets/READMEs/README.plugin-acme.md
  36. 0 249
      Source/ThirdParty/libwebsockets/READMEs/README.plugin-sshd-base.md
  37. 0 60
      Source/ThirdParty/libwebsockets/READMEs/README.porting.md
  38. 0 66
      Source/ThirdParty/libwebsockets/READMEs/README.problems.md
  39. 0 126
      Source/ThirdParty/libwebsockets/READMEs/README.release-policy.md
  40. 0 448
      Source/ThirdParty/libwebsockets/READMEs/README.test-apps.md
  41. 0 50
      Source/ThirdParty/libwebsockets/READMEs/README.udp.md
  42. 0 101
      Source/ThirdParty/libwebsockets/READMEs/README.unix-domain-reverse-proxy.md
  43. 0 12
      Source/ThirdParty/libwebsockets/READMEs/README.vulnerability-reporting.md
  44. 0 23
      Source/ThirdParty/libwebsockets/READMEs/mainpage.md
  45. 0 65
      Source/ThirdParty/libwebsockets/READMEs/release-checklist
  46. 2 0
      Source/ThirdParty/libwebsockets/VERSION.txt
  47. 37 0
      Source/ThirdParty/libwebsockets/bug_report.md
  48. 1 0
      Source/ThirdParty/libwebsockets/cmake/lws_config.h.in
  49. 9 31
      Source/ThirdParty/libwebsockets/include/libwebsockets.h
  50. 25 0
      Source/ThirdParty/libwebsockets/include/libwebsockets/lws-eventlib-exports.h
  51. 0 47
      Source/ThirdParty/libwebsockets/include/libwebsockets/lws-http.h
  52. 1 1
      Source/ThirdParty/libwebsockets/include/libwebsockets/lws-lejp.h
  53. 9 0
      Source/ThirdParty/libwebsockets/include/libwebsockets/lws-misc.h
  54. 1 6
      Source/ThirdParty/libwebsockets/include/libwebsockets/lws-secure-streams-client.h
  55. 1 18
      Source/ThirdParty/libwebsockets/include/libwebsockets/lws-secure-streams-policy.h
  56. 1 43
      Source/ThirdParty/libwebsockets/include/libwebsockets/lws-secure-streams.h
  57. 25 27
      Source/ThirdParty/libwebsockets/lib/CMakeLists.txt
  58. 3 7
      Source/ThirdParty/libwebsockets/lib/core-net/CMakeLists.txt
  59. 15 1
      Source/ThirdParty/libwebsockets/lib/core-net/adopt.c
  60. 0 0
      Source/ThirdParty/libwebsockets/lib/core-net/client.c
  61. 0 320
      Source/ThirdParty/libwebsockets/lib/core-net/client/connect2.c
  62. 0 558
      Source/ThirdParty/libwebsockets/lib/core-net/client/connect3.c
  63. 0 329
      Source/ThirdParty/libwebsockets/lib/core-net/client/connect4.c
  64. 1 0
      Source/ThirdParty/libwebsockets/lib/core-net/close.c
  65. 6 64
      Source/ThirdParty/libwebsockets/lib/core-net/connect.c
  66. 2 25
      Source/ThirdParty/libwebsockets/lib/core-net/network.c
  67. 6 8
      Source/ThirdParty/libwebsockets/lib/core-net/private-lib-core-net.h
  68. 11 3
      Source/ThirdParty/libwebsockets/lib/core-net/sorted-usec-list.c
  69. 6 1
      Source/ThirdParty/libwebsockets/lib/core-net/wsi-timeout.c
  70. 10 1
      Source/ThirdParty/libwebsockets/lib/core-net/wsi.c
  71. 5 8
      Source/ThirdParty/libwebsockets/lib/core/context.c
  72. 19 45
      Source/ThirdParty/libwebsockets/lib/core/private-lib-core.h
  73. 0 1
      Source/ThirdParty/libwebsockets/lib/event-libs/CMakeLists.txt
  74. 28 4
      Source/ThirdParty/libwebsockets/lib/event-libs/libuv/libuv.c
  75. 2 1
      Source/ThirdParty/libwebsockets/lib/misc/base64-decode.c
  76. 1 0
      Source/ThirdParty/libwebsockets/lib/misc/dir.c
  77. 1 0
      Source/ThirdParty/libwebsockets/lib/misc/lejp.c
  78. 1 0
      Source/ThirdParty/libwebsockets/lib/misc/lws-ring.c
  79. 1 0
      Source/ThirdParty/libwebsockets/lib/misc/sha-1.c
  80. 21 2
      Source/ThirdParty/libwebsockets/lib/plat/freertos/freertos-pipe.c
  81. 10 1
      Source/ThirdParty/libwebsockets/lib/plat/unix/unix-spawn.c
  82. 6 2
      Source/ThirdParty/libwebsockets/lib/plat/windows/windows-init.c
  83. 7 2
      Source/ThirdParty/libwebsockets/lib/plat/windows/windows-pipe.c
  84. 101 39
      Source/ThirdParty/libwebsockets/lib/plat/windows/windows-service.c
  85. 17 15
      Source/ThirdParty/libwebsockets/lib/plat/windows/windows-sockets.c
  86. 3 2
      Source/ThirdParty/libwebsockets/lib/roles/CMakeLists.txt
  87. 2 2
      Source/ThirdParty/libwebsockets/lib/roles/h1/ops-h1.c
  88. 1 1
      Source/ThirdParty/libwebsockets/lib/roles/h2/ops-h2.c
  89. 22 22
      Source/ThirdParty/libwebsockets/lib/roles/h2/private-lib-roles-h2.h
  90. 1 2
      Source/ThirdParty/libwebsockets/lib/roles/http/CMakeLists.txt
  91. 1559 0
      Source/ThirdParty/libwebsockets/lib/roles/http/client/client-handshake.c
  92. 67 218
      Source/ThirdParty/libwebsockets/lib/roles/http/client/client-http.c
  93. 0 209
      Source/ThirdParty/libwebsockets/lib/roles/http/date.c
  94. 1 17
      Source/ThirdParty/libwebsockets/lib/roles/http/header.c
  95. 0 9
      Source/ThirdParty/libwebsockets/lib/roles/http/private-lib-roles-http.h
  96. 1 1
      Source/ThirdParty/libwebsockets/lib/roles/private-lib-roles.h
  97. 1 1
      Source/ThirdParty/libwebsockets/lib/roles/raw-proxy/ops-raw-proxy.c
  98. 1 0
      Source/ThirdParty/libwebsockets/lib/roles/ws/client-parser-ws.c
  99. 12 2
      Source/ThirdParty/libwebsockets/lib/roles/ws/ext/extension-permessage-deflate.c
  100. 4 2
      Source/ThirdParty/libwebsockets/lib/roles/ws/ops-ws.c

+ 0 - 7
CMake/Modules/UrhoCommon.cmake

@@ -896,13 +896,6 @@ macro (define_dependency_libs TARGET)
         endif ()
         endif ()
     endif ()
     endif ()
 
 
-    # Urho3D external dependency
-    if (${TARGET} MATCHES Urho3D)
-        if (URHO3D_NETWORK AND URHO3D_WEBSOCKETS AND NOT WEB)
-            list (APPEND LIBS websockets)
-        endif ()
-    endif ()
-
     # Urho3D/LuaJIT external dependency
     # Urho3D/LuaJIT external dependency
     if (URHO3D_LUAJIT AND ${TARGET} MATCHES LuaJIT|Urho3D)
     if (URHO3D_LUAJIT AND ${TARGET} MATCHES LuaJIT|Urho3D)
         if (NOT WIN32 AND NOT WEB)
         if (NOT WIN32 AND NOT WEB)

+ 2 - 1
Source/Samples/55_WebsocketsSceneReplication/SceneReplication.cpp

@@ -89,7 +89,8 @@ void SceneReplication::Start()
     // Create the scene content
     // Create the scene content
     CreateScene();
     CreateScene();
 
 
-    if (!GetSubsystem<Engine>()->IsHeadless()) {
+    if (!GetSubsystem<Engine>()->IsHeadless())
+    {
         // Execute base class startup
         // Execute base class startup
         Sample::Start();
         Sample::Start();
 
 

+ 64 - 0
Source/ThirdParty/libwebsockets/.gitignore

@@ -0,0 +1,64 @@
+#Ignore build files
+CMakeCache.txt
+CMakeFiles
+build
+cmake_install.cmake
+lws-minimal*
+Makefile
+.cproject
+.project
+config.h
+config.log
+config.status
+libtool
+stamp-h1
+output/
+win32port/ipch/
+win32port/Debug*/
+win32port/Release*/
+win32port/server/Debug*/
+win32port/server/Release*/
+win32port/client/Debug*/
+win32port/client/Release*/
+win32port/libwebsocketswin32/Debug*/
+win32port/libwebsocketswin32/Release*/
+win32port/zlib/Debug*/
+win32port/zlib/Release*/
+*.vcxproj.user
+*.opensdf
+*.sdf
+*.suo
+*.su
+*.m4
+*.a
+missing
+depcomp
+install-sh
+configure
+compile
+config.guess
+*~
+*.orig
+autom4te.cache/
+ltmain.sh
+config.sub
+ar-lib
+libwebsockets.pc
+build/
+*.swp
+doc
+/build2/
+/build3/
+/cov-int/
+/.vs/
+/build-mtls/
+/build-mingw64/
+/n9/
+/bb/
+/openssl3/
+/bb-linkit/
+/bq/
+/cros/
+/q/
+/b1/
+/destdir/

+ 3 - 0
Source/ThirdParty/libwebsockets/.mailmap

@@ -0,0 +1,3 @@
+Andy Green <[email protected]> <[email protected]>
+Joakim Söderberg <[email protected]>
+

+ 198 - 0
Source/ThirdParty/libwebsockets/.sai.json

@@ -0,0 +1,198 @@
+{
+	"schema": "sai-1",
+
+	# We're doing separate install into destdir so that the test server
+	# has somewhere to go to find its /usr/share content like certs
+
+	"platforms": {
+		"linux-ubuntu-1804/x86_64-amd/gcc": {
+			"build": "mkdir build destdir;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G DEB\";cmake .. ${cmake} && make -j && make -j DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}"
+		},
+		"linux-ubuntu-2004/x86_64-amd/gcc": {
+			"build": "mkdir build destdir;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G DEB\";cmake .. ${cmake} && make -j && make -j DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}"
+		},
+		"linux-fedora-32/x86_64-amd/gcc": {
+			"build": "rm -rf build destdir ; mkdir build destdir;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G RPM\";cmake .. ${cmake} && make -j && make -j DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}"
+		},
+		"linux-gentoo/x86_64-amd/gcc": {
+			"build": "mkdir build destdir;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G ZIP\";cmake .. ${cmake} && make -j && make -j DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}"
+		},
+		"linux-centos-8/x86_64-amd/gcc": {
+			"build": "mkdir build destdir;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G RPM\";cmake .. ${cmake} && make -j && make -j DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}"
+		},
+		"linux-ubuntu-2004/aarch64-a72-bcm2711-rpi4/gcc": {
+			"build": "mkdir build;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G DEB\";cmake .. ${cmake} && make -j3 && make -j DESTDIR=../destdir install && ctest -j3 --output-on-failure ${cpack}",
+			"default": false
+		},
+		"linux-android/aarch64/llvm": {
+			"build": "mkdir build;cd build;cmake .. -DCMAKE_TOOLCHAIN_FILE=../libwebsockets/contrib/cross-aarch64-android.cmake ${cmake} && make -j",
+			"default": false
+		},
+		"netbsd-iOS/aarch64/llvm": {
+			"build": "mkdir build destdir; cd build; export SAI_CPACK=\"-G ZIP\";cmake .. -DCMAKE_MAKE_PROGRAM=/usr/bin/make -DCMAKE_IOS_DEVELOPER_ROOT=/opt/Xcode-beta.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer -DCMAKE_TOOLCHAIN_FILE=contrib/iOS.cmake -DIOS_PLATFORM=OS ${cmake} && make -j",
+			"default": false
+		},
+		"netbsd-OSX-catalina/x86_64-intel-i3/llvm": {
+			"build": "mkdir build destdir; cd build; export SAI_CPACK=\"-G ZIP\";export MACOSX_DEPLOYMENT_TARGET=10.14 ; cmake .. -DCMAKE_MAKE_PROGRAM=/usr/bin/make -DLWS_OPENSSL_INCLUDE_DIRS=/usr/local/opt/[email protected]/include -DLWS_OPENSSL_LIBRARIES=\"/usr/local/opt/openssl/lib/libssl.dylib;/usr/local/opt/openssl/lib/libcrypto.dylib\" ${cmake} && make -j && make -j DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}"
+		},
+
+		"freertos-linkit/arm32-m4-mt7697-usi/gcc": {
+			"build": "mkdir build;cd build;export CCACHE_DISABLE=1;cmake .. -DCMAKE_INSTALL_PREFIX:PATH=/tmp -DCMAKE_TOOLCHAIN_FILE=../contrib/cross-linkit.cmake -DLWS_PLAT_FREERTOS=1 -DLWS_WITH_ZLIB=0 -DLWS_WITHOUT_EXTENSIONS=1 -DLWS_WITH_ZIP_FOPS=0 -DLWS_WITH_HTTP_STREAM_COMPRESSION=0 -DLWS_WITH_MBEDTLS=1 -DLWS_WITH_FILE_OPS=0 ${cmake};make -j",
+			"default": false
+		},
+		"windows-10/x86_64-amd/msvc": {
+			"build": "mkdir build && cd build && set SAI_CPACK=\"-G ZIP\" && cmake .. -DLWS_OPENSSL_LIBRARIES=\"C:\\Program Files\\OpenSSL\\lib\\libssl.lib;C:\\Program Files\\OpenSSL\\lib\\libcrypto.lib\" -DLWS_OPENSSL_INCLUDE_DIRS=\"C:\\Program Files\\OpenSSL\\include\" -DLWS_EXT_PTHREAD_INCLUDE_DIR=\"C:\\Program Files (x86)\\pthreads\\include\" -DLWS_EXT_PTHREAD_LIBRARIES=\"C:\\Program Files (x86)\\pthreads\\lib\\x64\\libpthreadGC2.a\" ${cmake} && cmake --build . --config DEBUG && set CTEST_OUTPUT_ON_FAILURE=1 && ctest . -C DEBUG -j4 --output-on-failure",
+			"default": false
+		},
+		"windows-10/x86_64-amd/mingw32": {
+			"build": "mkdir build && cd build && cmake .. -DCMAKE_TOOLCHAIN_FILE=../contrib/cross-w32.cmake ${cmake} && cmake --build . --config DEBUG",
+			"default": false
+		},
+		"windows-10/x86_64-amd/mingw64": {
+			"build": "mkdir build && cd build && cmake .. -DCMAKE_TOOLCHAIN_FILE=../contrib/cross-w64.cmake ${cmake} && cmake --build . --config DEBUG",
+			"default": false
+		},
+		"freertos-espidf/xl6-esp32/gcc": {
+			# official way to get sdkconfig.h is idf.py menuconfig, but
+			# no obvious way to do that in CI
+			"build":	"rm -rf ebuild ; mkdir ebuild; cd ebuild; cp -rp ../minimal-examples/embedded/esp32/${cpack} . ;  cd ${cpack} ; . /opt/esp/esp-idf/export.sh ; ln -sf ../.. libwebsockets ; idf.py set-target esp32 && cp libwebsockets/minimal-examples/embedded/esp32/${cpack}/sdkconfig . && cp sdkconfig.h build && idf.py ${cmake} build size size-components size-files && cd build && /usr/local/bin/sai-device ${cpack} ESPPORT=0 ctest --output-on-failure",
+			"default":	false
+		},
+		"linux-fedora-32/riscv64-virt/gcc": {
+			"build":	"mkdir build destdir;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G RPM\";cmake .. ${cmake} && make -j12 && make -j12 DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}",
+			"default":	false
+		},
+		"freebsd-12/x86_64-amd/llvm": {
+			"build":	"mkdir build destdir;cd build;export CCACHE_DISABLE=1;cmake .. ${cmake} && make -j12 && make -j12 DESTDIR=../destdir install"
+		}
+	},
+
+	"configurations": {
+		"default": {
+			"cmake":	"",
+			"platforms":	"windows-10/x86_64-amd/msvc, freertos-linkit/arm32-m4-mt7697-usi/gcc, linux-ubuntu-2004/aarch64-a72-bcm2711-rpi4/gcc, windows-10/x86_64-amd/mingw32, windows-10/x86_64-amd/mingw64"
+		},
+		"esp32-heltec": {
+			"cmake":	"",
+			"cpack":	"esp-heltec-wb32",
+			"platforms":	"none, freertos-espidf/xl6-esp32/gcc"
+		},
+		"esp32-wrover": {
+			"cmake":	"",
+			"cpack":	"esp-wrover-kit",
+			"platforms":	"none, freertos-espidf/xl6-esp32/gcc"
+		},
+		"esp32-wrover-static": {
+			"cmake":	"-DLWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY=1 ",
+			"cpack":	"esp-wrover-kit",
+			"platforms":	"none, freertos-espidf/xl6-esp32/gcc"
+		},
+
+#		"default-examples-openssl-v3": {
+#			"cmake":	"-DLWS_OPENSSL_LIBRARIES=\"/usr/local/src/openssl/v3/usr/local/lib64/libssl.a;/usr/local/src/openssl/v3/usr/local/lib64/libcrypto.a\" -DLWS_OPENSSL_INCLUDE_DIRS=\"/usr/local/src/openssl/v3/usr/local/include/\" -DLWS_WITH_MINIMAL_EXAMPLES=1 -DLWS_WITH_GENCRYPTO=1",
+#			"platforms":	"none,linux-fedora-32/x86_64-amd/gcc"
+#		},
+		"default-examples-boringssl": {
+			"cmake":	"cmake .. -DLWS_WITH_BORINGSSL=1 -DLWS_OPENSSL_INCLUDE_DIRS=\"/usr/local/src/boringssl/include\" -DLWS_OPENSSL_LIBRARIES=\"/usr/local/src/boringssl/build/ssl/libssl.so;/usr/local/src/boringssl/build/crypto/libcrypto.so\" -DLWS_WITH_MINIMAL_EXAMPLES=1",
+			"platforms":	"none,linux-fedora-32/x86_64-amd/gcc"
+		},
+		"default-wolfssl": {
+			"cmake":	"-DLWS_WITH_WOLFSSL=1 -DLWS_WOLFSSL_INCLUDE_DIRS=/usr/local/include -DLWS_WOLFSSL_LIBRARIES=/usr/local/lib/libwolfssl.so",
+			"platforms":	"none,linux-fedora-32/x86_64-amd/gcc"
+		},
+		"default-examples": {
+			"cmake":	"-DLWS_WITH_MINIMAL_EXAMPLES=1",
+			"platforms":	"windows-10/x86_64-amd/msvc, linux-ubuntu-2004/aarch64-a72-bcm2711-rpi4/gcc"
+		},
+		"unix-domain": {
+			"cmake":	"-DUNIX_SOCK=1",
+			"platforms":	"windows-10/x86_64-amd/msvc"
+		},
+		"lws_system": {
+			"cmake":	"-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",
+			"platforms":	"windows-10/x86_64-amd/msvc"
+		},
+		"secure-streams": {
+			"cmake":	"-DLWS_WITH_SECURE_STREAMS=1",
+			"platforms":	"windows-10/x86_64-amd/msvc"
+		},
+		"secure-streams-proxy": {
+			"cmake":	"-DLWS_WITH_SECURE_STREAMS=1 -DLWS_WITH_SECURE_STREAMS_PROXY_API=1",
+			"platforms":	"not windows-10/x86_64-amd/msvc"
+		},
+		"distro_recommended": {
+			"cmake":	"-DLWS_WITH_DISTRO_RECOMMENDED=1",
+			"platforms":	"not freebsd-12/x86_64-amd/llvm, not linkit-cross, not windows-10/x86_64-amd/msvc, linux-ubuntu-2004/aarch64-a72-bcm2711-rpi4/gcc, linux-fedora-32/riscv64-virt/gcc",
+			"cpack":	"&& cpack $SAI_CPACK",
+			"artifacts":	"build/*.rpm, build/*.deb, build/*.zip"
+		},
+		"lwsws": {
+			"cmake":	"-DLWS_WITH_LWSWS=ON -DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_HTTP2=1 -DLWS_WITH_ACME=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DCMAKE_BUILD_TYPE=DEBUG -DLWS_WITH_GENCRYPTO=1 -DLWS_WITH_JOSE=1 -DLWS_WITH_SYS_ASYNC_DNS=1 -DLWS_WITH_SYS_NTPCLIENT=1",
+			# no distro -devel package for libuv
+			"platforms":	"not linux-centos-8/x86_64-amd/gcc"
+		},
+		"lwsws2": {
+			"cmake":	"-DLWS_WITH_LWSWS=ON -DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_HTTP2=1 -DLWS_WITH_ACME=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DCMAKE_BUILD_TYPE=DEBUG -DLWS_WITH_LWS_DSH=1",
+			# no distro -devel package for libuv
+			"platforms":	"not linux-centos-8/x86_64-amd/gcc"
+		},
+		"justmbedtls": {
+			"cmake": "-DLWS_WITH_MBEDTLS=1 -DLWS_WITHOUT_TESTAPPS=1",
+			"platforms": "none, linux-android/aarch64/llvm"
+		},
+		"mbedtls": {
+			"cmake":	"-DLWS_WITH_MBEDTLS=1 -DLWS_WITH_HTTP2=1 -DLWS_WITH_LWSWS=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DLWS_WITH_JOSE=1 -DCMAKE_BUILD_TYPE=DEBUG",
+			# no distro -devel package for mbedtls
+			"platforms":	"not linux-centos-8/x86_64-amd/gcc"
+		},
+		"noserver": {
+			"cmake":	"-DLWS_WITHOUT_SERVER=ON -DLWS_WITH_MINIMAL_EXAMPLES=1"
+		},
+		"noclient": {
+			"cmake":	"-DLWS_WITHOUT_CLIENT=ON -DLWS_WITH_MINIMAL_EXAMPLES=1"
+		},
+		"ext": {
+			"cmake":	"-DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_MINIMAL_EXAMPLES=1"
+		},
+		"nonetwork": {
+			"cmake":	"-DLWS_WITH_NETWORK=0"
+		},
+		"libev": {
+			"cmake":	"-DLWS_WITH_LIBEV=ON"
+		},
+		"libevent": {
+			"cmake":	"-DLWS_WITH_LIBEVENT=ON"
+		},
+		"libglib": {
+			"cmake":	"-DLWS_WITH_GLIB=ON"
+		},
+		"ipv6":	{
+			"cmake":	"-DLWS_IPV6=ON",
+			"platforms":	"windows-10/x86_64-amd/mingw64, windows-10/x86_64-amd/msvc"
+		},
+		"nossl": {
+			"cmake":	"-DLWS_WITH_SSL=OFF",
+			"platforms":	"netbsd-iOS/aarch64/llvm"
+		},
+		"daemon": {
+			"cmake":	"-DLWS_WITHOUT_DAEMONIZE=OFF"
+		},
+		"cgi": {
+			"cmake":	"-DLWS_WITH_CGI=ON"
+		},
+		"nologs": {
+			"cmake":	"-DLWS_WITH_NO_LOGS=ON"
+		},
+		"smp": {
+			"cmake":	"-DLWS_MAX_SMP=32 -DLWS_WITH_MINIMAL_EXAMPLES=1"
+		},
+		"nows": {
+			"cmake":	"-DLWS_ROLE_WS=0"
+		},
+		"threadpool": {
+			"cmake":	"-DLWS_WITH_THREADPOOL=1 -DLWS_WITH_MINIMAL_EXAMPLES=1",
+			"platforms":	"windows-10/x86_64-amd/msvc"
+		}
+	}
+}
+

+ 99 - 740
Source/ThirdParty/libwebsockets/CMakeLists.txt

@@ -1,13 +1,11 @@
 #
 #
-# libwebsockets - small server side websockets and web server implementation
-#
-# Copyright (C) 2010 - 2020 Andy Green <[email protected]>
+# Copyright (c) 2008-2020 the Urho3D project.
 #
 #
 # Permission is hereby granted, free of charge, to any person obtaining a copy
 # Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to
-# deal in the Software without restriction, including without limitation the
-# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-# sell copies of the Software, and to permit persons to whom the Software is
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
 # furnished to do so, subject to the following conditions:
 # furnished to do so, subject to the following conditions:
 #
 #
 # The above copyright notice and this permission notice shall be included in
 # The above copyright notice and this permission notice shall be included in
@@ -17,54 +15,28 @@
 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-# IN THE SOFTWARE.
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
 #
 #
 
 
-cmake_minimum_required(VERSION 2.8.9)
-include(CheckFunctionExists)
-include(CheckSymbolExists)
-include(CheckIncludeFile)
-include(CheckIncludeFiles)
-include(CheckLibraryExists)
-include(CheckTypeSize)
-include(CheckCSourceCompiles)
-
-if (POLICY CMP0048)
-	cmake_policy(SET CMP0048 NEW)
-endif()
-
-#if (POLICY CMP0024)
-#	cmake_policy(SET CMP0024 NEW)
-#endif()
-
-if (POLICY CMP0075)
-	cmake_policy(SET CMP0075 NEW)
-endif()
-
-# General Advice
-#
-# For selecting between DEBUG / RELEASE, use -DCMAKE_BUILD_TYPE=DEBUG or =RELEASE
-#   debug builds include source level debug info and extra logging
+# Define target name
+set (TARGET_NAME libwebsockets)
 
 
+########
 set(LWS_WITH_BUNDLED_ZLIB_DEFAULT OFF)
 set(LWS_WITH_BUNDLED_ZLIB_DEFAULT OFF)
-if(WIN32)
-	set(LWS_WITH_BUNDLED_ZLIB_DEFAULT ON)
-endif()
+if (WIN32)
+    set(LWS_WITH_BUNDLED_ZLIB_DEFAULT ON)
+endif ()
 
 
 set(LWS_ROLE_RAW 1)
 set(LWS_ROLE_RAW 1)
 set(LWS_WITH_POLL 1)
 set(LWS_WITH_POLL 1)
 
 
 if (ESP_PLATFORM)
 if (ESP_PLATFORM)
-	set(LWS_ESP_PLATFORM 1)
-	set(CMAKE_TOOLCHAIN_FILE contrib/cross-esp32.cmake)
-	set(LWIP_PROVIDE_ERRNO 1)
-endif()
-
-# it's at this point any toolchain file is brought in
-project(libwebsockets C)
-include(CTest)
+    set(LWS_ESP_PLATFORM 1)
+    set(CMAKE_TOOLCHAIN_FILE contrib/cross-esp32.cmake)
+    set(LWIP_PROVIDE_ERRNO 1)
+endif ()
 
 
 #
 #
 # Select features recommended for PC distro packaging
 # Select features recommended for PC distro packaging
@@ -72,6 +44,7 @@ include(CTest)
 option(LWS_WITH_DISTRO_RECOMMENDED "Enable features recommended for distro packaging" OFF)
 option(LWS_WITH_DISTRO_RECOMMENDED "Enable features recommended for distro packaging" OFF)
 option(LWS_FOR_GITOHASHI "Enable features recommended for use with gitohashi" OFF)
 option(LWS_FOR_GITOHASHI "Enable features recommended for use with gitohashi" OFF)
 
 
+
 #
 #
 # Compiler features
 # Compiler features
 #
 #
@@ -156,12 +129,12 @@ option(LWS_WITH_LIBEVENT "Compile with support for libevent" OFF)
 option(LWS_WITH_GLIB "Compile with support for glib event loop" OFF)
 option(LWS_WITH_GLIB "Compile with support for glib event loop" OFF)
 
 
 if (UNIX)
 if (UNIX)
-# since v4.1, on unix platforms default is build any event libs as runtime plugins
-option(LWS_WITH_EVLIB_PLUGINS "Compile event lib support into runtime-selected plugins" ON)
-else()
-# otherwise default to linking the event lib(s) to libwebsockets.so
-option(LWS_WITH_EVLIB_PLUGINS "Compile event lib support into runtime-selected plugins" OFF)
-endif()
+    # since v4.1, on unix platforms default is build any event libs as runtime plugins
+    option(LWS_WITH_EVLIB_PLUGINS "Compile event lib support into runtime-selected plugins" ON)
+else ()
+    # otherwise default to linking the event lib(s) to libwebsockets.so
+    option(LWS_WITH_EVLIB_PLUGINS "Compile event lib support into runtime-selected plugins" OFF)
+endif ()
 #
 #
 # LWS Drivers
 # LWS Drivers
 #
 #
@@ -212,11 +185,11 @@ option(LWS_WITH_STRUCT_SQLITE3 "Generic struct serialization to and from SQLITE3
 # broken atm
 # broken atm
 #option(LWS_WITH_SMTP "Provide SMTP support" OFF)
 #option(LWS_WITH_SMTP "Provide SMTP support" OFF)
 if (LWS_WITH_ESP32)
 if (LWS_WITH_ESP32)
-option(LWS_WITH_DIR "Directory scanning api support" OFF)
-option(LWS_WITH_LEJP_CONF "With LEJP configuration parser as used by lwsws" OFF)
+    option(LWS_WITH_DIR "Directory scanning api support" OFF)
+    option(LWS_WITH_LEJP_CONF "With LEJP configuration parser as used by lwsws" OFF)
 else()
 else()
-option(LWS_WITH_DIR "Directory scanning api support" ON)
-option(LWS_WITH_LEJP_CONF "With LEJP configuration parser as used by lwsws" ON)
+    option(LWS_WITH_DIR "Directory scanning api support" ON)
+    option(LWS_WITH_LEJP_CONF "With LEJP configuration parser as used by lwsws" ON)
 endif()
 endif()
 option(LWS_WITH_NO_LOGS "Disable all logging other than _err and _user from being compiled in" OFF)
 option(LWS_WITH_NO_LOGS "Disable all logging other than _err and _user from being compiled in" OFF)
 set(LWS_LOGGING_BITFIELD_SET 0 CACHE STRING "Bitfield describing which log levels to force included into the build")
 set(LWS_LOGGING_BITFIELD_SET 0 CACHE STRING "Bitfield describing which log levels to force included into the build")
@@ -266,712 +239,98 @@ set(LIB_LIST "")
 set(LIB_LIST_AT_END)
 set(LIB_LIST_AT_END)
 set(LWS_LIBRARIES)
 set(LWS_LIBRARIES)
 
 
+set(LWS_LIBRARY_VERSION "4.1.3")
+set(LWS_LIBRARY_VERSION_MAJOR 4)
+set(LWS_LIBRARY_VERSION_MINOR 1)
+set(LWS_LIBRARY_VERSION_PATCH 3)
+
 # Modfied for Urho3D to allow building libwebsockets with SSL support
 # Modfied for Urho3D to allow building libwebsockets with SSL support
 if (URHO3D_SSL)
 if (URHO3D_SSL)
-	message(STATUS "Adding SSL support for libwebsockets")
-	set(LWS_OPENSSL_SUPPORT 1)
-	set(LWS_WITH_SSL 1)
+    message(STATUS "Adding SSL support for libwebsockets")
+    set(LWS_OPENSSL_SUPPORT 1)
+    set(LWS_WITH_SSL 1)
 endif ()
 endif ()
 
 
 include(CMakeLists-implied-options.txt)
 include(CMakeLists-implied-options.txt)
 
 
-#
-# Structural helpers for cmake in subdirs
-#
-
-macro(add_subdir_include_directories arg1)
-	add_subdirectory(${arg1})
-	include_directories(${_CMAKE_INC_LIST})
-endmacro()
-
 macro(exports_to_parent_scope)
 macro(exports_to_parent_scope)
-	set(SOURCES ${SOURCES} PARENT_SCOPE)
-	if (LIB_LIST)
-		set(LIB_LIST ${LIB_LIST} PARENT_SCOPE)
-	endif()
-	get_property(_CURR DIRECTORY PROPERTY INCLUDE_DIRECTORIES) 
-	set(_CMAKE_INC_LIST ${_CURR} PARENT_SCOPE)
-	if (LWS_LIB_BUILD_INC_PATHS)
-		set(LWS_LIB_BUILD_INC_PATHS ${LWS_LIB_BUILD_INC_PATHS} PARENT_SCOPE)
-	endif()
+    foreach(file ${SOURCES})
+        list(APPEND SOURCE_FILES "lib/${file}")
+    endforeach(file)
+    set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
+    if (LIB_LIST)
+        set(LIB_LIST ${LIB_LIST} PARENT_SCOPE)
+    endif()
+    get_property(_CURR DIRECTORY PROPERTY INCLUDE_DIRECTORIES)
+    set(_CMAKE_INC_LIST ${_CURR} PARENT_SCOPE)
+    if (LWS_LIB_BUILD_INC_PATHS)
+        set(LWS_LIB_BUILD_INC_PATHS ${LWS_LIB_BUILD_INC_PATHS} PARENT_SCOPE)
+    endif()
 endmacro()
 endmacro()
 
 
 macro(export_to_parent_intermediate)
 macro(export_to_parent_intermediate)
-	set(SOURCES ${SOURCES} PARENT_SCOPE)
-	if (LIB_LIST)
-		set(LIB_LIST ${LIB_LIST} PARENT_SCOPE)
-	endif()
-	set(_CMAKE_INC_LIST ${_CMAKE_INC_LIST} PARENT_SCOPE)
-	if (LWS_LIB_BUILD_INC_PATHS)
-		set(LWS_LIB_BUILD_INC_PATHS ${LWS_LIB_BUILD_INC_PATHS} PARENT_SCOPE)
-	endif()
-endmacro()
-
-#
-# Try to find the current Git hash
-#
-
-find_package(Git)
-if(GIT_EXECUTABLE)
-	execute_process(
-		WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
-		COMMAND "${GIT_EXECUTABLE}" describe --tags --always
-		OUTPUT_VARIABLE GIT_HASH
-		OUTPUT_STRIP_TRAILING_WHITESPACE
-		)
-	set(LWS_BUILD_HASH ${GIT_HASH})
-
-	# append the build user and hostname
-	if (NOT LWS_REPRODUCIBLE)
-		execute_process(
-			WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
-			COMMAND "whoami"
-			OUTPUT_VARIABLE GIT_USER
-			OUTPUT_STRIP_TRAILING_WHITESPACE
-			)
-		execute_process(
-			WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
-			COMMAND "hostname"
-			OUTPUT_VARIABLE GIT_HOST
-			OUTPUT_STRIP_TRAILING_WHITESPACE
-			)
-		string(REGEX REPLACE "([^\\])[\\]([^\\])" "\\1\\\\\\\\\\2" GIT_USER ${GIT_USER})
-		set(LWS_BUILD_HASH ${GIT_USER}@${GIT_HOST}-${GIT_HASH})
-	endif()
-
-	message("Git commit hash: ${LWS_BUILD_HASH}")
-endif()
-
-set(PACKAGE "libwebsockets")
-set(CPACK_RPM_PACKAGE_LICENSE "MIT")
-set(CPACK_PACKAGE_NAME "${PACKAGE}")
-set(CPACK_PACKAGE_VERSION_MAJOR "4")
-set(CPACK_PACKAGE_VERSION_MINOR "1")
-set(CPACK_PACKAGE_VERSION_PATCH_NUMBER "99")
-
-set(CPACK_PACKAGE_VERSION_PATCH "${CPACK_PACKAGE_VERSION_PATCH_NUMBER}-${LWS_BUILD_HASH}")
-set(CPACK_PACKAGE_RELEASE 1)
-
-set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
-set(CPACK_PACKAGE_VENDOR "[email protected]")
-set(CPACK_PACKAGE_CONTACT "[email protected]")
-set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PACKAGE} ${CPACK_PACKAGE_VERSION}")
-set(SOVERSION "17")
-if(NOT CPACK_GENERATOR)
-    if(UNIX)
-        set(CPACK_GENERATOR "TGZ")
-    else()
-        set(CPACK_GENERATOR "ZIP")
-    endif()
-endif()
-set(CPACK_SOURCE_GENERATOR "TGZ")
-set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
-set(VERSION "${CPACK_PACKAGE_VERSION}")
-
-set(CPACK_RPM_PACKAGE_RELEASE_DIST ON)
-set(CPACK_RPM_FILE_NAME "RPM-DEFAULT")
-# below makes path length problems in CI
-set(CPACK_RPM_DEBUGINFO_PACKAGE OFF)
-# below makes some kind of chimera rpm with binaries and sources
-set(CPACK_RPM_PACKAGE_SOURCES OFF)
-set(CPACK_RPM_INSTALL_WITH_EXEC ON)
-set(CPACK_RPM_COMPONENT_INSTALL ON)
-
-set(CPACK_DEBIAN_FILE_NAME "DEB-DEFAULT")
-set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
-set(CPACK_DEBIAN_DEBUGINFO_PACKAGE ON)
-set(CPACK_DEBIAN_PACKAGE_SOURCE ON)
-set(CPACK_DEBIAN_COMPONENT_INSTALL ON)
-
-
-set(LWS_LIBRARY_VERSION ${CPACK_PACKAGE_VERSION})
-set(LWS_LIBRARY_VERSION_MAJOR ${CPACK_PACKAGE_VERSION_MAJOR})
-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 CMAKE_MODULE_PATH)
-	set(CMAKE_MODULE_PATH "")
-endif()
-set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/")
-
-
-if (CMAKE_TOOLCHAIN_FILE)
-	message(STATUS "CMAKE_TOOLCHAIN_FILE='${CMAKE_TOOLCHAIN_FILE}'")
-endif()
-
-if (NOT LIB_SUFFIX)
-	set(LIB_SUFFIX "")
-endif()
-
-if (WIN32)
-	configure_file(${CMAKE_CURRENT_SOURCE_DIR}/win32port/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/win32port/version.rc @ONLY)
-	set(RESOURCES ${CMAKE_CURRENT_BINARY_DIR}/win32port/version.rc)
-endif()
-
-include_directories(include)
-
-# Allow the user to override installation directories.
-set(LWS_INSTALL_LIB_DIR       lib CACHE PATH "Installation directory for libraries")
-set(LWS_INSTALL_BIN_DIR       bin CACHE PATH "Installation directory for executables")
-set(LWS_INSTALL_INCLUDE_DIR   include CACHE PATH "Installation directory for header files")
-set(LWS_INSTALL_EXAMPLES_DIR  bin CACHE PATH "Installation directory for example files")
-
-# if you gave LWS_WITH_MINIZ, point to MINIZ here if not found
-# automatically
-
-set(LWS_ZLIB_LIBRARIES CACHE PATH "Path to the zlib/miniz library")
-set(LWS_ZLIB_INCLUDE_DIRS CACHE PATH "Path to the zlib/miniz include directory")
-set(LWS_SQLITE3_LIBRARIES CACHE PATH "Path to the sqlite3 library")
-set(LWS_SQLITE3_INCLUDE_DIRS CACHE PATH "Path to the sqlite3 include directory")
-set(LWS_LIBMOUNT_INCLUDE_DIRS CACHE PATH "Path to the libmount include directory")
-set(LWS_LIBMOUNT_LIBRARIES CACHE PATH "Path to the libmount library")
-# on unix, these are in the toolchain.  On win32 you have to put them somewhere
-# yourself and point to them here
-set(LWS_EXT_PTHREAD_INCLUDE_DIR CACHE PATH "Path to an external pthreads include directory")
-set(LWS_EXT_PTHREAD_LIBRARIES CACHE PATH "Path to an external pthreads library")
-
-
-if (LWS_WITH_HTTP_STREAM_COMPRESSION)
-	set(LWS_WITH_ZLIB 1)
-endif()
-
-if (LWS_WITH_ZLIB AND NOT LWS_WITH_BUNDLED_ZLIB)
-	if ("${LWS_ZLIB_LIBRARIES}" STREQUAL "" OR "${LWS_ZLIB_INCLUDE_DIRS}" STREQUAL "")
-	else()
-		set(ZLIB_LIBRARIES ${LWS_ZLIB_LIBRARIES})
-		set(ZLIB_INCLUDE_DIRS ${LWS_ZLIB_INCLUDE_DIRS})
-		set(ZLIB_FOUND 1)
-	endif()
-endif()
-
-
-if (LWS_WITH_SQLITE3)
-	if ("${LWS_SQLITE3_LIBRARIES}" STREQUAL "" OR "${LWS_SQLITE3_INCLUDE_DIRS}" STREQUAL "")
-	else()
-		set(SQLITE3_LIBRARIES ${LWS_SQLITE3_LIBRARIES})
-		set(SQLITE3_INCLUDE_DIRS ${LWS_SQLITE3_INCLUDE_DIRS})
-		set(SQLITE3_FOUND 1)
-	endif()
-endif()
-
-include_directories("${PROJECT_BINARY_DIR}")
-
-# Check for different inline keyword versions.
-foreach(KEYWORD "inline" "__inline__" "__inline")
-	set(CMAKE_REQUIRED_DEFINITIONS "-DKEYWORD=${KEYWORD}")
-	CHECK_C_SOURCE_COMPILES(
-		"
-		#include <stdio.h>
-		static KEYWORD void a() {}
-		int main(int argc, char **argv) { a(); return 0; }
-		" LWS_HAVE_${KEYWORD})
-endforeach()
-
-if (NOT LWS_HAVE_inline)
-	if (LWS_HAVE___inline__)
-		set(inline __inline__)
-	elseif(LWS_HAVE___inline)
-		set(inline __inline)
-	endif()
-endif()
-
-# Put the libraries and binaries that get built into directories at the
-# top of the build tree rather than in hard-to-find leaf directories. 
-SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin")
-SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
-SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
-
-SET(LWS_INSTALL_PATH "${CMAKE_INSTALL_PREFIX}")
-
-# Put absolute path of dynamic libraries into the object code. Some
-# architectures, notably Mac OS X, need this.
-SET(CMAKE_INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/${LWS_INSTALL_LIB_DIR}${LIB_SUFFIX}")
-
-if (LWS_WITHOUT_BUILTIN_SHA1)
-	set(LWS_SHA1_USE_OPENSSL_NAME 1)
-endif()
-
-CHECK_C_SOURCE_COMPILES(
-	"#include <malloc.h>
-	int main(int argc, char **argv) { return malloc_trim(0); }
-	" LWS_HAVE_MALLOC_TRIM)
-CHECK_C_SOURCE_COMPILES(
-	"#include <malloc.h>
-	int main(int argc, char **argv) { return (int)malloc_usable_size((void *)0); }
-	" LWS_HAVE_MALLOC_USABLE_SIZE)
-
-CHECK_FUNCTION_EXISTS(fork LWS_HAVE_FORK)
-CHECK_FUNCTION_EXISTS(getenv LWS_HAVE_GETENV)
-CHECK_FUNCTION_EXISTS(malloc LWS_HAVE_MALLOC)
-CHECK_FUNCTION_EXISTS(memset LWS_HAVE_MEMSET)
-CHECK_FUNCTION_EXISTS(realloc LWS_HAVE_REALLOC)
-CHECK_FUNCTION_EXISTS(socket LWS_HAVE_SOCKET)
-CHECK_FUNCTION_EXISTS(strerror LWS_HAVE_STRERROR)
-CHECK_FUNCTION_EXISTS(vfork LWS_HAVE_VFORK)
-CHECK_FUNCTION_EXISTS(execvpe LWS_HAVE_EXECVPE)
-CHECK_FUNCTION_EXISTS(getifaddrs LWS_HAVE_GETIFADDRS)
-CHECK_FUNCTION_EXISTS(snprintf LWS_HAVE_SNPRINTF)
-CHECK_FUNCTION_EXISTS(_snprintf LWS_HAVE__SNPRINTF)
-CHECK_FUNCTION_EXISTS(_vsnprintf LWS_HAVE__VSNPRINTF)
-CHECK_FUNCTION_EXISTS(getloadavg LWS_HAVE_GETLOADAVG)
-CHECK_FUNCTION_EXISTS(atoll LWS_HAVE_ATOLL)
-CHECK_FUNCTION_EXISTS(_atoi64 LWS_HAVE__ATOI64)
-CHECK_FUNCTION_EXISTS(_stat32i64 LWS_HAVE__STAT32I64)
-CHECK_FUNCTION_EXISTS(clock_gettime LWS_HAVE_CLOCK_GETTIME)
-
-
-if (NOT LWS_HAVE_GETIFADDRS)
-	if (LWS_WITHOUT_BUILTIN_GETIFADDRS)
-		message(FATAL_ERROR "No getifaddrs was found on the system. Turn off the LWS_WITHOUT_BUILTIN_GETIFADDRS compile option to use the supplied BSD version.")
-	endif()
-	set(LWS_BUILTIN_GETIFADDRS 1)
-endif()
-
-if (LWS_EXT_PTHREAD_INCLUDE_DIR)
-	set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES};${LWS_EXT_PTHREAD_INCLUDE_DIR})
-	include_directories(${LWS_EXT_PTHREAD_INCLUDE_DIR})
-
-	list(APPEND LIB_LIST_AT_END ${LWS_EXT_PTHREAD_LIBRARIES})
-	set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} " -DHAVE_STRUCT_TIMESPEC=1")
-endif()
-
-#
-# add libs here that need to be at the end of the link order
-#
-
-if (LWS_EXT_PTHREAD_INCLUDE_DIR)
-	list(APPEND LIB_LIST_AT_END ${LWS_EXT_PTHREAD_LIBRARIES})
-endif()
-
-if (LWS_WITH_ZLIB AND NOT LWS_WITH_BUNDLED_ZLIB)
-	list(APPEND LIB_LIST_AT_END "${ZLIB_LIBRARIES}")
-endif()
-
-if (LWS_WITH_PLUGINS_API AND UNIX AND NOT (${CMAKE_SYSTEM_NAME} MATCHES "QNX"))
-	list(APPEND LIB_LIST_AT_END "dl")
-endif()
-
-
-CHECK_INCLUDE_FILE(in6addr.h LWS_HAVE_IN6ADDR_H)
-CHECK_INCLUDE_FILE(memory.h LWS_HAVE_MEMORY_H)
-CHECK_INCLUDE_FILE(netinet/in.h LWS_HAVE_NETINET_IN_H)
-CHECK_INCLUDE_FILE(stdint.h LWS_HAVE_STDINT_H)
-CHECK_INCLUDE_FILE(stdlib.h LWS_HAVE_STDLIB_H)
-CHECK_INCLUDE_FILE(strings.h LWS_HAVE_STRINGS_H)
-CHECK_INCLUDE_FILE(string.h LWS_HAVE_STRING_H)
-CHECK_INCLUDE_FILE(sys/prctl.h LWS_HAVE_SYS_PRCTL_H)
-CHECK_INCLUDE_FILE(sys/socket.h LWS_HAVE_SYS_SOCKET_H)
-CHECK_INCLUDE_FILE(sys/sockio.h LWS_HAVE_SYS_SOCKIO_H)
-CHECK_INCLUDE_FILE(sys/stat.h LWS_HAVE_SYS_STAT_H)
-CHECK_INCLUDE_FILE(sys/types.h LWS_HAVE_SYS_TYPES_H)
-CHECK_INCLUDE_FILE(unistd.h LWS_HAVE_UNISTD_H)
-CHECK_INCLUDE_FILE(vfork.h LWS_HAVE_VFORK_H)
-CHECK_INCLUDE_FILE(sys/capability.h LWS_HAVE_SYS_CAPABILITY_H)
-CHECK_INCLUDE_FILE(malloc.h LWS_HAVE_MALLOC_H)
-CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H)
-CHECK_INCLUDE_FILE(inttypes.h LWS_HAVE_INTTYPES_H)
-
-if (WIN32 OR MSVC)
-	CHECK_C_SOURCE_COMPILES("#include <winsock2.h>
-				 #include <afunix.h>
-				 int main() { return 0; }" LWS_HAVE_WIN32_AFUNIX_H)
-
-	if (LWS_UNIX_SOCK AND NOT LWS_HAVE_WIN32_AFUNIX_H)
-		message("No afunix.h found. Disabling LWS_UNIX_SOCK.")
-		set(LWS_WITH_UNIX_SOCK OFF)
-	endif()
-endif()
-
-CHECK_LIBRARY_EXISTS(cap cap_set_flag "" LWS_HAVE_LIBCAP)
-
-
-if (LWS_WITH_ZLIB AND NOT LWS_WITH_BUNDLED_ZLIB)
-	if (LWS_WITH_MINIZ)
-		CHECK_INCLUDE_FILE(miniz.h LWS_HAVE_ZLIB_H)
-	else()
-		CHECK_INCLUDE_FILE(zlib.h LWS_HAVE_ZLIB_H)
-	endif()
-endif()
-
-CHECK_INCLUDE_FILES("stdlib.h;stdarg.h;string.h" STDC_HEADERS)
-
-if (NOT CMAKE_REQUIRED_FLAGS)
-	set(CMAKE_REQUIRED_FLAGS "")
-endif()
-if (NOT CMAKE_REQUIRED_INCLUDES)
-	set(CMAKE_REQUIRED_INCLUDES "")
-endif()
-if (NOT CMAKE_REQUIRED_LIBRARIES)
-	set(CMAKE_REQUIRED_LIBRARIES "")
-endif()
-
-CHECK_C_SOURCE_COMPILES("#include <stdint.h> 
-	int main(void) {
-		intptr_t test = 1;
-		return 0;
-	}" LWS_HAS_INTPTR_T)
-
-if ((CMAKE_C_COMPILER_ID MATCHES "Clang") OR
-    (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
-	set(COMPILER_IS_CLANG ON)
-endif()
-
-if (LWS_HAVE_PTHREAD_H AND NOT LWS_PLAT_FREERTOS)
-	CHECK_C_SOURCE_COMPILES("#define _GNU_SOURCE
-		#include <pthread.h>
-		int main(void) {
-			pthread_t th = 0;
-			pthread_setname_np(th, NULL);
-			return 0;
-		}" LWS_HAS_PTHREAD_SETNAME_NP)
-endif()
-
-CHECK_C_SOURCE_COMPILES("#include <stddef.h>
-	#include <getopt.h>
-	int main(void) {
-		void *p = (void *)getopt_long;
-		return p != NULL;
-	}" LWS_HAS_GETOPT_LONG)
-
-
-if (NOT PID_T_SIZE)
-	set(pid_t int)
-endif()
-
-if (NOT SIZE_T_SIZE)
-	set(size_t "unsigned int")
-endif()
-
-if (NOT LWS_HAVE_MALLOC)
-	set(malloc rpl_malloc)
-endif()
-
-if (NOT LWS_HAVE_REALLOC)
-	set(realloc rpl_realloc)
-endif()
-
-
-
-
-if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR COMPILER_IS_CLANG)
-    include (CheckCCompilerFlag)
-    CHECK_C_COMPILER_FLAG(-fvisibility=hidden LWS_HAVE_VISIBILITY)
-    if (LWS_WITH_FANALYZER)
-	    CHECK_C_COMPILER_FLAG(-fanalyzer LWS_HAVE_FANALYZER)
-    endif()
-    if (LWS_HAVE_VISIBILITY)
-                set(VISIBILITY_FLAG -fvisibility=hidden)
+    foreach(file ${SOURCES})
+        list(APPEND SOURCE_FILES "lib/${file}")
+    endforeach(file)
+    set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
+    if (LIB_LIST)
+        set(LIB_LIST ${LIB_LIST} PARENT_SCOPE)
     endif()
     endif()
-    if (LWS_WITH_GCOV)
-	    set (GCOV_FLAGS "-fprofile-arcs -ftest-coverage ")
-    else()
-	    set(GCOV_FLAGS "")
+    set(_CMAKE_INC_LIST ${_CMAKE_INC_LIST} PARENT_SCOPE)
+    if (LWS_LIB_BUILD_INC_PATHS)
+        set(LWS_LIB_BUILD_INC_PATHS ${LWS_LIB_BUILD_INC_PATHS} PARENT_SCOPE)
     endif()
     endif()
+endmacro()
 
 
-	if (LWS_WITH_ASAN)
-		set (ASAN_FLAGS "-fsanitize=address -fsanitize=undefined -fsanitize-address-use-after-scope -fsanitize-undefined-trap-on-error")
-		if (NOT COMPILER_IS_CLANG)
-			set (ASAN_FLAGS "${ASAN_FLAGS} -fsanitize=pointer-compare -fsanitize=pointer-subtract -fsanitize=leak")
-		endif()
-		message("Enabling ASAN")
-	else()
-		set(ASAN_FLAGS "")
-	endif()
-
-	check_c_compiler_flag("-Wignored-qualifiers" LWS_GCC_HAS_IGNORED_QUALIFIERS)
-	check_c_compiler_flag("-Wtype-limits" LWS_GCC_HAS_TYPE_LIMITS)
-
-	if (LWS_GCC_HAS_IGNORED_QUALIFIERS)
-		set(CMAKE_C_FLAGS "-Wignored-qualifiers ${CMAKE_C_FLAGS}" )
-	endif()
-
-	if (LWS_GCC_HAS_TYPE_LIMITS)
-		set(CMAKE_C_FLAGS "-Wtype-limits ${CMAKE_C_FLAGS}" )
-	endif()
-
-	if (LWS_WITH_FANALYZER AND LWS_HAVE_FANALYZER)
-		set(CMAKE_C_FLAGS "-fanalyzer ${CMAKE_C_FLAGS}" )
-	endif()
-
-	if (CMAKE_COMPILER_IS_CLANG OR CMAKE_C_COMPILER_VERSION VERSION_GREATER 4.4)
-		set(CMAKE_C_FLAGS "-Wuninitialized ${CMAKE_C_FLAGS}")
-	endif()
-
-	# always warn all and generate debug info
-	if (UNIX AND NOT LWS_PLAT_FREERTOS)
-		set(CMAKE_C_FLAGS "-g -Wall -Wsign-compare -Wstrict-aliasing ${VISIBILITY_FLAG} -Wundef ${GCOV_FLAGS} ${CMAKE_C_FLAGS} ${ASAN_FLAGS}" )
-	else()
-		set(CMAKE_C_FLAGS "-g -Wall -Wsign-compare ${VISIBILITY_FLAG} ${GCOV_FLAGS} ${CMAKE_C_FLAGS}" )
-	endif()
-
-	if ("${DISABLE_WERROR}" STREQUAL "OFF")
-		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
-	endif()
-endif ()
-
-if ((CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) AND NOT LWS_WITHOUT_TESTAPPS)
-	if (UNIX AND LWS_HAVE_PTHREAD_H AND NOT (${CMAKE_SYSTEM_NAME} MATCHES "QNX"))
-	# jeez clang understands -pthread but dies if he sees it at link time!
-	# http://stackoverflow.com/questions/2391194/what-is-gs-pthread-equiv-in-clang
-	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread" )
-    endif()
-endif()
-
-if (COMPILER_IS_CLANG)
-
-	# otherwise osx blows a bunch of openssl deprecated api errors
-	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-declarations" )
-	if (UNIX AND LWS_HAVE_PTHREAD_H)
-		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread -Wno-error=unused-command-line-argument" )
-	endif()
-endif()
-
-if (WINCE)
-	list(APPEND LIB_LIST_AT_END ws2.lib)
-elseif (WIN32)
-	list(APPEND LIB_LIST_AT_END ws2_32.lib userenv.lib psapi.lib iphlpapi.lib crypt32.lib)
-endif()
-
-if (MSVC)
-	# Turn off pointless microsoft security warnings.
-	add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE)
-	# Fail the build if any warnings
-	add_compile_options(/W3 /WX)
-endif(MSVC)
-
-if (MINGW)
-	set(LWS_MINGW_SUPPORT 1)
-	set(CMAKE_C_FLAGS "-D__USE_MINGW_ANSI_STDIO ${CMAKE_C_FLAGS}")
-	add_definitions(-DWINVER=0x0601 -D_WIN32_WINNT=0x0601)
-endif()
-
-if (HDR_PRIVATE)
-	source_group("Headers Private"  FILES ${HDR_PRIVATE})
-endif()
-if (HDR_PUBLIC)
-	source_group("Headers Public"   FILES ${HDR_PUBLIC})
-endif()
-if (SOURCES)
-	source_group("Sources"          FILES ${SOURCES})
-endif()
-if (RESOURCES)
-	source_group("Resources"        FILES ${RESOURCES})
-endif()
-
-
-#
-# ZLIB (needed for deflate extension and if LWS_WITH_HTTP_STREAM_COMPRESSION)
-#
-if (LWS_WITH_ZLIB)
-	if (NOT ZLIB_FOUND)
-		if (LWS_WITH_MINIZ)
-			find_package(Miniz REQUIRED)
-			set(ZLIB_INCLUDE_DIRS ${MINIZ_INCLUDE_DIRS})
-			set(ZLIB_LIBRARIES ${MINIZ_LIBRARIES})
-		else()
-			find_package(ZLIB REQUIRED)
-		endif()
-	endif()
-	message("zlib/miniz include dirs: ${ZLIB_INCLUDE_DIRS}")
-	message("zlib/miniz libraries: ${ZLIB_LIBRARIES}")
-	include_directories(${ZLIB_INCLUDE_DIRS})
-	# done later at end of link list
-	# list(APPEND LIB_LIST ${ZLIB_LIBRARIES})
-	set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${ZLIB_LIBRARIES})
-	list(APPEND LIB_LIST_AT_END ${ZLIB_LIBRARIES})
-endif()
-
-
-if (LWS_WITH_FSMOUNT AND ${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
-	if (NOT LWS_LIBMOUNT_INCLUDE_DIRS STREQUAL "")
-		include_directories(${LWS_LIBMOUNT_INCLUDE_DIRS})
-		message("libmount include dir: ${LWS_LIBMOUNT_INCLUDE_DIRS}")
-	endif()
-	if (NOT LWS_LIBMOUNT_LIBRARIES STREQUAL "")
-		message("libmount libraries: ${LWS_LIBMOUNT_LIBRARIES}")
-		list(APPEND LIB_LIST ${LWS_LIBMOUNT_LIBRARIES})
-	else()
-		list(APPEND LIB_LIST mount)
-	endif()
-endif()
-
-
-if (LWS_WITH_SQLITE3)
-	if (NOT SQLITE3_FOUND)
-		find_path(SQLITE3_INCLUDE_DIRS NAMES sqlite3.h)
-		find_library(SQLITE3_LIBRARIES NAMES sqlite3)
-		if(SQLITE3_INCLUDE_DIRS AND SQLITE3_LIBRARIES)
-			set(SQLITE3_FOUND 1)
-		endif()
-	endif()
-	message("sqlite3 include dir: ${SQLITE3_INCLUDE_DIRS}")
-	message("sqlite3 libraries: ${SQLITE3_LIBRARIES}")
-	include_directories("${SQLITE3_INCLUDE_DIRS}")
-	list(APPEND LIB_LIST ${SQLITE3_LIBRARIES})
-endif()
-
-
-if (LWS_WITH_HUBBUB)
-	find_library(LIBHUBBUB_LIBRARIES NAMES hubbub)
-	list(APPEND LIB_LIST ${LIBHUBBUB_LIBRARIES} )
-endif()
-
-if (LWS_HAVE_LIBCAP)
-	find_library(LIBCAP_LIBRARIES NAMES cap)
-	list(APPEND LIB_LIST ${LIBCAP_LIBRARIES} )
-endif()
-
-
-#
-# Append the "at end" pieces to the lib list
-#
-list(APPEND LIB_LIST ${LIB_LIST_AT_END})
+macro(add_subdir_include_directories arg1)
+    add_subdirectory(${arg1})
+#    include_directories(${_CMAKE_INC_LIST})
+#    list(APPEND INCLUDE_DIRECTORIES ${_CMAKE_INC_LIST})
+    list(APPEND INCLUDE_DIRS lib/${arg1} lib/system/${arg1} lib/roles/${arg1})
+    set(INCLUDE_DIRS ${INCLUDE_DIRS} PARENT_SCOPE)
+endmacro()
 
 
-#
-# Second-level CMakeLists
-#
+macro(add_subdir_include_dirs arg1)
+    add_subdirectory(${arg1})
+    list(APPEND INCLUDE_DIRS lib/${arg1} lib/system/${arg1} lib/role/${arg1})
+    set(INCLUDE_DIRS ${INCLUDE_DIRS} PARENT_SCOPE)
+#    list(APPEND LWS_LIB_BUILD_INC_PATHS ${_CMAKE_INC_LIST})
+#    list(APPEND INCLUDE_DIRECTORIES ${_CMAKE_INC_LIST})
+endmacro()
+########
 
 
-include_directories("${PROJECT_SOURCE_DIR}/lib")
+# Define source files
 add_subdirectory(lib)
 add_subdirectory(lib)
+#define_source_files (RECURSE GLOB_CPP_PATTERNS lib/*.c GLOB_H_PATTERNS src/*.h)
 
 
+# Generate libwebsockets configuration file with defined macros
+configure_file(
+        cmake/lws_config.h.in
+        "${PROJECT_BINARY_DIR}/Source/ThirdParty/libwebsockets/include/lws_config.h")
 
 
-
-if(WIN32 AND NOT CYGWIN)
-  set(DEF_INSTALL_CMAKE_DIR cmake)
-else()
-  set(DEF_INSTALL_CMAKE_DIR lib${LIB_SUFFIX}/cmake/libwebsockets)
-endif()
-
-if (DEFINED REL_INCLUDE_DIR)
-    set(LWS__INCLUDE_DIRS "\${LWS_CMAKE_DIR}/${REL_INCLUDE_DIR}")
-endif() 
-
-configure_file(${PROJECT_SOURCE_DIR}/cmake/libwebsockets-config.cmake.in
-                ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/libwebsockets-config.cmake 
-                @ONLY)
-
-# Generate version info for both build-tree and install-tree.
-configure_file(${PROJECT_SOURCE_DIR}/cmake/libwebsockets-config-version.cmake.in
-                ${PROJECT_BINARY_DIR}/libwebsockets-config-version.cmake 
-                @ONLY)
-
-# Generate the config file for the build-tree.
-set(LWS__INCLUDE_DIRS 
-    "${PROJECT_SOURCE_DIR}/lib"
-    "${PROJECT_BINARY_DIR}")
-set(LIBWEBSOCKETS_INCLUDE_DIRS ${LWS__INCLUDE_DIRS} CACHE PATH "Libwebsockets include directories")
-configure_file(${PROJECT_SOURCE_DIR}/cmake/libwebsockets-config.cmake.in
-                ${PROJECT_BINARY_DIR}/libwebsockets-config.cmake 
-                @ONLY)
-set(LWS_INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH "Installation directory for CMake files")
-
-# Export targets (This is used for other CMake projects to easily find the libraries and include files).
-if (LWS_WITH_EXPORT_LWSTARGETS)
-    export(TARGETS ${LWS_LIBRARIES}
-            FILE "${PROJECT_BINARY_DIR}/LibwebsocketsTargets.cmake")
-endif()
-
-
-
-set(libwebsockets_DIR ${PROJECT_BINARY_DIR})
-set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
-message("DIR ${libwebsockets_DIR} CMP ${CMAKE_MODULE_PATH}")
-
-if (LWS_WITH_MINIMAL_EXAMPLES)
-	add_subdirectory(minimal-examples)
-endif()
-
-if (NOT LWS_WITHOUT_TESTAPPS)
-	add_subdirectory(test-apps)
-endif()
-
-#add_subdirectory(plugins)
-add_subdirectory(lwsws)
-
-# Generate the lws_config.h that includes all the public compilation settings.
 configure_file(
 configure_file(
-       "${PROJECT_SOURCE_DIR}/cmake/lws_config.h.in"
-       "${PROJECT_BINARY_DIR}/lws_config.h")
-       
+        cmake/lws_config_private.h.in
+        "${PROJECT_BINARY_DIR}/Source/ThirdParty/libwebsockets/include/lws_config_private.h")
+
 add_custom_command(
 add_custom_command(
-		OUTPUT ${PROJECT_BINARY_DIR}/include/lws_config.h
-			${PROJECT_BINARY_DIR}/include/libwebsockets
-			${PROJECT_BINARY_DIR}/include/libwebsockets.h
-		COMMENT "Creating build include dir"
-		COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/include/libwebsockets.h
-     			${CMAKE_CURRENT_BINARY_DIR}/include/libwebsockets.h
-		COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/include/libwebsockets/
-			${CMAKE_CURRENT_BINARY_DIR}/include/libwebsockets
-		COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/lws_config.h
-     			${CMAKE_CURRENT_BINARY_DIR}/include/lws_config.h
-		MAIN_DEPENDENCY ${PROJECT_BINARY_DIR}/lws_config.h
+        OUTPUT ${PROJECT_BINARY_DIR}/include/lws_config.h
+        ${PROJECT_BINARY_DIR}/include/libwebsockets
+        ${PROJECT_BINARY_DIR}/include/libwebsockets.h
+        COMMENT "Creating build include dir"
+        COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/include/libwebsockets.h
+        ${CMAKE_CURRENT_BINARY_DIR}/include/libwebsockets.h
+        COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/include/libwebsockets/
+        ${CMAKE_CURRENT_BINARY_DIR}/include/libwebsockets
+        COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/lws_config.h
+        ${CMAKE_CURRENT_BINARY_DIR}/include/lws_config.h
+        MAIN_DEPENDENCY ${PROJECT_BINARY_DIR}/lws_config.h
 )
 )
 
 
-add_custom_target(GENHDR DEPENDS  ${PROJECT_BINARY_DIR}/include/lws_config.h)
-
-file(GLOB HDR_PUBLIC1 RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} include/libwebsockets/*.h)
-file(GLOB HDR_PUBLIC2 RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} include/libwebsockets.h)
-file(GLOB HDR_PUBLIC3 RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/include/lws_config.h)
-list(APPEND HDR_PUBLIC ${HDR_PUBLIC1} ${HDR_PUBLIC2} ${HDR_PUBLIC3})
-
-set_source_files_properties(${HDR_PUBLIC} PROPERTIES GENERATED 1)
+list (APPEND INCLUDE_DIRS ${PROJECT_BINARY_DIR}/Source/ThirdParty/libwebsockets/include)
 
 
-if (LWS_WITH_STATIC)
-	add_dependencies(websockets GENHDR)
-endif()
-if (LWS_WITH_SHARED)
-	add_dependencies(websockets_shared GENHDR)
-endif()
-
-
-
-#
-#
-# Installation preparations.
-#
-
-export(PACKAGE libwebsockets)
-
-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)
-
-# Generate the config file for the installation tree.
-get_filename_component(LWS_ABSOLUTE_INSTALL_CMAKE_DIR ${LWS_INSTALL_CMAKE_DIR} ABSOLUTE)
-get_filename_component(LWS_ABSOLUTE_INSTALL_INCLUDE_DIR ${LWS_INSTALL_INCLUDE_DIR} ABSOLUTE)
-file(RELATIVE_PATH 
-    REL_INCLUDE_DIR 
-    "${LWS_ABSOLUTE_INSTALL_CMAKE_DIR}"
-    "${LWS_ABSOLUTE_INSTALL_INCLUDE_DIR}") # Calculate the relative directory from the cmake dir.
-
-set_target_properties(${LWS_LIBRARIES}
-		PROPERTIES PUBLIC_HEADER "${HDR_PUBLIC}")
-
-# Install the LibwebsocketsConfig.cmake and LibwebsocketsConfigVersion.cmake
-install(FILES
-               "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/libwebsockets-config.cmake"
-               "${PROJECT_BINARY_DIR}/libwebsockets-config-version.cmake"
-               "${PROJECT_SOURCE_DIR}/cmake/LwsCheckRequirements.cmake"
-               DESTINATION "${LWS_INSTALL_CMAKE_DIR}" COMPONENT dev)
-
-# Install exports for the install-tree.
-if (LWS_WITH_EXPORT_LWSTARGETS)
-    install(EXPORT LibwebsocketsTargets
-            DESTINATION "${LWS_INSTALL_CMAKE_DIR}" COMPONENT dev)
-endif()
-
-# build subdir is not part of sources
-set(CPACK_SOURCE_IGNORE_FILES $(CPACK_SOURCE_IGNORE_FILES) "/.git/" "/build/" "\\\\.tgz$" "\\\\.tar\\\\.gz$")
-
-# Most people are more used to "make dist" compared to "make package_source"
-add_custom_target(dist COMMAND "${CMAKE_MAKE_PROGRAM}" package_source)
-
-
-#
-## This must always be last!
-#include(CPack)
+message (STATUS SOURCEFILES "${SOURCE_FILESs} - ${INCLUDE_DIRS}")
+# Setup target
+setup_library ()
 
 
 # Install headers for building the Urho3D library
 # Install headers for building the Urho3D library
-#install_header_files (DIRECTORY ./include/ DESTINATION ${DEST_INCLUDE_DIR}/ThirdParty/libwebsockets FILES_MATCHING PATTERN *.h BUILD_TREE_ONLY)  # Note: the trailing slash is significant
+install_header_files (DIRECTORY include/ DESTINATION ${DEST_INCLUDE_DIR}/ThirdParty/libwebsockets FILES_MATCHING PATTERN *.h BUILD_TREE_ONLY)  # Note: the trailing slash is significant

+ 0 - 100
Source/ThirdParty/libwebsockets/READMEs/README.async-dns.md

@@ -1,100 +0,0 @@
-# Asynchronous DNS
-
-## Introduction
-
-Lws now features optional asynchronous, ie, nonblocking recursive DNS
-resolution done on the event loop, enable `-DLWS_WITH_SYS_ASYNC_DNS=1`
-at cmake to build it in.
-
-## Description
-
-The default libc name resolution is via libc `getaddrinfo()`, which is
-blocking, possibly for quite long periods (seconds).  If you are
-taking care about latency, but want to create outgoing connections,
-you can't tolerate this exception from the rule that everything in
-lws is nonblocking.
-
-Lws' asynchronous DNS resolver creates a caching name resolver
-that directly queries the configured nameserver itself over UDP,
-from the event loop.
-
-It supports both ipv4 / A records and ipv6 / AAAA records (see later
-for a description about how).  One server supported over UDP :53,
-and the nameserver is autodicovered on linux, windows, and freertos.
-    
-Other features
-
- - lws-style paranoid response parsing
- - random unique tid generation to increase difficulty of poisoning
- - it's really integrated with the lws event loop, it does not spawn
-   threads or use the libc resolver, and of course no blocking at all
- - platform-specific server address capturing (from /etc/resolv.conf
-   on linux, windows apis on windows)
- - LRU caching
- - piggybacking (multiple requests before the first completes go on
-    a list on the first request, not spawn multiple requests)
- - observes TTL in cache
- - TTL and timeout use `lws_sul` timers on the event loop
- - 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
-
-## Api
-
-If enabled at cmake, the async DNS implementation is used automatically
-for lws client connections.  It's also possible to call it directly, see
-the api-test-async-dns example for how.
-
-The Api follows that of `getaddrinfo()` but results are not created on
-the heap.  Instead a single, const cached copy of the addrinfo struct
-chain is reference-counted, with `lws_async_dns_freeaddrinfo()` provided
-to deduct from the reference count.  Cached items with a nonzero
-reference count can't be destroyed from the cache, so it's safe to keep
-a pointer to the results and iterate through them.
-
-## Dealing with IPv4 and IPv6
-
-DNS is a very old standard that has some quirks... one of them is that
-multiple queries are not supported in one packet, even though the protocol
-suggests it is.  This creates problems on ipv6 enabled systems, where
-it may prefer to have AAAA results, but the server may only have A records.
-
-To square the circle, for ipv4 only systems (`LWS_IPV6=0`) the resolver
-requests only A records.  For ipv6-capable systems, it always requests
-first A and then immediately afterwards AAAA records.
-
-To simplify the implementation, the tid b0 is used to differentiate
-between A (b0 = 0) and AAAA (b0 = 1) requests and responses using the
-same query body.
-
-The first response to come back is parsed, and a cache entry made...
-it leaves a note in the query about the address of the last `struct addrinfo`
-record.  When the second response comes, a second allocation is made,
-but not added to the logical cache... instead it's chained on to the
-first cache entry and the `struct addrinfo` linked-list from the
-first cache entry is extended into the second one.  At the time the
-second result arrives, the query is destroyed and the cached results
-provided on the result callback.
-
-## Recursion
-
-Where CNAMEs are returned, DNS servers may take two approaches... if the
-CNAME is also resolved by the same server and so it knows what it should
-resolve to, it may provide the CNAME resolution in the same response
-packet.
-
-In the case the CNAME is actually resolved by a different name server,
-the server with the CNAME does not have the information to hand to also
-resolve the CNAME in the same response.  So it just leaves it for the
-client to sort out.
-
-The lws implementation can deal with both of these, first it "recurses"
-(it does not recurse on the process stack but uses its own manual stack)
-to look for results in the same packet that told it about the CNAME.  If
-there are no results, it resets the query to look instead for the CNAME,
-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.
-
-

+ 0 - 77
Source/ThirdParty/libwebsockets/READMEs/README.build-android.md

@@ -1,77 +0,0 @@
-# Building for Android NDK
-
-If you have the ndk and prebuilt toolchains with that, you can simply build
-lws library for your android app from one cmake and one make command.
-
-However if you want a tls lib, you have to take care of building and pointing
-to that first.  But if it's a cmake project like mbedtls, that also is just a
-matter of one cmake and one make.
-
-## Installing NDK pieces
-
-There's probably a more direct way but the official way is install the whole
-Android Studio and then run `sdkmanager` to install a recent NDK.
-
-I installed the sdk and ndk pieces into /opt/android/ and that's how the
-`./contrib/cross-aarch64-android.cmake` toolchain file is shipped.  You can
-adapt some settings at the top of that file including the path if needed.
-
-## Fetching lws (needed first for cross toolchain file)
-
-It doesn't care where you put these projects, but for simplicity they should
-be in the same parent dir, like
-
-```
- - /home/someone
-  - /home/someone/libwebsockets
-  - /home/someone/mbedtls
-```
-
-The reason is that building mbedtls need the cross toolchain file from
-libwebsockets, that's also why we have to get libwebsockets first now but
-build it later.
-
-```
-$ git clone https://libwebsockets.org/repo/libwebsockets
-```
-
-## Building mbedtls
-
-```
-$ git clone https://github.com/ARMmbed/mbedtls.git
-$ cd mbedtls
-$ mkdir build
-$ cd build
-$ rm -f CMakeCache.txt && \
-  cmake .. -DCMAKE_TOOLCHAIN_FILE=../libwebsockets/contrib/cross-aarch64-android.cmake \
-  -DUSE_SHARED_MBEDTLS_LIBRARY=1 \
-  -DENABLE_PROGRAMS=0 \
-  -Wno-dev && \
-  make -j && \
-  cmake --install .
-```
-
-The lws toolchain file sets the path to install into as the cross root path, so
-despite it looks like the destination dir is missing for the install, it will
-go into, eg `/opt/android/ndk/21.1.6352462/platforms/android-24/arch-arm64/lib/libmbedcrypto.a`
-where lws will look for it
-
-## Building lws
-
-You don't need to explain where mbedtls can be found... lws will build with the
-same toolchain file that sets the cross root to the same place as mbedtls, it
-will easily find them there without any further hints.
-
-```
-$ mkdir build
-$ cd build
-$ rm -f CMakeCache.txt && \
-  cmake .. -DCMAKE_TOOLCHAIN_FILE=../libwebsockets/contrib/cross-aarch64-android.cmake \
-  -DLWS_WITH_MBEDTLS=1 \
-  -DLWS_WITHOUT_TESTAPPS=1 && \
-  make && \
-  cmake --install .
-```
-
-That's it, both mbedtls and lws library and header files are installed into the
-ndk cross root.

+ 0 - 214
Source/ThirdParty/libwebsockets/READMEs/README.build-windows.md

@@ -1,214 +0,0 @@
-# Some notes for the windows jungle
-
-This was how I compiled libwebsockets starting from a blank windows install
-in March - April 2020.  Doing this on a linux distro is way simpler and quicker
-than all this!
-
-## Notes on vm installation
-
-### Disk size
-
-For building you'll need 40GB+ available for the guest storage.
-
-### Required: Windows product key
-
-Assuming like me the first thing you do with a new laptop is install Linux over
-the windows it came with, you can recover your 'windows tax' windows product key
-from your device typically using `sudo strings /sys/firmware/acpi/tables/MSDM`,
-and use that for your VM install.
-
-### Required: Spice guest 
-
-To have shared clipboard, and for windows video driver to match your vm window
-resolution, you must install spice guest tools inside the windows VM.  It also
-installs some virtio pieces you will want.
-
-https://www.spice-space.org/download/windows/spice-guest-tools/spice-guest-tools-latest.exe
-
-### Blood-pressure reduction: Firefox
-
-https://www.mozilla.org/en-US/exp/firefox/
-
-When it's up, add-ons: ublock origin, privacy badger, noscript, disable search
-bar prediction
-
-### Blood-pressure reduction: Clink
-
-This is a hack on cmd.exe that lets it understand Ctrl-R and fixup unix-style
-slashes automagically.
-
-https://github.com/mridgers/clink/releases/download/0.4.9/clink_0.4.9_setup.exe
-
-If you're usually using *nix, you definitely need this to keep your sanity.
-
-### Required: cmake
-
-CMake have a windows installer thing downloadable from here
-
-[cmake](https://cmake.org/download/)
-
-after that you can use `cmake` from the terminal OK.
-
-### Required: git
-
-Visit the canonical git site to download their windows installer thing
-
-[git](https://git-scm.com/download/win)
-
-**Select the install option for "extra unix commands"** so you can get `ls -l`,
-`cp`, `mv` and suchlike working in cmd.exe... that's awesome, thanks git!
-
-Afterwards you can just use `git` as normal from cmd.exe as well.
-
-### Required: Install the "free" "community" visual studio
-
-You can do this through "windows store" by searching for "visual studio"
-
-I installed as little as possible, we just want the C "C++" tools... 7GB :-)
-
-It still wouldn't link without the "mt" helper tool from the
-huge windows SDK, so you have to install GB of that as well.
-
-They don't mention it during the install, but after 30 days this "free"
-"community" edition demands you open a microsoft account or it stops working.
-In the install they give you the option to add a microsoft account and the
-alternative is, "not now, maybe later".  Compare and contrast to gcc or git or
-the other FOSS projects.
-
-### Required: OpenSSL
-
-Ugh... I tried using prebuilts but it's unreliable and needs an unfeasible
-amount of trust.  So I recommend bite the bullet and build your own... that's
-trivial on Linux but of course windows makes everything nasty.
-
-At least hopefully all the "research" is done and listed out here.
-
-#### OpenSSL build Prerequisite: install perl binary
-
-Move the git version of perl out of the way, it won't work for OpenSSL build
-
-```
-mv /usr/bin/perl /usr/bin/perl-git
-```
-
-For windows, OpenSSL "recommends" ActiveState perl but it doesn't work for me,
-complaining about stuff needed from cpan and then dying when it was installed.
-"Strawberry Perl" is installed in `C:\Strawberry` and worked out the box.
-
-http://strawberryperl.com/download/5.30.2.1/strawberry-perl-5.30.2.1-64bit.msi
-
-The installer sets up `%PATH%` if you open a new cmd window.  
-
-#### OpenSSL build Prerequisite: NASM
-
-Go here and click on the latest stable, download the win32 .exe
-
-https://nasm.us/
-
-Just install via the defaults.  Then add it to the PATH temporarily...
-
-```
-$ set PATH=%PATH%;C:\Program Files (x86)\NASM
-```
-
-#### OpenSSL build setup: source VC env vars
-
-These fix up the PATH and include dirs etc necessary for VC build in the cmd
-window.
-
-```
-$ call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x86_amd64
-```
-
-### OpenSSL build:
-
-Grab openssl from git... assuming the prerequisites above went well it will
-just sit there building for 30 minutes or whatever.
-
-```
-$ git clone https://github.com/openssl/openssl
-$ cd openssl
-$ perl Configure VC-WIN64A
-$ nmake
-```
-
-Afterwards, open an Administrator mode cmd.exe, redo the msvc path and then
-install the build.
-
-```
-$ cd openssl
-$ call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x86_amd64
-$ nmake install
-```
-
-Oh another grindingly slow windows build action.  Finally it's in there in
-`C:\Program Files\OpenSSL`.
-
-libraries are looking for a cert bundle at "C:\Program Files\Common Files\SSL\cert.pem"...
-it's not documented or included in the zip file from the above, so...
-
-#### Installing a cert bundle
-
-You can get a trusted cert bundle from here
-
-[drwetter/testssl cert bundle](https://raw.githubusercontent.com/drwetter/testssl.sh/3.1dev/etc/Microsoft.pem)
-
-Save it into `C:\Program Files\Common Files\SSL\cert.pem` where openssl will be able to see it.
-
-## Required: pthreads
-
-It's amazing but after all these years windows doesn't offer pthreads compatibility
-itself.  Just like the many other missing POSIX bits like fork().
-
-I downloaded the latest (2012) zip release of pthreads-win32 from here
-
-ftp://sourceware.org/pub/pthreads-win32
-
-Then I created a dir "C:\Program Files (x86)\pthreads", and copied the `dll`,
-`include` and `lib` subdirs from the `prebuilt` folder in the zip there.
-
-The cmake incantation to build against pthreads set up like that is
-
-```
- $ cmake .. -DLWS_HAVE_PTHREAD_H=1 -DLWS_EXT_PTHREAD_INCLUDE_DIR="C:\Program Files (x86)\pthreads\include" -DLWS_EXT_PTHREAD_LIBRARIES="C:\Program Files (x86)\pthreads\lib\x64\libpthreadGC2.a" -DLWS_WITH_MINIMAL_EXAMPLES=1
-```
-
-## Building libwebsockets
-
-We'll clone libwebsockets then use cmake to build via vs tools
-
-```
-> git clone https://libwebsockets.org/repo/libwebsockets
-> cd libwebsockets
-> mkdir build
-> cd build
-> cmake ..
-> cmake --build . --config DEBUG
-```
-
-Installing requires admin privs, I opened a second cmd window as admin and did it
-there.
-
-```
-> cmake --install . --config DEBUG
-```
-
-### Hack the libs into view
-
-The libs we built against aren't visible in the system, I don't know what
-Real Windows Programmers are supposed to do about that, but I used an Admin cmd
-prompt to copy them into C:\windows\system32
-
-```
-$ cp "C:\Program Files (x86)\pthreads\dll\x64\pthreadGC2.dll" "C:\Program Files\OpenSSL\bin\libcrypto-3.dll"  "C:\Program Files\OpenSSL\bin\libssl-3.dll" C:\Windows\system32
-```
-
-After that you can run the test apps OK, eg
-
-```
-$ libwebsockets-test-server.exe -s
-```
-
-## Note about using paths with spaces in with cmake
-
-

+ 0 - 741
Source/ThirdParty/libwebsockets/READMEs/README.build.md

@@ -1,741 +0,0 @@
-Notes about building lws
-========================
-
-You can download and install lws using the [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager:
-```
-git clone https://github.com/microsoft/vcpkg.git
-cd vcpkg
-./bootstrap-vcpkg.sh
-./vcpkg integrate install
-vcpkg install libwebsockets
-```
-The 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.
-
-@section cm Introduction to CMake
-
-CMake is a multi-platform build tool that can generate build files for many
-different target platforms. See more info at http://www.cmake.org
-
-CMake also allows/recommends you to do "out of source"-builds, that is,
-the build files are separated from your sources, so there is no need to
-create elaborate clean scripts to get a clean source tree, instead you
-simply remove your build directory.
-
-Libwebsockets has been tested to build successfully on the following platforms
-with SSL support (for OpenSSL/wolfSSL/BoringSSL):
-
-- Windows (Visual Studio)
-- Windows (MinGW)
-- Linux (x86 and ARM)
-- OSX
-- NetBSD
-
-
-@section build1 Building the library and test apps
-
-The project settings used by CMake to generate the platform specific build
-files is called [CMakeLists.txt](../CMakeLists.txt). CMake then uses one of its "Generators" to
-output a Visual Studio project or Make file for instance. To see a list of
-the available generators for your platform, simply run the "cmake" command.
-
-Note that by default OpenSSL will be linked, if you don't want SSL support
-see below on how to toggle compile options.
-
-
-@section bu Building on Unix:
-
-1. Install CMake 2.8 or greater: http://cmake.org/cmake/resources/software.html
-   (Most Unix distributions comes with a packaged version also)
-
-2. Install OpenSSL.
-
-3. Generate the build files (default is Make files):
-```
-        $ cd /path/to/src
-        $ mkdir build
-        $ cd build
-        $ cmake ..
-```
-
-4. Finally you can build using the generated Makefile:
-```
-    $ make && sudo make install
-```
-**NOTE**: The `build/`` directory can have any name and be located anywhere
- on your filesystem, and that the argument `..` given to cmake is simply
- the source directory of **libwebsockets** containing the [CMakeLists.txt](../CMakeLists.txt)
- project file. All examples in this file assumes you use ".."
-
-**NOTE2**:
-A common option you may want to give is to set the install path, same
-as --prefix= with autotools.  It defaults to /usr/local.
-You can do this by, eg
-```
-    $ cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr .
-```
-
-**NOTE3**:
-On machines that want libraries in lib64, you can also add the
-following to the cmake line
-```
-    -DLIB_SUFFIX=64
-```
-
-**NOTE4**:
-If you are building against a non-distro OpenSSL (eg, in order to get
-access to ALPN support only in newer OpenSSL versions) the nice way to
-express that in one cmake command is eg,
-```
-    $ cmake .. -DOPENSSL_ROOT_DIR=/usr/local/ssl \
-         -DCMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE=/usr/local/ssl \
-         -DLWS_WITH_HTTP2=1
-```
-
-When you run the test apps using non-distro SSL, you have to force them
-to use your libs, not the distro ones
-```
-    $ LD_LIBRARY_PATH=/usr/local/ssl/lib libwebsockets-test-server --ssl
-```
-
-To get it to build on latest openssl (2016-04-10) it needed this approach
-```
-    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"
-```
-
-Mac users have reported
-
-```
- $ export OPENSSL_ROOT_DIR=/usr/local/Cellar/openssl/1.0.2k; cmake ..; make -j4
-```
-
-worked for them when using "homebrew" OpenSSL
-
-**NOTE5**:
-To build with debug info and _DEBUG for lower priority debug messages
-compiled in, use
-```
-    $ cmake .. -DCMAKE_BUILD_TYPE=DEBUG
-```
-
-**NOTE6**
-To build on Solaris the linker needs to be informed to use lib socket
-and libnsl, and only builds in 64bit mode.
-
-```bash
-    $ cmake .. -DCMAKE_C_FLAGS=-m64 -DCMAKE_EXE_LINKER_FLAGS="-lsocket -lnsl"
-```
-
-**NOTE7**
-
-Build and test flow against boringssl.  Notice `LWS_WITH_GENHASH` is currently
-unavailable with boringssl due to their removing the necessary apis.
-
-Build current HEAD boringssl
-
-```
- $ cd /projects
- $ git clone https://boringssl.googlesource.com/boringssl
- $ cd boringssl
- $ mkdir build
- $ cd build
- $ cmake ..  -DBUILD_SHARED_LIBS=1
- $ make -j8
-```
-
-Build and test lws against it
-
-```
- $ cd /projects/libwebsockets/build
- $ cmake .. -DOPENSSL_LIBRARIES="/projects/boringssl/build/ssl/libssl.so;\
-   /projects/boringssl/build/crypto/libcrypto.so" \
-   -DOPENSSL_INCLUDE_DIRS=/projects/boringssl/include \
-   -DLWS_WITH_BORINGSSL=1 -DCMAKE_BUILD_TYPE=DEBUG
- $ make -j8 && sudo make install
- $ LD_PRELOAD="/projects/boringssl/build/ssl/libssl.so \
-   /projects/boringssl/build/crypto/libcrypto.so" \
-   /usr/local/bin/libwebsockets-test-server -s
-```
-
-4. Finally you can build using the generated Makefile:
-
-```bash
-    $ make
- ```
-
-@section lcap Linux Capabilities
-
-On Linux, lws now lets you retain selected root capabilities when dropping
-privileges.  If libcap-dev or similar package is installed providing
-sys/capabilities.h, and libcap or similar package is installed providing
-libcap.so, CMake will enable the capability features.
-
-The context creation info struct .caps[] and .count_caps members can then
-be set by user code to enable selected root capabilities to survive the
-transition to running under an unprivileged user.
-
-@section cmq Quirk of cmake
-
-When changing cmake options, for some reason the only way to get it to see the
-changes sometimes is delete the contents of your build directory and do the
-cmake from scratch.
-
-deleting build/CMakeCache.txt may be enough.
-
-
-@section cmw Building on Windows (Visual Studio)
-
-1. Install CMake 2.6 or greater: http://cmake.org/cmake/resources/software.html
-
-2. Install OpenSSL binaries. https://wiki.openssl.org/index.php/Binaries
-
-   (**NOTE**: Preferably in the default location to make it easier for CMake to find them)
-
-   **NOTE2**: 
-   Be sure that OPENSSL_CONF environment variable is defined and points at 
-   <OpenSSL install location>\bin\openssl.cfg
-
-3. Generate the Visual studio project by opening the Visual Studio cmd prompt:
-
-```
-    cd <path to src>
-    md build
-    cd build
-    cmake -G "Visual Studio 10" ..
-```
-
-   (**NOTE**: There is also a cmake-gui available on Windows if you prefer that)
-   
-   **NOTE2**:
-   See this link to find out the version number corresponding to your Visual Studio edition:
-   http://superuser.com/a/194065
-
-4. Now you should have a generated Visual Studio Solution in  your
-   `<path to src>/build` directory, which can be used to build.
-
-5. Some additional deps may be needed
-
- - iphlpapi.lib
- - psapi.lib
- - userenv.lib
-
-6. If you're using libuv, you must make sure to compile libuv with the same multithread-dll / Mtd attributes as libwebsockets itself
-
-
-@section cmwmgw Building on Windows (MinGW)
-
-1. Install MinGW
-
-    For Fedora, it's, eg, `dnf install mingw64-gcc`
-
-2. Install current CMake package
-
-    For Fedora, it's `dnf install cmake`
-
-3. Instal mingw-built OpenSSL pieces
-
-    For Fedora, it's `mingw64-openssl.noarch mingw64-openssl-static.noarch`
-
-    mingw64-cmake as described below will auto-find the libs and includes
-    for build.  But to execute the apps, they either need to go into the same
-    `/usr/x86_64-w64-mingw32/sys-root/mingw/bin/` as the dlls are installed to,
-    or the dlls have to be copied into the same dir as your app executable.
-
-4. Generate the build files (default is Make files) using MSYS shell.
-
-   For Fedora, they provide a `mingw64-cmake` wrapper in the package
-   `mingw64-filesystem`, with this you can run that instead of cmake directly
-   and don't have to get involved with setting the cmake generator.
-
-   Otherwise doing it by hand is like this:
-
-```
-    $ cd /drive/path/to/src
-    $ mkdir build
-    $ cd build
-    $ cmake -G "MSYS Makefiles" -DCMAKE_INSTALL_PREFIX=C:/MinGW ..
-```
-
-   To generate build files allowing to create libwebsockets binaries with debug information
-   set the CMAKE_BUILD_TYPE flag to DEBUG:
-```
-    $ cmake -G "MSYS Makefiles" -DCMAKE_INSTALL_PREFIX=C:/MinGW -DCMAKE_BUILD_TYPE=DEBUG ..
-```
-5. Finally you can build using the generated Makefile and get the results deployed into your MinGW installation:
-
-```
-    $ make && make install
-```
-
-@section distro Selecting CMake options useful for distros
-
-Distro packagers should select the CMake option "LWS_WITH_DISTRO_RECOMMENDED",
-which selects common additional options like support for various event libraries,
-plugins and lwsws.
-
-@section ssllib Choosing Your TLS Poison
-
- - If you are really restricted on memory, code size, or don't care about TLS
-   speed, mbedTLS is a good choice: `cmake .. -DLWS_WITH_MBEDTLS=1`
- 
- - If cpu and memory is not super restricted and you care about TLS speed,
-   OpenSSL or a directly compatible variant like Boring SSL is a good choice.
- 
-Just building lws against stock Fedora OpenSSL or stock Fedora mbedTLS, for
-SSL handhake mbedTLS takes ~36ms and OpenSSL takes ~1ms on the same x86_64
-build machine here, with everything else the same.  Over the 144 connections of
-h2spec compliance testing for example, this ends up completing in 400ms for
-OpenSSL and 5.5sec for mbedTLS on x86_64.  In other words mbedTLS is very slow
-compared to OpenSSL under the (fairly typical) conditions I tested it.
-
-This isn't an inefficiency in the mbedtls interface implementation, it's just
-mbedTLS doing the crypto much slower than OpenSSL, which has accelerated
-versions of common crypto operations it automatically uses for platforms
-supporting it.  As of Oct 2017 mbedTLS itself has no such optimizations for any
-platform that I could find.  It's just pure C running on the CPU.
-
-Lws supports both almost the same, so instead of taking my word for it you are
-invited to try it both ways and see which the results (including, eg, binary
-size and memory usage as well as speed) suggest you use.
-
-NOTE: one major difference with mbedTLS is it does not load the system trust
-store by default.  That has advantages and disadvantages, but the disadvantage
-is you must provide the CA cert to lws built against mbedTLS for it to be able
-to validate it, ie, use -A with the test client.  The minimal test clients
-have the CA cert for warmcat.com and libwebsockets.org and use it if they see
-they were built with mbedTLS.
-
-@section optee Building for OP-TEE
-
-OP-TEE is a "Secure World" Trusted Execution Environment.
-
-Although lws is only part of the necessary picture to have an https-enabled
-TA, it does support OP-TEE as a platform and if you provide the other
-pieces, does work very well.
-
-Select it in cmake with `-DLWS_PLAT_OPTEE=1`
-
-
-@section cmco Setting compile options
-
-To set compile time flags you can either use one of the CMake gui applications
-or do it via the command line.
-
-@subsection cmcocl Command line
-
-To list available options (omit the H if you don't want the help text):
-
-    cmake -LH ..
-
-Then to set an option and build (for example turn off SSL support):
-
-    cmake -DLWS_WITH_SSL=0 ..
-or
-    cmake -DLWS_WITH_SSL:BOOL=OFF ..
-
-@subsection cmcoug Unix GUI
-
-If you have a curses-enabled build you simply type:
-(not all packages include this, my debian install does not for example).
-
-    ccmake
-
-@subsection cmcowg Windows GUI
-
-On windows CMake comes with a gui application:
-    Start -> Programs -> CMake -> CMake (cmake-gui)
-
-
-@section wolf wolfSSL/CyaSSL replacement for OpenSSL
-
-wolfSSL/CyaSSL is a lightweight SSL library targeted at embedded systems:
-https://www.wolfssl.com/wolfSSL/Products-wolfssl.html
-
-It contains a OpenSSL compatibility layer which makes it possible to pretty
-much link to it instead of OpenSSL, giving a much smaller footprint.
-
-**NOTE**: wolfssl needs to be compiled using the `--enable-opensslextra` flag for
-this to work.
-
-@section wolf1 Compiling libwebsockets with wolfSSL
-
-```
-    cmake .. -DLWS_WITH_WOLFSSL=1 \
-         -DLWS_WOLFSSL_INCLUDE_DIRS=/path/to/wolfssl \
-         -DLWS_WOLFSSL_LIBRARIES=/path/to/wolfssl/wolfssl.a ..
-```
-
-**NOTE**: On windows use the .lib file extension for `LWS_WOLFSSL_LIBRARIES` instead.
-
-@section cya Compiling libwebsockets with CyaSSL
-
-```
-    cmake .. -DLWS_WITH_CYASSL=1 \
-         -DLWS_CYASSL_INCLUDE_DIRS=/path/to/cyassl \
-         -DLWS_CYASSL_LIBRARIES=/path/to/wolfssl/cyassl.a ..
-```
-
-**NOTE**: On windows use the .lib file extension for `LWS_CYASSL_LIBRARIES` instead.
-
-@section gzip Selecting GZIP or MINIZ
-
-By default lws supports gzip when compression is needed.  But you can tell it to use
-MINIZ instead by using `-DLWS_WITH_MINIZ=1`.
-
-For native build cmake will try to find an existing libminiz.so or .a and build
-against that and the found includes automatically.
-
-For cross-build or building against local miniz, you need the following kind of
-cmake to tell it where to get miniz
-
-```
-cmake .. -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  
-```
-
-@section esp32 Building for ESP32
-
-Building for ESP32 requires the ESP-IDF framework. It can be built under Linux, OSX or Windows (MSYS2).
-
-1. Install ESP-IDF, follow the getting started guide here - http://esp-idf.readthedocs.io/en/latest/get-started/
-2. Set ESP-IDF to last known working version (assuming ESP-IDF is in `~/esp/esp-idf`) :
-```
-    cd ~/esp/esp-idf
-    git checkout 0c50b65a34cd6b3954f7435193411a88adb49cb0
-    git submodule update --recursive
-```
-3. Add `libwebsockets` as a submodule in the `components` folder of your ESP-IDF project:
-```
-    git submodule add https://github.com/warmcat/libwebsockets.git components/libwebsockets
-```
-4. If on Windows (MSYS2) you will need to install CMake in the MSYS2 environment:
-```
-    pacman -S mingw-w64-i686-cmake
-```
-If you're on Linux or OSX ensure CMake version is at least 3.7.
-
-@section extplugins Building plugins outside of lws itself
-
-The directory ./plugin-standalone/ shows how easy it is to create plugins
-outside of lws itself.  First build lws itself with -DLWS_WITH_PLUGINS,
-then use the same flow to build the standalone plugin
-```
-    cd ./plugin-standalone
-    mkdir build
-    cd build
-    cmake ..
-    make && sudo make install
-```
-
-if you changed the default plugin directory when you built lws, you must
-also give the same arguments to cmake here (eg,
-` -DCMAKE_INSTALL_PREFIX:PATH=/usr/something/else...` )
-
-Otherwise if you run lwsws or libwebsockets-test-server-v2.0, it will now
-find the additional plugin "libprotocol_example_standalone.so"
-```
-    lwsts[21257]:   Plugins:
-    lwsts[21257]:    libprotocol_dumb_increment.so
-    lwsts[21257]:    libprotocol_example_standalone.so
-    lwsts[21257]:    libprotocol_lws_mirror.so
-    lwsts[21257]:    libprotocol_lws_server_status.so
-    lwsts[21257]:    libprotocol_lws_status.so
-```
-If you have multiple vhosts, you must enable plugins at the vhost
-additionally, discovered plugins are not enabled automatically for security
-reasons.  You do this using info->pvo or for lwsws, in the JSON config.
-
-
-@section http2rp Reproducing HTTP/2 tests
-
-Enable `-DLWS_WITH_HTTP2=1` in cmake to build with http/2 support enabled.
-
-You must have built and be running lws against a version of openssl that has
-ALPN.  At the time of writing, recent distros have started upgrading to OpenSSL
-1.1+ that supports this already.  You'll know it's right by seeing
-
-```
-    lwsts[4752]:  Compiled with OpenSSL support
-    lwsts[4752]:  Using SSL mode
-    lwsts[4752]:  HTTP2 / ALPN enabled
-```
-at lws startup.
-
-Recent Firefox and Chrome also support HTTP/2 by ALPN, so these should just work
-with the test server running in -s / ssl mode.
-
-For testing with nghttp client:
-
-```
-    $ nghttp -nvas https://localhost:7681/test.html
-```
-
-Testing with h2spec (https://github.com/summerwind/h2spec)
-
-```
-        $ h2spec  -h 127.0.0.1 -p 7681 -t -k -v -o 1
-```
-
-```
-145 tests, 145 passed, 0 skipped, 0 failed
-
-```
-
-@section coverage Automated Coverage Testing
-
-./test-apps/attack.sh contains scripted tests that are the basis
-of the automated test coverage assessment available for gcc and clang.
-
-To reproduce
-
- $ cd build
- $ cmake .. -DLWS_WITH_GCOV=1 -DCMAKE_BUILD_TYPE=DEBUG
- $ ../scripts/build-gcov.sh
- $ ../test-apps/attack.sh
- $ ../scripts/gcov.sh
-...
-Lines executed:51.24% of 8279
-
-@section windowsprebuilt Using Windows binary builds on Appveyor
-
-The CI builds on Appveyor now produce usable binary outputs.  Visit
-
-[lws on Appveyor](https://ci.appveyor.com/project/lws-team/libwebsockets)
-
-and select one of the builds, then click on ARTIFACTS at the top right.  The zip file
-want 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
-
-@section cross Cross compiling
-
-To enable cross-compiling **libwebsockets** using CMake you need to create
-a "Toolchain file" that you supply to CMake when generating your build files.
-CMake will then use the cross compilers and build paths specified in this file
-to look for dependencies and such.
-
-**Libwebsockets** includes an example toolchain file [cross-arm-linux-gnueabihf.cmake](../contrib/cross-arm-linux-gnueabihf.cmake)
-you can use as a starting point.
-
-The commandline to configure for cross with this would look like
-```
-    $ cmake .. -DCMAKE_INSTALL_PREFIX:PATH=/usr/lib/my-cross-root \
-         -DCMAKE_TOOLCHAIN_FILE=../contrib/cross-arm-linux-gnueabihf.cmake \
-         -DLWS_WITHOUT_EXTENSIONS=1 -DLWS_WITH_SSL=0 \
-         -DLWS_WITH_ZIP_FOPS=0 -DLWS_WITH_ZLIB=0
-```
-The example shows how to build with no external cross lib dependencies, you
-need to provide the cross libraries otherwise.
-
-**NOTE**: start from an EMPTY build directory if you had a non-cross build in there
-    before the settings will be cached and your changes ignored.
-    Delete `build/CMakeCache.txt` at least before trying a new cmake config
-    to ensure you are really building the options you think you are.
-
-Additional information on cross compilation with CMake:
-    http://www.vtk.org/Wiki/CMake_Cross_Compiling
-
-@section cross_example Complex Cross compiling example
-
-Here are step by step instructions for cross-building the external projects needed for lws with lwsws + mbedtls as an example.
-
-In 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.
-
-Likewise I do all this in /tmp but it has no special meaning, you can adapt that to somewhere else.
-
-All "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/]....
-
-## Prepare the cmake toolchain file
-
-1) `cd /tmp`
-
-2) `wget -O mytoolchainfile https://raw.githubusercontent.com/warmcat/libwebsockets/master/contrib/cross-arm-linux-gnueabihf.cmake` 
-
-3) 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:
-
-```
-set(CROSS_PATH /projects/aist-tb/arm-tc/)
-set(CMAKE_C_COMPILER "${CROSS_PATH}/bin/arm-linux-gnueabihf-gcc")
-set(CMAKE_CXX_COMPILER "${CROSS_PATH}/bin/arm-linux-gnueabihf-g++")
-```
-
-## 1/4: Building libuv cross:
-
-1) `export PATH=/projects/aist-tb/arm-tc/bin:$PATH`  Notice there is a **/bin** on the end of the toolchain path
-
-2) `cd /tmp ; mkdir cross` we will put the cross-built libs in /tmp/cross
-
-3) `git clone https://github.com/libuv/libuv.git` get libuv
-
-4) `cd libuv`
-
-5) `./autogen.sh`
-
-```
-+ libtoolize --copy
-libtoolize: putting auxiliary files in '.'.
-libtoolize: copying file './ltmain.sh'
-libtoolize: putting macros in AC_CONFIG_MACRO_DIRS, 'm4'.
-libtoolize: copying file 'm4/libtool.m4'
-libtoolize: copying file 'm4/ltoptions.m4'
-libtoolize: copying file 'm4/ltsugar.m4'
-libtoolize: copying file 'm4/ltversion.m4'
-libtoolize: copying file 'm4/lt~obsolete.m4'
-+ aclocal -I m4
-+ autoconf
-+ automake --add-missing --copy
-configure.ac:38: installing './ar-lib'
-configure.ac:25: installing './compile'
-configure.ac:22: installing './config.guess'
-configure.ac:22: installing './config.sub'
-configure.ac:21: installing './install-sh'
-configure.ac:21: installing './missing'
-Makefile.am: installing './depcomp'
-```
-If it has problems, you will need to install `automake`, `libtool` etc.
-
-6) `./configure  --host=arm-linux-gnueabihf --prefix=/tmp/cross`
-
-7) `make && make install` this will install to `/tmp/cross/...`
-
-8) `file /tmp/cross/lib/libuv.so.1.0.0`  Check it's really built for ARM
-```
-/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
-```
-
-## 2/4: Building zlib cross
-
-1) `cd /tmp`
-
-2) `git clone https://github.com/madler/zlib.git`
-
-3) `CC=arm-linux-gnueabihf-gcc ./configure --prefix=/tmp/cross`
-```
-Checking for shared library support...
-Building shared library libz.so.1.2.11 with arm-linux-gnueabihf-gcc.
-Checking for size_t... Yes.
-Checking for off64_t... Yes.
-Checking for fseeko... Yes.
-Checking for strerror... Yes.
-Checking for unistd.h... Yes.
-Checking for stdarg.h... Yes.
-Checking whether to use vs[n]printf() or s[n]printf()... using vs[n]printf().
-Checking for vsnprintf() in stdio.h... Yes.
-Checking for return value of vsnprintf()... Yes.
-Checking for attribute(visibility) support... Yes.
-```
-
-4)  `make && make install`
-```
-arm-linux-gnueabihf-gcc -O3 -D_LARGEFILE64_SOURCE=1 -DHAVE_HIDDEN -I. -c -o example.o test/example.c
-...
-rm -f /tmp/cross/include/zlib.h /tmp/cross/include/zconf.h
-cp zlib.h zconf.h /tmp/cross/include
-chmod 644 /tmp/cross/include/zlib.h /tmp/cross/include/zconf.h
-```
-
-5) `file /tmp/cross/lib/libz.so.1.2.11`  This is just to confirm we built an ARM lib as expected
-```
-/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
-```
-
-## 3/4: Building mbedtls cross
-
-1) `cd /tmp`
-
-2) `git clone https://github.com/ARMmbed/mbedtls.git`
-
-3) `cd mbedtls ; mkdir build ; cd build`
-
-3) `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.
-
-4) `make && make install`
-
-5) `file /tmp/cross/lib/libmbedcrypto.so.2.6.0`
-```
-/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
-```
-
-## 4/4: Building libwebsockets with everything
-
-1) `cd /tmp`
-
-2) `git clone ssh://[email protected]/warmcat/libwebsockets`
-
-3) `cd libwebsockets ; mkdir build ; cd build`
-
-4)  (this is all one line on the commandline)
-```
-cmake .. -DCMAKE_TOOLCHAIN_FILE=/tmp/mytoolchainfile \
--DCMAKE_INSTALL_PREFIX:PATH=/tmp/cross \
--DLWS_WITH_LWSWS=1 \
--DLWS_WITH_MBEDTLS=1 \
--DLWS_MBEDTLS_LIBRARIES="/tmp/cross/lib/libmbedcrypto.so;/tmp/cross/lib/libmbedtls.so;/tmp/cross/lib/libmbedx509.so" \
--DLWS_MBEDTLS_INCLUDE_DIRS=/tmp/cross/include \
--DLWS_LIBUV_LIBRARIES=/tmp/cross/lib/libuv.so \
--DLWS_LIBUV_INCLUDE_DIRS=/tmp/cross/include \
--DLWS_ZLIB_LIBRARIES=/tmp/cross/lib/libz.so \
--DLWS_ZLIB_INCLUDE_DIRS=/tmp/cross/include
-```
-
-3) `make && make install`
-
-4) `file /tmp/cross/lib/libwebsockets.so.11`
-```
-/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
-```
-
-5) `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)
-```
-  NEEDED               libz.so.1
-  NEEDED               libmbedcrypto.so.0
-  NEEDED               libmbedtls.so.10
-  NEEDED               libmbedx509.so.0
-  NEEDED               libuv.so.1
-  NEEDED               libm.so.6
-  NEEDED               libc.so.6
-```
-
-You 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.
-
-@section mem Memory efficiency
-
-Embedded server-only configuration without extensions (ie, no compression
-on websocket connections), but with full v13 websocket features and http
-server, built on ARM Cortex-A9:
-
-Update at 8dac94d (2013-02-18)
-```
-    $ ./configure --without-client --without-extensions --disable-debug --without-daemonize
-
-    Context Creation, 1024 fd limit[2]:   16720 (includes 12 bytes per fd)
-    Per-connection [3]:                      72 bytes, +1328 during headers
-
-    .text	.rodata	.data	.bss
-    11512	2784	288	4
-```
-This shows the impact of the major configuration with/without options at
-13ba5bbc633ea962d46d using Ubuntu ARM on a PandaBoard ES.
-
-These are accounting for static allocations from the library elf, there are
-additional dynamic allocations via malloc.  These are a bit old now but give
-the right idea for relative "expense" of features.
-
-Static allocations, ARM9
-
-|                                | .text   | .rodata | .data | .bss |
-|--------------------------------|---------|---------|-------|------|
-| All (no without)               | 35024   | 9940    | 336   | 4104 |
-| without client                 | 25684   | 7144    | 336   | 4104 |
-| without client, exts           | 21652   | 6288    | 288   | 4104 |
-| without client, exts, debug[1] | 19756   | 3768    | 288   | 4104 |
-| without server                 | 30304   | 8160    | 336   | 4104 |
-| without server, exts           | 25382   | 7204    | 288   | 4104 |
-| without server, exts, debug[1] | 23712   | 4256    | 288   | 4104 |
-
-[1] `--disable-debug` only removes messages below `lwsl_notice`.  Since that is
-the default logging level the impact is not noticeable, error, warn and notice
-logs are all still there.
-
-[2] `1024` fd per process is the default limit (set by ulimit) in at least Fedora
-and Ubuntu.  You can make significant savings tailoring this to actual expected
-peak fds, ie, at a limit of `20`, context creation allocation reduces to `4432 +
-240 = 4672`)
-
-[3] known header content is freed after connection establishment

+ 0 - 88
Source/ThirdParty/libwebsockets/READMEs/README.captive-portal-detection.md

@@ -1,88 +0,0 @@
-# Captive Portal Detection
-
-## Background
-
-Wifi devices may face some interception of their connection to the
-internet, it's very common for, eg, coffee shop wifi to present some
-kind of login or other clickthrough before access to the Internet is
-granted.  Devices may need to understand that they are in this
-situation, and there are several different techniques for trying to
-gague it.
-
-Sequence-wise the device has been granted a DHCP lease and has been
-configured with DNS, but the DNS may be wrongly resolving everything
-to an address on the LAN or a portal on the net.
-
-Whether there is a captive portal active should be a sticky state for a given
-connection if there is not going to be any attempt to login or pass the landing
-page, it only needs checking for after DHCP acquisition then.  If there will be
-an attempt to satisfy the landing page, the test should be repeated after the
-attempt.
-
-## Detection schemes
-
-The most popular detection scheme by numbers is Android's method,
-which is to make an HTTP client GET to `http://connectivitycheck.android.com/generate_204`
-and see if a 204 is coming back... if intercepted, typically there'll be a
-3xx redirect to the portal, perhaps on https.  Or, it may reply on http with
-a 200 and show the portal directly... either way it won't deliver a 204
-like the real remote server does.
-
-Variations include expecting a 200 but with specific http body content, and
-doing a DNS lookup for a static IP that the device knows; if it's resolved to
-something else, it knows there's monkey business implying a captive portal.
-
-Other schemes involve https connections going out and detecting that the cert
-of the server it's actually talking to doesn't check out, although this is
-potentially ambiguous.
-
-Yet more methods are possible outside of tcp or http.
-
-## lws captive portal detect support
-
-lws provides a generic api to start captive portal detection...
-
-```
-LWS_EXTERN LWS_VISIBLE int
-lws_system_cpd_start(struct lws_context *context);
-```
-
-and two states in `lws_system` states to trigger it from, either
-`LWS_SYSTATE_CPD_PRE_TIME` which happens after DHCP acquisition but before
-ntpclient and is suitable for non https-based scheme where the time doesn't
-need to be known, or the alternative `LWS_SYSTATE_CPD_POST_TIME` state which
-happens after ntpclient has completed and we know the time.
-
-The actual platform implementation is set using `lws_system_ops_t` function
-pointer `captive_portal_detect_request`, ie
-
-```
-	int (*captive_portal_detect_request)(struct lws_context *context);
-	/**< Check if we can go out on the internet cleanly, or if we are being
-	 * redirected or intercepted by a captive portal.
-	 * Start the check that proceeds asynchronously, and report the results
-	 * by calling lws_captive_portal_detect_result() api
-	 */
-```
-
-User platform code can provide this to implement whatever scheme they want, when
-it has arrived at a result, it can call the lws api `lws_system_cpd_result()` to
-inform lws.  If there isn't any captive portal, this will also try to advance the
-system state towards OPERATIONAL.
-
-```
-/**
- * lws_system_cpd_result() - report the result of the captive portal detection
- *
- * \param context: the lws_context
- * \param result: one of the LWS_CPD_ constants representing captive portal state
- * \param redirect_url: NULL, or the url we were redirected to if result is
- *     LWS_CPD_HTTP_REDIRECT
- *
- * Sets the context's captive portal detection state to result.  User captive
- * portal detection code would call this once it had a result from its test.
- */
-LWS_EXTERN LWS_VISIBLE int
-lws_system_cpd_result(struct lws_context *context, int result, const char *redirect_url);
-```
-

+ 0 - 29
Source/ThirdParty/libwebsockets/READMEs/README.ci.md

@@ -1,29 +0,0 @@
-## Need for CI
-
-Generally if we're adding something that's supposed to work ongoing, the stuff
-should be exercised in CI (at least Travis).
-
-If there are few users for a particular feature, experience has shown that
-refactors or other upheaval can easily break it into a state of uselessness
-without anyone noticing until later.
-
-Therefore here's a description of how to add something to the CI tests... this
-is certainly a nonproductive PITA and I have never been thanked for the work
-involved.  But if the promise of the various features working is going to
-remain alive, it's necessary to include CI test where possible with new
-nontrivial code.
-
-## Integration points
-
-### cmake
-
-`.travis.yml` maps the various test activities to CMake options needed.
-
-### including dependent packages into travis
-
-See `./scripts/travis_install.sh`
-
-### performing prepared test actions
-
-See `./scripts/travis_control.sh`
-

+ 0 - 41
Source/ThirdParty/libwebsockets/READMEs/README.cmake.md

@@ -1,41 +0,0 @@
-# Tips about CMake
-
-## Don't be afraid to nuke your build dir
-
-CMake likes to cache options and other things in the build dir... if you stop
-asserting the state of something like `-DMY_OPTION=1`, then the last way it was
-set it cached.  On order to keep track of what you have set and not set, it's
-very advisable to explicitly keep all your options and set them all on one cmake
-line.
-
-Then, when you meet a situation you changed something but somehow cmake is
-sticking with what it knew before, you can fearlessly delete your build dir
-and create a new one with your explicit config.
-
-On Linux, it's usually enough to delete `CMakeCache.txt` to trigger it to config
-from the start again, but on, eg, windows, it isn't, for whatever reason it
-literally needs the build dir removing.
-
-## CMake presence tests that fail
-
-Lws makes use of various CMake features to figure out what apis your libraries
-offer, eg, OpenSSL has many different apis based on version, lws knows how to
-work around most of the changes, but to do it it must find out what apis are
-available first on your build environment.
-
-CMake basically builds little throwaway test programs using each api in turn, and
-if it builds, it understands that the api was available and sets a preprocessor
-symbol that's available in the main build accordingly.  Then we can do `#if xxx`
-to figure out if we can use `xxx` or need to do a workaround at build-time.
-
-This works very well, but unfortunately if the program didn't build, there are
-many possible ways for the build to break even if the api being tested is
-really available... for example, some library in your toolchain isn't being
-linked for the throwaway test program.
-
-When this happens, cmake indicates that apis that must be available are not available...
-CMake keeps a log of what happened with the failed test programs in
-`./build/CMakeFiles/CMakeError.log`.  This is appeneded to, so the best way is blow
-away the build dir and reconfig a new one from scratch, and go look in there to
-find out what the compiler or linker was complaining about.
-

+ 0 - 1373
Source/ThirdParty/libwebsockets/READMEs/README.coding.md

@@ -1,1373 +0,0 @@
-Notes about coding with lws
-===========================
-
-@section era Old lws and lws v2.0+
-
-Originally lws only supported the "manual" method of handling everything in the
-user callback found in test-server.c / test-server-http.c.
-
-Since v2.0, the need for most or all of this manual boilerplate has been
-eliminated: the protocols[0] http stuff is provided by a generic lib export
-`lws_callback_http_dummy()`.  You can serve parts of your filesystem at part of
-the URL space using mounts, the dummy http callback will do the right thing.
-
-It's much preferred to use the "automated" v2.0 type scheme, because it's less
-code and it's easier to support.
-
-The minimal examples all use the modern, recommended way.
-
-If you just need generic serving capability, without the need to integrate lws
-to some other app, consider not writing any server code at all, and instead use
-the generic server `lwsws`, and writing your special user code in a standalone
-"plugin".  The server is configured for mounts etc using JSON, see
-./READMEs/README.lwsws.md.
-
-Although the "plugins" are dynamically loaded if you use lwsws or lws built
-with libuv, actually they may perfectly well be statically included if that
-suits your situation better, eg, ESP32 test server, where the platform does
-not support processes or dynamic loading, just #includes the plugins
-one after the other and gets the same benefit from the same code.
-
-Isolating and collating the protocol code in one place also makes it very easy
-to maintain and understand.
-
-So it if highly recommended you put your protocol-specific code into the
-form of a "plugin" at the source level, even if you have no immediate plan to
-use it dynamically-loaded.
-
-@section writeable Only send data when socket writeable
-
-You should only send data on a websocket connection from the user callback
-`LWS_CALLBACK_SERVER_WRITEABLE` (or `LWS_CALLBACK_CLIENT_WRITEABLE` for
-clients).
-
-If you want to send something, do NOT just send it but request a callback
-when the socket is writeable using
-
- - `lws_callback_on_writable(wsi)` for a specific `wsi`, or
- 
- - `lws_callback_on_writable_all_protocol(protocol)` for all connections
-using that protocol to get a callback when next writeable.
-
-Usually you will get called back immediately next time around the service
-loop, but if your peer is slow or temporarily inactive the callback will be
-delayed accordingly.  Generating what to write and sending it should be done
-in the ...WRITEABLE callback.
-
-See the test server code for an example of how to do this.
-
-Otherwise evolved libs like libuv get this wrong, they will allow you to "send"
-anything you want but it only uses up your local memory (and costs you
-memcpys) until the socket can actually accept it.  It is much better to regulate
-your send action by the downstream peer readiness to take new data in the first
-place, avoiding all the wasted buffering.
-
-Libwebsockets' concept is that the downstream peer is truly the boss, if he,
-or our connection to him, cannot handle anything new, we should not generate
-anything new for him.  This is how unix shell piping works, you may have
-`cat a.txt | grep xyz > remote", but actually that does not cat anything from
-a.txt while remote cannot accept anything new. 
-
-@section oneper Only one lws_write per WRITEABLE callback
-
-From v2.5, lws strictly enforces only one lws_write() per WRITEABLE callback.
-
-You will receive a message about "Illegal back-to-back write of ... detected"
-if there is a second lws_write() before returning to the event loop.
-
-This is because with http/2, the state of the network connection carrying a
-wsi is unrelated to any state of the wsi.  The situation on http/1 where a
-new request implied a new tcp connection and new SSL buffer, so you could
-assume some window for writes is no longer true.  Any lws_write() can fail
-and be buffered for completion by lws; it will be auto-completed by the
-event loop.
-
-Note that if you are handling your own http responses, writing the headers
-needs to be done with a separate lws_write() from writing any payload.  That
-means after writing the headers you must call `lws_callback_on_writable(wsi)`
-and send any payload from the writable callback.
-
-@section otherwr Do not rely on only your own WRITEABLE requests appearing
-
-Libwebsockets may generate additional `LWS_CALLBACK_CLIENT_WRITEABLE` events
-if it met network conditions where it had to buffer your send data internally.
-
-So your code for `LWS_CALLBACK_CLIENT_WRITEABLE` needs to own the decision
-about what to send, it can't assume that just because the writeable callback
-came something is ready to send.
-
-It's quite possible you get an 'extra' writeable callback at any time and
-just need to `return 0` and wait for the expected callback later.
-
-@section dae Daemonization
-
-There's a helper api `lws_daemonize` built by default that does everything you
-need to daemonize well, including creating a lock file.  If you're making
-what's basically a daemon, just call this early in your init to fork to a
-headless background process and exit the starting process.
-
-Notice stdout, stderr, stdin are all redirected to /dev/null to enforce your
-daemon is headless, so you'll need to sort out alternative logging, by, eg,
-syslog via `lws_set_log_level(..., lwsl_emit_syslog)`.
-
-@section conns Maximum number of connections
-
-The maximum number of connections the library can deal with is decided when
-it starts by querying the OS to find out how many file descriptors it is
-allowed to open (1024 on Fedora for example).  It then allocates arrays that
-allow up to that many connections, minus whatever other file descriptors are
-in use by the user code.
-
-If you want to restrict that allocation, or increase it, you can use ulimit or
-similar to change the available number of file descriptors, and when restarted
-**libwebsockets** will adapt accordingly.
-
-@section peer_limits optional LWS_WITH_PEER_LIMITS
-
-If you select `LWS_WITH_PEER_LIMITS` at cmake, then lws will track peer IPs
-and monitor how many connections and ah resources they are trying to use
-at one time.  You can choose to limit these at context creation time, using
-`info.ip_limit_ah` and `info.ip_limit_wsi`.
-
-Note that although the ah limit is 'soft', ie, the connection will just wait
-until the IP is under the ah limit again before attaching a new ah, the
-wsi limit is 'hard', lws will drop any additional connections from the
-IP until it's under the limit again.
-
-If you use these limits, you should consider multiple clients may simultaneously
-try to access the site through NAT, etc.  So the limits should err on the side
-of being generous, while still making it impossible for one IP to exhaust
-all the server resources.
-
-@section evtloop Libwebsockets is singlethreaded
-
-Libwebsockets works in a serialized event loop, in a single thread.  It supports
-the default poll() backend, and libuv, libev, and libevent event loop
-libraries that also take this locking-free, nonblocking event loop approach that
-is not threadsafe.  There are several advantages to this technique, but one
-disadvantage, it doesn't integrate easily if there are multiple threads that
-want to use libwebsockets.
-
-However integration to multithreaded apps is possible if you follow some guidelines.
-
-1) Aside from two APIs, directly calling lws apis from other threads is not allowed.
-
-2) If you want to keep a list of live wsi, you need to use lifecycle callbacks on
-the protocol in the service thread to manage the list, with your own locking.
-Typically you use an ESTABLISHED callback to add ws wsi to your list and a CLOSED
-callback to remove them.
-
-3) LWS regulates your write activity by being able to let you know when you may
-write more on a connection.  That reflects the reality that you cannot succeed to
-send data to a peer that has no room for it, so you should not generate or buffer
-write data until you know the peer connection can take more.
-
-Other libraries pretend that the guy doing the writing is the boss who decides
-what happens, and absorb as much as you want to write to local buffering.  That does
-not scale to a lot of connections, because it will exhaust your memory and waste
-time copying data around in memory needlessly.
-
-The truth is the receiver, along with the network between you, is the boss who
-decides what will happen.  If he stops accepting data, no data will move.  LWS is
-designed to reflect that.
-
-If you have something to send, you call `lws_callback_on_writable()` on the
-connection, and when it is writeable, you will get a `LWS_CALLBACK_SERVER_WRITEABLE`
-callback, where you should generate the data to send and send it with `lws_write()`.
-
-You cannot send data using `lws_write()` outside of the WRITEABLE callback.
-
-4) For multithreaded apps, this corresponds to a need to be able to provoke the
-`lws_callback_on_writable()` action and to wake the service thread from its event
-loop wait (sleeping in `poll()` or `epoll()` or whatever).  The rules above
-mean directly sending data on the connection from another thread is out of the
-question.
-
-Therefore the two apis mentioned above that may be used from another thread are
-
- - For LWS using the default poll() event loop, `lws_callback_on_writable()`
-
- - For LWS using libuv/libev/libevent event loop, `lws_cancel_service()`
-
-If you are using the default poll() event loop, one "foreign thread" at a time may
-call `lws_callback_on_writable()` directly for a wsi.  You need to use your own
-locking around that to serialize multiple thread access to it.
-
-If you implement LWS_CALLBACK_GET_THREAD_ID in protocols[0], then LWS will detect
-when it has been called from a foreign thread and automatically use
-`lws_cancel_service()` to additionally wake the service loop from its wait.
-
-For libuv/libev/libevent event loop, they cannot handle being called from other
-threads.  So there is a slightly different scheme, you may call `lws_cancel_service()` 
-to force the event loop to end immediately.  This then broadcasts a callback (in the
-service thread context) `LWS_CALLBACK_EVENT_WAIT_CANCELLED`, to all protocols on all
-vhosts, where you can perform your own locking and walk a list of wsi that need
-`lws_callback_on_writable()` calling on them.
-
-`lws_cancel_service()` is very cheap to call.
-
-5) The obverse of this truism about the receiver being the boss is the case where
-we are receiving.  If we get into a situation we actually can't usefully
-receive any more, perhaps because we are passing the data on and the guy we want
-to send to can't receive any more, then we should "turn off RX" by using the
-RX flow control API, `lws_rx_flow_control(wsi, 0)`.  When something happens where we
-can accept more RX, (eg, we learn our onward connection is writeable) we can call
-it again to re-enable it on the incoming wsi.
-
-LWS stops calling back about RX immediately you use flow control to disable RX, it
-buffers the data internally if necessary.  So you will only see RX when you can
-handle it.  When flow control is disabled, LWS stops taking new data in... this makes
-the situation known to the sender by TCP "backpressure", the tx window fills and the
-sender finds he cannot write any more to the connection.
-
-See the mirror protocol implementations for example code.
-
-If you need to service other socket or file descriptors as well as the
-websocket ones, you can combine them together with the websocket ones
-in one poll loop, see "External Polling Loop support" below, and
-still do it all in one thread / process context.  If the need is less
-architectural, you can also create RAW mode client and serving sockets; this
-is how the lws plugin for the ssh server works.
-
-@section anonprot Working without a protocol name
-
-Websockets allows connections to negotiate without a protocol name...
-in that case by default it will bind to the first protocol in your
-vhost protocols[] array.
-
-You can tell the vhost to use a different protocol by attaching a
-pvo (per-vhost option) to the 
-
-```
-/*
- * this sets a per-vhost, per-protocol option name:value pair
- * the effect is to set this protocol to be the default one for the vhost,
- * ie, selected if no Protocol: header is sent with the ws upgrade.
- */
-
-static const struct lws_protocol_vhost_options pvo_opt = {
-	NULL,
-	NULL,
-	"default",
-	"1"
-};
-
-static const struct lws_protocol_vhost_options pvo = {
-	NULL,
-	&pvo_opt,
-	"my-protocol",
-	""
-};
-
-...
-
-	context_info.pvo = &pvo;
-...
-
-```
-
-Will select "my-protocol" from your protocol list (even if it came
-in by plugin) as being the target of client connections that don't
-specify a protocol.
-
-@section closing Closing connections from the user side
-
-When you want to close a connection, you do it by returning `-1` from a
-callback for that connection.
-
-You can provoke a callback by calling `lws_callback_on_writable` on
-the wsi, then notice in the callback you want to close it and just return -1.
-But usually, the decision to close is made in a callback already and returning
--1 is simple.
-
-If the socket knows the connection is dead, because the peer closed or there
-was an affirmitive network error like a FIN coming, then **libwebsockets**  will
-take care of closing the connection automatically.
-
-If you have a silently dead connection, it's possible to enter a state where
-the send pipe on the connection is choked but no ack will ever come, so the
-dead connection will never become writeable.  To cover that, you can use TCP
-keepalives (see later in this document) or pings.
-
-@section gzip Serving from inside a zip file
-
-Lws now supports serving gzipped files from inside a zip container.  Thanks to
-Per Bothner for contributing the code.
-
-This has the advtantage that if the client can accept GZIP encoding, lws can
-simply send the gzip-compressed file from inside the zip file with no further
-processing, saving time and bandwidth.
-
-In the case the client can't understand gzip compression, lws automatically
-decompressed the file and sends it normally.
-
-Clients with limited storage and RAM will find this useful; the memory needed
-for the inflate case is constrained so that only one input buffer at a time
-is ever in memory.
-
-To use this feature, ensure LWS_WITH_ZIP_FOPS is enabled at CMake.
-
-`libwebsockets-test-server-v2.0` includes a mount using this technology
-already, run that test server and navigate to http://localhost:7681/ziptest/candide.html
-
-This will serve the book Candide in html, together with two jpgs, all from
-inside a .zip file in /usr/[local/]share-libwebsockets-test-server/candide.zip
-
-Usage is otherwise automatic, if you arrange a mount that points to the zipfile,
-eg, "/ziptest" -> "mypath/test.zip", then URLs like `/ziptest/index.html` will be
-servied from `index.html` inside `mypath/test.zip`
-
-@section frags Fragmented messages
-
-To support fragmented messages you need to check for the final
-frame of a message with `lws_is_final_fragment`. This
-check can be combined with `libwebsockets_remaining_packet_payload`
-to gather the whole contents of a message, eg:
-
-```
-	    case LWS_CALLBACK_RECEIVE:
-	    {
-	        Client * const client = (Client *)user;
-	        const size_t remaining = lws_remaining_packet_payload(wsi);
-	
-	        if (!remaining && lws_is_final_fragment(wsi)) {
-	            if (client->HasFragments()) {
-	                client->AppendMessageFragment(in, len, 0);
-	                in = (void *)client->GetMessage();
-	                len = client->GetMessageLength();
-	            }
-	
-	            client->ProcessMessage((char *)in, len, wsi);
-	            client->ResetMessage();
-	        } else
-	            client->AppendMessageFragment(in, len, remaining);
-	    }
-	    break;
-```
-
-The test app libwebsockets-test-fraggle sources also show how to
-deal with fragmented messages.
-
-
-@section debuglog Debug Logging
-
-Also using `lws_set_log_level` api you may provide a custom callback to actually
-emit the log string.  By default, this points to an internal emit function
-that sends to stderr.  Setting it to `NULL` leaves it as it is instead.
-
-A helper function `lwsl_emit_syslog()` is exported from the library to simplify
-logging to syslog.  You still need to use `setlogmask`, `openlog` and `closelog`
-in your user code.
-
-The logging apis are made available for user code.
-
-- `lwsl_err(...)`
-- `lwsl_warn(...)`
-- `lwsl_notice(...)`
-- `lwsl_info(...)`
-- `lwsl_debug(...)`
-
-The difference between notice and info is that notice will be logged by default
-whereas info is ignored by default.
-
-If you are not building with _DEBUG defined, ie, without this
-
-```
-	$ cmake .. -DCMAKE_BUILD_TYPE=DEBUG
-```
-
-then log levels below notice do not actually get compiled in.
-
-@section asan Building with ASAN
-
-Under GCC you can select for the build to be instrumented with the Address
-Sanitizer, 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
-standard and depend on platform behaviours.
-
-Run your application like this
-
-```
-	$ sudo ASAN_OPTIONS=verbosity=2:halt_on_error=1  /usr/local/bin/lwsws
-```
-
-and attach gdb to catch the place it halts.
-
-@section extpoll External Polling Loop support
-
-**libwebsockets** maintains an internal `poll()` array for all of its
-sockets, but you can instead integrate the sockets into an
-external polling array.  That's needed if **libwebsockets** will
-cooperate with an existing poll array maintained by another
-server.
-
-Three callbacks `LWS_CALLBACK_ADD_POLL_FD`, `LWS_CALLBACK_DEL_POLL_FD`
-and `LWS_CALLBACK_CHANGE_MODE_POLL_FD` appear in the callback for protocol 0
-and allow interface code to manage socket descriptors in other poll loops.
-
-You can pass all pollfds that need service to `lws_service_fd()`, even
-if the socket or file does not belong to **libwebsockets** it is safe.
-
-If **libwebsocket** handled it, it zeros the pollfd `revents` field before returning.
-So you can let **libwebsockets** try and if `pollfd->revents` is nonzero on return,
-you know it needs handling by your code.
-
-Also note that when integrating a foreign event loop like libev or libuv where
-it doesn't natively use poll() semantics, and you must return a fake pollfd
-reflecting the real event:
-
- - be sure you set .events to .revents value as well in the synthesized pollfd
-
- - check the built-in support for the event loop if possible (eg, ./lib/libuv.c)
-   to see how it interfaces to lws
-   
- - use LWS_POLLHUP / LWS_POLLIN / LWS_POLLOUT from libwebsockets.h to avoid
-   losing windows compatibility
-
-You also need to take care about "forced service" somehow... these are cases
-where the network event was consumed, incoming data was all read, for example,
-but the work arising from it was not completed.  There will not be any more
-network event to trigger the remaining work, Eg, we read compressed data, but
-we did not use up all the decompressed data before returning to the event loop
-because we had to write some of it.
-
-Lws provides an API to determine if anyone is waiting for forced service,
-`lws_service_adjust_timeout(context, 1, tsi)`, normally tsi is 0.  If it returns
-0, then at least one connection has pending work you can get done by calling
-`lws_service_tsi(context, -1, tsi)`, again normally tsi is 0.
-
-For eg, the default poll() event loop, or libuv/ev/event, lws does this
-checking for you and handles it automatically.  But in the external polling
-loop case, you must do it explicitly.  Handling it after every normal service
-triggered by the external poll fd should be enough, since the situations needing
-it are initially triggered by actual network events.
-
-An example of handling it is shown in the test-server code specific to
-external polling.
-
-@section cpp Using with in c++ apps
-
-The library is ready for use by C++ apps.  You can get started quickly by
-copying the test server
-
-```
-	$ cp test-apps/test-server.c test.cpp
-```
-
-and building it in C++ like this
-
-```
-	$ g++ -DINSTALL_DATADIR=\"/usr/share\" -ocpptest test.cpp -lwebsockets
-```
-
-`INSTALL_DATADIR` is only needed because the test server uses it as shipped, if
-you remove the references to it in your app you don't need to define it on
-the g++ line either.
-
-
-@section headerinfo Availability of header information
-
-HTTP Header information is managed by a pool of "ah" structs.  These are a
-limited resource so there is pressure to free the headers and return the ah to
-the pool for reuse.
-
-For that reason header information on HTTP connections that get upgraded to
-websockets is lost after the ESTABLISHED callback.  Anything important that
-isn't processed by user code before then should be copied out for later.
-
-For HTTP connections that don't upgrade, header info remains available the
-whole time.
-
-@section http2compat Code Requirements for HTTP/2 compatibility
-
-Websocket connections only work over http/1, so there is nothing special to do
-when you want to enable -DLWS_WITH_HTTP2=1.
-
-The internal http apis already follow these requirements and are compatible with
-http/2 already.  So if you use stuff like mounts and serve stuff out of the
-filesystem, there's also nothing special to do.
-
-However if you are getting your hands dirty with writing response headers, or
-writing bulk data over http/2, you need to observe these rules so that it will
-work over both http/1.x and http/2 the same.
-
-1) LWS_PRE requirement applies on ALL lws_write().  For http/1, you don't have
-to take care of LWS_PRE for http data, since it is just sent straight out.
-For http/2, it will write up to LWS_PRE bytes behind the buffer start to create
-the http/2 frame header.
-
-This has implications if you treated the input buffer to lws_write() as const...
-it isn't any more with http/2, up to 9 bytes behind the buffer will be trashed.
-
-2) Headers are encoded using a sophisticated scheme in http/2.  The existing
-header access apis are already made compatible for incoming headers,
-for outgoing headers you must:
-
- - observe the LWS_PRE buffer requirement mentioned above
- 
- - Use `lws_add_http_header_status()` to add the transaction status (200 etc)
- 
- - use lws apis `lws_add_http_header_by_name()` and `lws_add_http_header_by_token()`
-   to put the headers into the buffer (these will translate what is actually
-   written to the buffer depending on if the connection is in http/2 mode or not)
-   
- - use the `lws api lws_finalize_http_header()` api after adding the last
-   response header
-   
- - write the header using lws_write(..., `LWS_WRITE_HTTP_HEADERS`);
- 
- 3) http/2 introduces per-stream transmit credit... how much more you can send
- on a stream is decided by the peer.  You start off with some amount, as the
- stream sends stuff lws will reduce your credit accordingly, when it reaches
- zero, you must not send anything further until lws receives "more credit" for
- that stream the peer.  Lws will suppress writable callbacks if you hit 0 until
- more credit for the stream appears, and lws built-in file serving (via mounts
- etc) already takes care of observing the tx credit restrictions.  However if
- you write your own code that wants to send http data, you must consult the
- `lws_get_peer_write_allowance()` api to find out the state of your tx credit.
- For http/1, it will always return (size_t)-1, ie, no limit.
- 
- This is orthogonal to the question of how much space your local side's kernel
- will make to buffer your send data on that connection.  So although the result
- from `lws_get_peer_write_allowance()` is "how much you can send" logically,
- and may be megabytes if the peer allows it, you should restrict what you send
- at one time to whatever your machine will generally accept in one go, and
- further reduce that amount if `lws_get_peer_write_allowance()` returns
- something smaller.  If it returns 0, you should not consume or send anything
- and return having asked for callback on writable, it will only come back when
- more tx credit has arrived for your stream.
- 
- 4) Header names with captital letters are illegal in http/2.  Header names in
- http/1 are case insensitive.  So if you generate headers by name, change all
- your header name strings to lower-case to be compatible both ways.
- 
- 5) Chunked Transfer-encoding is illegal in http/2, http/2 peers will actively
- reject it.  Lws takes care of removing the header and converting CGIs that
- emit chunked into unchunked automatically for http/2 connections.
- 
-If you follow these rules, your code will automatically work with both http/1.x
-and http/2.
-
-@section ka TCP Keepalive
-
-It is possible for a connection which is not being used to send to die
-silently somewhere between the peer and the side not sending.  In this case
-by default TCP will just not report anything and you will never get any more
-incoming data or sign the link is dead until you try to send.
-
-To deal with getting a notification of that situation, you can choose to
-enable TCP keepalives on all **libwebsockets** sockets, when you create the
-context.
-
-To enable keepalive, set the ka_time member of the context creation parameter
-struct to a nonzero value (in seconds) at context creation time.  You should
-also fill ka_probes and ka_interval in that case.
-
-With keepalive enabled, the TCP layer will send control packets that should
-stimulate a response from the peer without affecting link traffic.  If the
-response is not coming, the socket will announce an error at `poll()` forcing
-a close.
-
-Note that BSDs don't support keepalive time / probes / interval per-socket
-like Linux does.  On those systems you can enable keepalive by a nonzero
-value in `ka_time`, but the systemwide kernel settings for the time / probes/
-interval are used, regardless of what nonzero value is in `ka_time`.
-
-
-@section sslopt Optimizing SSL connections
-
-There's a member `ssl_cipher_list` in the `lws_context_creation_info` struct
-which allows the user code to restrict the possible cipher selection at
-context-creation time.
-
-You might want to look into that to stop the ssl peers selecting a cipher which
-is too computationally expensive.  To use it, point it to a string like
-
-	`"RC4-MD5:RC4-SHA:AES128-SHA:AES256-SHA:HIGH:!DSS:!aNULL"`
-
-if left `NULL`, then the "DEFAULT" set of ciphers are all possible to select.
-
-You can also set it to `"ALL"` to allow everything (including insecure ciphers).
-
-
-@section sslcerts Passing your own cert information direct to SSL_CTX
-
-For most users it's enough to pass the SSL certificate and key information by
-giving filepaths to the info.ssl_cert_filepath and info.ssl_private_key_filepath
-members when creating the vhost.
-
-If you want to control that from your own code instead, you can do so by leaving
-the related info members NULL, and setting the info.options flag
-LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX at vhost creation time.  That will create
-the vhost SSL_CTX without any certificate, and allow you to use the callback
-LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS to add your certificate to
-the SSL_CTX directly.  The vhost SSL_CTX * is in the user parameter in that
-callback.
-
-@section clientasync Async nature of client connections
-
-When you call `lws_client_connect_info(..)` and get a `wsi` back, it does not
-mean your connection is active.  It just means it started trying to connect.
-
-Your client connection is actually active only when you receive
-`LWS_CALLBACK_CLIENT_ESTABLISHED` for it.
-
-There's a 5 second timeout for the connection, and it may give up or die for
-other reasons, if any of that happens you'll get a
-`LWS_CALLBACK_CLIENT_CONNECTION_ERROR` callback on protocol 0 instead for the
-`wsi`.
-
-After attempting the connection and getting back a non-`NULL` `wsi` you should
-loop calling `lws_service()` until one of the above callbacks occurs.
-
-As usual, see [test-client.c](../test-apps/test-client.c) for example code.
-
-Notice that the client connection api tries to progress the connection
-somewhat before returning.  That means it's possible to get callbacks like
-CONNECTION_ERROR on the new connection before your user code had a chance to
-get the wsi returned to identify it (in fact if the connection did fail early,
-NULL will be returned instead of the wsi anyway).
-
-To avoid that problem, you can fill in `pwsi` in the client connection info
-struct to point to a struct lws that get filled in early by the client
-connection api with the related wsi.  You can then check for that in the
-callback to confirm the identity of the failing client connection.
-
-
-@section fileapi Lws platform-independent file access apis
-
-lws now exposes his internal platform file abstraction in a way that can be
-both used by user code to make it platform-agnostic, and be overridden or
-subclassed by user code.  This allows things like handling the URI "directory
-space" as a virtual filesystem that may or may not be backed by a regular
-filesystem.  One example use is serving files from inside large compressed
-archive storage without having to unpack anything except the file being
-requested.
-
-The test server shows how to use it, basically the platform-specific part of
-lws prepares a file operations structure that lives in the lws context.
-
-The user code can get a pointer to the file operations struct
-
-```
-	LWS_VISIBLE LWS_EXTERN struct lws_plat_file_ops *
-		`lws_get_fops`(struct lws_context *context);
-```
-
-and then can use helpers to also leverage these platform-independent
-file handling apis
-
-```
-	lws_fop_fd_t
-	`lws_plat_file_open`(struct lws_plat_file_ops *fops, const char *filename,
-			   lws_fop_flags_t *flags)
-	int
-	`lws_plat_file_close`(lws_fop_fd_t fop_fd)
-
-	unsigned long
-	`lws_plat_file_seek_cur`(lws_fop_fd_t fop_fd, lws_fileofs_t offset)
-
-	int
-	`lws_plat_file_read`(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
-		   uint8_t *buf, lws_filepos_t len)
-
-	int
-	`lws_plat_file_write`(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
-		   uint8_t *buf, lws_filepos_t len )
-```
-
-Generic helpers are provided which provide access to generic fops information or
-call through to the above fops
-
-```
-lws_filepos_t
-lws_vfs_tell(lws_fop_fd_t fop_fd);
-
-lws_filepos_t
-lws_vfs_get_length(lws_fop_fd_t fop_fd);
-
-uint32_t
-lws_vfs_get_mod_time(lws_fop_fd_t fop_fd);
-
-lws_fileofs_t
-lws_vfs_file_seek_set(lws_fop_fd_t fop_fd, lws_fileofs_t offset);
-
-lws_fileofs_t
-lws_vfs_file_seek_end(lws_fop_fd_t fop_fd, lws_fileofs_t offset);
-```
-
-
-The user code can also override or subclass the file operations, to either
-wrap or replace them.  An example is shown in test server.
-
-### Changes from v2.1 and before fops
-
-There are several changes:
-
-1) 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.
-
-2) 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.
-
-3) Everything is wrapped in typedefs.  See lws-plat-unix.c for examples of how to implement.
-
-4) Position in the file, File Length, and a copy of Flags left after open are now generically held in the fop_fd.
-VFS implementation must set and manage this generic information now.  See the implementations in lws-plat-unix.c for
-examples.
-
-5) The file length is no longer set at a pointer provided by the open() fop.  The api `lws_vfs_get_length()` is provided to
-get the file length after open.
-
-6) If your file namespace is virtual, ie, is not reachable by platform fops directly, you must set LWS_FOP_FLAG_VIRTUAL
-on the flags during open.
-
-7) There is an optional `mod_time` uint32_t member in the generic fop_fd.  If you are able to set it during open, you
-should indicate it by setting `LWS_FOP_FLAG_MOD_TIME_VALID` on the flags.
-
-@section rawfd RAW file descriptor polling
-
-LWS allows you to include generic platform file descriptors in the lws service / poll / event loop.
-
-Open your fd normally and then
-
-```
-	lws_sock_file_fd_type u;
-
-	u.filefd = your_open_file_fd;
-
-	if (!lws_adopt_descriptor_vhost(vhost, 0, u,
-					"protocol-name-to-bind-to",
-					optional_wsi_parent_or_NULL)) {
-		// failed
-	}
-
-	// OK
-```
-
-A wsi is created for the file fd that acts like other wsi, you will get these
-callbacks on the named protocol
-
-```
-	LWS_CALLBACK_RAW_ADOPT_FILE
-	LWS_CALLBACK_RAW_RX_FILE
-	LWS_CALLBACK_RAW_WRITEABLE_FILE
-	LWS_CALLBACK_RAW_CLOSE_FILE
-```
-
-starting with LWS_CALLBACK_RAW_ADOPT_FILE.
-
-The minimal example `raw/minimal-raw-file` demonstrates how to use it.
-
-`protocol-lws-raw-test` plugin also provides a method for testing this with
-`libwebsockets-test-server-v2.0`:
-
-The plugin creates a FIFO on your system called "/tmp/lws-test-raw"
-
-You can feed it data through the FIFO like this
-
-```
-  $ sudo sh -c "echo hello > /tmp/lws-test-raw"
-```
-
-This plugin simply prints the data.  But it does it through the lws event
-loop / service poll.
-
-@section rawsrvsocket RAW server socket descriptor polling
-
-You can also enable your vhost to accept RAW socket connections, in addition to
-HTTP[s] and WS[s].  If the first bytes written on the connection are not a
-valid HTTP method, then the connection switches to RAW mode.
-
-This is disabled by default, you enable it by setting the `.options` flag
-LWS_SERVER_OPTION_FALLBACK_TO_APPLY_LISTEN_ACCEPT_CONFIG, and setting
-`.listen_accept_role` to `"raw-skt"` when creating the vhost.
-
-RAW mode socket connections receive the following callbacks
-
-```
-	LWS_CALLBACK_RAW_ADOPT
-	LWS_CALLBACK_RAW_RX
-	LWS_CALLBACK_RAW_WRITEABLE
-	LWS_CALLBACK_RAW_CLOSE
-```
-
-You can control which protocol on your vhost handles these RAW mode
-incoming connections by setting the vhost info struct's `.listen_accept_protocol`
-to the vhost protocol name to use.
-
-`protocol-lws-raw-test` plugin provides a method for testing this with
-`libwebsockets-test-server-v2.0`:
-
-Run libwebsockets-test-server-v2.0 and connect to it by telnet, eg
-
-```
-    $ telnet 127.0.0.1 7681
-```
-
-type something that isn't a valid HTTP method and enter, before the
-connection times out.  The connection will switch to RAW mode using this
-protocol, and pass the unused rx as a raw RX callback.
-    
-The test protocol echos back what was typed on telnet to telnet.
-
-@section rawclientsocket RAW client socket descriptor polling
-
-You can now also open RAW socket connections in client mode.
-
-Follow the usual method for creating a client connection, but set the
-`info.method` to "RAW".  When the connection is made, the wsi will be
-converted to RAW mode and operate using the same callbacks as the
-server RAW sockets described above.
-
-The libwebsockets-test-client supports this using raw:// URLS.  To
-test, open a netcat listener in one window
-
-```
- $ nc -l 9999
-```
-
-and in another window, connect to it using the test client
-
-```
- $ libwebsockets-test-client raw://127.0.0.1:9999
-```
-
-The connection should succeed, and text typed in the netcat window (including a CRLF)
-will be received in the client.
-
-@section rawudp RAW UDP socket integration
-
-Lws provides an api to create, optionally bind, and adopt a RAW UDP
-socket (RAW here means an uninterpreted normal UDP socket, not a
-"raw socket").
-
-```
-LWS_VISIBLE LWS_EXTERN struct lws *
-lws_create_adopt_udp(struct lws_vhost *vhost, int port, int flags,
-		     const char *protocol_name, struct lws *parent_wsi);
-```
-
-`flags` should be `LWS_CAUDP_BIND` if the socket will receive packets.
-
-The callbacks `LWS_CALLBACK_RAW_ADOPT`, `LWS_CALLBACK_RAW_CLOSE`,
-`LWS_CALLBACK_RAW_RX` and `LWS_CALLBACK_RAW_WRITEABLE` apply to the
-wsi.  But UDP is different than TCP in some fundamental ways.
-
-For receiving on a UDP connection, data becomes available at
-`LWS_CALLBACK_RAW_RX` as usual, but because there is no specific
-connection with UDP, it is necessary to also get the source address of
-the data separately, using `struct lws_udp * lws_get_udp(wsi)`.
-You should take a copy of the `struct lws_udp` itself (not the
-pointer) and save it for when you want to write back to that peer.
-
-Writing is also a bit different for UDP.  By default, the system has no
-idea about the receiver state and so asking for a `callback_on_writable()`
-always believes that the socket is writeable... the callback will
-happen next time around the event loop.
-
-With UDP, there is no single "connection".  You need to write with sendto() and
-direct the packets to a specific destination.  To return packets to a
-peer who sent something earlier and you copied his `struct lws_udp`, you
-use the .sa and .salen members as the last two parameters of the sendto().
-
-The kernel may not accept to buffer / write everything you wanted to send.
-So you are responsible to watch the result of sendto() and resend the
-unsent part next time (which may involve adding new protocol headers to
-the remainder depending on what you are doing).
-
-@section ecdh ECDH Support
-
-ECDH Certs are now supported.  Enable the CMake option
-
-	cmake .. -DLWS_SSL_SERVER_WITH_ECDH_CERT=1 
-
-**and** the info->options flag
-
-	LWS_SERVER_OPTION_SSL_ECDH
-
-to build in support and select it at runtime.
-
-@section sslinfo SSL info callbacks
-
-OpenSSL allows you to receive callbacks for various events defined in a
-bitmask in openssl/ssl.h.  The events include stuff like TLS Alerts.
-
-By default, lws doesn't register for these callbacks.
-
-However if you set the info.ssl_info_event_mask to nonzero (ie, set some
-of the bits in it like `SSL_CB_ALERT` at vhost creation time, then
-connections to that vhost will call back using LWS_CALLBACK_SSL_INFO
-for the wsi, and the `in` parameter will be pointing to a struct of
-related args:
-
-```
-struct lws_ssl_info {
-	int where;
-	int ret;
-};
-```
-
-The default callback handler in lws has a handler for LWS_CALLBACK_SSL_INFO
-which prints the related information,  You can test it using the switch
--S -s  on `libwebsockets-test-server-v2.0`.
-
-Returning nonzero from the callback will close the wsi.
-
-@section smp SMP / Multithreaded service
-
-SMP support is integrated into LWS without any internal threading.  It's
-very simple to use, libwebsockets-test-server-pthread shows how to do it,
-use -j n argument there to control the number of service threads up to 32.
-
-Two new members are added to the info struct
-
-	unsigned int count_threads;
-	unsigned int fd_limit_per_thread;
-	
-leave them at the default 0 to get the normal singlethreaded service loop.
-
-Set count_threads to n to tell lws you will have n simultaneous service threads
-operating on the context.
-
-There is still a single listen socket on one port, no matter how many
-service threads.
-
-When a connection is made, it is accepted by the service thread with the least
-connections active to perform load balancing.
-
-The user code is responsible for spawning n threads running the service loop
-associated to a specific tsi (Thread Service Index, 0 .. n - 1).  See
-the libwebsockets-test-server-pthread for how to do.
-
-If you leave fd_limit_per_thread at 0, then the process limit of fds is shared
-between the service threads; if you process was allowed 1024 fds overall then
-each thread is limited to 1024 / n.
-
-You can set fd_limit_per_thread to a nonzero number to control this manually, eg
-the overall supported fd limit is less than the process allowance.
-
-You can control the context basic data allocation for multithreading from Cmake
-using -DLWS_MAX_SMP=, if not given it's set to 1.  The serv_buf allocation
-for the threads (currently 4096) is made at runtime only for active threads.
-
-Because lws will limit the requested number of actual threads supported
-according to LWS_MAX_SMP, there is an api lws_get_count_threads(context) to
-discover how many threads were actually allowed when the context was created.
-
-See the test-server-pthreads.c sample for how to use.
-
-@section smplocking SMP Locking Helpers
-
-Lws provide a set of pthread mutex helpers that reduce to no code or
-variable footprint in the case that LWS_MAX_SMP == 1.
-
-Define your user mutex like this
-
-```
-	lws_pthread_mutex(name);
-```
-
-If LWS_MAX_SMP > 1, this produces `pthread_mutex_t name;`.  In the case
-LWS_MAX_SMP == 1, it produces nothing.
-
-Likewise these helpers for init, destroy, lock and unlock
-
-
-```
-	void lws_pthread_mutex_init(pthread_mutex_t *lock)
-	void lws_pthread_mutex_destroy(pthread_mutex_t *lock)
-	void lws_pthread_mutex_lock(pthread_mutex_t *lock)
-	void lws_pthread_mutex_unlock(pthread_mutex_t *lock)
-```
-
-resolve to nothing if LWS_MAX_SMP == 1, otherwise produce the equivalent
-pthread api.
-
-pthreads is required in lws only if LWS_MAX_SMP > 1.
-
-
-@section libevuv libev / libuv / libevent support
-
-You can select either or both
-
-	-DLWS_WITH_LIBEV=1
-	-DLWS_WITH_LIBUV=1
-	-DLWS_WITH_LIBEVENT=1
-
-at cmake configure-time.  The user application may use one of the
-context init options flags
-
-	LWS_SERVER_OPTION_LIBEV
-	LWS_SERVER_OPTION_LIBUV
-	LWS_SERVER_OPTION_LIBEVENT
-
-to indicate it will use one of the event libraries at runtime.
-
-libev and libevent headers conflict, they both define critical constants like
-EV_READ to different values.  Attempts to discuss clearing that up with both
-libevent and libev did not get anywhere useful.  Therefore CMakeLists.txt will
-error out if you enable both LWS_WITH_LIBEV and LWS_WITH_LIBEVENT.
-
-In addition depending on libev / compiler version, building anything with libev
-apis using gcc may blow strict alias warnings (which are elevated to errors in
-lws).  I did some googling at found these threads related to it, the issue goes
-back at least to 2010 on and off
-
-https://github.com/redis/hiredis/issues/434
-https://bugs.gentoo.org/show_bug.cgi?id=615532
-http://lists.schmorp.de/pipermail/libev/2010q1/000916.html
-http://lists.schmorp.de/pipermail/libev/2010q1/000920.html
-http://lists.schmorp.de/pipermail/libev/2010q1/000923.html
-
-We worked around this problem by disabling -Werror on the parts of lws that
-use libev.  FWIW as of Dec 2019 using Fedora 31 libev 4.27.1 and its gcc 9.2.1
-doesn't seem to trigger the problem even without the workaround.
-
-For these reasons and the response I got trying to raise these issues with
-them, if you have a choice about event loop, I would gently encourage you
-to avoid libev.  Where lws uses an event loop itself, eg in lwsws, we use
-libuv.
-
-@section extopts Extension option control from user code
-
-User code may set per-connection extension options now, using a new api
-`lws_set_extension_option()`.
-
-This should be called from the ESTABLISHED callback like this
-```
-	 lws_set_extension_option(wsi, "permessage-deflate",
-	                          "rx_buf_size", "12"); /* 1 << 12 */
-```
-
-If the extension is not active (missing or not negotiated for the
-connection, or extensions are disabled on the library) the call is
-just returns -1.  Otherwise the connection's extension has its
-named option changed.
-
-The extension may decide to alter or disallow the change, in the
-example above permessage-deflate restricts the size of his rx
-output buffer also considering the protocol's rx_buf_size member.
-
-
-@section httpsclient Client connections as HTTP[S] rather than WS[S]
-
-You may open a generic http client connection using the same
-struct lws_client_connect_info used to create client ws[s]
-connections.
-
-To stay in http[s], set the optional info member "method" to
-point to the string "GET" instead of the default NULL.
-
-After the server headers are processed, when payload from the
-server is available the callback LWS_CALLBACK_RECEIVE_CLIENT_HTTP
-will be made.
-
-You can choose whether to process the data immediately, or
-queue a callback when an outgoing socket is writeable to provide
-flow control, and process the data in the writable callback.
-
-Either way you use the api `lws_http_client_read()` to access the
-data, eg
-
-```
-	case LWS_CALLBACK_RECEIVE_CLIENT_HTTP:
-		{
-			char buffer[1024 + LWS_PRE];
-			char *px = buffer + LWS_PRE;
-			int lenx = sizeof(buffer) - LWS_PRE;
-
-			lwsl_notice("LWS_CALLBACK_RECEIVE_CLIENT_HTTP\n");
-
-			/*
-			 * Often you need to flow control this by something
-			 * else being writable.  In that case call the api
-			 * to get a callback when writable here, and do the
-			 * pending client read in the writeable callback of
-			 * the output.
-			 */
-			if (lws_http_client_read(wsi, &px, &lenx) < 0)
-				return -1;
-			while (lenx--)
-				putchar(*px++);
-		}
-		break;
-```
-
-Notice that if you will use SSL client connections on a vhost, you must
-prepare the client SSL context for the vhost after creating the vhost, since
-this is not normally done if the vhost was set up to listen / serve.  Call
-the api lws_init_vhost_client_ssl() to also allow client SSL on the vhost.
-
-@section clipipe Pipelining Client Requests to same host
-
-If you are opening more client requests to the same host and port, you
-can give the flag LCCSCF_PIPELINE on `info.ssl_connection` to indicate
-you wish to pipeline them.
-
-Without the flag, the client connections will occur concurrently using a
-socket and tls wrapper if requested for each connection individually.
-That is fast, but resource-intensive.
-
-With the flag, lws will queue subsequent client connections on the first
-connection to the same host and port.  When it has confirmed from the
-first connection that pipelining / keep-alive is supported by the server,
-it lets the queued client pipeline connections send their headers ahead
-of time to create a pipeline of requests on the server side.
-
-In this way only one tcp connection and tls wrapper is required to transfer
-all the transactions sequentially.  It takes a little longer but it
-can make a significant difference to resources on both sides.
-
-If lws learns from the first response header that keepalive is not possible,
-then it marks itself with that information and detaches any queued clients
-to make their own individual connections as a fallback.
-
-Lws can also intelligently combine multiple ongoing client connections to
-the same host and port into a single http/2 connection with multiple
-streams if the server supports it.
-
-Unlike http/1 pipelining, with http/2 the client connections all occur
-simultaneously using h2 stream multiplexing inside the one tcp + tls
-connection.
-
-You can turn off the h2 client support either by not building lws with
-`-DLWS_WITH_HTTP2=1` or giving the `LCCSCF_NOT_H2` flag in the client
-connection info struct `ssl_connection` member.
-
-@section vhosts Using lws vhosts
-
-If you set LWS_SERVER_OPTION_EXPLICIT_VHOSTS options flag when you create
-your context, it won't create a default vhost using the info struct
-members for compatibility.  Instead you can call lws_create_vhost()
-afterwards to attach one or more vhosts manually.
-
-```
-	LWS_VISIBLE struct lws_vhost *
-	lws_create_vhost(struct lws_context *context,
-			 struct lws_context_creation_info *info);
-```
-
-lws_create_vhost() uses the same info struct as lws_create_context(),
-it ignores members related to context and uses the ones meaningful
-for vhost (marked with VH in libwebsockets.h).
-
-```
-	struct lws_context_creation_info {
-		int port;					/* VH */
-		const char *iface;				/* VH */
-		const struct lws_protocols *protocols;		/* VH */
-		const struct lws_extension *extensions;		/* VH */
-	...
-```
-
-When you attach the vhost, if the vhost's port already has a listen socket
-then both vhosts share it and use SNI (is SSL in use) or the Host: header
-from the client to select the right one.  Or if no other vhost already
-listening the a new listen socket is created.
-
-There are some new members but mainly it's stuff you used to set at
-context creation time.
-
-
-@section sni How lws matches hostname or SNI to a vhost
-
-LWS first strips any trailing :port number.
-
-Then it tries to find an exact name match for a vhost listening on the correct
-port, ie, if SNI or the Host: header provided abc.com:1234, it will match on a
-vhost named abc.com that is listening on port 1234.
-
-If there is no exact match, lws will consider wildcard matches, for example
-if cats.abc.com:1234 is provided by the client by SNI or Host: header, it will
-accept a vhost "abc.com" listening on port 1234.  If there was a better, exact,
-match, it will have been chosen in preference to this.
-
-Connections with SSL will still have the client go on to check the
-certificate allows wildcards and error out if not.
- 
-
-
-@section mounts Using lws mounts on a vhost
-
-The last argument to lws_create_vhost() lets you associate a linked
-list of lws_http_mount structures with that vhost's URL 'namespace', in
-a similar way that unix lets you mount filesystems into areas of your /
-filesystem how you like and deal with the contents transparently.
-
-```
-	struct lws_http_mount {
-		struct lws_http_mount *mount_next;
-		const char *mountpoint; /* mountpoint in http pathspace, eg, "/" */
-		const char *origin; /* path to be mounted, eg, "/var/www/warmcat.com" */
-		const char *def; /* default target, eg, "index.html" */
-	
-		struct lws_protocol_vhost_options *cgienv;
-	
-		int cgi_timeout;
-		int cache_max_age;
-	
-		unsigned int cache_reusable:1;
-		unsigned int cache_revalidate:1;
-		unsigned int cache_intermediaries:1;
-	
-		unsigned char origin_protocol;
-		unsigned char mountpoint_len;
-	};
-```
-
-The last mount structure should have a NULL mount_next, otherwise it should
-point to the 'next' mount structure in your list.
-
-Both the mount structures and the strings must persist until the context is
-destroyed, since they are not copied but used in place.
-
-`.origin_protocol` should be one of
-
-```
-	enum {
-		LWSMPRO_HTTP,
-		LWSMPRO_HTTPS,
-		LWSMPRO_FILE,
-		LWSMPRO_CGI,
-		LWSMPRO_REDIR_HTTP,
-		LWSMPRO_REDIR_HTTPS,
-		LWSMPRO_CALLBACK,
-	};
-```
-
- - LWSMPRO_FILE is used for mapping url namespace to a filesystem directory and
-serve it automatically.
-
- - LWSMPRO_CGI associates the url namespace with the given CGI executable, which
-runs when the URL is accessed and the output provided to the client.
-
- - LWSMPRO_REDIR_HTTP and LWSMPRO_REDIR_HTTPS auto-redirect clients to the given
-origin URL.
-
- - LWSMPRO_CALLBACK causes the http connection to attach to the callback
-associated with the named protocol (which may be a plugin).
-
-
-@section mountcallback Operation of LWSMPRO_CALLBACK mounts
-
-The feature provided by CALLBACK type mounts is binding a part of the URL
-namespace to a named protocol callback handler.
-
-This allows protocol plugins to handle areas of the URL namespace.  For example
-in test-server-v2.0.c, the URL area "/formtest" is associated with the plugin
-providing "protocol-post-demo" like this
-
-```
-	static const struct lws_http_mount mount_post = {
-		NULL,		/* linked-list pointer to next*/
-		"/formtest",		/* mountpoint in URL namespace on this vhost */
-		"protocol-post-demo",	/* handler */
-		NULL,	/* default filename if none given */
-		NULL,
-		0,
-		0,
-		0,
-		0,
-		0,
-		LWSMPRO_CALLBACK,	/* origin points to a callback */
-		9,			/* strlen("/formtest"), ie length of the mountpoint */
-	};
-```
-
-Client access to /formtest[anything] will be passed to the callback registered
-with the named protocol, which in this case is provided by a protocol plugin.
-
-Access by all methods, eg, GET and POST are handled by the callback.
-
-protocol-post-demo deals with accepting and responding to the html form that
-is in the test server HTML.
-
-When a connection accesses a URL related to a CALLBACK type mount, the
-connection protocol is changed until the next access on the connection to a
-URL outside the same CALLBACK mount area.  User space on the connection is
-arranged to be the size of the new protocol user space allocation as given in
-the protocol struct.
-
-This allocation is only deleted / replaced when the connection accesses a
-URL region with a different protocol (or the default protocols[0] if no
-CALLBACK area matches it).
-
-This "binding connection to a protocol" lifecycle in managed by
-`LWS_CALLBACK_HTTP_BIND_PROTOCOL` and `LWS_CALLBACK_HTTP_DROP_PROTOCOL`.
-Because of HTTP/1.1 connection pipelining, one connection may perform
-many transactions, each of which may map to different URLs and need
-binding to different protocols.  So these messages are used to
-create the binding of the wsi to your protocol including any
-allocations, and to destroy the binding, at which point you should
-destroy any related allocations.
-
-@section BINDTODEV SO_BIND_TO_DEVICE
-
-The .bind_iface flag in the context / vhost creation struct lets you
-declare that you want all traffic for listen and transport on that
-vhost to be strictly bound to the network interface named in .iface.
-
-This Linux-only feature requires SO_BIND_TO_DEVICE, which in turn
-requires CAP_NET_RAW capability... root has this capability.
-
-However this feature needs to apply the binding also to accepted
-sockets during normal operation, which implies the server must run
-the whole time as root.
-
-You can avoid this by using the Linux capabilities feature to have
-the unprivileged user inherit just the CAP_NET_RAW capability.
-
-You can confirm this with the test server
-
-
-```
- $ sudo /usr/local/bin/libwebsockets-test-server -u agreen -i eno1 -k
-```
-
-The part that ensures the capability is inherited by the unprivileged
-user is
-
-```
-#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
-                        info.caps[0] = CAP_NET_RAW;
-                        info.count_caps = 1;
-#endif
-```
-
-
-@section dim Dimming webpage when connection lost
-
-The lws test plugins' html provides useful feedback on the webpage about if it
-is still connected to the server, by greying out the page if not.  You can
-also add this to your own html easily
-
- - include lws-common.js from your HEAD section
- 
-   \<script src="/lws-common.js">\</script>
-   
- - dim the page during initialization, in a script section on your page
- 
-   lws_gray_out(true,{'zindex':'499'});
-   
- - in your ws onOpen(), remove the dimming
- 
-   lws_gray_out(false);
-   
- - in your ws onClose(), reapply the dimming
- 
-   lws_gray_out(true,{'zindex':'499'});
-
-@section errstyle Styling http error pages
-
-In the code, http errors should be handled by `lws_return_http_status()`.
-
-There are basically two ways... the vhost can be told to redirect to an "error
-page" URL in response to specifically a 404... this is controlled by the
-context / vhost info struct (`struct lws_context_creation_info`) member
-`.error_document_404`... if non-null the client is redirected to this string.
-
-If it wasn't redirected, then the response code html is synthesized containing
-the user-selected text message and attempts to pull in `/error.css` for styling.
-
-If this file exists, it can be used to style the error page.  See 
-https://libwebsockets.org/git/badrepo for an example of what can be done (
-and https://libwebsockets.org/error.css for the corresponding css).
-

+ 0 - 148
Source/ThirdParty/libwebsockets/READMEs/README.content-security-policy.md

@@ -1,148 +0,0 @@
-## Using Content Security Policy (CSP)
-
-### What is it?
-
-Modern browsers have recently implemented a new feature providing
-a sort of "selinux for your web page".  If the server sends some
-new headers describing the security policy for the content, then
-the browser strictly enforces it.
-
-### Why would we want to do that?
-
-Scripting on webpages is pretty universal, sometimes the scripts
-come from third parties, and sometimes attackers find a way to
-inject scripts into the DOM, eg, through scripts in content.
-
-CSP lets the origin server define what is legitimate for the page it
-served and everything else is denied.
-
-The CSP for warmcat.com and libwebsockets.org looks like this,
-I removed a handful of whitelisted image sources like travis
-status etc for clarity...
-
-```
-"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';",
-"x-content-type-options": "nosniff",
-"x-xss-protection": "1; mode=block",
-"x-frame-options": "deny",
-"referrer-policy": "no-referrer"
-```
-
-The result of this is the browser won't let the site content be iframed, and it
-will reject any inline styles or inline scripts.  Fonts, css, ajax, ws and
-images are only allowed to come from 'self', ie, the server that served the
-page.  You may inject your script, or deceptive styles: it won't run or be shown.
-
-Because inline scripts are banned, the usual methods for XSS are dead;
-the attacker can't even load js from another server.  So these rules
-provide a very significant increase in client security.
-
-### Implications of strict CSP
-
-Halfhearted CSP isn't worth much.  The only useful approach is to start
-with `default-src 'none'` which disables everything, and then whitelist the
-minimum needed for the pages to operate.
-
-"Minimum needed for the pages to operate" doesn't mean defeat the protections
-necessary so everything in the HTML can stay the same... it means adapt the
-pages to want the minimum and then enable the minimum.
-
-The main point is segregation of styles and script away from the content, in
-files referenced in the document `<head>` section, along these lines:
-
-```
-<head>
- <meta charset=utf-8 http-equiv="Content-Language" content="en"/>
- <link rel="stylesheet" type="text/css" href="test.css"/>
- <script type='text/javascript' src="/lws-common.js"></script>
- <script type='text/javascript' src='test.js'></script>
- <title>Minimal Websocket test app</title>
-</head>
-```
-
-#### Inline styles must die
-
-All styling must go in one or more `.css` file(s) best served by the same
-server... while you can whitelist other sources in the CSP if you have to,
-unless you control that server as well, you are allowing whoever gains
-access to that server access to your users.
-
-Inline styles are no longer allowed (eg, "style='font-size:120%'" in the
-HTML)... they must be replaced by reference to one or more CSS class, which
-in this case includes "font-size:120%".  This has always been the best
-practice anyway, and your pages will be cleaner and more maintainable.
-
-#### Inline scripts must die
-
-Inline scripts need to be placed in a `.js` file and loaded in the page head
-section, again it should only be from the server that provided the page.
-
-Then, any kind of inline script, yours or injected or whatever, will be
-completely rejected by the browser.
-
-#### onXXX must be replaced by eventListener
-
-Inline `onclick()` etc are kinds of inline scripting and are banned.
-
-Modern browsers have offered a different system called ["EventListener" for
-a while](https://developer.mozilla.org/en-US/docs/Web/API/EventListener)
-which allows binding of events to DOM elements in JS.
-
-A bunch of different named events are possible to listen on, commonly the
-`.js` file will ask for one or both of
-
-```
-window.addEventListener("load", function() {
-...
-}, false);
-
-document.addEventListener("DOMContentLoaded", function() {
-...
-}, false);
-```
-
-These give the JS a way to trigger when either everything on the page has
-been "loaded" or the DOM has been populated from the initial HTML.  These
-can set up other event listeners on the DOM objects and aftwards the
-events will drive what happens on the page from user interaction and / or
-timers etc.
-
-If you have `onclick` in your HTML today, you would replace it with an id
-for the HTML element, then eg in the DOMContentLoaded event listener,
-apply 
-
-```
-   document.getElementById("my-id").addEventListener("click", function() {
-   ...
-   }, false);
-```
-
-ie the .js file becomes the only place with the "business logic" of the
-elements mentioned in the HTML, applied at runtime.
-
-#### Do you really need external sources?
-
-Do your scripts and fonts really need to come from external sources?
-If your caching policy is liberal, they are not actually that expensive
-to serve once and then the user is using his local copy for the next
-days.
-
-Some external sources are marked as anti-privacy in modern browsers, meaning
-they track your users, in turn meaning if your site refers to them, you
-will lose your green padlock in the browser.  If the content license allows
-it, hosting them on "self", ie, the same server that provided the HTML,
-will remove that problem.
-
-Bringing in scripts from external sources is actually quite scary from the
-security perspective.  If someone hacks the `ajax.googleapis.com` site to serve
-a hostile, modified jquery, half the Internet will instantly
-become malicious.  However if you serve it yourself, unless your server
-was specifically targeted you know it will continue to serve what you
-expect.
-
-Since these scripts are usually sent with cache control headers for local
-caching duration of 1 year, the cost of serving them yourself under the same
-conditions is small but your susceptibility to attack is reduced to only taking
-care of your own server.  And there is a privacy benefit that google is not
-informed of your users' IPs and activities on your site.
-

+ 0 - 41
Source/ThirdParty/libwebsockets/READMEs/README.contributing.md

@@ -1,41 +0,0 @@
-## Contributing to lws
-
-### How to contribute
-
-Sending a patch with a bug report is very welcome.
-
-For nontrivial problems, it's probably best to discuss on the mailing list,
-or on github if you prefer, how to best solve it.
-
-However your contribution is coming is fine:
-
- - paste a `git diff`
-
- - send a patch series by mail or mailing list
-
- - paste in a github issue
-
- - github PR
-
-are all OK.
-
-### Coding Standards
-
-Code should look roughly like the existing code, which follows linux kernel
-coding style.
-
-If there are non-functional problems I will clean them out when I apply the
-patch.
-
-If there are functional problems (eg broken error paths etc) if they are
-small compared to the working part I will also clean them.  If there are
-larger problems, or consequences to the patch will have to discuss how to
-solve them with a retry.
-
-### Funding specific work
-
-If there is a feature you wish was supported in lws, consider paying for the
-work to be done.  The maintainer is a consultant and if we can agree the
-task, you can quickly get a high quality result that does just what you need,
-maintained ongoing along with the rest of lws.
-

+ 0 - 181
Source/ThirdParty/libwebsockets/READMEs/README.crypto-apis.md

@@ -1,181 +0,0 @@
-# Lws Crypto Apis
-
-## Overview
-
-![lws crypto overview](/doc-assets/lws-crypto-overview.svg)
-
-Lws provides a "generic" crypto layer on top of both OpenSSL and
-compatible tls library, and mbedtls.  Using this layer, your code
-can work without any changes on both types of tls library crypto
-backends... it's as simple as rebuilding lws with `-DLWS_WITH_MBEDTLS=0`
-or `=1` at cmake.
-
-The generic layer can be used directly (as in, eg, the sshd plugin),
-or via another layer on top, which processes JOSE JSON objects using
-JWS (JSON Web Signatures), JWK (JSON Web Keys), and JWE (JSON Web
-Encryption).
-
-The `JW` apis use the generic apis (`lws_genrsa_`, etc) to get the crypto tasks
-done, so anything they can do you can also get done using the generic apis.
-The main difference is that with the generic apis, you must instantiate the
-correct types and use type-specfic apis.  With the `JW` apis, there is only
-one interface for all operations, with the details hidden in the api and
-controlled by the JSON objects.
-
-Because of this, the `JW` apis are often preferred because they give you
-"crypto agility" cheaply... to change your crypto to another supported algorithm
-once it's working, you literally just change your JSON defining the keys and
-JWE or JWS algorithm.  (It's up to you to define your policy for which
-combinations are acceptable by querying the parsed JW structs).
-
-## Crypto supported in generic layer
-
-### Generic Hash
-
- - SHA1
- - SHA256
- - SHA384
- - SHA512
-
-### Generic HMAC
-
- - SHA256
- - SHA384
- - SHA512
-
-### Generic AES
-
- - CBC
- - CFB128
- - CFB8
- - CTR
- - ECB
- - OFB
- - XTS
- - GCM
- - KW (Key Wrap)
-
-### Generic RSA
-
- - PKCS 1.5
- - OAEP / PSS
-
-### Generic EC
-
- - ECDH
- - ECDSA
- - P256 / P384 / P521 (sic) curves
-
-## Using the generic layer
-
-All the necessary includes are part of `libwebsockets.h`.
-
-Enable `-DLWS_WITH_GENCRYPTO=1` at cmake.
-
-|api|header|Functionality|
-|---|---|---|
-|genhash|[./include/libwebsockets/lws-genhash.h](https://libwebsockets.org/git/libwebsockets/tree/include/libwebsockets/lws-genhash.h)|Provides SHA1 + SHA2 hashes and hmac|
-|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|
-|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|
-|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|
-|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|
-
-Unit 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)
-
-### Keys in the generic layer
-
-The necessary types and defines are brought in by `libwebsockets.h`.
-
-Keys are represented only by an array of `struct lws_jwk_elements`... the
-length of the array is defined by the cipher... it's one of
-
-|key elements count|definition|
-|---|---|
-|`LWS_COUNT_OCT_KEY_ELEMENTS`|1|
-|`LWS_COUNT_RSA_KEY_ELEMENTS`|8|
-|`LWS_COUNT_EC_KEY_ELEMENTS`|4|
-|`LWS_COUNT_AES_KEY_ELEMENTS`|1|
-
-`struct lws_jwk_elements` is a simple pointer / length combination used to
-store arbitrary octets that make up the key element's binary representation.
-
-## Using the JOSE layer
-
-The JOSE (JWK / JWS / JWE) stuff is a crypto-agile JSON-based layer
-that uses the gencrypto support underneath.
-
-"Crypto Agility" means the JSON structs include information about the
-algorithms and ciphers used in that particular object, making it easy to
-upgrade system crypto strength or cycle keys over time while supporting a
-transitional period where the old and new keys or algorithms + ciphers
-are also valid.
-
-Uniquely lws generic support means the JOSE stuff also has "tls library
-agility", code written to the lws generic or JOSE apis is completely unchanged
-even if the underlying tls library changes between OpenSSL and mbedtls, meaning
-sharing code between server and client sides is painless.
-
-All the necessary includes are part of `libwebsockets.h`.
-
-Enable `-DLWS_WITH_JOSE=1` at CMake.
-
-|api|header|Functionality|
-|---|---|---|
-|JOSE|[./include/libwebsockets/lws-jose.h](https://libwebsockets.org/git/libwebsockets/tree/include/libwebsockets/lws-jose.h)|Provides crypto agility for JWS / JWE|
-|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|
-|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|
-|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|
-
-Minimal examples are provided in the form of commandline tools for JWK / JWS / JWE / x509 handling:
-
- - [JWK minimal example](https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/crypto/minimal-crypto-jwk)
- - [JWS minimal example](https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/crypto/minimal-crypto-jws)
- - [JWE minimal example](https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/crypto/minimal-crypto-jwe)
- - [X509 minimal example](https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/crypto/minimal-crypto-x509)
-
-Unit 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)
-
-## Crypto supported in the JOSE layer
-
-The JOSE RFCs define specific short names for different algorithms
-
-### JWS
-
-|JSOE name|Hash|Signature|
----|---|---
-|RS256, RS384, RS512|SHA256/384/512|RSA
-|ES256, ES384, ES521|SHA256/384/512|EC
-
-### JWE
-
-|Key Encryption|Payload authentication + crypt|
-|---|---|
-|`RSAES-PKCS1-v1.5` 2048b & 4096b|`AES_128_CBC_HMAC_SHA_256`|
-|`RSAES-PKCS1-v1.5` 2048b|`AES_192_CBC_HMAC_SHA_384`|
-|`RSAES-PKCS1-v1.5` 2048b|`AES_256_CBC_HMAC_SHA_512`|
-|`RSAES-OAEP`|`AES_256_GCM`|
-|`AES128KW`, `AES192KW`, `AES256KW`|`AES_128_CBC_HMAC_SHA_256`|
-|`AES128KW`, `AES192KW`, `AES256KW`|`AES_192_CBC_HMAC_SHA_384`|
-|`AES128KW`, `AES192KW`, `AES256KW`|`AES_256_CBC_HMAC_SHA_512`|
-|`ECDH-ES` (P-256/384/521 key)|`AES_128/192/256_GCM`|
-|`ECDH-ES+A128/192/256KW` (P-256/384/521 key)|`AES_128/192/256_GCM`|
-
-### Keys in the JOSE layer
-
-Keys in the JOSE layer use a `struct lws_jwk`, this contains two arrays of
-`struct lws_jwk_elements` sized for the worst case (currently RSA).  One
-array contains the key elements as described for the generic case, and the
-other contains various nonencrypted key metadata taken from JWK JSON.
-
-|metadata index|function|
-|---|---|
-|`JWK_META_KTY`|Key type, eg, "EC"|
-|`JWK_META_KID`|Arbitrary ID string|
-|`JWK_META_USE`|What the public key may be used to validate, "enc" or "sig"|
-|`JWK_META_KEY_OPS`|Which operations the key is authorized for, eg, "encrypt"|
-|`JWK_META_X5C`|Optional X.509 cert version of the key|
-|`JWK_META_ALG`|Optional overall crypto algorithm the key is intended for use with|
-
-`lws_jwk_destroy()` should be called when the jwk is going out of scope... this
-takes care to zero down any key element data in the jwk.
-

+ 0 - 67
Source/ThirdParty/libwebsockets/READMEs/README.ctest.md

@@ -1,67 +0,0 @@
-## Using CTest with lws
-
-### Updating ancient cmake
-
-You need a recent cmake to have the CTest tests work properly, if you're on an
-older distro you need to update your cmake.  Luckily Kitware provide a repo for
-common distros.  These instructions work for bionic and xenial.
-
-First remove the old distro cmake and install the pieces needed to get the new repo keys
-
-```
-# apt purge --auto-remove cmake
-# apt install gnupg wget apt-transport-https ca-certificates
-# wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | sudo apt-key add -
-# apt edit-sources
-```
-
-Add the line `deb https://apt.kitware.com/ubuntu/ bionic main` at the end
-replacing `bionic` with `xenial` as needed, and save (:wq).  Then
-
-```
-# apt update
-# apt install cmake
-```
-
-## Generating the tests
-
-The main tests just need `-DLWS_WITH_MINIMAL_EXAMPLES=1`.  You can optionally set
-`-DLWS_CTEST_INTERNET_AVAILABLE=0` to indicate you can't run the tests that need
-internet connectivity.
-
-## Preparing to run the tests
-
-The tests have to spawn by script some "test buddies", for example the client
-tests have to run a test server from the built lws image.  For that reason you
-have to do a side-install into `./destdir` using `make install DESTDIR=../destdir`
-from the build directory before all the tests will work properly.
-
-## Running the tests
-
-CMake puts the test action into a build-host type specific form, for unix type
-platforms you just run `make test` or `CTEST_OUTPUT_ON_FAILURE=1 make test` to
-see what happened to any broken tests.
-
-On windows, it looks like `ctest . -C DEBUG` or RELEASE if that was the build
-type.
-
-## Considerations for creating tests
-
-### Timeout
-
-The default test timeout is 1500s, for that reason it's good practice to set
-a more suitable `TIMEOUT` property on every test.
-
-### Working Directory
-
-Server-side test apps usually need to be run from their `./minimal-examples/...`
-directory so they can access their assets like index.html etc.
-
-However when building with `-DLWS_WITH_MBEDTLS=1` then even client-side apps
-need to be run from their directory, since they need to get the trusted CA for
-warmcat.com or libwebsockets.org additionally.
-
-For that reason it's good practice to set the `WORKING_DIRECTORY` property to
-the home dir of the example app in all cases.
-
-

+ 0 - 63
Source/ThirdParty/libwebsockets/READMEs/README.debugging.md

@@ -1,63 +0,0 @@
-# Tips on debugging with lws
-
-## Problem with the library, or your code?
-
-Because lws is only really used when already combined with user code,
-it can be a headache figuring out if the actual problem is inside lws
-or in the user code.
-
-If it's in lws, I would really like to solve it, but if it's in your
-code, that's your problem.  Finding out which side it's on when it
-involves your code is also something you need to try to resolve.
-
-The minimal examples are useful because if they demonstrate the same
-problem, it's something about your platform or lws itself, I have the
-minimal examples so I can test it and find out if it's your platform.
-If I can reproduce it, it's my problem.
-
-## Debug builds
-
-With cmake, build with `-DCMAKE_BUILD_TYPE=DEBUG` to build in extra
-logging, and use a log level bitmap of eg, 1039 or 1151 to enable
-the extra logs for print.
-
-The minimal examples take a -d xxx commandline parameter so you can
-select the logging level when you run it.
-
-The extra logging can be very useful to understand the sequencing of
-problematic actions.
-
-## Valgrind
-
-If your problems involve heap corruption or use-after-free, Valgrind
-is indespensible.  It's simple to use, if you normally run `xxx`, just
-run `valgrind xxx`.  Your code will run slower, usually something
-like 2 - 4x slower but it depends on the exact code.  However you will
-get a backtrace as soon as there is some kind of misbehaviour of either
-lws or your code.
-
-lws is developed using valgrind routinely and strives to be completely
-valgrind-clean.  So typically any problems reported are telling you
-about problems in user code (or my bugs).
-
-## Traffic dumping
-
-The best place for dumping traffic, assuming you are linking against a
-tls library, is `lws_ssl_capable_read()` and `lws_ssl_capable_write()`
-in either `./lib/tls/openssl/openssl-ssl.c` or
-`./lib/tls/mbedtls/mbedtls-ssl.c` according to which tls library you
-are using.  There are default-`#if 0` sections in each function like
-
-```
-#if 0
-	/*
-	 * If using mbedtls type tls library, this is the earliest point for all
-	 * paths to dump what was received as decrypted data from the tls tunnel
-	 */
-	lwsl_notice("%s: len %d\n", __func__, len);
-	lwsl_hexdump_notice(buf, len);
-#endif
-```
-
-Enable these to get hexdumps for all unencrypted data in both directions.
-

+ 0 - 117
Source/ThirdParty/libwebsockets/READMEs/README.detailed-latency.md

@@ -1,117 +0,0 @@
-# lws detailed latency
-
-![lws detailed latency example plot](../doc-assets/lws-detailed-latency-example.png)
-
-## Introduction
-
-lws has the capability to make detailed latency measurements and
-report them in realtime to a specified callback.
-
-A default callback is provided that renders the data as text in
-space-separated format suitable for gnuplot, to a specified file.
-
-## Configuring
-
-Enable `LWS_WITH_DETAILED_LATENCY` at cmake.
-
-Create your context with something similar to this
-
-```
-#if defined(LWS_WITH_DETAILED_LATENCY)
-	info.detailed_latency_cb = lws_det_lat_plot_cb;
-	info.detailed_latency_filepath = "/tmp/lws-latency-results";
-#endif
-```
-
-`lws_det_lat_plot_cb` is provided by lws as a convenience to convert
-the stuct data provided at the callback interface to space-separated
-text data that is easy to process with shell commands and gnuplot.
-
-## `lws_det_lat_plot_cb` format
-
-```
-728239173547 N 23062 0 0 23062 0 0 0
-728239192554 C 18879 0 0 18879 0 0 0
-728239217894 T 25309 0 0 25309 0 0 0
-728239234998 r 0 0 0 0 271 172 256
-728239250611 r 0 0 0 0 69 934 4096
-728239255679 w 19 122 18 159 20 80 80
-728239275718 w 20 117 15 152 18 80 80
-728239295578 w 10 73 7 90 7 80 80
-728239315567 w 9 67 5 81 7 80 80
-728239335745 w 23 133 9 165 14 80 80
-...
-```
-
-Each event is shown in 9 columns
-
- - unix time in us
- - event type
-   - N = Name resolution
-   - C = TCP Connection
-   - T = TLS negotiation server
-   - t = TLS negotiation client
-   - r = Read
-   - w = Write
- - us duration, for w time client spent waiting to write
- - us duration, for w time data spent in transit to proxy
- - us duration, for w time proxy waited to send data
- - as a convenience, sum of last 3 columns above
- - us duration, time spent in callback
- - last 2 are actual / requested size in bytes
-
-## Processing captured data with ministat
-
-Eg, to summarize overall latencies on all captured writes
-
-```
- $ cat /tmp/lws-latency-results | grep " w " | cut -d' ' -f6 | ministat
-...
-    N           Min           Max        Median           Avg        Stddev
-x 1000            43           273           141       132.672     32.471693
-```
-
-## Processing captured data with gnuplot
-
-### Gnuplot plotting script
-
-Create a gnuplot script, eg myscript.gp
-
-```
-reset
-set term pngcairo enhanced nocrop font "OpenSans, 12" size 800,600#output terminal and file
-set output "lws-latency.png"
-#set yrange [0:10000]
-#to put an empty boundary around the
-#data inside an autoscaled graph.
-set offset graph 0.05,0.05,0.05,0.0
-set style fill transparent solid 0.5 #fillstyle
-set tics out nomirror
-set xlabel "event"
-set ylabel "latency (us)"
-set format x ""
-set title "Write latency"
-set key invert reverse Right inside nobox
-set key autotitle columnheader
-set style data histogram
-set style histogram rowstacked
-set style fill solid border -1
-set boxwidth 0.75
-set style fill solid 1.00 noborder
-set tic scale 0
-set grid ytics lc rgb "#505050"
-unset border
-unset xtics
-
-plot '/tmp/1' \
-	   using ($3 + $4 + $5):xtic(1)         w boxes lt rgbcolor "blue"  title 'prox wr wait', \
-	'' using ($3 + $4):xtic(1)         w boxes lt rgbcolor "green" title 'txfr to prox', \
-	'' using 3:xtic(1) w boxes lt rgbcolor "red"   title 'cli wri wait'
-```
-
-### gnuplot invocation
-
-```
- $ cat /tmp/lws-latency-results | grep " w " \>/tmp/1 ; gnuplot myscript.gp && eog lws-latency.png
-```
-

+ 0 - 37
Source/ThirdParty/libwebsockets/READMEs/README.esp32.md

@@ -1,37 +0,0 @@
-ESP32 Support
-=============
-
-See \ref esp32 for details on how to build lws as a component in an ESP-IDF project.
-
-Lws provides a "factory" application
-
-https://github.com/warmcat/lws-esp32-factory
-
-and a test application which implements the generic lws server test apps
-
-https://github.com/warmcat/lws-esp32-test-server-demos
-
-The 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.
-
-The 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.
-
-The 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.
-
-State|Image|AP SSID|Port|URL|Mode
----|---|---|---|---|---
-Factory Reset or Uninitialized|Factory|AP: ESP_012345|80|http://192.168.4.1|factory.html - to set certificates and serial
-User configuration|Factory|AP: config-model-serial|443|https://192.168.4.1|index.html - user set up his AP information
-Operation|OTA|Station only|443|https://model-serial.local|OTA application
-
-## Basic Auth
-
-The lws-esp32-test-server-demos app also demos basic auth.
-
-On a normal platform this is done by binding a mount to a text file somewhere in the filesystem, which
-contains user:password information one per line.
-
-On ESP32 there is not necessarily any generic VFS in use.  So instead, the basic auth lookup is bound to
-a given nvs domain, where the username is the key and the password the value.  main/main.c in the test
-demos app shows how to both make the mount use basic auth, and how to set a user:password combination
-using nvs.
-

+ 0 - 80
Source/ThirdParty/libwebsockets/READMEs/README.event-libs.md

@@ -1,80 +0,0 @@
-# lws event library support
-
-## v4.0 and below
-
-Before v4.1, lws allowed selecting some event library support for inclusion
-in the libwebsockets library
-
-Option|Feature
----|---
-`LWS_WITH_GLIB`|glib
-`LWS_WITH_LIBEVENT`|libevent
-`LWS_WITH_LIBUV`|libuv
-`LWS_WITH_LIBEV`|libev
-
-The user code can select by `info->options` flags at runtime which event loop
-it wants to use.
-
-The only restriction is that libev and libevent can't coexist, because their
-header namespace conflicts.
-
-## v4.1 and above
-
-Lws continues to support the old way described above, but there's an additional
-new cmake option that decides how they are built if any are selected,
-`LWS_WITH_EVLIB_PLUGINS`.
-
-The old behaviour is set by `LWS_WITH_EVLIB_PLUGINS=0`, for UNIX platforms, this
-is set to 1 by default.  This causes the enabled event lib support to each be built into
-its own dynamically linked plugin, and lws will bring in the requested support alone
-at runtime after seeing the `info->options` flags requested by the user code.
-
-This has two main benefits, first the conflict around building libevent and libev
-together is removed, they each build isolated in their own plugin; the libwebsockets
-core library build doesn't import any of their headers (see below for exception).
-And second, for distro packaging, the event lib support plugins can be separately
-packaged, and apps take dependencies on the specific event lib plugin package, which
-itself depends on the libwebsockets core library.  This allows just the needed
-dependencies for the packageset without forcing everything to bring everything in.
-
-Separately, lws itself has some optional dependencies on libuv, if you build lwsws
-or on Windows you want plugins at all.  CMake will detect these situations and
-select to link the lws library itself to libuv if so as well, independent of whatever
-is happening with the event lib support.
-
-## evlib plugin install
-
-The produced plugins are named
-
-event lib|plugin name
----|---
-glib|`libwebsockets-evlib_glib.so`
-event|`libwebsockets-evlib_event.so`
-uv|`libwebsockets-evlib_uv.so`
-ev|`libwebsockets-evlib_ev.so`
-
-The evlib plugins are installed alongside libwebsockets.so/.a into the configured
-library dir, it's often `/usr/local/lib/` by default on linux.
-
-Lws looks for them at runtime using the build-time-configured path.
-
-## Component packaging
-
-The canonical package name is `libwebsockets`, the recommended way to split the
-packaging is put the expected libs and pkgconfig in `libwebsockets` or `libwebsockets-core`,
-the latter is followed by the provided cmake, and produce an additional package per build
-event library plugin, named, eg `libwebsockets-evlib_glib`, which has a dependency on
-`libwebsockets[-core]`.
-
-Applications that use the default event loop can directly require `libwebsockets[-core]`,
-and application packages that need specific event loop support can just require, eg,
-`libwebsockets-evlib_glib`, which will bring that in and the core lws pieces in one step.
-There is then no problem with multiple apps requiring different event libs, they will
-bring in all the necessary pieces which will not conflict either as packages or at
-runtime.
-
-## `LWS_WITH_DISTRO_RECOMMENDED`
-
-The cmake helper config `LWS_WITH_DISTRO_RECOMMENDED` is adapted to build all the
-event libs with the event lib plugin support enabled.
-

+ 0 - 55
Source/ThirdParty/libwebsockets/READMEs/README.h2-long-poll.md

@@ -1,55 +0,0 @@
-# h2 long poll in lws
-
-lws server and client can support "immortal" streams that are
-not subject to normal timeouts under a special condition.  These
-are read-only (to the client).
-
-Network connections that contain at least one immortal stream
-are themselves not subject to timeouts until the last immortal
-stream they are carrying closes.
-
-Because of this, it's recommended there is some other way of
-confirming that the client is still active.
-
-## Setting up lws server for h2 long poll
-
-Vhosts that wish to allow clients to serve these immortal
-streams need to set the info.options flag `LWS_SERVER_OPTION_VH_H2_HALF_CLOSED_LONG_POLL`
-at vhost creation time.  The JSON config equivalent is to set
-
-```
-"h2-half-closed-long-poll": "1"
-```
-
-on the vhost.  That's all that is needed.
-
-Streams continue to act normally for timeout with the exception
-client streams are allowed to signal they are half-closing by
-sending a zero-length DATA frame with END_STREAM set.  These
-streams are allowed to exist outside of any timeout and data
-can be sent on them at will in the server -> client direction.
-
-## Setting client streams for long poll
-
-An API is provided to allow established h2 client streams to
-transition to immortal mode and send the END_STREAM to the server
-to indicate it.
-
-```
-int
-lws_h2_client_stream_long_poll_rxonly(struct lws *wsi);
-```
-
-## Example applications
-
-You can confirm the long poll flow simply using example applications.
-Build and run `http-server/minimal-http-server-h2-long-poll` in one
-terminal.
-
-In another, build the usual `http-client/minimal-http-client` example
-and run it with the flags `-l --long-poll`
-
-The client will connect to the server and transition to the immortal mode.
-The server sends a timestamp every minute to the client, and that will
-stay up without timeouts.
-

+ 0 - 172
Source/ThirdParty/libwebsockets/READMEs/README.http-fallback.md

@@ -1,172 +0,0 @@
-# Http fallback and raw proxying
-
-Lws has several interesting options and features that can be applied to get
-some special behaviours... this article discusses them and how they work.
-
-## Overview of normal vhost selection
-
-Lws supports multiple http or https vhosts sharing a listening socket on the
-same port.
-
-For unencrypted http, the Host: header is used to select which vhost the
-connection should bind to, by comparing what is given there against the
-names the server was configured with for the various vhosts.  If no match, it
-selects the first configured vhost.
-
-For TLS, it has an extension called SNI (Server Name Indication) which tells
-the server early in the TLS handshake the host name the connection is aimed at.
-That allows lws to select the vhost early, and use vhost-specific TLS certs
-so everything is happy.  Again, if there is no match the connection proceeds
-using the first configured vhost and its certs.
-
-## Http(s) fallback options
-
-What happens if you try to connect, eg, an ssh client to the http server port
-(this is not an idle question...)?  Obviously the http server part or the tls
-part of lws will fail the connection and close it.  (We will look at that flow
-in a moment in detail for both unencrypted and tls listeners.)
-
-However if the first configured vhost for the port was created with the
-vhost creation info struct `.options` flag `LWS_SERVER_OPTION_FALLBACK_TO_APPLY_LISTEN_ACCEPT_CONFIG`,
-then instead of the error, the connection transitions to whatever role was
-given in the vhost creation info struct `.listen_accept_role` and `.listen_accept_protocol`.
-
-With lejp-conf / lwsws, the options can be applied to the first vhost using:
-
-```
-   "listen-accept-role": "the-role-name",
-   "listen-accept-protocol": "the-protocol-name",
-   "fallback-listen-accept": "1"
-```
-
-See `./minimal-examples/raw/minimal-raw-fallback-http-server` for examples of
-all the options in use via commandline flags.
-
-So long as the first packet for the protocol doesn't look like GET, POST, or
-a valid tls packet if connection to an https vhost, this allows the one listen
-socket to handle both http(s) and a second protocol, as we will see, like ssh.
-
-Notice there is a restriction that no vhost selection processing is possible,
-neither for tls listeners nor plain http ones... the packet belonging to a
-different protocol will not send any Host: header nor tls SNI.
-
-Therefore although the flags and settings are applied to the first configured
-vhost, actually their effect is global for a given listen port.  If enabled,
-all vhosts on the same listen port will do the fallback action.
-
-### Plain http flow
-
-![plain http flow](/doc-assets/accept-flow-1.svg)
-
-Normally, if the first received packet does not contain a valid HTTP method,
-then the connection is dropped.  Which is what you want from an http server.
-
-However if enabled, the connection can transition to the defined secondary
-role / protocol.
-
-|Flag|lejp-conf / lwsws|Function|
-|---|---|---|
-|`LWS_SERVER_OPTION_FALLBACK_TO_APPLY_LISTEN_ACCEPT_CONFIG`|`"fallback-listen-accept": "1"`|Enable fallback processing|
-
-### TLS https flow
-
-![tls https flow](/doc-assets/accept-flow-2.svg)
-
-If the port is listening with tls, the point that a packet from a different
-protocol will fail is earlier, when the tls tunnel is being set up.
-
-|Flag|lejp-conf / lwsws|Function|
-|---|---|---|
-|`LWS_SERVER_OPTION_FALLBACK_TO_APPLY_LISTEN_ACCEPT_CONFIG`|`"fallback-listen-accept": "1"`|Enable fallback processing|
-|`LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS`|`"redirect-http": "1"`|Treat invalid tls packet as http, issue http redirect to https://|
-|`LWS_SERVER_OPTION_ALLOW_HTTP_ON_HTTPS_LISTENER`|`"allow-http-on-https": "1"`|Accept unencrypted http connections on this tls port (dangerous)|
-
-The latter two options are higher priority than, and defeat, the first one.
-
-### Non-http listener
-
-![non-http flow](/doc-assets/accept-flow-3.svg)
-
-It's also possible to skip the fallback processing and just force the first
-vhost on the port to use the specified role and protocol in the first place.
-
-|Flag|lejp-conf / lwsws|Function|
-|---|---|---|
-|LWS_SERVER_OPTION_ADOPT_APPLY_LISTEN_ACCEPT_CONFIG|`"apply-listen-accept": "1"`|Force vhost to use listen-accept-role / listen-accept-protocol|
-
-## Using http(s) fallback with raw-proxy
-
-If enabled for build with `cmake .. -DLWS_ROLE_RAW_PROXY=1 -DLWS_WITH_PLUGINS=1`
-then lws includes ready-to-use support for raw tcp proxying.
-
-This can be used standalone on the first vhost on a port, but most intriguingly
-it can be specified as the fallback for http(s)...
-
-See `./minimal-examples/raw/minimal-raw-proxy-fallback.c` for a working example.
-
-### fallback with raw-proxy in code
-
-On the first vhost for the port, specify the required "onward" pvo to configure
-the raw-proxy protocol...you can adjust the "ipv4:127.0.0.1:22" to whatever you
-want...
-
-```
-	static struct lws_protocol_vhost_options pvo1 = {
-	        NULL,
-	        NULL,
-	        "onward",		/* pvo name */
-	        "ipv4:127.0.0.1:22"	/* pvo value */
-	};
-
-	static const struct lws_protocol_vhost_options pvo = {
-	        NULL,           	/* "next" pvo linked-list */
-	        &pvo1,			/* "child" pvo linked-list */
-	        "raw-proxy",		/* protocol name we belong to on this vhost */
-	        ""              	/* ignored */
-	};
-```
-
-... and set up the fallback enable and bindings...
-
-```
-	info.options |= LWS_SERVER_OPTION_FALLBACK_TO_APPLY_LISTEN_ACCEPT_CONFIG;
-	info.listen_accept_role = "raw_proxy";
-	info.listen_accept_proxy = "raw_proxy";
-	info.pvo = &pvo;
-```
-
-### fallback with raw-proxy in JSON conf
-
-On the first vhost for the port, enable the raw-proxy protocol on the vhost and
-set the pvo config
-
-```
-                "ws-protocols": [{
-                        "raw-proxy": {
-                         "status": "ok",
-                         "onward": "ipv4:127.0.0.1:22"
-                        }
-                 }],
-```
-
-Enable the fallback behaviour on the vhost and the role / protocol binding
-
-```
-	"listen-accept-role": "raw-proxy",
-	"listen-accept-protocol": "raw-proxy",
-	"fallback-listen-accept": "1"
-```
-
-### Testing
-
-With this configured, the listen port will function normally for http or https
-depending on how it was set up.
-
-But if you try to connect to it with an ssh client, that will also work fine.
-
-The libwebsockets.org server is set up in this way, you can confirm it by
-visiting `https://libwebsockets.org` on port 443 as usual, but also trying
-`ssh -p 443 [email protected]`... you will get permission denied from
-your ssh client.  With valid credentials in fact that works perfectly for
-ssh, scp, git-over-ssh etc all on port 443...
-

+ 0 - 176
Source/ThirdParty/libwebsockets/READMEs/README.jwt.md

@@ -1,176 +0,0 @@
-# JWT support in lws
-
-lws supports the common usage scenarios of JWS (signed) JWT generation,
-parsing and transferring in and out as http cookies.  Care is taken to provide
-helpers that implement the current security best practices for cookie handling
-and JWT validation.  All of the common algorithms like ES512 are supported
-along with JWK generation and handling apis.
-
-The build options needed are `-DLWS_WITH_JOSE=1` `-DLWS_WITH_GENCRYPTO=1`.
-
-Underlying JOSE primitives are exposed as apis, some JWT specific primitives
-and finally a JWT-via http cookie level creation apis each building on top of
-what was underneath.
-
-The higher level APIs are provided additionally because they have the most
-opportunity for implementation pitfalls like not validating alg carefully, or
-not using the latest cookie security options; the provided APIs handle that
-centrally for you.  If your needs vary from what the higher level apis are
-doing, you can cut-and-paste out those implementations and create your own
-using the public lower level apis.
-
-## LWS JWT fields
-
-Lws JWT uses mainly well-known fields
-
-Field|Std|Meaning
----|---|---
-iss|yes|Issuer, typically the domain like "warmcat.com"
-aud|yes|Audience, typically a url path like "https://warmcat.com/sai"
-iat|yes|Unix-time "Issued At"
-nbf|yes|Unix-time "Not Before"
-exp|yes|Unix-time "Expired"
-sub|yes|Subject, eg, a username or user email
-csrf|no|A random 16-char hex token generated with the JWT for use in links specific to the JWT bearer
-ext|no|Application-specific JSON sub-object with whatever fields you need, eg, `"authorization": 1`
-
-## Approach for JWT as session token
-
-Once JWTs are produced, they are autonomous bearer tokens, if they are not kept
-secret between the browser and the site, they will be accepted as evidence for
-having rights to the session from anyone.
-
-Requiring https, and various other cookie hardening techniques make it more
-difficult for them to leak, but it is still necessary to strictly constrain the
-token's validity time, usually to a few tens of minutes or how long it takes a
-user to login and get stuff done on the site in one session.
-
-## CSRF mitigation
-
-Cross Site Request Forgery (CSRF) is a hacking scenario where an authorized
-user with a valid token is tricked into clicking on an external link that
-performs some action with side-effects on the site he has active auth on.  For
-example, he has a cookie that's logged into his bank, and the link posts a form
-to the bank site transferring money to the attacker.
-
-Lws JWT mitigates this possibility by putting a random secret in the generated
-JWT; when the authorized user presents his JWT to generate the page, generated
-links that require auth to perform their actions include the CSRF string from
-that user's current JWT.
-
-When the user clicks those links intentionally, the CSRF string in the link
-matches the CSRF string in the currently valid JWT that was also provided to
-the server along with the click, and all is well.
-
-An attacker does not know the random, ephemeral JWT CSRF secret to include in
-forged links, so the attacker-controlled action gets rejected at the server as
-having used an invalid link.
-
-The checking and link manipulation need to be implemented in user code / JS...
-lws JWT provides the random CSRF secret in the JWT and makes it visible to the
-server when the incoming JWT is processed.
-
-## Need for client tracking of short JWT validity times
-
-Many links or references on pages do not require CSRF strings, only those that
-perform actions with side-effects like deletion or money transfer should need
-protecting this way.
-
-Due to CSRF mitigation, generated pages containing the protected links
-effectively have an expiry time linked to that of the JWT, since only the bearer
-of the JWT used to generate the links on the page can use them; once that
-expires actually nobody can use them and the page contents, which may anyway
-be showing content that only authenticated users can see must be invalidated and
-re-fetched.  Even if the contents are visible without authentication, additional
-UI elements like delete buttons that should only be shown when authenticated
-will wrongly still be shown 
-
-For that reason, the client should be informed by the server along with the
-authentication status, the expiry time of it.  The client should then by itself
-make arrangements to refresh the page when this time is passed,
-either showing an unauthenticated version of the same page if it exists, or by
-redirecting to the site homepage if showing any of the contents required
-authentication.  The user can then log back in using his credientials typically
-stored in the browser's password store and receive a new short-term JWT with a
-new random csrf token along with a new page using the new csrf token in its
-links.
-
-## Considerations for long-lived connections
-
-Once established as authorized, websocket links may be very long-lived and hold
-their authorization state at the server.  Although the browser monitoring the
-JWT reloading the page on auth expiry should mitigate this, an attacker can
-choose to just not do that and have an immortally useful websocket link.
-
-At least for actions on the long-lived connection, it should not only confirm
-the JWT authorized it but that the current time is still before the "exp" time
-in the JWT, this is made available as `expiry_unix_time` in the args struct
-after successful validation.
-
-Ideally the server should close long-lived connections according to their auth
-expiry time.
-
-## JWT lower level APIs
-
-The related apis are in `./include/libwebsockets/lws-jws.h`
-
-### Validation of JWT
-
-```
-int
-lws_jwt_signed_validate(struct lws_context *ctx, struct lws_jwk *jwk,
-			const char *alg_list, const char *com, size_t len,
-			char *temp, int tl, char *out, size_t *out_len);
-```
-
-### Composing and signing JWT
-
-```
-int
-lws_jwt_sign_compact(struct lws_context *ctx, struct lws_jwk *jwk,
-		     const char *alg, char *out, size_t *out_len, char *temp,
-		     int tl, const char *format, ...);
-```
-
-## JWT creation and cookie get / set API
-
-Both the validation and signing apis use the same struct to contain their
-aguments.
-
-```
-struct lws_jwt_sign_set_cookie {
-	struct lws_jwk			*jwk;
-	/**< entry: required signing key */
-	const char			*alg;
-	/**< entry: required signing alg, eg, "ES512" */
-	const char 			*iss;
-	/**< entry: issuer name to use */
-	const char			*aud;
-	/**< entry: audience */
-	const char			*cookie_name;
-	/**< entry: the name of the cookie */
-	char				sub[33];
-	/**< sign-entry, validate-exit: subject */
-	const char			*extra_json;
-	/**< sign-entry, validate-exit:
-	 * optional "ext" JSON object contents for the JWT */
-	size_t				extra_json_len;
-	/**< validate-exit:
-	 * length of optional "ext" JSON object contents for the JWT */
-	const char			*csrf_in;
-	/**< validate-entry:
-	 * NULL, or an external CSRF token to check against what is in the JWT */
-	unsigned long			expiry_unix_time;
-	/**< sign-entry: seconds the JWT and cookie may live,
-	 * validate-exit: expiry unix time */
-};
-
-int
-lws_jwt_sign_token_set_http_cookie(struct lws *wsi,
-				   const struct lws_jwt_sign_set_cookie *i,
-				   uint8_t **p, uint8_t *end);
-int
-lws_jwt_get_http_cookie_validate_jwt(struct lws *wsi,
-				     struct lws_jwt_sign_set_cookie *i,
-				     char *out, size_t *out_len);
-```

+ 0 - 43
Source/ThirdParty/libwebsockets/READMEs/README.lifecycle.md

@@ -1,43 +0,0 @@
-# lws lifecycles
-
-## Context
-
-![context lifecycle](/doc-assets/lifecycle-context.png)
-
-## Client wsi
-
-![client wsi](/doc-assets/lifecycle-wsi.png)
-
-## Server wsi
-
-![server wsi](/doc-assets/lifecycle-server-wsi.png)
-
-## role-specific events
-
-role|client|server
----|---|---
-http COMPLETED|`LWS_CALLBACK_COMPLETED_CLIENT_HTTP`|-
-http RECEIVE|`LWS_CALLBACK_RECEIVE_CLIENT_HTTP`|`LWS_CALLBACK_RECEIVE_HTTP`
-http WRITEABLE|`LWS_CALLBACK_CLIENT_HTTP_WRITEABLE`|`LWS_CALLBACK_HTTP_WRITEABLE`
-http CLOSE|`LWS_CALLBACK_CLOSED_CLIENT_HTTP`|`LWS_CALLBACK_CLOSED_HTTP`
-http BIND|`LWS_CALLBACK_CLIENT_HTTP_BIND_PROTOCOL`|`LWS_CALLBACK_HTTP_BIND_PROTOCOL`
-http DROP|`LWS_CALLBACK_CLIENT_HTTP_DROP_PROTOCOL`|`LWS_CALLBACK_HTTP_DROP_PROTOCOL`
-
-role|client|server
----|---|---
-ws ESTABLISHED|`LWS_CALLBACK_CLIENT_ESTABLISHED`|`LWS_CALLBACK_ESTABLISHED`
-ws RECEIVE|`LWS_CALLBACK_CLIENT_RECEIVE`|`LWS_CALLBACK_RECEIVE`
-ws WRITEABLE|`LWS_CALLBACK_CLIENT_WRITEABLE`|`LWS_CALLBACK_SERVER_WRITEABLE`
-ws CLOSE|`LWS_CALLBACK_CLIENT_CLOSED`|`LWS_CALLBACK_CLOSED`
-ws BIND|`LWS_CALLBACK_WS_CLIENT_BIND_PROTOCOL`|`LWS_CALLBACK_WS_BIND_PROTOCOL`
-ws DROP|`LWS_CALLBACK_WS_CLIENT_DROP_PROTOCOL`|`LWS_CALLBACK_WS_DROP_PROTOCOL`
-
-role|client|server
----|---|---
-raw ESTABLISHED|`LWS_CALLBACK_RAW_CONNECTED`|`LWS_CALLBACK_RAW_ADOPT`
-raw RECEIVE|`LWS_CALLBACK_RAW_RX`|`LWS_CALLBACK_RAW_RX`
-raw WRITEABLE|`LWS_CALLBACK_RAW_WRITEABLE`|`LWS_CALLBACK_RAW_WRITEABLE`
-raw CLOSE|`LWS_CALLBACK_RAW_CLOSE`|`LWS_CALLBACK_RAW_CLOSE`
-raw BIND|`LWS_CALLBACK_RAW_SKT_BIND_PROTOCOL`|`LWS_CALLBACK_RAW_SKT_BIND_PROTOCOL`
-raw DROP|`LWS_CALLBACK_RAW_SKT_DROP_PROTOCOL`|`LWS_CALLBACK_RAW_SKT_DROP_PROTOCOL`
-

+ 0 - 130
Source/ThirdParty/libwebsockets/READMEs/README.lws_dll.md

@@ -1,130 +0,0 @@
-# lws_dll Doubly-linked list
-
-## Introduction
-
-Lws supports two kinds of doubly-linked list, `lws_dll` and `lws_dll2`.
-
-Unless memory is at a big premium, or it has to work on lws < v3.2, it's
-best to simply use `lws_dll2`.
-
-![lws_dll overview](../doc-assets/lws_dll.svg)
-
-## How to use
-
-The basics are the same for lws_dll and lws_dll2.
-
-The list objects point only to themselves, and you use the `lws_container_of`
-macro to get a pointer to your struct that contains the list object.  Doing
-it this way
-
- - the list object does not have to be the first thing in your struct
- 
- - your struct can contain multiple list objects and appear on lists belonging
-   to multiple owners simultaenously,
-   
-### lws_dll Minimal example
-
-```
-struct mystruct {
-	....
-	lws_dll list;
-	...
-};
-
-lws_dll owner;
-```
-
-Adding a mystruct to the owner list (...add_tail() works the same way but adds
-to the other end of the list)
-
-```
-	struct mystruct *p;
-	
-	...
-	
-	lws_dll_add_head(&p->list, &owner);
-```
-
-Removing the list object from its owner
-
-```
-	lws_dll2_remove(&p->list, &owner);
-```
-
-If you have a `struct lws_dll *d` pointing to `list` in struct mystruct, you can
-convert it to a `struct mystruct *p` ike this
-
-```
-	struct mystruct *p = lws_container_of(d, struct lws_dll, list);
-```
-
-### lws_dll2 Minimal example
-
-
-```
-struct mystruct {
-	....
-	lws_dll2 list;
-	...
-};
-
-lws_dll2_owner owner;
-```
-
-Adding a mystruct to the owner list (...add_tail() works the same way but adds
-to the other end of the list)
-
-```
-	struct mystruct *p;
-	
-	...
-	
-	lws_dll2_add_head(&p->list, &owner);
-```
-
-Removing the list object from its owner (notice compared to lws_dll, it doesn't
-need to be told the owner)
-
-```
-	lws_dll2_remove(&p->list);
-```
-
-If you have a `struct lws_dll2 *d` pointing to `list` in struct mystruct, you
-can convert it to a `struct mystruct *p` ike this
-
-```
-	struct mystruct *p = lws_container_of(d, struct lws_dll2, list);
-```
-
-## Summary Comparing lws_dll and lws_dll2
-
- - both offer a doubly-linked list object, and (since v3.2) track both the
-   head and tail in an "list owner" object
-   
- - both are initalized by memsetting to 0
-
- - for `lws_dll`, it reuses an `lws_dll` as the "owner", for `lws_dll2`, there's a
-   specific `lws_dll2_owner` structure for that
-   
- - `lws_dll2_owner` also keeps count of the number of list elements
- 
- - `lws_dll2` knows which owner's list it is participating on.  So it can remove
-   itself and update the owner without the caller needing to know its owner.
-   In the case there are several potential owners list objects may be on, this
-   is very convenient.
-
- - `lws_dll` is simpler and has a smaller footprint (two pointers per entry vs
-   three).  But you have to know the exact list owner to perform operations on
-   it.
- 
-## apis
- 
-|function|lws_dll|lws_dll2|
-|---|---|---|
-|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)`|
-|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)`|
-|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)`|
-|get owner|(not supported)|`struct lws_dll2_owner * lws_dll2_owner(const struct lws_dll2 *d)`|
-|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)`|
-|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))`|
-

+ 0 - 105
Source/ThirdParty/libwebsockets/READMEs/README.lws_plugins.md

@@ -1,105 +0,0 @@
-# lws_plugins
-
-Lws now offers apis to manage your own user plugins with `LWS_WITH_PLUGINS_API`.
-Lws uses these apis internally for protocol plugins and event loop plugins
-if they're selected for build.  But they are also exported for user code to
-use them how you like.
-
-## Creating your plugin export
-
-### Specifying your plugin export type
-
-Lws plugins have a single exported struct with a specified header and a user
-defined remainder.  The public `lws_plugin_header_t` describes the common
-plugin export header, it's defined via libwebsockets.h as
-
-```
-typedef struct lws_plugin_header {
-	const char *name;
-	const char *_class;
-
-	unsigned int api_magic;
-	/* set to LWS_PLUGIN_API_MAGIC at plugin build time */
-
-	/* plugin-class specific superclass data follows */
-} lws_plugin_header_t;
-```
-
-The exported symbol name itself must match the plugin filename, for
-example if the symbol name is `my_plugin`, then the filename of the
-plugin might be `libmyapp-my_plugin.so` or similar... the matching
-part is after the first `-` or `_`, up to the first `.`.  The exact
-details differ by platform but these rules cover the supported
-platforms.  If lws has the filename of the plugin, it can then
-deduce the symbol export it should look for in the plugin.
-
-`name` is a freeform human-readable description for the plugin.
-
-`_class` is shared by your plugins and used to select them from other kinds
-of plugin that may be in the same dir.  So choose a unique name like
-`"myapp xxx plugin"` or whatever shared by all plugins of that class.
-
-`api_magic` is set to `LWS_PLUGIN_API_MAGIC` to detect if the plugin is
-incompatible with the lws plugin apis version.
-
-So for example your plugin type wrapping the header might look like
-
-```
-typedef struct myapp_plugin {
-        lws_plugin_header_t	hdr; /* must be first */
-
-	/* optional extra data like function pointers from your plugin */
-	mytype_t		mymember;
-	/* ... */
-} myapp_plugin_t;
-```
-
-Typically, you will put function pointers to whatever capability your plugin
-class offers as the additional members.
-
-## Building your own plugins
-
-Plugins are built standalone, cmake is recommended but you can do what you want.
-
-The only requirement is the single visible export of the plugin name, eg
-
-```
-const myapp_plugin_t my_plugin = {
-	.hdr = {
-		"my_plugin",
-		"myapp xxx plugin",
-		LWS_PLUGIN_API_MAGIC
-	},
-
-	.mymember	= my_plugin_init,
-	/*...*/
-};
-```
-
-## Bringing in plugins at runtime
-
-Lws provides an api to import plugins into the process space and another to
-remove and destroy plugins.
-
-You can take two approaches depending on what you're doing, either bring in and
-later destroy a whole class of plugins at once, and walk them via a linked-list,
-or bring in and later destroy a single specific plugin from the class by filtering
-on its specific export name.
-
-See `include/libwebsockets/lws-protocols-plugins.h` for documentation.
-
-```
-LWS_VISIBLE LWS_EXTERN int
-lws_plugins_init(struct lws_plugin **pplugin, const char * const *d,
-		 const char *_class, const char *filter,
-		 each_plugin_cb_t each, void *each_user);
-
-LWS_VISIBLE LWS_EXTERN int
-lws_plugins_destroy(struct lws_plugin **pplugin, each_plugin_cb_t each,
-		    void *each_user);
-```
-
-`struct lws_plugin` is a public struct that contains the linked-list of loaded
-plugins and a pointer to its exported header object, so you can walk this
-after loading.
-

+ 0 - 98
Source/ThirdParty/libwebsockets/READMEs/README.lws_retry.md

@@ -1,98 +0,0 @@
-# `lws_retry_bo_t` client connection management
-
-This struct sets the policy for delays between retries, and for
-how long a connection may be 'idle' before it first tries to
-ping / pong on it to confirm it's up, or drops the connection
-if still idle.
-
-## Retry rate limiting
-
-You can define a table of ms-resolution delays indexed by which
-connection attempt number is ongoing, this is pointed to by
-`.retry_ms_table` with `.retry_ms_table_count` containing the
-count of table entries.
-
-`.conceal_count` is the number of retries that should be allowed
-before informing the parent that the connection has failed.  If it's
-greater than the number of entries in the table, the last entry is
-reused for the additional attempts.
-
-`.jitter_percent` controls how much additional random delay is
-added to the actual interval to be used... this stops a lot of
-devices all synchronizing when they try to connect after a single
-trigger event and DDoS-ing the server.
-
-The struct and apis are provided for user implementations, lws does
-not offer reconnection itself.
-
-## Connection validity management
-
-Lws has a sophisticated idea of connection validity and the need to
-reconfirm that a connection is still operable if proof of validity
-has not been seen for some time.  It concerns itself only with network
-connections rather than streams, for example, it only checks h2
-network connections rather than the individual streams inside (which
-is consistent with h2 PING frames only working at the network stream
-level itself).
-
-Connections may fail in a variety of ways, these include that no traffic
-at all is passing, or, eg, incoming traffic may be received but no
-outbound traffic is making it to the network, and vice versa.  In the
-case that tx is not failing at any point but just isn't getting sent,
-endpoints can potentially kid themselves that since "they are sending"
-and they are seeing RX, the combination means the connection is valid.
-This can potentially continue for a long time if the peer is not
-performing keepalives.
-
-"Connection validity" is proven when one side sends something and later
-receives a response that can only have been generated by the peer
-receiving what was just sent.  This can happen for some kinds of user
-transactions on any stream using the connection, or by sending PING /
-PONG protocol packets where the PONG is only returned for a received PING.
-
-To ensure that the generated traffic is only sent when necessary, user
-code can report for any stream that it has observed a transaction amounting
-to a proof of connection validity using an api.  This resets the timer for
-the associated network connection before the validity is considered
-expired.
-
-`.secs_since_valid_ping` in the retry struct sets the number of seconds since
-the last validity after which lws will issue a protocol-specific PING of some
-kind on the connection.  `.secs_since_valid_hangup` specifies how long lws
-will allow the connection to go without a confirmation of validity before
-simply hanging up on it.
-
-## Defaults
-
-The context defaults to having a 5m valid ping interval and 5m10s hangup interval,
-ie, it'll send a ping at 5m idle if the protocol supports it, and if no response
-validating the connection arrives in another 10s, hang up the connection.
-
-User code can set this in the context creation info and can individually set the
-retry policy per vhost for server connections.  Client connections can set it
-per connection in the client creation info `.retry_and_idle_policy`.
-
-## Checking for h2 and ws
-
-Check using paired minimal examples with the -v flag on one or both sides to get a
-small validity check period set of 3s / 10s
-
-Also give, eg, -d1039 to see info level debug logging
-
-### h2
-
-```
-$ lws-minimal-http-server-h2-long-poll -v
-
-$ lws-minimal-http-client -l -v
-```
-
-### ws
-
-```
-$ lws-minimal-ws-server-h2 -s -v
-
-$ lws-minimal-ws-client-ping -n --server 127.0.0.1 --port 7681 -v
-```
-
-

+ 0 - 149
Source/ThirdParty/libwebsockets/READMEs/README.lws_sequencer.md

@@ -1,149 +0,0 @@
-# `struct lws_sequencer` introduction
-
-Often a single network action like a client GET is just part of a
-larger series of actions, perhaps involving different connections.
-
-Since lws operates inside an event loop, if the outer sequencing
-doesn't, it can be awkward to synchronize these steps with what's
-happening on the network with a particular connection on the event
-loop thread.
-
-![lws_sequencer](/doc-assets/lws_sequencer.svg)
-
-`struct lws_sequencer` provides a generic way to stage multi-step
-operations from inside the event loop.  Because it participates
-in the event loop similar to a wsi, it always operates from the
-service thread context and can access structures that share the
-service thread without locking.  It can also provide its own
-higher-level timeout handling.
-
-Naturally you can have many of them running in the same event
-loop operating independently.
-
-Sequencers themselves bind to a pt (per-thread) service thread,
-by default there's only one of these and it's the same as saying
-they bind to an `lws_context`.  The sequencer callback may create
-wsi which in turn are bound to a vhost, but the sequencer itself
-is above all that.
-
-## Sequencer timeouts
-
-The sequencer additionally maintains its own second-resolution timeout
-checked by lws for the step being sequenced... this is independent of
-any lws wsi timeouts which tend to be set and reset for very short-term
-timeout protection inside one transaction.
-
-The sequencer timeout operates separately and above any wsi timeout, and
-is typically only reset by the sequencer callback when it receives an
-event indicating a step completed or failed, or it sets up the next sequence
-step.
-
-If the sequencer timeout expires, then the sequencer receives a queued
-`LWSSEQ_TIMED_OUT` message informing it, and it can take corrective action
-or schedule a retry of the step.  This message is queued and sent normally
-under the service thread context and in order of receipt.
-
-Unlike lws timeouts which force the wsi to close, the sequencer timeout
-only sends the message.  This allows the timeout to be used to, eg, wait
-out a retry cooloff period and then start the retry when the
-`LWSSEQ_TIMED_OUT` is received, according to the state of the sequencer.
-
-## Creating an `struct lws_sequencer`
-
-```
-typedef struct lws_seq_info {
-	struct lws_context		*context;   /* lws_context for seq */
-	int				tsi;	    /* thread service idx */
-	size_t				user_size;  /* size of user alloc */
-	void				**puser;    /* place ptr to user */
-	lws_seq_event_cb		cb;	    /* seq callback */
-	const char			*name;	    /* seq name */
-	const lws_retry_bo_t		*retry;	    /* retry policy */
-} lws_seq_info_t;
-```
-
-```
-struct lws_sequencer *
-lws_sequencer_create(lws_seq_info_t *info);
-```
-
-When created, in lws the sequencer objects are bound to a 'per-thread',
-which is by default the same as to say bound to the `lws_context`.  You
-can tag them with an opaque user data pointer, and they are also bound to
-a user-specified callback which handles sequencer events
-
-```
-typedef int (*lws_seq_event_cb)(struct lws_sequencer *seq, void *user_data,
-				lws_seq_events_t event, void *data);
-```
-
-`struct lws_sequencer` objects are private to lws and opaque to the user.  A small
-set of apis lets you perform operations on the pointer returned by the
-create api.
-
-## Queueing events on a sequencer
-
-Each sequencer object can be passed "events", which are held on a per-sequencer
-queue and handled strictly in the order they arrived on subsequent event loops.
-`LWSSEQ_CREATED` and `LWSSEQ_DESTROYED` events are produced by lws reflecting
-the sequencer's lifecycle, but otherwise the event indexes have a user-defined
-meaning and are queued on the sequencer by user code for eventual consumption
-by user code in the sequencer callback.
-
-Pending events are removed from the sequencer queues and sent to the sequencer
-callback from inside the event loop at a rate of one per event loop wait.
-
-## Destroying sequencers
-
-`struct lws_sequencer` objects are cleaned up during context destruction if they are
-still around.
-
-Normally the sequencer callback receives a queued message that
-informs it that it's either failed at the current step, or succeeded and that
-was the last step, and requests that it should be destroyed by returning
-`LWSSEQ_RET_DESTROY` from the sequencer callback.
-
-## Lifecycle considerations
-
-Sequencers may spawn additional assets like client wsi as part of the sequenced
-actions... the lifecycle of the sequencer and the assets overlap but do not
-necessarily depend on each other... that is a wsi created by the sequencer may
-outlive the sequencer.
-
-It's important therefore to detach assets from the sequencer and the sequencer
-from the assets when each step is over and the asset is "out of scope" for the
-sequencer.  It doesn't necessarily mean closing the assets, just making sure
-pointers are invalidated.  For example, if a client wsi held a pointer to the
-sequencer as its `.user_data`, when the wsi is out of scope for the sequencer
-it can set it to NULL, eg, `lws_set_wsi_user(wsi, NULL);`.
-
-Under some conditions wsi may want to hang around a bit to see if there is a
-subsequent client wsi transaction they can be reused on.  They will clean
-themselves up when they time out.
-
-## Watching wsi lifecycle from a sequencer
-
-When a sequencer is creating a wsi as part of its sequence, it will be very
-interested in lifecycle events.  At client wsi creation time, the sequencer
-callback can set info->seq to itself in order to receive lifecycle messages
-about its wsi.
-
-|message|meaning|
-|---|---|
-|`LWSSEQ_WSI_CONNECTED`|The wsi has become connected|
-|`LWSSEQ_WSI_CONN_FAIL`|The wsi has failed to connect|
-|`LWSSEQ_WSI_CONN_CLOSE`|The wsi had been connected, but has now closed|
-
-By receiving these, the sequencer can understand when it should attempt
-reconnections or that it cannot progress the sequence.
-
-When dealing with wsi that were created by the sequencer, they may close at
-any time, eg, be closed by the remote peer or an intermediary.  The
-`LWSSEQ_WSI_CONN_CLOSE` message may have been queued but since they are
-strictly handled in the order they arrived, before it was
-handled an earlier message may want to cause some api to be called on
-the now-free()-d wsi.  To detect this situation safely, there is a
-sequencer api `lws_sequencer_check_wsi()` which peeks the message
-buffer and returns nonzero if it later contains an `LWSSEQ_WSI_CONN_CLOSE`
-already.
-

+ 0 - 38
Source/ThirdParty/libwebsockets/READMEs/README.lws_struct.md

@@ -1,38 +0,0 @@
-# lws_struct
-
-## Overview
-
-lws_struct provides a lightweight method for serializing and deserializing C
-structs to and from JSON, and to and from sqlite3.
-
-![lws_struct overview](../doc-assets/lws_struct-overview.svg)
-
- - you provide a metadata array describing struct members one-time, then call
-   generic apis to serialize and deserialize 
-
- - supports flat structs, single child struct pointers, and unbounded arrays /
-   linked-lists of child objects automatically using [lws_dll2 linked-lists](./README.lws_dll.md)
- 
- - supports boolean and C types char, int, long, long long in explicitly signed
-   and unsigned forms
- 
- - supports both char * type string members where the unbounded content is
-   separate and pointed to, and fixed length char array[] type members where
-   the content is part of the struct
-
- - huge linear strings are supported by storing to a temp lwsac of chained chunks,
-   which is written into a single linear chunk in the main lwsac once the
-   total string length is known
-   
- - deserialization allocates into an [lwsac](../lib/misc/lwsac/README.md), so everything is inside as few
-   heap allocations as possible while still able to expand to handle arbitrary
-   array or strins sizes
-   
- - when deserialized structs are finished with, a single call to free the
-   lwsac frees the whole thing without having to walk it
-   
- - stateful serializaton and deserialization allows as-you-get packets incremental
-   parsing and production of chunks of as-you-can-send incremental serialization
-   output cleanly
-
-## Examples

+ 0 - 99
Source/ThirdParty/libwebsockets/READMEs/README.lws_sul.md

@@ -1,99 +0,0 @@
-# `lws_sul` scheduler api
-
-Since v3.2 lws no longer requires periodic checking for timeouts and
-other events.  A new system was refactored in where future events are
-scheduled on to a single, unified, sorted linked-list in time order,
-with everything at us resolution.
-
-This makes it very cheap to know when the next scheduled event is
-coming and restrict the poll wait to match, or for event libraries
-set a timer to wake at the earliest event when returning to the
-event loop.
-
-Everything that was checked periodically was converted to use `lws_sul`
-and schedule its own later event.  The end result is when lws is idle,
-it will stay asleep in the poll wait until a network event or the next
-scheduled `lws_sul` event happens, which is optimal for power.
-
-# Side effect for older code
-
-If your older code uses `lws_service_fd()`, it used to be necessary
-to call this with a NULL pollfd periodically to indicate you wanted
-to let the background checks happen.  `lws_sul` eliminates the whole
-concept of periodic checking and NULL is no longer a valid pollfd
-value for this and related apis.
-
-# Using `lws_sul` in user code
-
-See `minimal-http-client-multi` for an example of using the `lws_sul`
-scheduler from your own code; it uses it to spread out connection
-attempts so they are staggered in time.  You must create an
-`lws_sorted_usec_list_t` object somewhere, eg, in you own existing object.
-
-```
-static lws_sorted_usec_list_t sul_stagger;
-```
-
-Create your own callback for the event... the argument points to the sul object
-used when the callback was scheduled.  You can use pointer arithmetic to translate
-that to your own struct when the `lws_sorted_usec_list_t` was a member of the
-same struct.
-
-```
-static void
-stagger_cb(lws_sorted_usec_list_t *sul)
-{
-...
-}
-```
-
-When you want to schedule the callback, use `lws_sul_schedule()`... this will call
-it 10ms in the future
-
-```
-	lws_sul_schedule(context, 0, &sul_stagger, stagger_cb, 10 * LWS_US_PER_MS);
-```
-
-In the case you destroy your object and need to cancel the scheduled callback, use
-
-```
-	lws_sul_schedule(context, 0, &sul_stagger, NULL, LWS_SET_TIMER_USEC_CANCEL);
-```
-
-# lws_sul2 and system suspend
-
-In v4.1, alongside the existing `lws_sul` apis there is a refactor and additional
-functionality aimed at negotiating system suspend, while remaining completely
-backwards-compatible with v3.2+ lws_sul apis.
-
-Devicewide suspend is basically the withdrawal of CPU availability for an unbounded
-amount of time, so what may have been scheduled by the user code may miss its time
-slot because the cpu was down and nothing is getting serviced.  Whether that is
-actively desirable, OK, a big disaster, or a failure that will be corrected at other
-layers at the cost of, eg, some additional latency, depends on the required device
-behaviours and the function of the user code that was scheduled, and its meaning to
-the system.
-
-Before v4.1, lws just offers the same scheduling service for everything both internal
-and arranged by user code, and has no way to know what is critical for the device to
-operate as intended, and so must force wake from suspend, or if for that scheduled
-event 'failure [to get the event] is an option'.
-
-For example locally-initiated periodic keepalive pings not happening may allow
-persistently dead (ie, no longer passing data) connections to remain unrenewed, but
-eventually when suspend ends for another reason, the locally-initiated PING probes
-will resume and it will be discovered and if the connectivity allows, corrected.
-
-If the device's function can handle the latency of there being no connectivity in
-suspend under those conditions until it wakes for another reason, it's OK for these
-kind of timeouts to be suppressed during suspend and basically take the power saving
-instead.  If for a particular device it's intolerable to ever have a silently dead
-connection for more than a very short time compared to suspend durations, then these
-kind of timeouts must have the priority to wake the whole device from suspend so
-they continue to operate unimpeded.
-
-That is just one example, lws offers generic scheduler services the user code can
-exploit for any purpose, including mission-critical ones.  The changes give the user
-code a way to tell lws if a particular scheduled event is important enough to the
-system operation to wake the system from devicewide suspend.
-

+ 0 - 219
Source/ThirdParty/libwebsockets/READMEs/README.lws_system.md

@@ -1,219 +0,0 @@
-# `lws_system`
-
-See `include/libwebsockets/lws-system.h` for function and object prototypes.
-
-## System integration api
-
-`lws_system` allows you to set a `system_ops` struct at context creation time,
-which can write up some function callbacks for system integration.  The goal
-is the user code calls these by getting the ops struct pointer from the
-context using `lws_system_get_ops(context)` and so does not spread system
-dependencies around the user code, making it directly usable on completely
-different platforms.
-
-```
-typedef struct lws_system_ops {
-	int (*reboot)(void);
-	int (*set_clock)(lws_usec_t us);
-	int (*attach)(struct lws_context *context, int tsi, lws_attach_cb_t cb,
-		      lws_system_states_t state, void *opaque,
-		      struct lws_attach_item **get);
-} lws_system_ops_t;
-```
-
-|Item|Meaning|
-|---|---|
-|`(*reboot)()`|Reboot the system|
-|`(*set_clock)()`|Set the system clock|
-|`(*attach)()`|Request an event loop callback from another thread context|
-
-### `reboot`
-
-Reboots the device
-
-### `set_clock`
-
-Set the system clock to us-resolution Unix time in seconds
-
-### `attach`
-
-Request a callback from the event loop from a foreign thread.  This is used, for
-example, for foreign threads to set up their event loop activity in their
-callback, and eg, exit once it is done, with their event loop activity able to
-continue wholly from the lws event loop thread and stack context.
-
-## Foreign thread `attach` architecture
-
-When lws is started, it should define an `lws_system_ops_t` at context creation
-time which defines its `.attach` handler.  In the `.attach` handler
-implementation, it should perform platform-specific locking around a call to
-`__lws_system_attach()`, a public lws api that actually queues the callback
-request and does the main work.  The platform-specific wrapper is just there to
-do the locking so multiple calls from different threads to the `.attach()`
-operation can't conflict.
-
-User code can indicate it wants a callback from the lws event loop like this:
-
-```
-lws_system_get_ops(context)->attach(context, tsi, cb, state, opaque, NULL)
-```
-
-`context` is a pointer to the lws_context, `tsi` is normally 0, `cb` is the user
-callback in the form  
-
-```
-void (*lws_attach_cb_t)(struct lws_context *context, int tsi, void *opaque);
-```
-
-`state` is the `lws_system` state we should have reached before performing the
-callback (usually, `LWS_SYSTATE_OPERATIONAL`), and `opaque` is a user pointer that
-will be passed into the callback.
-
-`cb` will normally want to create scheduled events and set up lws network-related
-activity from the event loop thread and stack context.
-
-Once the event loop callback has been booked by calling this api, the thread and
-its stack context that booked it may be freed.  It will be called back and can
-continue operations from the lws event loop thread and stack context.  For that
-reason, if `opaque` is needed it will usually point to something on the heap,
-since the stack context active at the time the callback was booked may be long
-dead by the time of the callback. 
-
-See ./lib/system/README.md for more details.
-
-## `lws_system` blobs
-
-"Blobs" are arbitrary binary objects that have a total length.  Lws lets you set
-them in two ways
-
- - "directly", by pointing to them, which has no heap implication
-
- - "heap", by adding one or more arbitrary chunk to a chained heap object
-
-In the "heap" case, it can be incrementally defined and the blob doesn't all
-have to be declared at once.
-
-For read, the same api allows you to read all or part of the blob into a user
-buffer. 
-
-The following kinds of blob are defined 
-
-|Item|Meaning|
-|---|---|
-|`LWS_SYSBLOB_TYPE_AUTH`|Auth-related blob 1, typically a registration token|
-|`LWS_SYSBLOB_TYPE_AUTH + 1`|Auth-related blob 2, typically an auth token|
-|`LWS_SYSBLOB_TYPE_CLIENT_CERT_DER`|Client cert public part|
-|`LWS_SYSBLOB_TYPE_CLIENT_KEY_DER`|Client cert key part|
-|`LWS_SYSBLOB_TYPE_DEVICE_SERIAL`|Arbitrary device serial number|
-|`LWS_SYSBLOB_TYPE_DEVICE_FW_VERSION`|Arbitrary firmware version|
-|`LWS_SYSBLOB_TYPE_DEVICE_TYPE`|Arbitrary Device Type identifier|
-|`LWS_SYSBLOB_TYPE_NTP_SERVER`|String with the ntp server address (defaults to pool.ntp.org)|
-
-### Blob handle api
-
-Returns an object representing the blob for a particular type (listed above)
-
-```
-lws_system_blob_t *
-lws_system_get_blob(struct lws_context *context, lws_system_blob_item_t type,
-                    int idx);
-```
-
-### Blob Setting apis
-
-Sets the blob to point length `len` at `ptr`.  No heap allocation is used.
-
-```
-void
-lws_system_blob_direct_set(lws_system_blob_t *b, const uint8_t *ptr, size_t len);
-```
-
-Allocates and copied `len` bytes from `buf` into heap and chains it on the end of
-any existing.
-
-```
-int
-lws_system_blob_heap_append(lws_system_blob_t *b, const uint8_t *buf, size_t len)
-```
-
-Remove any content from the blob, freeing it if it was on the heap
-
-```
-void
-lws_system_blob_heap_empty(lws_system_blob_t *b)
-```
-
-### Blob getting apis
-
-Get the total size of the blob (ie, if on the heap, the aggreate size of all the
-chunks that were appeneded)
-
-```
-size_t
-lws_system_blob_get_size(lws_system_blob_t *b)
-```
-
-Copy part or all of the blob starting at offset ofs into a user buffer at buf.
-`*len` should be the length of the user buffer on entry, on exit it's set to
-the used extent of `buf`.  This works the same whether the bob is a direct pointer
-or on the heap.
-
-```
-int
-lws_system_blob_get(lws_system_blob_t *b, uint8_t *buf, size_t *len, size_t ofs)
-```
-
-If you know that the blob was handled as a single direct pointer, or a single
-allocation, you can get a pointer to it without copying using this.
-
-```
-int
-lws_system_blob_get_single_ptr(lws_system_blob_t *b, const uint8_t **ptr)
-```
-
-### Blob destroy api
-
-Deallocates any heap allocation for the blob
-
-```
-void
-lws_system_blob_destroy(lws_system_blob_t *b)
-```
-
-
-## System state and notifiers
-
-Lws implements a state in the context that reflects the readiness of the system
-for various steps leading up to normal operation.  By default it acts in a
-backwards-compatible way and directly reaches the OPERATIONAL state just after
-the context is created.
-
-However other pieces of lws, and user, code may define notification handlers
-that get called back when the state changes incrementally, and may veto or delay
-the changes until work necessary for the new state has completed asynchronously.
-
-The generic states defined are:
-
-|State|Meaning|
-|---|---|
-|`LWS_SYSTATE_CONTEXT_CREATED`|The context was just created.|
-|`LWS_SYSTATE_INITIALIZED`|The vhost protocols have been initialized|
-|`LWS_SYSTATE_IFACE_COLDPLUG`|Existing network interfaces have been iterated|
-|`LWS_SYSTATE_DHCP`|Network identity is available|
-|`LWS_SYSTATE_TIME_VALID`|The system knows the time|
-|`LWS_SYSTATE_POLICY_VALID`|If the system needs information about how to act from the net, it has it|
-|`LWS_SYSTATE_REGISTERED`|The device has a registered identity|
-|`LWS_SYSTATE_AUTH1`|The device identity has produced a time-limited access token|
-|`LWS_SYSTATE_AUTH2`|Optional second access token for different services|
-|`LWS_SYSTATE_OPERATIONAL`|The system is ready for user code to work normally|
-|`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|
-
-### Inserting a notifier
-
-You should create an object `lws_system_notify_link_t` in non-const memory and zero it down.
-Set the `notify_cb` member and the `name` member and then register it using either
-`lws_system_reg_notifier()` or the `.register_notifier_list`
-member of the context creation info struct to make sure it will exist early
-enough to see all events.  The context creation info method takes a list of
-pointers to notify_link structs ending with a NULL entry.
-

+ 0 - 702
Source/ThirdParty/libwebsockets/READMEs/README.lwsws.md

@@ -1,702 +0,0 @@
-Notes about lwsws
-=================
-
-@section lwsws Libwebsockets Web Server
-
-lwsws is an implementation of a very lightweight, ws-capable generic web
-server, which uses libwebsockets to implement everything underneath.
-
-If you are basically implementing a standalone server with lws, you can avoid
-reinventing the wheel and use a debugged server including lws.
-
-
-@section lwswsb Build
-
-Just enable -DLWS_WITH_LWSWS=1 at cmake-time.
-
-It enables libuv and plugin support automatically.
-
-NOTICE on Ubuntu, the default libuv package is called "libuv-0.10".  This is ancient.
-
-You should replace this with libuv1 and libuv1-dev before proceeding.
-
-@section lwswsc Lwsws Configuration
-
-lwsws uses JSON config files, they're pure JSON except:
-
- - '#' may be used to turn the rest of the line into a comment.
-
- - There's also a single substitution, if a string contains "_lws_ddir_", then that is
-replaced with the LWS install data directory path, eg, "/usr/share" or whatever was
-set when LWS was built + installed.  That lets you refer to installed paths without
-having to change the config if your install path was different.
-
-There is a single file intended for global settings
-
-/etc/lwsws/conf
-```
-	# these are the server global settings
-	# stuff related to vhosts should go in one
-	# file per vhost in ../conf.d/
-
-	{
-	  "global": {
-	   "username": "apache",
-	   "groupname": "apache",
-	   "count-threads": "1",
-	   "server-string": "myserver v1", # returned in http headers
-	   "ws-pingpong-secs": "200", # confirm idle established ws connections this often
-	   "init-ssl": "yes"
-	 }
-	}
-```
-and a config directory intended to take one file per vhost
-
-/etc/lwsws/conf.d/warmcat.com
-```
-	{
-		"vhosts": [{
-			"name": "warmcat.com",
-			"port": "443",
-			"interface": "eth0",  # optional
-			"host-ssl-key": "/etc/pki/tls/private/warmcat.com.key",  # if given enable ssl
-			"host-ssl-cert": "/etc/pki/tls/certs/warmcat.com.crt",
-			"host-ssl-ca": "/etc/pki/tls/certs/warmcat.com.cer",
-			"mounts": [{  # autoserve
-				"mountpoint": "/",
-				"origin": "file:///var/www/warmcat.com",
-				"default": "index.html"
-			}]
-		}]
-	}
-```
-To get started quickly, an example config reproducing the old test server
-on port 7681, non-SSL is provided.  To set it up
-```
-	# mkdir -p /etc/lwsws/conf.d /var/log/lwsws
-	# cp ./lwsws/etc-lwsws-conf-EXAMPLE /etc/lwsws/conf
-	# cp ./lwsws/etc-lwsws-conf.d-localhost-EXAMPLE /etc/lwsws/conf.d/test-server
-	# sudo lwsws
-```
-
-@section lwswsacme Using Letsencrypt or other ACME providers
-
-Lws supports automatic provisioning and renewal of TLS certificates.
-
-See ./READMEs/README.plugin-acme.md for examples of how to set it up on an lwsws vhost.
-
-@section lwsogo Other Global Options
-
- - `reject-service-keywords` allows you to return an HTTP error code and message of your choice
-if a keyword is found in the user agent
-
-```
-   "reject-service-keywords": [{
-        "scumbot": "404 Not Found"
-   }]
-```
-
- - `timeout-secs` lets you set the global timeout for various network-related
- operations in lws, in seconds.  It defaults to 5.
- 
-@section lwswsv Lwsws Vhosts
-
-One server can run many vhosts, where SSL is in use SNI is used to match
-the connection to a vhost and its vhost-specific SSL keys during SSL
-negotiation.
-
-Listing multiple vhosts looks something like this
-```
-	{
-	 "vhosts": [ {
-	     "name": "localhost",
-	     "port": "443",
-	     "host-ssl-key":  "/etc/pki/tls/private/libwebsockets.org.key",
-	     "host-ssl-cert": "/etc/pki/tls/certs/libwebsockets.org.crt",
-	     "host-ssl-ca":   "/etc/pki/tls/certs/libwebsockets.org.cer",
-	     "mounts": [{
-	       "mountpoint": "/",
-	       "origin": "file:///var/www/libwebsockets.org",
-	       "default": "index.html"
-	       }, {
-	        "mountpoint": "/testserver",
-	        "origin": "file:///usr/local/share/libwebsockets-test-server",
-	        "default": "test.html"
-	       }],
-	     # which protocols are enabled for this vhost, and optional
-	     # vhost-specific config options for the protocol
-	     #
-	     "ws-protocols": [{
-	       "warmcat,timezoom": {
-	         "status": "ok"
-	       }
-	     }]
-	    },
-	    {
-	    "name": "localhost",
-	    "port": "7681",
-	     "host-ssl-key":  "/etc/pki/tls/private/libwebsockets.org.key",
-	     "host-ssl-cert": "/etc/pki/tls/certs/libwebsockets.org.crt",
-	     "host-ssl-ca":   "/etc/pki/tls/certs/libwebsockets.org.cer",
-	     "mounts": [{
-	       "mountpoint": "/",
-	       "origin": ">https://localhost"
-	     }]
-	   },
-	    {
-	    "name": "localhost",
-	    "port": "80",
-	     "mounts": [{
-	       "mountpoint": "/",
-	       "origin": ">https://localhost"
-	     }]
-	   }
-	
-	  ]
-	}
-```
-
-That 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
-
-
-@section lwswsvn Lwsws Vhost name and port sharing
-
-The vhost name field is used to match on incoming SNI or Host: header, so it
-must always be the host name used to reach the vhost externally.
-
- - Vhosts may have the same name and different ports, these will each create a
-listening socket on the appropriate port.
-
- - Vhosts may also have the same port and different name: these will be treated as
-true vhosts on one listening socket and the active vhost decided at SSL
-negotiation time (via SNI) or if no SSL, then after the Host: header from
-the client has been parsed.
-
-
-@section lwswspr Lwsws Protocols
-
-Vhosts by default have available the union of any initial protocols from context creation time, and
-any protocols exposed by plugins.
-
-Vhosts can select which plugins they want to offer and give them per-vhost settings using this syntax
-```
-	     "ws-protocols": [{
-	       "warmcat-timezoom": {
-	         "status": "ok"
-	       }
-	     }]
-```
-
-The "x":"y" parameters like "status":"ok" are made available to the protocol during its per-vhost
-LWS_CALLBACK_PROTOCOL_INIT (in is a pointer to a linked list of struct lws_protocol_vhost_options
-containing the name and value pointers).
-
-To indicate that a protocol should be used when no Protocol: header is sent
-by the client, you can use "default": "1"
-```
-	     "ws-protocols": [{
-	       "warmcat-timezoom": {
-	         "status": "ok",
-	         "default": "1"
-	       }
-	     }]
-```
-
-Similarly, if your vhost is serving a raw protocol, you can mark the protocol
-to be selected using "raw": "1"
-```
-	     "ws-protocols": [{
-	       "warmcat-timezoom": {
-	         "status": "ok",
-	         "raw": "1"
-	       }
-	     }]
-```
-
-See also "apply-listen-accept" below.
-
-@section lwswsovo Lwsws Other vhost options
-
- - If the three options `host-ssl-cert`, `host-ssl-ca` and `host-ssl-key` are given, then the vhost supports SSL.
-
- 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.
-
- - `keeplive-timeout` (in secs) defaults to 60 for lwsws, it may be set as a vhost option
-
- - `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.
-
- - "`unix-socket`": "1" causes the unix socket specified in the interface option to be used instead of an INET socket
-
- - "`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.
-
- - "`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.
-
- - "`access-log`": "filepath"   sets where apache-compatible access logs will be written
-
- - `"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.
-
- - "`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.
- 
- If you need to allow weaker ciphers, you can provide an alternative list here per-vhost.
-
- - "`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
-
- - "`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.
-
- - "`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.
- 
- - "`ecdh-curve`": "<curve name>"   The default ecdh curve is "prime256v1", but you can override it here, per-vhost
-
- - "`noipv6`": "on"  Disable ipv6 completely for this vhost
-
- - "`ipv6only`": "on"  Only allow ipv6 on this vhost / "off" only allow ipv4 on this vhost
-
- - "`ssl-option-set`": "<decimal>"  Sets the SSL option flag value for the vhost.
- It may be used multiple times and OR's the flags together.
- 
- The values are derived from /usr/include/openssl/ssl.h
-```
-	 # define SSL_OP_NO_TLSv1_1                               0x10000000L
-```
- 
- would equate to
- 
-```
-	 "`ssl-option-set`": "268435456"
- ```
- - "`ssl-option-clear'": "<decimal>"   Clears the SSL option flag value for the vhost.
- It may be used multiple times and OR's the flags together.
-
- - "`ssl-client-option-set`" and "`ssl-client-option-clear`" work the same way for the vhost Client SSL context
-
- - "`headers':: [{ "header1": "h1value", "header2": "h2value" }] 
-
-allows you to set arbitrary headers on every file served by the vhost
-
-recommended vhost headers for good client security are
-
-```
-                   "headers": [{
-                        "Content-Security-Policy": "script-src 'self'",
-                        "X-Content-Type-Options": "nosniff",
-                        "X-XSS-Protection": "1; mode=block",
-                        "X-Frame-Options": "SAMEORIGIN"
-                 }]
-
-```
-
- - "`apply-listen-accept`": "on"  This vhost only serves a non-http protocol, specified in "listen-accept-role" and "listen-accept-protocol"
-
-@section lwswsm Lwsws Mounts
-
-Where mounts are given in the vhost definition, then directory contents may
-be auto-served if it matches the mountpoint.
-
-Mount protocols are used to control what kind of translation happens
-
- - file://  serve the uri using the remainder of the url past the mountpoint based on the origin directory.
-
- Eg, with this mountpoint
-```
-	       {
-	        "mountpoint": "/",
-	        "origin": "file:///var/www/mysite.com",
-	        "default": "/"
-	       }
-```
- The uri /file.jpg would serve /var/www/mysite.com/file.jpg, since / matched.
-
- - ^http:// or ^https://  these cause any url matching the mountpoint to issue a redirect to the origin url
-
- - cgi://   this causes any matching url to be given to the named cgi, eg
-```
-	       {
-	        "mountpoint": "/git",
-	        "origin": "cgi:///var/www/cgi-bin/cgit",
-	        "default": "/"
-	       }, {
-	        "mountpoint": "/cgit-data",
-	        "origin": "file:///usr/share/cgit",
-	        "default": "/"
-	       },
-```
- would cause the url /git/myrepo to pass "myrepo" to the cgi /var/www/cgi-bin/cgit and send the results to the client.
-
- - http:// or https://  these perform reverse proxying, serving the remote origin content from the mountpoint.  Eg
-
-```
-		{
-		 "mountpoint": "/proxytest",
-		 "origin": "https://libwebsockets.org"
-		}
-```
-
-This 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.
-
-`/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.
-
-In addition link and src urls in the document are rewritten so / or the origin url part are rewritten to the mountpoint part.
-
-
-@section lwswsomo Lwsws Other mount options
-
-1) Some protocols may want "per-mount options" in name:value format.  You can
-provide them using "pmo"
-
-	       {
-	        "mountpoint": "/stuff",
-	        "origin": "callback://myprotocol",
-	        "pmo": [{
-	                "myname": "myvalue"
-	        }]
-	       }
-
-2) When using a cgi:// protocol origin at a mountpoint, you may also give cgi environment variables specific to the mountpoint like this
-```
-	       {
-	        "mountpoint": "/git",
-	        "origin": "cgi:///var/www/cgi-bin/cgit",
-	        "default": "/",
-	        "cgi-env": [{
-	                "CGIT_CONFIG": "/etc/cgitrc/libwebsockets.org"
-	        }]
-	       }
-```
- This allows you to customize one cgi depending on the mountpoint (and / or vhost).
-
-3) It's also possible to set the cgi timeout (in secs) per cgi:// mount, like this
-```
-	"cgi-timeout": "30"
-```
-4) `callback://` protocol may be used when defining a mount to associate a
-named protocol callback with the URL namespace area.  For example
-```
-	       {
-	        "mountpoint": "/formtest",
-	        "origin": "callback://protocol-post-demo"
-	       }
-```
-All handling of client access to /formtest[anything] will be passed to the
-callback registered to the protocol "protocol-post-demo".
-
-This is useful for handling POST http body content or general non-cgi http
-payload generation inside a plugin.
-
-See the related notes in README.coding.md
-
-5) Cache policy of the files in the mount can also be set.  If no
-options are given, the content is marked uncacheable.
-```
-	       {
-	        "mountpoint": "/",
-	        "origin": "file:///var/www/mysite.com",
-	        "cache-max-age": "60",      # seconds
-	        "cache-reuse": "1",         # allow reuse at client at all
-	        "cache-revalidate": "1",    # check it with server each time
-	        "cache-intermediaries": "1" # allow intermediary caches to hold
-	       }
-```
-
-6) You can also define a list of additional mimetypes per-mount
-```
-	        "extra-mimetypes": {
-	                 ".zip": "application/zip",
-	                 ".doc": "text/evil"
-	         }
-```
-
-Normally a file suffix MUST match one of the canned mimetypes or one of the extra
-mimetypes, or the file is not served.  This adds a little bit of security because
-even if there is a bug somewhere and the mount dirs are circumvented, lws will not
-serve, eg, /etc/passwd.
-
-If you provide an extra mimetype entry
-
-			"*": ""
-
-Then any file is served, if the mimetype was not known then it is served without a
-Content-Type: header.
-
-7) A mount can be protected by HTTP Basic Auth.  This only makes sense when using
-https, since otherwise the password can be sniffed.
-
-You can add a `basic-auth` entry on an http mount like this
-
-```
-{
-        "mountpoint": "/basic-auth",
-        "origin": "file://_lws_ddir_/libwebsockets-test-server/private",
-        "basic-auth": "/var/www/balogins-private"
-}
-```
-
-Before serving anything, lws will signal to the browser that a username / password
-combination is required, and it will pop up a dialog.  When the user has filled it
-in, lwsws checks the user:password string against the text file named in the `basic-auth`
-entry.
-
-The file should contain user:pass one per line
-
-```
-testuser:testpass
-myuser:hispass
-```
-
-The file should be readable by lwsws, and for a little bit of extra security not
-have a file suffix, so lws would reject to serve it even if it could find it on
-a mount.
-
-After successful authentication, `WSI_TOKEN_HTTP_AUTHORIZATION` contains the
-authenticated username.
-
-In the case you want to also protect being able to connect to a ws protocol on
-a particular vhost by requiring the http part can authenticate using Basic
-Auth before the ws upgrade, this is also possible.  In this case, the
-"basic-auth": and filepath to the credentials file is passed as a pvo in the
-"ws-protocols" section of the vhost definition.
-
-@section lwswscc Requiring a Client Cert on a vhost
-
-You can make a vhost insist to get a client certificate from the peer before
-allowing the connection with
-
-```
-	"client-cert-required": "1"
-```
-
-the connection will only proceed if the client certificate was signed by the
-same CA as the server has been told to trust.
-
-@section rawconf Configuring Fallback and Raw vhosts
-
-Lws supports some unusual modes for vhost listen sockets, which may be
-configured entirely using the JSON per-vhost config language in the related
-vhost configuration section.
-
-There are three main uses for them
-
-1) A vhost bound to a specific role and protocol, not http.  This binds all
-incoming connections on the vhost listen socket to the "raw-proxy" role and
-protocol "myprotocol".
-
-```
-	"listen-accept-role":		"raw-proxy",
-	"listen-accept-protocol":	"myprotocol",
-	"apply-listen-accept":		"1"
-```
-
-2) A vhost that wants to treat noncompliant connections for http or https as
-   belonging to a secondary fallback role and protocol.  This causes non-https
-   connections to an https listener to stop being treated as https, to lose the
-   tls wrapper, and bind to role "raw-proxy" and protocol "myprotocol".  For
-   example, connect a browser on your external IP :443 as usual and it serves
-   as normal, but if you have configured the raw-proxy to portforward
-   127.0.0.1:22, then connecting your ssh client to your external port 443 will
-   instead proxy your sshd over :443 with no http or tls getting in the way.
-
-```
-	"listen-accept-role":		"raw-proxy",
-	"listen-accept-protocol":	"myprotocol",
-	"fallback-listen-accept":	"1",
-	"allow-non-tls":		"1"
-```
-
-3) A vhost wants to either redirect stray http traffic back to https, or to
-   actually serve http on an https listen socket (this is not recommended
-   since it allows anyone to drop the security assurances of https by
-   accident or design).
-
-```
-	"allow-non-tls":		"1",
-	"redirect-http":		"1",
-```
-
-...or,
-
-```
-	"allow-non-tls":		"1",
-	"allow-http-on-https":		"1",
-```
-
-@section lwswspl Lwsws Plugins
-
-Protcols and extensions may also be provided from "plugins", these are
-lightweight dynamic libraries.  They are scanned for at init time, and
-any protocols and extensions found are added to the list given at context
-creation time.
-
-Protocols receive init (LWS_CALLBACK_PROTOCOL_INIT) and destruction
-(LWS_CALLBACK_PROTOCOL_DESTROY) callbacks per-vhost, and there are arrangements
-they can make per-vhost allocations and get hold of the correct pointer from
-the wsi at the callback.
-
-This allows a protocol to choose to strictly segregate data on a per-vhost
-basis, and also allows the plugin to handle its own initialization and
-context storage.
-
-To help that happen conveniently, there are some new apis
-
- - lws_vhost_get(wsi)
- - lws_protocol_get(wsi)
- - lws_callback_on_writable_all_protocol_vhost(vhost, protocol)
- - lws_protocol_vh_priv_zalloc(vhost, protocol, size)
- - lws_protocol_vh_priv_get(vhost, protocol)
- 
-dumb increment, mirror and status protocol plugins are provided as examples.
-
-
-@section lwswsplaplp Additional plugin search paths
-
-Packages that have their own lws plugins can install them in their own
-preferred dir and ask lwsws to scan there by using a config fragment
-like this, in its own conf.d/ file managed by the other package
-```
-	{
-	  "global": {
-	   "plugin-dir": "/usr/local/share/coherent-timeline/plugins"
-	  }
-	}
-```
-
-@section lwswsssp lws-server-status plugin
-
-One provided protocol can be used to monitor the server status.
-
-Enable the protocol like this on a vhost's ws-protocols section
-```
-	       "lws-server-status": {
-	         "status": "ok",
-	         "update-ms": "5000"
-	       }
-```
-`"update-ms"` is used to control how often updated JSON is sent on a ws link.
-
-And map the provided HTML into the vhost in the mounts section
-```
-	       {
-	        "mountpoint": "/server-status",
-	        "origin": "file:///usr/local/share/libwebsockets-test-server/server-status",
-	        "default": "server-status.html"
-	       }
-```
-You might choose to put it on its own vhost which has "interface": "lo", so it's not
-externally visible, or use the Basic Auth support to require authentication to
-access it.
-
-`"hide-vhosts": "{0 | 1}"` lets you control if information about your vhosts is included.
-Since this includes mounts, you might not want to leak that information, mount names,
-etc.
-
-`"filespath":"{path}"` lets you give a server filepath which is read and sent to the browser
-on each refresh.  For example, you can provide server temperature information on most
-Linux systems by giving an appropriate path down /sys.
-
-This may be given multiple times.
-
-
-@section lwswsreload Lwsws Configuration Reload
-
-You may send lwsws a `HUP` signal, by, eg
-
-```
-$ sudo killall -HUP lwsws
-```
-
-This causes lwsws to "deprecate" the existing lwsws process, and remove and close all of
-its listen sockets, but otherwise allowing it to continue to run, until all
-of its open connections close.
-
-When a deprecated lwsws process has no open connections left, it is destroyed
-automatically.
-
-After sending the SIGHUP to the main lwsws process, a new lwsws process, which can
-pick up the newly-available listen sockets, and use the current configuration
-files, is automatically started.
-
-The new configuration may differ from the original one in arbitrary ways, the new
-context is created from scratch each time without reference to the original one.
-
-Notes
-
-1) Protocols that provide a "shared world" like mirror will have as many "worlds"
-as there are lwsws processes still active.  People connected to a deprecated lwsws
-process remain connected to the existing peers.
-
-But any new connections will apply to the new lwsws process, which does not share
-per-vhost "shared world" data with the deprecated process.  That means no new
-connections on the deprecated context, ie a "shrinking world" for those guys, and a
-"growing world" for people who connect after the SIGHUP.
-
-2) The new lwsws process owes nothing to the previous one.  It starts with fresh
-plugins, fresh configuration, fresh root privileges if that how you start it.
-
-The plugins may have been updated in arbitrary ways including struct size changes
-etc, and lwsws or lws may also have been updated arbitrarily.
-
-3) A root parent process is left up that is not able to do anything except
-respond to SIGHUP or SIGTERM.  Actual serving and network listening etc happens
-in child processes which use the privileges set in the lwsws config files.
-
-@section lwswssysd Lwsws Integration with Systemd
-
-lwsws needs a service file like this as `/usr/lib/systemd/system/lwsws.service`
-```
-[Unit]
-Description=Libwebsockets Web Server
-After=syslog.target
-
-[Service]
-ExecStart=/usr/local/bin/lwsws 
-ExecReload=/usr/bin/killall -s SIGHUP lwsws ; sleep 1 ; /usr/local/bin/lwsws
-StandardError=null
-
-[Install]
-WantedBy=multi-user.target
-```
-
-You can find this prepared in `./lwsws/usr-lib-systemd-system-lwsws.service`
-
-
-@section lwswslr Lwsws Integration with logrotate
-
-For correct operation with logrotate, `/etc/logrotate.d/lwsws` (if that's
-where we're putting the logs) should contain
-```
-	/var/log/lwsws/*log {
-	    copytruncate
-	    missingok
-	    notifempty
-	    delaycompress
-	}
-```
-You can find this prepared in `/lwsws/etc-logrotate.d-lwsws`
-
-Prepare the log directory like this
-
-```
-	sudo mkdir /var/log/lwsws
-	sudo chmod 700 /var/log/lwsws
-```
-
-@section lwswsgdb Debugging lwsws with gdb
-
-Hopefully 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
-
-```
-sudo gdb -ex "set follow-fork-mode child" -ex "run" --args /usr/local/bin/lwsws
-
-```
-
-this will give nice backtraces in lwsws itself and in plugins, if they were built with symbols.
-
-@section lwswsvgd Running lwsws under valgrind
-
-You can just run lwsws under valgrind as usual and get valid results.  However the results / analysis part of valgrind runs
-after the plugins have removed themselves, this means valgrind backtraces into plugin code is opaque, without
-source-level info because the dynamic library is gone.
-
-There's a simple workaround, use LD_PRELOAD=<plugin.so> before running lwsws, this has the loader bring the plugin
-in before executing lwsws as if it was a direct dependency.  That means it's still mapped until the whole process
-exits after valgtind has done its thing.
-
-

+ 0 - 180
Source/ThirdParty/libwebsockets/READMEs/README.plugin-acme.md

@@ -1,180 +0,0 @@
-lws-acme-client Plugin
-======================
-
-## Introduction
-
-lws-acme-client is a protcol plugin for libwebsockets that implements an
-ACME client able to communicate with let's encrypt and other certificate
-providers.
-
-It implements `tls-sni-01` challenge, and is able to provision tls certificates
-"from thin air" that are accepted by all the major browsers.  It also manages
-re-requesting the certificate when it only has two weeks left to run.
-
-It works with both the OpenSSL and mbedTLS backends.
-
-## Overview for use
-
-You need to:
-
- - Provide name resolution to the IP with your server, ie, myserver.com needs to
- resolve to the IP that hosts your server
-
- - Enable port forwarding / external firewall access to your port, usually 443
-
- - Enable the "lws-acme-client" plugin on the vhosts you want it to manage
-   certs for
-
- - Add per-vhost options describing what should be in the certificate
-
-After that the plugin will sort everything else out.
-
-## Example lwsws setup
-
-```
- "vhosts": [ {
-	"name": 		   "home.warmcat.com",
-	"port":			   "443",
-        "host-ssl-cert":           "/etc/lwsws/acme/home.warmcat.com.crt.pem",
-        "host-ssl-key":            "/etc/lwsws/acme/home.warmcat.com.key.pem",
-        "ignore-missing-cert":     "1",
-	"access-log": 		   "/var/log/lwsws/test-access-log",
-        "ws-protocols": [{
-	  "lws-acme-client": {
-	    "auth-path":	   "/etc/lwsws/acme/auth.jwk",
-	    "cert-path":           "/etc/lwsws/acme/home.warmcat.com.crt.pem",
-	    "key-path":            "/etc/lwsws/acme/home.warmcat.com.key.pem",
-	    "directory-url":       "https://acme-staging.api.letsencrypt.org/directory",
-	    "country":             "TW",
-	    "state":               "Taipei",
-	    "locality":            "Xiaobitan",
-	    "organization":        "Crash Barrier Ltd",
-	    "common-name":         "home.warmcat.com",
-	    "email":               "[email protected]"
-	  },
-	  ...
-```
-
-## Required PVOs
-
-Notice that the `"host-ssl-cert"` and `"host-ssl-key"` entries have the same
-meaning as usual, they point to your certificate and private key.  However
-because the ACME plugin can provision these, you should also mark the vhost with
-`"ignore-missing-cert" : "1"`, so lwsws will ignore what will initially be
-missing certificate / keys on that vhost, and will set about creating the
-necessary certs and keys instead of erroring out.
-
-You must make sure the directories mentioned here exist, lws doesn't create them
-for you.  They should be 0700 root:root, even if you drop lws privileges.
-
-If you are implementing support in code, this corresponds to making sure the
-vhost creating `info.options` has the `LWS_SERVER_OPTION_IGNORE_MISSING_CERT`
-bit set.
-
-Similarly, in code, the each of the per-vhost options shown above can be
-provided in a linked-list of structs at vhost creation time.  See
-`./test-apps/test-server-v2.0.c` for example code for providing pvos.
-
-### auth-path
-
-This is where the plugin will store the auth keys it generated.
-
-### cert-path
-
-Where the plugin will store the certificate file.  Should match `host-ssl-cert`
-that the vhost wants to use.
-
-The path should include at least one 0700 root:root directory.
-
-### key-path
-
-Where the plugin will store the certificate keys.  Again it should match
-`host-ssl-key` the vhost is trying to use.
-
-The path should include at least one 0700 root:root directory.
-
-### directory-url
-
-This defines the URL of the certification server you will get your
-certificates from.  For let's encrypt, they have a "practice" one
-
- - `https://acme-staging.api.letsencrypt.org/directory`
-
-and they have a "real" one
-
- - `https://acme-v01.api.letsencrypt.org/directory`
-
-the main difference is the CA certificate for the real one is in most browsers
-already, but the staging one's CA certificate isn't.  The staging server will
-also let you abuse it more in terms of repeated testing etc.
-
-It's recommended you confirm expected operation with the staging directory-url,
-and then switch to the "real" URL.
-
-### common-name
-
-Your server DNS name, like "libwebsockets.org".  The remote ACME server will
-use this to find your server to perform the SNI challenges.
-
-### email
-
-The contact email address for the certificate.
-
-## Optional PVOs
-
-These are not included in the cert by letsencrypt
-
-### country
-
-Two-letter country code for the certificate
-
-### state
-
-State "or province" for the certificate
-
-### locality
-
-Locality for the certificate
-
-### organization
-
-Your company name
-
-## Security / Key storage considerations
-
-The `lws-acme-client` plugin is able to provision and update your certificate
-and keys in an entirely root-only storage environment, even though lws runs
-as a different uid / gid with no privileges to access the storage dir.
-
-It does this by opening and holding two WRONLY fds on "update paths" inside the
-root directory structure for each cert and key it manages; these are the normal
-cert and key paths with `.upd` appended.  If during the time the server is up
-the certs become within two weeks of expiry, the `lws-acme-client` plugin will
-negotiate new certs and write them to the file descriptors.
-
-Next time the server starts, if it sees `.upd` cert and keys, it will back up
-the old ones and copy them into place as the new ones, before dropping privs.
-
-To also handle the long-uptime server case, lws will update the vhost with the
-new certs using in-memory temporary copies of the cert and key after updating
-the cert.
-
-In this way the cert and key live in root-only storage but the vhost is kept up
-to date dynamically with any cert changes as well.
-
-## Multiple vhosts using same cert
-
-In the case you have multiple vhosts using of the same cert, just attach
-the `lws-acme-client` plugin to one instance.  When the cert updates, all the
-vhosts are informed and vhosts using the same filepath to access the cert will
-be able to update their cert.
-
-## Implementation point
-
-You will need to remove the auth keys when switching from OpenSSL to
-mbedTLS.  They will be regenerated automatically.  It's the file at this
-path:
-
-```
-"auth-path":	   "/etc/lwsws/acme/auth.jwk",
-```

+ 0 - 249
Source/ThirdParty/libwebsockets/READMEs/README.plugin-sshd-base.md

@@ -1,249 +0,0 @@
-ssh-base Plugin
-================
-
-## Introduction
-
-lws-ssh-base is a protcol plugin for libwebsockets that implements a
-generic, abstract, ssh server.
-
- - very small footprint in code and memory, takes up small part of ESP32
- 
- - written with security in mind: valgrind and Coverity -clean
- 
- - binds to one or more vhosts, that controls listen port(s)
- 
- - all IO and settings abstracted through a single "ops" struct from user code
- 
- - each instance on a vhost has its own "ops" struct, defining server keys,
-   auth method and functions to implement IO and other operations
-
- - The plugin has no built-in behaviours like check ~/.ssh/authorized_keys,
-   treat auth usernames as system usernames, or spawn the user's shell.
-   Everything potentially dangerous is left to the user ops code to decide
-   how to handle.  It's NOT like sshd where running it implies it will accept
-   existing keys for any system user, will spawn a shell, etc, unless you
-   implement those parts in the ops callbacks.
-   
- - The plugin requires extra code around it in the form of the ops struct
-   handlers.  So it's role is something like an abstract base class for an ssh
-   server.  All the crypto, protocol sequencing and state machine are inside,
-   but all the IO except the network connection is outside.
-   
- - Built as part of libwebsockets, like all plugins may be dynamically loaded
-   at runtime or built statically.  Test app `libwebsockets-test-sshd` provided
-   
- - Uses hash and RSA functions from either mbedTLS or OpenSSL automatically,
-   according to which library libwebsockets was built for
-
-To maintain its small size, it implements a single "best of breed" crypto for
-the following functions:
-
-|Function|Crypto|
-|---|---|
-|KEX|[email protected]|
-|Server host key|ssh-rsa (4096b)|
-|Encryption|[email protected]|
-|Compression|None|
-
-## License
-
-lws-ssh-base is Free Software, available under libwebsockets' MIT license.
-
-The crypto parts are available elsewhere under a BSD license.  But for
-simplicity the whole plugin is under MIT.
-
-## Generating your own keys
-
-```
- $ ssh-keygen -t rsa -b 4096 -f mykeys
-```
-
-will ask for a passphrase and generate the private key in `mykeys` and the
-public key in `mykeys.pub`.  If you already have a suitable RSA key you use
-with ssh, you can just use that directly.
-
-lws installs a test keypair in /usr[/local]/share/libwebsockets-test-server
-that the test apps will accept.
-
-## Example code
-
-1) There's a working example app `libwebsockets-test-sshd` included that
-spawns a bash shell when an ssh client authenticates.  The username used on
-the remote ssh has no meaning, it spawns the shell under the credentials of
-"lws-test-sshd" was run under.  It accepts the lws ssh test key which is
-installed into /usr[/local]/share/libwebsockets-test-server.
-
-Start the server like this (it wants root only because the server key is stored
-in /etc)
-
-```
- $ sudo libwebsockets-test-sshd
-```
-
-Connect to it using the test private key like this
-
-```
- $ ssh -p 2200 -i /usr/local/share/libwebsockets-test-server/lws-ssh-test-keys [email protected]
-```
-
-2) There's also a working example plugin `lws-sshd-demo` that "subclasses" the
-abstract `lws-ssh-base` plugin to make a protocol which can be used from,
-eg, lwsws.  For an lwsws vhost that listens on port 2222 and responds with
-the lws-sshd-demo ssh server, the related config is:
-
-```
-        {
-                "name": "sshd",
-                "port": "2222",
-                "onlyraw": "1",
-                "ws-protocols": [{
-                        "lws-ssh-base": {
-                                "status": "ok",
-                                "ops-from": "lws-sshd-demo"
-                        },
-                        "lws-sshd-demo": {
-                                "status": "ok",
-                                "raw": "1"
-                        }
-                }]
-        }
-```
-
-
-
-## Integration to other apps
-
-### Step 0: Build and install libwebsockets
-
-For the `libwebsockets-test-sshd` example, you will need CMake options
-`LWS_WITH_CGI`, since it uses lws helpers to spawn a shell.
-
-lws-ssh-base itself doesn't require CGI support in libwebsockets.
-
-### Step 1: make the code available in your app
-
-Include `lws-plugin-ssh-base` in your app, either as a runtime plugin or by using
-the lws static include scheme.
-
-To bring in the whole of the ssh-base plugin
-into your app in one step, statically, just include
-`plugins/ssh-base/include/lws-plugin-sshd-static-build-includes.h`, you can see
-an example of this in `./test-apps/test-sshd.c`.
-
-### Step 2: define your `struct lws_ssh_ops`
-
-`plugins/ssh-base/include/lws-plugin-ssh.h` defines
-`struct lws_ssh_ops` which is used for all customization and integration
-of the plugin per vhost.  Eg,
-
-```
-static const struct lws_ssh_ops ssh_ops = {
-	.channel_create			= ssh_ops_channel_create,
-	.channel_destroy		= ssh_ops_channel_destroy,
-	.tx_waiting			= ssh_ops_tx_waiting,
-	.tx				= ssh_ops_tx,
-	.rx				= ssh_ops_rx,
-	.get_server_key			= ssh_ops_get_server_key,
-	.set_server_key			= ssh_ops_set_server_key,
-	.set_env			= ssh_ops_set_env,
-	.pty_req			= ssh_ops_pty_req,
-	.child_process_io		= ssh_ops_child_process_io,
-	.child_process_terminated	= ssh_ops_child_process_terminated,
-	.exec				= ssh_ops_exec,
-	.shell				= ssh_ops_shell,
-	.is_pubkey_authorized		= ssh_ops_is_pubkey_authorized,
-	.banner				= ssh_ops_banner,
-	.disconnect_reason		= ssh_ops_disconnect_reason,
-	.server_string			= "SSH-2.0-Libwebsockets",
-	.api_version			= 1,
-};
-```
-The `ssh_ops_...()` functions are your implementations for the operations
-needed by the plugin for your purposes.
-
-### Step 3: enable `lws-ssh-base` protocol to a vhost and configure using pvo
-
-A pointer to your struct lws_ssh_ops is passed into the vhost instance of the
-protocol using per-vhost options
-
-```
-static const struct lws_protocol_vhost_options pvo_ssh_ops = {
-	NULL,
-	NULL,
-	"ops",
-	(void *)&ssh_ops
-};
-
-static const struct lws_protocol_vhost_options pvo_ssh = {
-	NULL,
-	&pvo_ssh_ops,
-	"lws-sshd-base",
-	"" /* ignored, just matches the protocol name above */
-};
-
-...
-	info.port = 22;
-	info.options = LWS_SERVER_OPTION_ONLY_RAW;
-	info.vhost_name = "sshd";
-	info.protocols = protocols_sshd;
-	info.pvo = &pvo_ssh;
-
-	vh_sshd = lws_create_vhost(context, &info);
-```
-
-There are two possible pvos supported, "ops", shown above, directly passes the
-ops structure in using the value on the "ops" pvo.
-
-To support other protocols that want to provide ops to lws-ssh-base themselves
-for a particular vhost, you can also provide a pvo `"ops-from"` whose value is
-the name of the protocol also enabled on this vhost, whose protocol ".user"
-pointer points to the ops struct lws-ssh-base should use.
-
-## Integration to other plugins
-
-A worked example of using the abstract `lws-ssh-base` plugin from another
-plugin that provides the ops struct is in `./plugins/protocol_lws_sshd_demo`.
-
-The key points to note
-
- - the plugin sets the ops struct for the vhost instantiation of `lws-ssh-base`
- by passing a pointer to the ops struct in its `lws_protocols` struct `user`
- member.
- 
- - the config for the vhost tells `lws-ssh-base` to pick up the ops struct
- pointer using an "ops-from" pvo that indicates the protocol name.
- 
-```
- 			"lws-ssh-base": {
-                                "status": "ok",
-                                "ops-from": "lws-sshd-demo"
-                        },
-```
-
- - the config for the vhost tells lws this vhost only serves RAW (ie, no http)
- 
-```
-         {
-                "name": "sshd",
-                "port": "2222",
-                "onlyraw": "1",
-                ...
-```
-
- - the config for the vhost marks the protocol that uses `lws-ssh-base`, not
- `lws-ssh-base` itself, as the protocol to be served for raw connections
-
-```
-                        "lws-sshd-demo": {
-                                "status": "ok",
-                                "raw": "1"
-                         ...
-```
-
-## Notes
-
-You can have the vhost it binds to listen on a nonstandard port.  The ssh
-commandline app cane be told to connect to a non-22 port with
-`ssh -p portnum user@hostname`
-
-

+ 0 - 60
Source/ThirdParty/libwebsockets/READMEs/README.porting.md

@@ -1,60 +0,0 @@
-# Guidance for porting to new platform
-
-Where differences existed between the initial POSIX platform for lws and other
-supported platforms like Windows, `lws_plat_...()` apis were added to move
-handling to platform-specific code in `./lib/plat/`.
-
-Depending o which platform is built, different platform-specific implementations
-of these `lws_plat...()` apis get built.
-
-## 1) Prepare the cmake cross-build file if necessary
-
-CMake isolates its settings for cross-build into a separate file, which can be
-used to different cmake projects for the same platform as well.
-
-Find a similar examples already in `./contrib/cross-*` and copy and adapt it
-as needed,
-
-All settings related to toolchain should go in there.  For cross-toolchain,
-the convention is to pass the path to its installed directory in `CROSS_PATH`
-environment variable.
-
-## 2) Copy the closest platform dir in ./lib/plat
-
-Wholesale copy the closest existing platform dir to `/lib/plat/myplatform` and
-rename the files.
-
-Remove stuff specific to the original platform.
-
-## 3) Add a flag in CMakeLists.txt
-
-Cut and paste a flag to select your platform, preferably `LWS_PLAT_MYPLATFORM` or so
-
-## 4) Add a section to force-select and deselect other cmake options based on platform flag
-
-Some options on by default may not make sense on your platform, and others off
-by default may be mandatory.  After the options() section in CMakeLists.txt, you
-can use this kind of structure
-
-```
-	if (LWS_PLAT_MYPLATFORM)
-		set(LWS_WITH_XXXX 0)
-	endif()
-```
-
-to enforce implicit requirements of your platform.  Optional stuff should be set by
-running cmake commandline as usual.
-
-## 5) Add building your platform files into CMakeLists.txt
-
-Add entries in CMakeLists.txt for building stuff in `./lib/plat/myplatform` when
-`LWS_PLAT_MYPLATFORM` is enabled.
-
-## 6) Adapt your copied ./lib/plat/myplatform/ files
-
-You can now do test builds using the cross-build file, your platform flag in
-cmake, and your copied ./lib/plat content... this last part since it was
-copied from another platform will initially be a plentiful source of errors.
-
-You can iteratively build and adapt the platform files.
-

+ 0 - 66
Source/ThirdParty/libwebsockets/READMEs/README.problems.md

@@ -1,66 +0,0 @@
-Debugging problems
-==================
-
-Check it's still a problem with latest lws
-------------------------------------------
-
-Older versions of lws don't attract any new work after they are released
-(see [the release policy](https://libwebsockets.org/git/libwebsockets/tree/READMEs/README.release-policy.md) for details);
-for a while they will get backported bugfixes but that's it.
-
-All new work and bugfixes happen on master branch.
-
-Old, old versions may be convenient for you to use for some reason.  But unless
-you pay for support or have contributed work to lws so we feel we owe you some
-consideration, nobody else has any reason to particularly care about solving
-issues on ancient versions.  Whereas if the problem exists on master, and can be
-reproduced by developers, it usually gets attention, often immediately.
-
-If the problem doesn't exist on master, you can either use master or check also
-the -stable branch of the last released version to see if it was already solved
-there.
-
-Library is a component
-----------------------
-
-As a library, lws is always just a component in a bigger application.
-
-When users have a problem involving lws, what is happening in the bigger
-application is usually critical to understand what is going on (and where the
-solution lies).  Sometimes access to the remote peer like server or client is also
-necessary to provoke the symptom.  Sometimes, the problem is in lws, but
-sometimes the problem is not in lws but in these other pieces.
-
-Many users are able to share their sources, but others decide not to, for
-presumed "commercial advantage" or whatever.  (In any event, it can be painful
-looking through large chunks of someone else's sources for problems when that
-is not the library author's responsibility.)
-
-This makes answering questions like "what is wrong with my code I am not
-going to show you?" or even "what is wrong with my code?" very difficult.
-
-Even if it's clear there is a problem somewhere, it cannot be understood or
-reproduced by anyone else if it needs user code that isn't provided.
-
-The biggest question is, "is this an lws problem actually"?  To solve that
-the best solution is to strip out all or as much user code as possible,
-and see if the problem is still coming.
-
-
-Use the test apps / minimal examples as sanity checks
------------------------------------------------------
-
-The test server and client, and any more specifically relevant minimal example
- are extremely useful for sanity checks and debugging guidance.
-
- - **test apps work on your platform**, then either
-   - your user code is broken, align it to how the test apps work, or,
-   - something from your code is required to show an lws problem, provide a
-     minimal patch on a test app so it can be reproduced
-     
- - **test apps break on your platform**, but work on, eg, x86_64, either
-   - toolchain or platform-specific (eg, OS) issue, or
-   - lws platform support issue
-
- - **test apps break everywhere**
-   - sounds like lws problem, info to reproduce and / or a patch is appreciated

+ 0 - 126
Source/ThirdParty/libwebsockets/READMEs/README.release-policy.md

@@ -1,126 +0,0 @@
-# lws release policy
-
-## How should users consume lws?
-
-The one definitively wrong way to consume lws (or anything else) is "import" some
-version of it into your proprietary tree and think you will stick with that
-forever, perhaps piling cryptic fixes or hacks on top until quite quickly,
-nobody dare think about updating it.
-
-The stable releases go on to a branch like v4.0-stable as described below, over
-time these attract dozens or even hundreds of minor or major fix patches
-backported from master.  So you should not consume tags like v4.0.0 but build
-into your planning that you will need to follow v4.0-stable in order to stay on
-top of known bugs.
-
-And we only backport fixes to the last stable release, although we will make
-exceptions for important fixes.  So after a while, trying to stick with one
-old versions means nobody is providing security fixes on it any more.  So you
-should build into your planning that you will follow lws release upgrades.
-
-If you find problems and create fixes, please upstream them, simplifying your
-life so you can just directly consume the upstream tree with no private changes.
-
-## Master branch
-
-Master branch is the default and all new work happens there.  It's unstable and
-subject to history rewrites, patches moving about and being squashed etc.  In
-terms of it working, it is subject to passing CI tests including a battery of
-runtime tests, so if it is passing CI as it usually is then it's probably in
-usable shape.  See "Why no history on master" below for why it's managed like
-that.
-
-![all work happens on master](../doc-assets/lws-relpol-1.svg)
-
-If you have patches (you are a hero) they should be targeted at master.
-
-To follow such a branch, `git pull` is the wrong tool... the starting point
-of what you currently have may no longer exist remotely due to rearranging the
-patches there.  Instead use a flow like this:
-
-```
- $ git fetch https://libwebsockets.org/repo/libwebsockets +master:m && git reset --hard m
-```
-
-This fetches current remote master into local branch `m`, and then forces your
-local checkout to exactly match `m`.  This replaces your checked-out tree
-including any of your local changes, so stash those first, or use stgit or so
-to pop them before updating your basis against lws master.
-
-## Stable branches
-
-Master is very useful for coordinating development, and integrating WIP,
-but for distros or integration into large user projects some stability is often
-more desirable than the latest development work.
-
-Periodically, when master seems in good shape and various new developments seem
-to be working, it's copied out into a versioned stable branch, like `v3.0-stable`.
-
-![stable branches are copied from master](../doc-assets/lws-relpol-2.svg)
-
-The initial copy is tagged with, eg, `v3.0.0`.
-
-(At that time, master's logical version is set to "...99", eg, `v3.0.99` so
-version comparisons show that version of master is "later" than any other
-v3.0 version, which will never reach 99 point releases itself, but "earlier"
-than, eg, v3.1.)
-
-## Backport policy
-
-Work continues on master, and as part of that usually bugs are reported and / or
-fixes found that may apply not just to current master, but the version of master
-that was copied to form the last -stable branch.
-
-In that case, the patch may be backported to the last stable branch to also fix
-the bug there.  In the case of refactors or major internal improvements, these
-typically do not get backported.
-
-This applies only to fixes and public API-neutral internal changes to lws... if
-new features were backported or API changes allowed, then there would be
-multiple apis under the same version name and library soname, which is
-madness.
-
-When new stable releases are made, the soname is bumped reflecting the API is
-different than that of previous versions.
-
-![backports from master to stable](../doc-assets/lws-relpol-3.svg)
-
-If there is something you need in a later lws version that is not backported,
-you need to either backport it yourself or use a later lws version.
-Using a more recent version of lws (and contributing fixes and changes so you
-yourself can get them easily as well as contributing for others) is almost
-always the correct way.
-
-## Stable point releases
-
-Periodically fix patches pile up on the -stable branch and are tagged out as
-"point releases".  So if the original stable release was "v3.0.0", the point
-release may be "v3.0.1".
-
-![point releases of stable](../doc-assets/lws-relpol-4.svg)
-
-## Critical fixes
-
-Sometimes a bug is found and fixed that had been hiding for a few versions.
-If the bug has some security dimension or is otherwise important, we may
-backport it to a few recent releases, not just the last one.  This is pretty
-uncommon though.
-
-![backport to multiple stable branches](../doc-assets/lws-relpol-5.svg)
-
-## Why no history on master
-
-Git is a wonderful tool that can be understood to have two main modes of operation,
-merge and rebase that are mutually exclusive.  Most devs only use merge / pull,
-but rebase / fetch is much more flexible.  Running master via rebases allows me to
-dispense with feature branches during development and enables tracking multiple
-in-progress patches in-tree by updating them in place.  If this doesn't make
-sense or seems heretical to you, it's OK I don't need devsplain'ing about it,
-just sit back and enjoy the clean, rapid development results.
-
-Since stable branches don't allow new features, they are run as traditional trees
-with a history, like a one-way pile of patches on top of the original release.  If
-CI shows something is messed up with the latest patch, I will edit it in-place if
-it has only been out for a few hours, but there is no re-ordering or other history
-manipulation.
-

+ 0 - 448
Source/ThirdParty/libwebsockets/READMEs/README.test-apps.md

@@ -1,448 +0,0 @@
-Overview of lws test apps
-=========================
-
-Are you building a client?  You just need to look at the test client
-[libwebsockets-test-client](../test-apps/test-client.c).
-
-If you are building a standalone server, there are three choices, in order of
-preferability.
-
-1) lwsws + protocol plugins
-
-Lws provides a generic web server app that can be configured with JSON
-config files.  https://libwebsockets.org itself uses this method.
-
-With lwsws handling the serving part, you only need to write an lws protocol
-plugin.  See [plugin-standalone](../plugin-standalone) for an example of how
-to do that outside lws itself, using lws public apis.
-
- $ cmake .. -DLWS_WITH_LWSWS=1
-
-See [README.lwsws.md](../READMEs/README.lwsws.md) for information on how to configure
-lwsws.
-
-NOTE this method implies libuv is used by lws, to provide crossplatform
-implementations of timers, dynamic lib loading etc for plugins and lwsws.
-
-2) Using plugins in code
-
-This method lets you configure web serving in code, instead of using lwsws.
-
-Plugins are still used, but you have a choice whether to dynamically load
-them or statically include them.  In this example, they are dynamically
-loaded.
-
- $ cmake .. -DLWS_WITH_PLUGINS=1
-
-See, eg, the [test-server](../test-apps/test-server.c)
-
-3) protocols in the server app
-
-This is the original way lws implemented servers, plugins and libuv are not
-required, but without plugins separating the protocol code directly, the
-combined code is all squidged together and is much less maintainable.
-
-This method is still supported in lws but all ongoing and future work is
-being done in protocol plugins only.
-
-You can simply include the plugin contents and have it buit statically into
-your server, just define this before including the plugin source
-
-```
-#define LWS_PLUGIN_STATIC
-```
-
-This gets you most of the advantages without needing dynamic loading +
-libuv.
-
-
-Notes about lws test apps
-=========================
-
-@section tsb Testing server with a browser
-
-If you run [libwebsockets-test-server](../test-apps/test-server.c) and point your browser
-(eg, Chrome) to
-
-	http://127.0.0.1:7681
-
-It will fetch a script in the form of `test.html`, and then run the
-script in there on the browser to open a websocket connection.
-Incrementing numbers should appear in the browser display.
-
-By default the test server logs to both stderr and syslog, you can control
-what is logged using `-d <log level>`, see later.
-
-
-@section tsd Running test server as a Daemon
-
-You can use the -D option on the test server to have it fork into the
-background and return immediately.  In this daemonized mode all stderr is
-disabled and logging goes only to syslog, eg, `/var/log/messages` or similar.
-
-The server maintains a lockfile at `/tmp/.lwsts-lock` that contains the pid
-of the master process, and deletes this file when the master process
-terminates.
-
-To stop the daemon, do
-```
-       $ kill \`cat /tmp/.lwsts-lock\`
-```
-If it finds a stale lock (the pid mentioned in the file does not exist
-any more) it will delete the lock and create a new one during startup.
-
-If the lock is valid, the daemon will exit with a note on stderr that
-it was already running.
-
-@section clicert Testing Client Certs
-
-Here is a very quick way to create a CA, and a client and server cert from it,
-for testing.
-
-```
-$ cp -rp ./scripts/client-ca /tmp
-$ cd /tmp/client-ca
-$ ./create-ca.sh
-$ ./create-server-cert.sh server
-$ ./create-client-cert.sh client
-```
-
-The last step wants an export password, you will need this password again to
-import the p12 format certificate into your browser.
-
-This will get you the following
-
-|name|function|
-|----|--------|
-|ca.pem|Your Certificate Authority cert|
-|ca.key|Private key for the CA cert|
-|client.pem|Client certificate, signed by your CA|
-|client.key|Client private key|
-|client.p12|combined client.pem + client.key in p12 format for browsers|
-|server.pem|Server cert, signed by your CA|
-|server.key|Server private key|
-
-You can confirm yourself the client and server certs are signed by the CA.
-
-```
- $ openssl verify -verbose -trusted ca.pem server.pem
- $ openssl verify -verbose -trusted ca.pem client.pem
-```
-
-Import the client.p12 file into your browser.  In FFOX57 it's
-
- - preferences
- - Privacy & Security
- - Certificates | View Certificates
- - Certificate Manager | Your Certificates | Import...
- - Enter the password you gave when creating client1.p12
- - Click OK.
-
-You can then run the test server like this:
-
-```
- $ libwebsockets-test-server -s -A ca.pem -K server.key -C server.pem -v
-```
-
-When you connect your browser to https://localhost:7681 after accepting the
-selfsigned server cert, your browser will pop up a prompt to send the server
-your client cert (the -v switch enables this).  The server will only accept
-a client cert that has been signed by ca.pem.
-
-@section sssl Using SSL on the server side
-
-To test it using SSL/WSS, just run the test server with
-```
-	$ libwebsockets-test-server --ssl
-```
-and use the URL
-```
-	https://127.0.0.1:7681
-```
-The connection will be entirely encrypted using some generated
-certificates that your browser will not accept, since they are
-not signed by any real Certificate Authority.  Just accept the
-certificates in the browser and the connection will proceed
-in first https and then websocket wss, acting exactly the
-same.
-
-[test-server.c](../test-apps/test-server.c) is all that is needed to use libwebsockets for
-serving both the script html over http and websockets.
-
-@section lwstsdynvhost Dynamic Vhosts
-
-You can send libwebsockets-test-server or libwebsockets-test-server-v2.0 a SIGUSR1
-to toggle the creation and destruction of an identical second vhost on port + 1.
-
-This is intended as a test and demonstration for how to bring up and remove
-vhosts dynamically.
-
-@section unixskt Testing Unix Socket Server support
-
-Start the test server with -U and the path to create the unix domain socket
-
-```
- $ libwebsockets-test-server -U /tmp/uds
-```
-
-On exit, lws will delete the socket inode.
-
-To test the client side, eg
-
-```
- $ nc -C -U /tmp/uds -i 30
-```
-
-and type
-
-`GET / HTTP/1.1`
-
-followed by two ENTER.  The contents of test.html should be returned.
-
-@section wscl Testing websocket client support
-
-If you run the test server as described above, you can also
-connect to it using the test client as well as a browser.
-
-```
-	$ libwebsockets-test-client localhost
-```
-
-will by default connect to the test server on localhost:7681
-and print the dumb increment number from the server at the
-same time as drawing random circles in the mirror protocol;
-if you connect to the test server using a browser at the
-same time you will be able to see the circles being drawn.
-
-The test client supports SSL too, use
-
-```
-	$ libwebsockets-test-client localhost --ssl -s
-```
-
-the -s tells it to accept the default self-signed cert from the server,
-otherwise it will strictly fail the connection if there is no CA cert to
-validate the server's certificate.
-
-
-@section choosingts Choosing between test server variations
-
-If you will be doing standalone serving with lws, ideally you should avoid
-making your own server at all, and use lwsws with your own protocol plugins.
-
-The second best option is follow test-server-v2.0.c, which uses a mount to
-autoserve a directory, and lws protocol plugins for ws, without needing any
-user callback code (other than what's needed in the protocol plugin).
-
-For those two options libuv is needed to support the protocol plugins, if
-that's not possible then the other variations with their own protocol code
-should be considered.
-
-@section tassl Testing SSL on the client side
-
-To test SSL/WSS client action, just run the client test with
-```
-	$ libwebsockets-test-client localhost --ssl
-```
-By default the client test applet is set to accept self-signed
-certificates used by the test server, this is indicated by the
-`use_ssl` var being set to `2`.  Set it to `1` to reject any server
-certificate that it doesn't have a trusted CA cert for.
-
-
-@section taping Using the websocket ping utility
-
-libwebsockets-test-ping connects as a client to a remote
-websocket server and pings it like the
-normal unix ping utility.
-```
-	$ libwebsockets-test-ping localhost
-	handshake OK for protocol lws-mirror-protocol
-	Websocket PING localhost.localdomain (127.0.0.1) 64 bytes of data.
-	64 bytes from localhost: req=1 time=0.1ms
-	64 bytes from localhost: req=2 time=0.1ms
-	64 bytes from localhost: req=3 time=0.1ms
-	64 bytes from localhost: req=4 time=0.2ms
-	64 bytes from localhost: req=5 time=0.1ms
-	64 bytes from localhost: req=6 time=0.2ms
-	64 bytes from localhost: req=7 time=0.2ms
-	64 bytes from localhost: req=8 time=0.1ms
-	^C
-	--- localhost.localdomain websocket ping statistics ---
-	8 packets transmitted, 8 received, 0% packet loss, time 7458ms
-	rtt min/avg/max = 0.110/0.185/0.218 ms
-	$
-```
-By default it sends 64 byte payload packets using the 04
-PING packet opcode type.  You can change the payload size
-using the `-s=` flag, up to a maximum of 125 mandated by the
-04 standard.
-
-Using the lws-mirror protocol that is provided by the test
-server, libwebsockets-test-ping can also use larger payload
-sizes up to 4096 is BINARY packets; lws-mirror will copy
-them back to the client and they appear as a PONG.  Use the
-`-m` flag to select this operation.
-
-The default interval between pings is 1s, you can use the -i=
-flag to set this, including fractions like `-i=0.01` for 10ms
-interval.
-
-Before you can even use the PING opcode that is part of the
-standard, you must complete a handshake with a specified
-protocol.  By default lws-mirror-protocol is used which is
-supported by the test server.  But if you are using it on
-another server, you can specify the protocol to handshake with
-by `--protocol=protocolname`
-
-
-@section ta fraggle Fraggle test app
-
-By default it runs in server mode
-```
-	$ libwebsockets-test-fraggle
-	libwebsockets test fraggle
-	(C) Copyright 2010-2011 Andy Green <[email protected]> licensed under MIT
-	 Compiled with SSL support, not using it
-	 Listening on port 7681
-	server sees client connect
-	accepted v06 connection
-	Spamming 360 random fragments
-	Spamming session over, len = 371913. sum = 0x2D3C0AE
-	Spamming 895 random fragments
-	Spamming session over, len = 875970. sum = 0x6A74DA1
-	...
-```
-You need to run a second session in client mode, you have to
-give the `-c` switch and the server address at least:
-```
-	$ libwebsockets-test-fraggle -c localhost
-	libwebsockets test fraggle
-	(C) Copyright 2010-2011 Andy Green <[email protected]> licensed under MIT
-	 Client mode
-	Connecting to localhost:7681
-	denied deflate-stream extension
-	handshake OK for protocol fraggle-protocol
-	client connects to server
-	EOM received 371913 correctly from 360 fragments
-	EOM received 875970 correctly from 895 fragments
-	EOM received 247140 correctly from 258 fragments
-	EOM received 695451 correctly from 692 fragments
-	...
-```
-The fraggle test sends a random number up to 1024 fragmented websocket frames
-each of a random size between 1 and 2001 bytes in a single message, then sends
-a checksum and starts sending a new randomly sized and fragmented message.
-
-The fraggle test client receives the same message fragments and computes the
-same checksum using websocket framing to see when the message has ended.  It
-then accepts the server checksum message and compares that to its checksum.
-
-
-@section taproxy proxy support
-
-The http_proxy environment variable is respected by the client
-connection code for both `ws://` and `wss://`.  It doesn't support
-authentication.
-
-You use it like this
-```
-	$ export http_proxy=myproxy.com:3128
-	$ libwebsockets-test-client someserver.com
-```
-
-@section talog debug logging
-
-By default logging of severity "notice", "warn" or "err" is enabled to stderr.
-
-Again by default other logging is compiled in but disabled from printing.
-
-By default debug logs below "notice" in severity are not compiled in.  To get
-them included, add this option in CMAKE
-
-```
-	$ cmake .. -DCMAKE_BUILD_TYPE=DEBUG
-```
-
-If you want to see more detailed debug logs, you can control a bitfield to
-select which logs types may print using the `lws_set_log_level()` api, in the
-test apps you can use `-d <number>` to control this.  The types of logging
-available are (OR together the numbers to select multiple)
-
- - 1   ERR
- - 2   WARN
- - 4   NOTICE
- - 8   INFO
- - 16  DEBUG
- - 32  PARSER
- - 64  HEADER
- - 128 EXTENSION
- - 256 CLIENT
- - 512 LATENCY
-
-
-@section ws13 Websocket version supported
-
-The final IETF standard is supported for both client and server, protocol
-version 13.
-
-
-@section latency Latency Tracking
-
-Since libwebsockets runs using `poll()` and a single threaded approach, any
-unexpected latency coming from system calls would be bad news.  There's now
-a latency tracking scheme that can be built in with `-DLWS_WITH_LATENCY=1` at
-cmake, logging the time taken for system calls to complete and if
-the whole action did complete that time or was deferred.
-
-You can see the detailed data by enabling logging level 512 (eg, `-d 519` on
-the test server to see that and the usual logs), however even without that
-the "worst" latency is kept and reported to the logs with NOTICE severity
-when the context is destroyed.
-
-Some care is needed interpreting them, if the action completed the first figure
-(in us) is the time taken for the whole action, which may have retried through
-the poll loop many times and will depend on network roundtrip times.  High
-figures here don't indicate a problem.  The figure in us reported after "lat"
-in the logging is the time taken by this particular attempt.  High figures
-here may indicate a problem, or if you system is loaded with another app at
-that time, such as the browser, it may simply indicate the OS gave preferential
-treatment to the other app during that call.
-
-
-@section autobahn Autobahn Test Suite
-
-Lws can be tested against the autobahn websocket fuzzer in both client and
-server modes
-
-1) pip install autobahntestsuite
-
-2) From your build dir:
-
-```
- $ cmake .. -DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_MINIMAL_EXAMPLES=1 && make
-```
-
-3) ../scripts/autobahn-test.sh
-
-4) In a browser go to the directory you ran wstest in (eg, /projects/libwebsockets)
-
-file:///projects/libwebsockets/build/reports/clients/index.html
-
-to see the results
-
-
-@section autobahnnotes Autobahn Test Notes
-
-1) Two of the tests make no sense for Libwebsockets to support and we fail them.
-
- - Tests 2.10 + 2.11: sends multiple pings on one connection.  Lws policy is to
-only allow one active ping in flight on each connection, the rest are dropped.
-The autobahn test itself admits this is not part of the standard, just someone's
-random opinion about how they think a ws server should act.  So we will fail
-this by design and it is no problem about RFC6455 compliance.
-
-2) Currently two parts of autobahn are broken and we skip them
-
-https://github.com/crossbario/autobahn-testsuite/issues/71
- 

+ 0 - 50
Source/ThirdParty/libwebsockets/READMEs/README.udp.md

@@ -1,50 +0,0 @@
-## Using UDP in lws
-
-UDP is supported in lws... the quickest way is to use the api
-`lws_create_adopt_udp()` which returns a wsi bound to the provided
-vhost, protocol, `lws_retry` struct, dns address and port.
-
-The wsi can be treated normally and `lws_write()` used to write on
-it.
-
-## Implementing UDP retries
-
-Retries are important in udp but there's no standardized ack method
-unlike tcp.  Lws allows you to bind an `lws_retry` struct describing
-the policy to the udp wsi, but since one UDP socket may have many
-transactions in flight, the `lws_sul` and `uint16_t` to count the
-retries must live in the user's transaction object like this
-
-```
-...
-	lws_sorted_usec_list_t	sul;
-	uint16_t		retry;
-...
-```
-
-in the `LWS_CALLBACK_RAW_WRITEABLE` callback, before doing the write,
-set up the retry like this
-
-```
-	if (lws_dll2_is_detached(&transaction->sul_write.list) &&
-	    lws_retry_sul_schedule_retry_wsi(wsi, &transaction->sul_write,
-					     transaction_retry_write_cb,
-					     &transaction->retry_count_write)) {
-			/* we have reached the end of our concealed retries */
-		lwsl_warn("%s: concealed retries done, failing\n", __func__);
-		goto retry_conn;
-	}
-```
-
-This manages the retry counter in the transaction object, guards against it wrapping,
-selects the timeout using the policy bound to the wsi, and sets the `lws_sul` in the
-transaction object to call the given callback if the sul time expires.
-
-In the callback, it should simply call `lws_callback_on_writable()` for the udp wsi.
-
-## Simulating packetloss
-
-lws now allows you to set the amount of simulated packetloss on udp rx and tx in
-the context creation info struct, using `.udp_loss_sim_tx_pc` and `.udp_loss_sim_rx_pc`,
-the values are percentages between 0 and 100.  0, the default, means no packetloss.
-

+ 0 - 101
Source/ThirdParty/libwebsockets/READMEs/README.unix-domain-reverse-proxy.md

@@ -1,101 +0,0 @@
-## Unix Domain Sockets Reverse Proxy
-
-### Introduction
-
-lws is able to use a mount to place reverse proxies into the URL space.
-
-These are particularly useful when using Unix Domain Sockets, basically
-files in the server filesystem, to communicate between lws and a separate
-server process and integrate the result into a coherent URL namespace on
-the lws side.  It's also possible to proxy using tcp sockets.
-
-![overview](../doc-assets/http-proxy-overview.svg)
-
-This has the advantage that the actual web server that forwards the
-data from the unix socket owner is in a different process than the server
-that serves on the unix socket.  If it has problems, they do not affect
-the actual public-facing web server.  The unix domain socket server may
-be in a completely different language than the web server.
-
-Compared to CGI, there are no forks to make a connection to the unix
-domain socket server.
-
-### Mount origin format
-
-Unix Domain Sockets are effectively "files" in the server filesystem, and
-are defined by their filepath.  The "server" side that is to be proxied opens
-the socket and listens on it, which creates a file in the server filesystem.
-The socket understands either http or https protocol.
-
-Lws can be told to act as a proxy for that at a mountpoint in the lws vhost
-url space.
-
-If your mount is expressed in C code, then the mount type is LWSMPRO_HTTP or
-LWSMPRO_HTTPS depending on the protocol the unix socket understands, and the
-origin address has the form `+/path/to/unix/socket:/path/inside/mount`.
-
-The + at the start indicates it is a local unix socket we are proxying, and
-the ':' acts as a delimiter for the socket path, since unlike other addresses
-the unix socket path can contain '/' itself.
-
-### Connectivity rules and translations
-
-Onward proxy connections from lws to the Unix Domain Socket happen using
-http/1.1.  That implies `transfer-encoding: chunking` in the case that the
-length of the output is not known beforehand.
-
-Lws takes care of stripping any chunking (which is illegal in h2) and
-translating between h1 and h2 header formats if the return connection is
-actually in http/2.
-
-The h1 onward proxy connection translates the following headers from the return
-connection, which may be h1 or h2:
-
-Header|Function
----|---
-host|Which vhost
-etag|Information on any etag the client has cached for this URI
-if-modified-since|Information on the freshness of any etag the client has cached for this URI
-accept-language|Which languages the return path client prefers
-accept-encoding|Which compression encodings the client can accept
-cache-control|Information from the return path client about cache acceptability
-x-forwarded-for|The IP address of the return path client
-
-This implies that the proxied connection can
-
- - return 301 etc to say the return path client's etag is still valid
-
- - choose to compress using an acceptable content-encoding
-
-The following headers are translated from the headers replied via the onward
-connection (always h1) back to the return path (which may be h1 or h2)
-
-Header|Function
----|---
-content-length|If present, an assertion of how much payload is expected
-content-type|The mimetype of the payload
-etag|The canonical etag for the content at this URI
-accept-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.
-content-encoding|Any compression format on the payload (selected from what the client sent in accept-encoding, if anything)
-cache-control|The onward server's response about cacheability of its payload
-
-### h1 -> h2 conversion
-
-Chunked encoding that may have been used on the outgoing proxy client connection
-is removed for h2 return connections (chunked encoding is illegal for h2).
-
-Headers are converted to all lower-case and hpack format for h2 return connections.
-
-Header and payload proxying is staged according to when the return connection
-(which may be an h2 child stream) is writable.
-
-### Behaviour if unix domain socket server unavailable
-
-If the server that listens on the unix domain socket is down or being restarted,
-lws understands that it couldn't connect to it and returns a clean 503 response
-`HTTP_STATUS_SERVICE_UNAVAILABLE` along with a brief human-readable explanation.
-
-The generated status page produced will try to bring in a stylesheet
-`/error.css`.  This allows you to produce a styled error pages with logos,
-graphics etc.  See [this](https://libwebsockets.org/git/badrepo) for an example of what you can do with it.
-

+ 0 - 12
Source/ThirdParty/libwebsockets/READMEs/README.vulnerability-reporting.md

@@ -1,12 +0,0 @@
-## Vulnerability Reporting
-
-If you become aware of an issue with lws that has a security
-dimension for users, please contact `[email protected]` by
-direct email.
-
-## Procedure for announcing vulnerability fixes
-
-The problem and fixed versions will be announced on the
-libwebsockets mailing list and a note added to the master
-README.md.
-

+ 0 - 23
Source/ThirdParty/libwebsockets/READMEs/mainpage.md

@@ -1,23 +0,0 @@
-##Libwebsockets API introduction
-
-Libwebsockets covers a lot of interesting features for people making embedded servers or clients
-
- - HTTP(S) serving and client operation
- - HTTP/2 support for serving and client operation
- - WS(S) serving and client operation
- - HTTP(S) apis for file transfer and upload
- - HTTP 1 + 2 POST form handling (including multipart / file upload)
- - cookie-based sessions
- - account management (including registration, email verification, lost pw etc)
- - strong SSL / TLS  PFS support (A+ on SSLlabs test)
- - ssh server integration
- - serving gzipped files directly from inside zip files, without conversion
- - support for linux, bsd, windows etc... and very small nonlinux targets like ESP32
-
-Please note you just need in include libwebsockets.h.  It includes all the individual
-includes in /usr/include/libwebsockets/ itself.
-
-You can browse by api category <a href="modules.html">here</a>
-
-A collection of READMEs for build, coding, lwsws etc are <a href="pages.html">here</a>
-

+ 0 - 65
Source/ThirdParty/libwebsockets/READMEs/release-checklist

@@ -1,65 +0,0 @@
-Release Checklist
------------------
-
-1) non-CI QA
- 
- a) valgrind test servers + client + browser
-
-2) soname bump?
-
- a) We need one if we added / changed / removed apis
-
-  - CMakeLists.txt
-
-   set(SOVERSION "6")
-
-  - scripts/libwebsockets.spec
-
-  -/%{_libdir}/libwebsockets.so.6
-  +/%{_libdir}/libwebsockets.so.7
-
-3) changelog
-
- a) Add next version tag header.
-
- b) Classify as
-
-    - NEW
-    - CHANGE
-    - REMOVE
-
-4) main version bump
-
-  - CMakeLists.txt
-
-   set(CPACK_PACKAGE_VERSION_MAJOR "1")
-   set(CPACK_PACKAGE_VERSION_MINOR "6")
-   set(CPACK_PACKAGE_VERSION_PATCH "0")
-
-5) Announce latest version on README.md
-
-6) Make sure all new READMEs and public headers are in libwebsockets.dox
-
-7) signed tag
-
-  git tag -s vX.Y[.Z]
-
-8) git
-
- a) push
- 
- b) final CI check, if fail delete tag, kill pushed tags, restart flow
-
-9) website
-
- a) update latest tag for release branch
-
-10) post-relase version bump
-
-Bump the PATCH part of the version to 99
-
--set(CPACK_PACKAGE_VERSION_PATCH "0")
-+set(CPACK_PACKAGE_VERSION_PATCH "99")
-
-to reflect it's newer than any stable release but not a new version yet.
-

+ 2 - 0
Source/ThirdParty/libwebsockets/VERSION.txt

@@ -0,0 +1,2 @@
+v4.1.3
+

+ 37 - 0
Source/ThirdParty/libwebsockets/bug_report.md

@@ -0,0 +1,37 @@
+** What version of lws **
+
+"vx.y.z" or "01234567 from master thismorning" etc
+
+If it's much older than last stable release, we will likely suggest you try that or master.
+
+** What platform and arch? **
+
+"Fedora 32 x86_64" or "OSX Catalina" etc
+
+** What parts of lws does it involve? **
+
+dunno / core / client / server
+raw / http / ws / mqtt / other (give me a hint)
+
+** How can I reproduce the problem just using lws code? **
+
+We can't guess your problem especially in your code.  It's great if you can give us a way to
+realize our own failure clearly with a reproducer that uses our own code.
+
+Try to remove your code from the equation by trying the same flow on an lws minimal example and provide a little diff against that. We can find out if it's only on your platform, or only on that version, or only in your code from that quickly, and if something to fix in lws, I can confirm it really is fixed using the same test.
+
+** Describe the bug **
+
+    "fails" --> this word is a red flag you didn't try to debug the issue much... exactly how does it "fail", what evidence is it leaving like logs or return codes or traces?
+    "hangs" --> this word is a red flag you didn't try to debug the issue much... exactly what does it mean, whole device frozen? Spinning 100% cpu? Just idle? Building on fire? Have you tried it via strace or similar if it seems frozen to see what it's doing? Attach a debugger like gdb -p pid and get a backtrace? perf top if Linux to see what it spends its time on.
+    "crashes" --> what happens if you run under valgrind? You know lws is not threadsafe except for lws_cancel_service(), right...
+    "sucks" --> let's discuss you writing a patch to improve whatever it is
+
+** Additional data **
+
+Build problems? Describe the toolchain and paste the warnings / errors.
+
+Crash? Get a usable backtrace by building with `cmake .. -DCMAKE_BUILD_TYPE=DEBUG` and run under gdb, lldb, or valgrind.
+
+Mysterious happenings? Get verbose lws logs by building with `cmake .. -DCMAKE_BUILD_TYPE=DEBUG` and run with `lws_set_log_level(1151, NULL)`, on the example apps they all take a switch like -d1151.
+

+ 1 - 0
Source/ThirdParty/libwebsockets/cmake/lws_config.h.in

@@ -179,6 +179,7 @@
 #cmakedefine LWS_WITH_STATS
 #cmakedefine LWS_WITH_STATS
 #cmakedefine LWS_WITH_STRUCT_SQLITE3
 #cmakedefine LWS_WITH_STRUCT_SQLITE3
 #cmakedefine LWS_WITH_STRUCT_JSON
 #cmakedefine LWS_WITH_STRUCT_JSON
+#cmakedefine LWS_WITH_SUL_DEBUGGING
 #cmakedefine LWS_WITH_SQLITE3
 #cmakedefine LWS_WITH_SQLITE3
 #cmakedefine LWS_WITH_SYS_NTPCLIENT
 #cmakedefine LWS_WITH_SYS_NTPCLIENT
 #cmakedefine LWS_WITH_SYS_DHCP_CLIENT
 #cmakedefine LWS_WITH_SYS_DHCP_CLIENT

+ 9 - 31
Source/ThirdParty/libwebsockets/include/libwebsockets.h

@@ -93,7 +93,7 @@ typedef unsigned long long lws_intptr_t;
 #define LWS_WARN_DEPRECATED
 #define LWS_WARN_DEPRECATED
 #define LWS_FORMAT(string_index)
 #define LWS_FORMAT(string_index)
 
 
-#if !defined(LWS_EXTERN) && defined(LWS_BUILDING_SHARED)
+#if !defined(LWS_EXTERN)
 #ifdef LWS_DLL
 #ifdef LWS_DLL
 #ifdef LWS_INTERNAL
 #ifdef LWS_INTERNAL
 #define LWS_EXTERN extern __declspec(dllexport)
 #define LWS_EXTERN extern __declspec(dllexport)
@@ -103,11 +103,6 @@ typedef unsigned long long lws_intptr_t;
 #endif
 #endif
 #endif
 #endif
 
 
-#if !defined(LWS_INTERNAL) && !defined(LWS_EXTERN)
-#define LWS_EXTERN
-#define LWS_VISIBLE
-#endif
-
 #define LWS_INVALID_FILE INVALID_HANDLE_VALUE
 #define LWS_INVALID_FILE INVALID_HANDLE_VALUE
 #define LWS_SOCK_INVALID (INVALID_SOCKET)
 #define LWS_SOCK_INVALID (INVALID_SOCKET)
 #define LWS_O_RDONLY _O_RDONLY
 #define LWS_O_RDONLY _O_RDONLY
@@ -155,6 +150,7 @@ typedef unsigned long long lws_intptr_t;
 #if defined(__FreeBSD__)
 #if defined(__FreeBSD__)
 #include <sys/signal.h>
 #include <sys/signal.h>
 #endif
 #endif
+
 #if defined(__GNUC__)
 #if defined(__GNUC__)
 
 
 /* warn_unused_result attribute only supported by GCC 3.4 or later */
 /* warn_unused_result attribute only supported by GCC 3.4 or later */
@@ -164,44 +160,25 @@ typedef unsigned long long lws_intptr_t;
 #define LWS_WARN_UNUSED_RESULT
 #define LWS_WARN_UNUSED_RESULT
 #endif
 #endif
 
 
-#if defined(LWS_BUILDING_SHARED)
-/* this is only set when we're building lws itself shared */
 #define LWS_VISIBLE __attribute__((visibility("default")))
 #define LWS_VISIBLE __attribute__((visibility("default")))
-#define LWS_EXTERN extern
-
-#else /* not shared */
-#if defined(WIN32) || defined(_WIN32) || defined(__MINGW32__)
-#define LWS_VISIBLE
-#define LWS_EXTERN extern
-#else
-/*
- * If we explicitly say hidden here, symbols exist as T but
- * cannot be imported at link-time.
- */
-#define LWS_VISIBLE
-#define LWS_EXTERN
-#endif
-
-#endif /* not shared */
-
 #define LWS_WARN_DEPRECATED __attribute__ ((deprecated))
 #define LWS_WARN_DEPRECATED __attribute__ ((deprecated))
 #define LWS_FORMAT(string_index) __attribute__ ((format(printf, string_index, string_index+1)))
 #define LWS_FORMAT(string_index) __attribute__ ((format(printf, string_index, string_index+1)))
-#else /* not GNUC */
-
+#else
 #define LWS_VISIBLE
 #define LWS_VISIBLE
 #define LWS_WARN_UNUSED_RESULT
 #define LWS_WARN_UNUSED_RESULT
 #define LWS_WARN_DEPRECATED
 #define LWS_WARN_DEPRECATED
 #define LWS_FORMAT(string_index)
 #define LWS_FORMAT(string_index)
-#if !defined(LWS_EXTERN)
-#define LWS_EXTERN extern
 #endif
 #endif
-#endif
-
 
 
 #if defined(__ANDROID__)
 #if defined(__ANDROID__)
 #include <netinet/in.h>
 #include <netinet/in.h>
 #include <unistd.h>
 #include <unistd.h>
 #endif
 #endif
+
+#endif
+
+#ifndef LWS_EXTERN
+#define LWS_EXTERN extern
 #endif
 #endif
 
 
 #ifdef _WIN32
 #ifdef _WIN32
@@ -368,6 +345,7 @@ struct lws_pollfd {
 	lws_sockfd_type fd; /**< file descriptor */
 	lws_sockfd_type fd; /**< file descriptor */
 	SHORT events; /**< which events to respond to */
 	SHORT events; /**< which events to respond to */
 	SHORT revents; /**< which events happened */
 	SHORT revents; /**< which events happened */
+	uint8_t write_blocked;
 };
 };
 #define LWS_POLLHUP (FD_CLOSE)
 #define LWS_POLLHUP (FD_CLOSE)
 #define LWS_POLLIN (FD_READ | FD_ACCEPT)
 #define LWS_POLLIN (FD_READ | FD_ACCEPT)

+ 25 - 0
Source/ThirdParty/libwebsockets/include/libwebsockets/lws-eventlib-exports.h

@@ -58,4 +58,29 @@ lws_destroy_event_pipe(struct lws *wsi);
 LWS_VISIBLE LWS_EXTERN void
 LWS_VISIBLE LWS_EXTERN void
 __lws_close_free_wsi_final(struct lws *wsi);
 __lws_close_free_wsi_final(struct lws *wsi);
 
 
+#if LWS_MAX_SMP > 1
 
 
+struct lws_mutex_refcount {
+	pthread_mutex_t lock;
+	pthread_t lock_owner;
+	const char *last_lock_reason;
+	char lock_depth;
+	char metadata;
+};
+
+LWS_VISIBLE LWS_EXTERN void
+lws_mutex_refcount_assert_held(struct lws_mutex_refcount *mr);
+
+LWS_VISIBLE LWS_EXTERN void
+lws_mutex_refcount_init(struct lws_mutex_refcount *mr);
+
+LWS_VISIBLE LWS_EXTERN void
+lws_mutex_refcount_destroy(struct lws_mutex_refcount *mr);
+
+LWS_VISIBLE LWS_EXTERN void
+lws_mutex_refcount_lock(struct lws_mutex_refcount *mr, const char *reason);
+
+LWS_VISIBLE LWS_EXTERN void
+lws_mutex_refcount_unlock(struct lws_mutex_refcount *mr);
+
+#endif

+ 0 - 47
Source/ThirdParty/libwebsockets/include/libwebsockets/lws-http.h

@@ -731,53 +731,6 @@ LWS_VISIBLE LWS_EXTERN int
 lws_urldecode(char *string, const char *escaped, int len);
 lws_urldecode(char *string, const char *escaped, int len);
 ///@}
 ///@}
 
 
-/**
- * lws_http_date_render_from_unix() - render unixtime as RFC7231 date string
- *
- * \param buf:		Destination string buffer
- * \param len:		avilable length of dest string buffer in bytes
- * \param t:		pointer to the time_t to render
- *
- * Returns 0 if time_t is rendered into the string buffer successfully, else
- * nonzero.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_http_date_render_from_unix(char *buf, size_t len, const time_t *t);
-
-/**
- * lws_http_date_parse_unix() - parse a RFC7231 date string into unixtime
- *
- * \param b:		Source string buffer
- * \param len:		avilable length of source string buffer in bytes
- * \param t:		pointer to the destination time_t to set
- *
- * Returns 0 if string buffer parsed as RFC7231 time successfully, and
- * *t set to the parsed unixtime, else return nonzero.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_http_date_parse_unix(const char *b, size_t len, time_t *t);
-
-/**
- * lws_http_check_retry_after() - increase a timeout if retry-after present
- *
- * \param wsi:		http stream this relates to
- * \param us_interval_in_out: default us retry interval on entry may be updated
- *
- * This function may extend the incoming retry interval if the server has
- * requested that using retry-after: header.  It won't reduce the incoming
- * retry interval, only leave it alone or increase it.
- *
- * *us_interval_in_out should be set to a default retry interval on entry, if
- * the wsi has a retry-after time or interval that resolves to an interval
- * longer than the entry *us_interval_in_out, that will be updated to the longer
- * interval and return 0.
- *
- * If no usable retry-after or the time is now or in the past,
- * *us_interval_in_out is left alone and the function returns nonzero.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_http_check_retry_after(struct lws *wsi, lws_usec_t *us_interval_in_out);
-
 /**
 /**
  * lws_return_http_status() - Return simple http status
  * lws_return_http_status() - Return simple http status
  * \param wsi:		Websocket instance (available from user callback)
  * \param wsi:		Websocket instance (available from user callback)

+ 1 - 1
Source/ThirdParty/libwebsockets/include/libwebsockets/lws-lejp.h

@@ -182,7 +182,7 @@ typedef signed char (*lejp_callback)(struct lejp_ctx *ctx, char reason);
 #define LEJP_MAX_DEPTH 12
 #define LEJP_MAX_DEPTH 12
 #endif
 #endif
 #ifndef LEJP_MAX_INDEX_DEPTH
 #ifndef LEJP_MAX_INDEX_DEPTH
-#define LEJP_MAX_INDEX_DEPTH 6
+#define LEJP_MAX_INDEX_DEPTH 5
 #endif
 #endif
 #ifndef LEJP_MAX_PATH
 #ifndef LEJP_MAX_PATH
 #define LEJP_MAX_PATH 128
 #define LEJP_MAX_PATH 128

+ 9 - 0
Source/ThirdParty/libwebsockets/include/libwebsockets/lws-misc.h

@@ -335,6 +335,15 @@ lws_get_library_version(void);
 LWS_VISIBLE LWS_EXTERN void *
 LWS_VISIBLE LWS_EXTERN void *
 lws_wsi_user(struct lws *wsi);
 lws_wsi_user(struct lws *wsi);
 
 
+/**
+ * lws_wsi_tsi() - get the service thread index the wsi is bound to
+ * \param wsi: lws connection
+ *
+ * Only useful is LWS_MAX_SMP > 1
+ */
+LWS_VISIBLE LWS_EXTERN int
+lws_wsi_tsi(struct lws *wsi);
+
 /**
 /**
  * lws_set_wsi_user() - set the user data associated with the client connection
  * lws_set_wsi_user() - set the user data associated with the client connection
  * \param wsi: lws connection
  * \param wsi: lws connection

+ 1 - 6
Source/ThirdParty/libwebsockets/include/libwebsockets/lws-secure-streams-client.h

@@ -52,7 +52,6 @@
 #define lws_ss_get_context		lws_sspc_get_context
 #define lws_ss_get_context		lws_sspc_get_context
 #define lws_ss_rideshare		lws_sspc_rideshare
 #define lws_ss_rideshare		lws_sspc_rideshare
 #define lws_ss_set_metadata		lws_sspc_set_metadata
 #define lws_ss_set_metadata		lws_sspc_set_metadata
-#define lws_ss_get_metadata		lws_sspc_get_metadata
 #define lws_ss_add_peer_tx_credit	lws_sspc_add_peer_tx_credit
 #define lws_ss_add_peer_tx_credit	lws_sspc_add_peer_tx_credit
 #define lws_ss_get_est_peer_tx_credit	lws_sspc_get_est_peer_tx_credit
 #define lws_ss_get_est_peer_tx_credit	lws_sspc_get_est_peer_tx_credit
 #define lws_ss_start_timeout		lws_sspc_start_timeout
 #define lws_ss_start_timeout		lws_sspc_start_timeout
@@ -158,7 +157,7 @@ lws_sspc_proxy_create(struct lws_context *context);
 LWS_VISIBLE LWS_EXTERN struct lws_context *
 LWS_VISIBLE LWS_EXTERN struct lws_context *
 lws_sspc_get_context(struct lws_sspc_handle *h);
 lws_sspc_get_context(struct lws_sspc_handle *h);
 
 
-LWS_VISIBLE extern const struct lws_protocols lws_sspc_protocols[2];
+LWS_VISIBLE LWS_EXTERN const struct lws_protocols lws_sspc_protocols[];
 
 
 LWS_VISIBLE LWS_EXTERN const char *
 LWS_VISIBLE LWS_EXTERN const char *
 lws_sspc_rideshare(struct lws_sspc_handle *h);
 lws_sspc_rideshare(struct lws_sspc_handle *h);
@@ -191,10 +190,6 @@ LWS_VISIBLE LWS_EXTERN int
 lws_sspc_set_metadata(struct lws_sspc_handle *h, const char *name,
 lws_sspc_set_metadata(struct lws_sspc_handle *h, const char *name,
 		      const void *value, size_t len);
 		      const void *value, size_t len);
 
 
-LWS_VISIBLE LWS_EXTERN int
-lws_sspc_get_metadata(struct lws_sspc_handle *h, const char *name,
-		      const void **value, size_t *len);
-
 LWS_VISIBLE LWS_EXTERN int
 LWS_VISIBLE LWS_EXTERN int
 lws_sspc_add_peer_tx_credit(struct lws_sspc_handle *h, int32_t add);
 lws_sspc_add_peer_tx_credit(struct lws_sspc_handle *h, int32_t add);
 
 

+ 1 - 18
Source/ThirdParty/libwebsockets/include/libwebsockets/lws-secure-streams-policy.h

@@ -154,29 +154,15 @@ enum {
 	_LWSSS_HBI_COUNT /* always last */
 	_LWSSS_HBI_COUNT /* always last */
 };
 };
 
 
-/*
- * This does for both the static policy metadata entry, and the runtime metadata
- * handling object.
- */
-
 typedef struct lws_ss_metadata {
 typedef struct lws_ss_metadata {
 	struct lws_ss_metadata	*next;
 	struct lws_ss_metadata	*next;
 	const char		*name;
 	const char		*name;
 	void			*value;
 	void			*value;
 	size_t			length;
 	size_t			length;
 
 
-	uint8_t			value_on_lws_heap; /* proxy + rx metadata does this */
-	uint8_t			value_is_http_token; /* valid if set by policy */
-	uint8_t			value_length; /* only valid if set by policy */
-#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)
-	uint8_t			pending_onward:1;
-#endif
+	uint8_t			value_on_lws_heap; /* proxy does this */
 } lws_ss_metadata_t;
 } lws_ss_metadata_t;
 
 
-typedef struct lws_ss_http_respmap {
-	uint16_t		resp;	/* the http response code */
-	uint16_t		state;	/* low 16-bits of associated state */
-} lws_ss_http_respmap_t;
 
 
 /**
 /**
  * lws_ss_policy_t: policy database entry for a stream type
  * lws_ss_policy_t: policy database entry for a stream type
@@ -225,8 +211,6 @@ typedef struct lws_ss_policy {
 			const char	*blob_header[_LWSSS_HBI_COUNT];
 			const char	*blob_header[_LWSSS_HBI_COUNT];
 			const char	*auth_preamble;
 			const char	*auth_preamble;
 
 
-			const lws_ss_http_respmap_t *respmap;
-
 			union {
 			union {
 //				struct { /* LWSSSP_H1 */
 //				struct { /* LWSSSP_H1 */
 //				} h1;
 //				} h1;
@@ -240,7 +224,6 @@ typedef struct lws_ss_policy {
 			} u;
 			} u;
 
 
 			uint16_t	resp_expect;
 			uint16_t	resp_expect;
-			uint8_t		count_respmap;
 			uint8_t		fail_redirect:1;
 			uint8_t		fail_redirect:1;
 		} http;
 		} http;
 
 

+ 1 - 43
Source/ThirdParty/libwebsockets/include/libwebsockets/lws-secure-streams.h

@@ -132,15 +132,7 @@
  *   -  1: 00, 04
  *   -  1: 00, 04
  *   -  3: 4-byte MSB-first addition tx credit bytes
  *   -  3: 4-byte MSB-first addition tx credit bytes
  *
  *
- * - Proxied rx metadata
- *
- *   -  0: LWSSS_SER_RXPRE_METADATA
- *   -  1: 2-byte MSB-first rest-of-frame length
- *   -  3: 1-byte metadata name length
- *   -  4: metadata name
- *   -  ...: metadata value (for rest of packet)
- *
- * - Proxied state (8 or 11 byte packet)
+ * - Proxied state
  *
  *
  *   -  0: LWSSS_SER_RXPRE_CONNSTATE
  *   -  0: LWSSS_SER_RXPRE_CONNSTATE
  *   -  1: 00, 05 if state < 256, else 00, 08
  *   -  1: 00, 05 if state < 256, else 00, 08
@@ -200,8 +192,6 @@ typedef enum {
 					 * stream joins the sink */
 					 * stream joins the sink */
 	LWSSSCS_SINK_PART,		/* sinks get this when a new source
 	LWSSSCS_SINK_PART,		/* sinks get this when a new source
 					 * stream leaves the sink */
 					 * stream leaves the sink */
-
-	LWSSSCS_USER_BASE = 1000
 } lws_ss_constate_t;
 } lws_ss_constate_t;
 
 
 enum {
 enum {
@@ -237,7 +227,6 @@ enum {
 	LWSSS_SER_RXPRE_CREATE_RESULT,
 	LWSSS_SER_RXPRE_CREATE_RESULT,
 	LWSSS_SER_RXPRE_CONNSTATE,
 	LWSSS_SER_RXPRE_CONNSTATE,
 	LWSSS_SER_RXPRE_TXCR_UPDATE,
 	LWSSS_SER_RXPRE_TXCR_UPDATE,
-	LWSSS_SER_RXPRE_METADATA,
 	LWSSS_SER_RXPRE_TLSNEG_ENCLAVE_SIGN,
 	LWSSS_SER_RXPRE_TLSNEG_ENCLAVE_SIGN,
 
 
 	/* tx (send by client) prepends for proxied connections */
 	/* tx (send by client) prepends for proxied connections */
@@ -575,37 +564,6 @@ LWS_VISIBLE LWS_EXTERN int
 lws_ss_set_metadata(struct lws_ss_handle *h, const char *name,
 lws_ss_set_metadata(struct lws_ss_handle *h, const char *name,
 		    const void *value, size_t len);
 		    const void *value, size_t len);
 
 
-/**
- * lws_ss_get_metadata() - get current value of stream metadata item
- *
- * \param h: secure streams handle
- * \param name: metadata name from the policy
- * \param value: pointer to pointer to be set to point at the value
- * \param len: pointer to size_t to set to the length of the value
- *
- * Binds user-managed data to the named metadata item from the ss policy.
- * If present, the metadata item is handled in a protocol-specific way using
- * the associated policy information.  For example, in the policy
- *
- *  	"\"metadata\":"		"["
- *		"{\"uptag\":"  "\"X-Upload-Tag:\"},"
- *		"{\"ctype\":"  "\"Content-Type:\"},"
- *		"{\"xctype\":" "\"\"}"
- *	"],"
- *
- * when the policy is using h1 is interpreted to add h1 headers of the given
- * name with the value of the metadata on the left.
- *
- * Return 0 if *value and *len set OK, or nonzero if, eg, metadata name does
- * not exist on the streamtype.
- *
- * The pointed-to values may only exist until the next time around the event
- * loop.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_ss_get_metadata(struct lws_ss_handle *h, const char *name,
-		    const void **value, size_t *len);
-
 /*
 /*
  * lws_ss_server_ack() - indicate how we feel about what the server has sent
  * lws_ss_server_ack() - indicate how we feel about what the server has sent
  *
  *

+ 25 - 27
Source/ThirdParty/libwebsockets/lib/CMakeLists.txt

@@ -24,10 +24,10 @@
 
 
 include_directories(.)
 include_directories(.)
 
 
-macro(add_subdir_include_dirs arg1)
-	add_subdirectory(${arg1})
-	list(APPEND LWS_LIB_BUILD_INC_PATHS ${_CMAKE_INC_LIST}) 
-endmacro()
+#macro(add_subdir_include_dirs arg1)
+#	add_subdirectory(${arg1})
+#	list(APPEND LWS_LIB_BUILD_INC_PATHS ${_CMAKE_INC_LIST})
+#endmacro()
 
 
 set(LWS_LIB_INCLUDES "")
 set(LWS_LIB_INCLUDES "")
 
 
@@ -115,9 +115,9 @@ if (LWS_WITH_TLS)
 endif()
 endif()
 
 
 # Generate the lws_config.h that includes all the private compilation settings.
 # Generate the lws_config.h that includes all the private compilation settings.
-configure_file(
-       "${PROJECT_SOURCE_DIR}/cmake/lws_config_private.h.in"
-       "${PROJECT_BINARY_DIR}/lws_config_private.h")
+#configure_file(
+#       "${PROJECT_SOURCE_DIR}/cmake/lws_config_private.h.in"
+#       "${PROJECT_BINARY_DIR}/lws_config_private.h")
 
 
 add_subdir_include_dirs(core)
 add_subdir_include_dirs(core)
 add_subdir_include_dirs(misc)
 add_subdir_include_dirs(misc)
@@ -150,18 +150,17 @@ if (LWS_WITH_STATIC)
         set(CMAKE_POSITION_INDEPENDENT_CODE ON)
         set(CMAKE_POSITION_INDEPENDENT_CODE ON)
     endif()
     endif()
 
 
-	add_library(websockets STATIC ${SOURCES})# ${HDR_PUBLIC})
-	set_target_properties(websockets PROPERTIES LINKER_LANGUAGE C)
+#	add_library(websockets STATIC ${SOURCES})# ${HDR_PUBLIC})
+#	set_target_properties(websockets PROPERTIES LINKER_LANGUAGE C)
 	list(APPEND LWS_LIBRARIES websockets)
 	list(APPEND LWS_LIBRARIES websockets)
-	target_include_directories(websockets PRIVATE ${LWS_LIB_BUILD_INC_PATHS})
-	target_compile_definitions(websockets PRIVATE LWS_BUILDING_STATIC)
+#	target_include_directories(websockets PRIVATE ${LWS_LIB_BUILD_INC_PATHS})
 
 
 	if (WIN32)
 	if (WIN32)
 		# Windows uses the same .lib ending for static libraries and shared
 		# Windows uses the same .lib ending for static libraries and shared
 		# library linker files, so rename the static library.
 		# library linker files, so rename the static library.
-		set_target_properties(websockets
-			PROPERTIES
-			OUTPUT_NAME websockets_static)
+#		set_target_properties(websockets
+#			PROPERTIES
+#			OUTPUT_NAME websockets_static)
 	endif()
 	endif()
 	
 	
 endif()
 endif()
@@ -175,7 +174,6 @@ if (LWS_WITH_SHARED)
 	set_target_properties(websockets_shared PROPERTIES LINKER_LANGUAGE C)
 	set_target_properties(websockets_shared PROPERTIES LINKER_LANGUAGE C)
 	list(APPEND LWS_LIBRARIES websockets_shared)
 	list(APPEND LWS_LIBRARIES websockets_shared)
 	target_include_directories(websockets_shared PRIVATE ${LWS_LIB_BUILD_INC_PATHS})
 	target_include_directories(websockets_shared PRIVATE ${LWS_LIB_BUILD_INC_PATHS})
-	target_compile_definitions(websockets_shared PRIVATE LWS_BUILDING_SHARED)
 
 
 	# We want the shared lib to be named "libwebsockets"
 	# We want the shared lib to be named "libwebsockets"
 	# not "libwebsocket_shared".
 	# not "libwebsocket_shared".
@@ -213,11 +211,11 @@ endif()
 # part of the lib build but different targets 
 # part of the lib build but different targets 
 #
 #
 
 
-if (LWS_WITH_SHARED)
-	get_target_property(LWS_LIB_INCLUDES websockets_shared INCLUDE_DIRECTORIES)
-else()
-	get_target_property(LWS_LIB_INCLUDES websockets INCLUDE_DIRECTORIES)
-endif()
+#if (LWS_WITH_SHARED)
+#	get_target_property(LWS_LIB_INCLUDES websockets_shared INCLUDE_DIRECTORIES)
+#else()
+#	get_target_property(LWS_LIB_INCLUDES websockets INCLUDE_DIRECTORIES)
+#endif()
 
 
 
 
 # Set the so version of the lib.
 # Set the so version of the lib.
@@ -234,7 +232,7 @@ endif()
 
 
 # Setup the linking for all libs.
 # Setup the linking for all libs.
 foreach (lib ${LWS_LIBRARIES})
 foreach (lib ${LWS_LIBRARIES})
-	target_link_libraries(${lib} ${LIB_LIST})
+#	target_link_libraries(${lib} ${LIB_LIST})
 endforeach()
 endforeach()
 
 
 #
 #
@@ -250,12 +248,12 @@ if (LWS_WITH_SHARED)
 endif()
 endif()
 
 
 # Install libs and headers.
 # Install libs and headers.
-install(TARGETS ${LWS_LIBRARIES}
-		EXPORT LibwebsocketsTargets
-		LIBRARY DESTINATION "${LWS_INSTALL_LIB_DIR}${LIB_SUFFIX}" COMPONENT core
-		ARCHIVE DESTINATION "${LWS_INSTALL_LIB_DIR}${LIB_SUFFIX}" COMPONENT core
-		RUNTIME DESTINATION "${LWS_INSTALL_BIN_DIR}" COMPONENT core # Windows DLLs
-		PUBLIC_HEADER DESTINATION "${LWS_INSTALL_INCLUDE_DIR}" COMPONENT dev)
+#install(TARGETS ${LWS_LIBRARIES}
+#		EXPORT LibwebsocketsTargets
+#		LIBRARY DESTINATION "${LWS_INSTALL_LIB_DIR}${LIB_SUFFIX}" COMPONENT core
+#		ARCHIVE DESTINATION "${LWS_INSTALL_LIB_DIR}${LIB_SUFFIX}" COMPONENT core
+#		RUNTIME DESTINATION "${LWS_INSTALL_BIN_DIR}" COMPONENT core # Windows DLLs
+#		PUBLIC_HEADER DESTINATION "${LWS_INSTALL_INCLUDE_DIR}" COMPONENT dev)
 		
 		
 	#set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries" PARENT_SCOPE)
 	#set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries" PARENT_SCOPE)
 set(CPACK_COMPONENT_DEV_DISPLAY_NAME "Development files" PARENT_SCOPE)
 set(CPACK_COMPONENT_DEV_DISPLAY_NAME "Development files" PARENT_SCOPE)

+ 3 - 7
Source/ThirdParty/libwebsockets/lib/core-net/CMakeLists.txt

@@ -60,14 +60,10 @@ if (LWS_WITH_SEQUENCER)
 		core-net/sequencer.c)
 		core-net/sequencer.c)
 endif()
 endif()
 
 
-if (LWS_WITH_CLIENT)
+if (NOT LWS_WITHOUT_CLIENT)
 	list(APPEND SOURCES
 	list(APPEND SOURCES
-		core-net/client/client.c
-		core-net/client/connect.c
-		core-net/client/connect2.c
-		core-net/client/connect3.c
-		core-net/client/connect4.c
-	)
+		core-net/connect.c
+		core-net/client.c)
 endif()
 endif()
 
 
 if (NOT LWS_WITHOUT_SERVER)
 if (NOT LWS_WITHOUT_SERVER)

+ 15 - 1
Source/ThirdParty/libwebsockets/lib/core-net/adopt.c

@@ -140,16 +140,22 @@ lws_adopt_descriptor_vhost1(struct lws_vhost *vh, lws_adoption_type type,
 	 * we initialize it, it may become "live" concurrently unexpectedly...
 	 * we initialize it, it may become "live" concurrently unexpectedly...
 	 */
 	 */
 
 
+	lws_context_lock(vh->context, __func__);
+
 	n = -1;
 	n = -1;
 	if (parent)
 	if (parent)
 		n = parent->tsi;
 		n = parent->tsi;
 	new_wsi = lws_create_new_server_wsi(vh, n);
 	new_wsi = lws_create_new_server_wsi(vh, n);
-	if (!new_wsi)
+	if (!new_wsi) {
+		lws_context_unlock(vh->context);
 		return NULL;
 		return NULL;
+	}
 
 
 	new_wsi->a.opaque_user_data = opaque;
 	new_wsi->a.opaque_user_data = opaque;
 
 
 	pt = &context->pt[(int)new_wsi->tsi];
 	pt = &context->pt[(int)new_wsi->tsi];
+	lws_pt_lock(pt, __func__);
+
 	lws_stats_bump(pt, LWSSTATS_C_CONNECTIONS, 1);
 	lws_stats_bump(pt, LWSSTATS_C_CONNECTIONS, 1);
 
 
 	if (parent) {
 	if (parent) {
@@ -181,6 +187,8 @@ lws_adopt_descriptor_vhost1(struct lws_vhost *vh, lws_adoption_type type,
 		goto bail;
 		goto bail;
 	}
 	}
 
 
+	lws_pt_unlock(pt);
+
 	/*
 	/*
 	 * he's an allocated wsi, but he's not on any fds list or child list,
 	 * he's an allocated wsi, but he's not on any fds list or child list,
 	 * join him to the vhost's list of these kinds of incomplete wsi until
 	 * join him to the vhost's list of these kinds of incomplete wsi until
@@ -191,6 +199,8 @@ lws_adopt_descriptor_vhost1(struct lws_vhost *vh, lws_adoption_type type,
 			  &new_wsi->a.vhost->vh_awaiting_socket_owner);
 			  &new_wsi->a.vhost->vh_awaiting_socket_owner);
 	lws_vhost_unlock(new_wsi->a.vhost);
 	lws_vhost_unlock(new_wsi->a.vhost);
 
 
+	lws_context_unlock(vh->context);
+
 	return new_wsi;
 	return new_wsi;
 
 
 bail:
 bail:
@@ -203,8 +213,12 @@ bail:
 	vh->context->count_wsi_allocated--;
 	vh->context->count_wsi_allocated--;
 
 
 	lws_vhost_unbind_wsi(new_wsi);
 	lws_vhost_unbind_wsi(new_wsi);
+
 	lws_free(new_wsi);
 	lws_free(new_wsi);
 
 
+	lws_pt_unlock(pt);
+	lws_context_unlock(vh->context);
+
 	return NULL;
 	return NULL;
 }
 }
 
 

+ 0 - 0
Source/ThirdParty/libwebsockets/lib/core-net/client/client.c → Source/ThirdParty/libwebsockets/lib/core-net/client.c


+ 0 - 320
Source/ThirdParty/libwebsockets/lib/core-net/client/connect2.c

@@ -1,320 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2020 Andy Green <[email protected]>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "private-lib-core.h"
-
-#if !defined(LWS_WITH_SYS_ASYNC_DNS)
-static int
-lws_getaddrinfo46(struct lws *wsi, const char *ads, struct addrinfo **result)
-{
-	struct addrinfo hints;
-	int n;
-
-	memset(&hints, 0, sizeof(hints));
-	*result = NULL;
-
-	hints.ai_socktype = SOCK_STREAM;
-
-#ifdef LWS_WITH_IPV6
-	if (wsi->ipv6) {
-
-#if !defined(__ANDROID__)
-		hints.ai_family = AF_UNSPEC;
-		hints.ai_flags = AI_V4MAPPED;
-#endif
-	} else
-#endif
-	{
-		hints.ai_family = PF_UNSPEC;
-	}
-
-	n = getaddrinfo(ads, NULL, &hints, result);
-
-	lwsl_info("%s: getaddrinfo '%s' says %d\n", __func__, ads, n);
-
-	return n;
-}
-#endif
-
-struct lws *
-lws_client_connect_2_dnsreq(struct lws *wsi)
-{
-	struct addrinfo *result = NULL;
-	const char *meth = NULL, *ads;
-#if defined(LWS_WITH_IPV6)
-	struct sockaddr_in addr;
-	const char *iface;
-#endif
-	const char *adsin;
-	int n, port = 0;
-	struct lws *w;
-
-	if (lwsi_state(wsi) == LRS_WAITING_DNS ||
-	    lwsi_state(wsi) == LRS_WAITING_CONNECT) {
-		lwsl_info("%s: LRS_WAITING_DNS / CONNECT\n", __func__);
-
-		return wsi;
-	}
-
-	/*
-	 * The first job is figure out if we want to pipeline on or just join
-	 * an existing "active connection" to the same place
-	 */
-
-	meth = lws_wsi_client_stash_item(wsi, CIS_METHOD,
-					 _WSI_TOKEN_CLIENT_METHOD);
-
-	/* we only pipeline connections that said it was okay */
-
-	if (!wsi->client_pipeline) {
-		lwsl_debug("%s: new conn on no pipeline flag\n", __func__);
-
-		goto solo;
-	}
-
-	/* only pipeline things we associate with being a stream */
-
-	if (meth && strcmp(meth, "RAW") && strcmp(meth, "GET") &&
-		    strcmp(meth, "POST") && strcmp(meth, "PUT") &&
-		    strcmp(meth, "UDP") && strcmp(meth, "MQTT"))
-		goto solo;
-
-	/* consult active connections to find out disposition */
-
-	adsin = lws_wsi_client_stash_item(wsi, CIS_ADDRESS,
-					  _WSI_TOKEN_CLIENT_PEER_ADDRESS);
-
-	if (!adsin)
-		/*
-		 * This cannot happen since user code must provide the client
-		 * address to get this far, it's here to satisfy Coverity
-		 */
-		return NULL;
-
-	switch (lws_vhost_active_conns(wsi, &w, adsin)) {
-	case ACTIVE_CONNS_SOLO:
-		break;
-	case ACTIVE_CONNS_MUXED:
-		lwsl_notice("%s: ACTIVE_CONNS_MUXED\n", __func__);
-		if (lwsi_role_h2(wsi)) {
-
-			if (wsi->a.protocol->callback(wsi,
-					LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP,
-					wsi->user_space, NULL, 0))
-				goto failed1;
-
-			//lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE2);
-			//lwsi_set_state(w, LRS_ESTABLISHED);
-			lws_callback_on_writable(wsi);
-		}
-
-		return wsi;
-	case ACTIVE_CONNS_QUEUED:
-		lwsl_debug("%s: ACTIVE_CONNS_QUEUED st 0x%x: \n", __func__,
-			   lwsi_state(wsi));
-		if (lwsi_state(wsi) == LRS_UNCONNECTED) {
-			if (lwsi_role_h2(w))
-				lwsi_set_state(wsi,
-					       LRS_H2_WAITING_TO_SEND_HEADERS);
-			else
-				lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE2);
-		}
-
-		return lws_client_connect_4_established(wsi, w, 0);
-	}
-
-solo:
-	wsi->addrinfo_idx = 0;
-
-	/*
-	 * clients who will create their own fresh connection keep a copy of
-	 * the hostname they originally connected to, in case other connections
-	 * want to use it too
-	 */
-
-	if (!wsi->cli_hostname_copy) {
-		if (wsi->stash && wsi->stash->cis[CIS_HOST])
-			wsi->cli_hostname_copy =
-					lws_strdup(wsi->stash->cis[CIS_HOST]);
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
-		else {
-			char *pa = lws_hdr_simple_ptr(wsi,
-					      _WSI_TOKEN_CLIENT_PEER_ADDRESS);
-			if (pa)
-				wsi->cli_hostname_copy = lws_strdup(pa);
-		}
-#endif
-	}
-
-	/*
-	 * If we made our own connection, and we're doing a method that can
-	 * take a pipeline, we are an "active client connection".
-	 *
-	 * Add ourselves to the vhost list of those so that others can
-	 * piggyback on our transaction queue
-	 */
-
-	if (meth && (!strcmp(meth, "RAW") || !strcmp(meth, "GET") ||
-		     !strcmp(meth, "POST") || !strcmp(meth, "PUT") ||
-		     !strcmp(meth, "MQTT")) &&
-	    lws_dll2_is_detached(&wsi->dll2_cli_txn_queue) &&
-	    lws_dll2_is_detached(&wsi->dll_cli_active_conns)) {
-		lws_vhost_lock(wsi->a.vhost);
-		lwsl_info("%s: adding active conn %p\n", __func__, wsi);
-		/* caution... we will have to unpick this on oom4 path */
-		lws_dll2_add_head(&wsi->dll_cli_active_conns,
-				 &wsi->a.vhost->dll_cli_active_conns_owner);
-		lws_vhost_unlock(wsi->a.vhost);
-	}
-
-	/*
-	 * unix socket destination?
-	 */
-
-	if (wsi->stash)
-		ads = wsi->stash->cis[CIS_ADDRESS];
-	else
-		ads = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS);
-
-	/*
-	 * Since address must be given at client creation, should not be
-	 * possible, but necessary to satisfy coverity
-	 */
-	if (!ads)
-		return NULL;
-
-#if defined(LWS_WITH_UNIX_SOCK)
-	if (*ads == '+') {
-		wsi->unix_skt = 1;
-		n = 0;
-		goto next_step;
-	}
-#endif
-
-	/*
-	 * start off allowing ipv6 on connection if vhost allows it
-	 */
-	wsi->ipv6 = LWS_IPV6_ENABLED(wsi->a.vhost);
-#ifdef LWS_WITH_IPV6
-	if (wsi->stash)
-		iface = wsi->stash->cis[CIS_IFACE];
-	else
-		iface = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_IFACE);
-
-	if (wsi->ipv6 && iface &&
-	    inet_pton(AF_INET, iface, &addr.sin_addr) == 1) {
-		lwsl_notice("%s: client connection forced to IPv4\n", __func__);
-		wsi->ipv6 = 0;
-	}
-#endif
-
-#if defined(LWS_WITH_DETAILED_LATENCY)
-	if (lwsi_state(wsi) == LRS_WAITING_DNS &&
-	    wsi->a.context->detailed_latency_cb) {
-		wsi->detlat.type = LDLT_NAME_RESOLUTION;
-		wsi->detlat.latencies[LAT_DUR_PROXY_CLIENT_REQ_TO_WRITE] =
-			lws_now_usecs() -
-			wsi->detlat.earliest_write_req_pre_write;
-		wsi->detlat.latencies[LAT_DUR_USERCB] = 0;
-		lws_det_lat_cb(wsi->a.context, &wsi->detlat);
-		wsi->detlat.earliest_write_req_pre_write = lws_now_usecs();
-	}
-#endif
-
-#if defined(LWS_CLIENT_HTTP_PROXYING) && \
-	(defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2))
-
-	/* Decide what it is we need to connect to:
-	 *
-	 * Priority 1: connect to http proxy */
-
-	if (wsi->a.vhost->http.http_proxy_port) {
-		ads = wsi->a.vhost->http.http_proxy_address;
-		port = wsi->a.vhost->http.http_proxy_port;
-#else
-		if (0) {
-#endif
-
-#if defined(LWS_WITH_SOCKS5)
-
-	/* Priority 2: Connect to SOCK5 Proxy */
-
-	} else if (wsi->a.vhost->socks_proxy_port) {
-		lwsl_client("Sending SOCKS Greeting\n");
-		ads = wsi->a.vhost->socks_proxy_address;
-		port = wsi->a.vhost->socks_proxy_port;
-#endif
-	} else {
-
-		/* Priority 3: Connect directly */
-
-		/* ads already set */
-		port = wsi->c_port;
-	}
-
-	/*
-	 * prepare the actual connection
-	 * to whatever we decided to connect to
-	 */
-	lwsi_set_state(wsi, LRS_WAITING_DNS);
-
-	lwsl_info("%s: %p: lookup %s:%u\n", __func__, wsi, ads, port);
-	(void)port;
-
-#if defined(LWS_WITH_DETAILED_LATENCY)
-	wsi->detlat.earliest_write_req_pre_write = lws_now_usecs();
-#endif
-#if !defined(LWS_WITH_SYS_ASYNC_DNS)
-	if (wsi->dns_results)
-		n = 0;
-	else
-		n = lws_getaddrinfo46(wsi, ads, &result);
-#else
-	lwsi_set_state(wsi, LRS_WAITING_DNS);
-	/* this is either FAILED, CONTINUING, or already called connect_4 */
-
-	n = lws_async_dns_query(wsi->a.context, wsi->tsi, ads,
-				LWS_ADNS_RECORD_A, lws_client_connect_3_connect,
-				wsi, NULL);
-	if (n == LADNS_RET_FAILED_WSI_CLOSED)
-		return NULL;
-
-	if (n == LADNS_RET_FAILED)
-		goto failed1;
-
-	return wsi;
-#endif
-
-#if defined(LWS_WITH_UNIX_SOCK)
-next_step:
-#endif
-	return lws_client_connect_3_connect(wsi, ads, result, n, NULL);
-
-//#if defined(LWS_WITH_SYS_ASYNC_DNS)
-failed1:
-	lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "client_connect2");
-
-	return NULL;
-//#endif
-}

+ 0 - 558
Source/ThirdParty/libwebsockets/lib/core-net/client/connect3.c

@@ -1,558 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2020 Andy Green <[email protected]>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "private-lib-core.h"
-
-void
-lws_client_conn_wait_timeout(lws_sorted_usec_list_t *sul)
-{
-	struct lws *wsi = lws_container_of(sul, struct lws,
-					   sul_connect_timeout);
-
-	/*
-	 * This is used to constrain the time we're willing to wait for a
-	 * connection before giving up on it and retrying.
-	 */
-
-	lwsl_info("%s: connect wait timeout has fired\n", __func__);
-	lws_client_connect_3_connect(wsi, NULL, NULL, 0, NULL);
-}
-
-struct lws *
-lws_client_connect_3_connect(struct lws *wsi, const char *ads,
-			     const struct addrinfo *result, int n, void *opaque)
-{
-#if defined(LWS_WITH_UNIX_SOCK)
-	struct sockaddr_un sau;
-#endif
-#ifdef LWS_WITH_IPV6
-	char ipv6only = lws_check_opt(wsi->a.vhost->options,
-				      LWS_SERVER_OPTION_IPV6_V6ONLY_MODIFY |
-				      LWS_SERVER_OPTION_IPV6_V6ONLY_VALUE);
-#endif
-	struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
-	const struct sockaddr *psa = NULL;
-	uint16_t port = wsi->c_port;
-	const char *cce, *iface;
-	lws_sockaddr46 sa46;
-	ssize_t plen = 0;
-	char ni[48];
-	int m;
-
-       if (n == LWS_CONNECT_COMPLETION_GOOD)
-               goto conn_good;
-
-#if defined(LWS_WITH_IPV6) && defined(__ANDROID__)
-	ipv6only = 0;
-#endif
-
-	/*
-	 * async dns calls back here for everybody who cares when it gets a
-	 * result... but if we are piggybacking, we do not want to connect
-	 * ourselves
-	 */
-
-	if (!lws_dll2_is_detached(&wsi->dll2_cli_txn_queue))
-		return wsi;
-
-	/*
-	* We can check using getsockopt if our connect actually completed.
-	* Posix connect() allows nonblocking to redo the connect to
-	* find out if it succeeded, for win32 we have to use this path
-	* and take WSAEALREADY as a successful connect.
-	*/
-
-	if (lwsi_state(wsi) == LRS_WAITING_CONNECT &&
-	    lws_socket_is_valid(wsi->desc.sockfd)) {
-#if !defined(WIN32)
-		socklen_t sl = sizeof(int);
-		int e = 0;
-#endif
-
-		if (!result && /* no dns results... */
-		    /* no ongoing connect timeout */
-		    !wsi->sul_connect_timeout.list.owner)
-			goto connect_to;
-#if defined(WIN32)
-		if (!connect(wsi->desc.sockfd, NULL, 0)) {
-			goto conn_good;
-               } else {
-			if (!LWS_ERRNO ||
-			    LWS_ERRNO == WSAEINVAL ||
-			    LWS_ERRNO == WSAEWOULDBLOCK ||
-			    LWS_ERRNO == WSAEALREADY) {
-				lwsl_info("%s: errno %d\n", __func__, errno);
-				return NULL;
-			}
-			lwsl_info("%s: connect check take as FAILED\n",
-				  __func__);
-		}
-#else
-		/*
-		* this resets SO_ERROR after reading it.  If there's an error
-		* condition the connect definitively failed.
-		*/
-
-		if (!getsockopt(wsi->desc.sockfd, SOL_SOCKET, SO_ERROR,
-				&e, &sl)) {
-			if (!e) {
-				lwsl_debug("%s: getsockopt check: "
-					   "conn OK errno %d\n", __func__,
-					   errno);
-
-				goto conn_good;
-			}
-
-			lwsl_debug("%s: getsockopt fd %d says err %d\n",
-				   __func__, wsi->desc.sockfd, e);
-		}
-#endif
-
-		lwsl_debug("%s: getsockopt check: conn fail: errno %d\n",
-				__func__, LWS_ERRNO);
-		goto try_next_result_fds;
-	}
-
-#if defined(LWS_WITH_UNIX_SOCK)
-	if (ads && *ads == '+') {
-		ads++;
-		memset(&sa46, 0, sizeof(sa46));
-		memset(&sau, 0, sizeof(sau));
-		sau.sun_family = AF_UNIX;
-		strncpy(sau.sun_path, ads, sizeof(sau.sun_path));
-		sau.sun_path[sizeof(sau.sun_path) - 1] = '\0';
-
-		lwsl_info("%s: Unix skt: %s\n", __func__, ads);
-
-		if (sau.sun_path[0] == '@')
-			sau.sun_path[0] = '\0';
-
-		goto ads_known;
-	}
-#endif
-
-#if defined(LWS_WITH_SYS_ASYNC_DNS)
-	if (n == LADNS_RET_FAILED) {
-		lwsl_notice("%s: adns failed %s\n", __func__, ads);
-		/*
-		 * Caller that is giving us LADNS_RET_FAILED will deal
-		 * with cleanup
-		 */
-		return NULL;
-	}
-#endif
-
-	if (!wsi->dns_results) {
-		wsi->dns_results_next = wsi->dns_results = result;
-		if (result)
-			lwsl_debug("%s: result %p result->ai_next %p\n",
-					__func__, result, result->ai_next);
-	}
-
-#if defined(LWS_WITH_DETAILED_LATENCY)
-	if (lwsi_state(wsi) == LRS_WAITING_DNS &&
-	    wsi->a.context->detailed_latency_cb) {
-		wsi->detlat.type = LDLT_NAME_RESOLUTION;
-		wsi->detlat.latencies[LAT_DUR_PROXY_CLIENT_REQ_TO_WRITE] =
-			lws_now_usecs() -
-			wsi->detlat.earliest_write_req_pre_write;
-		wsi->detlat.latencies[LAT_DUR_USERCB] = 0;
-		lws_det_lat_cb(wsi->a.context, &wsi->detlat);
-		wsi->detlat.earliest_write_req_pre_write = lws_now_usecs();
-	}
-#endif
-#if defined(LWS_CLIENT_HTTP_PROXYING) && \
-	(defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2))
-
-	/* Decide what it is we need to connect to:
-	 *
-	 * Priority 1: connect to http proxy */
-
-	if (wsi->a.vhost->http.http_proxy_port) {
-		port = wsi->a.vhost->http.http_proxy_port;
-#else
-		if (0) {
-#endif
-
-#if defined(LWS_WITH_SOCKS5)
-
-	/* Priority 2: Connect to SOCK5 Proxy */
-
-	} else if (wsi->a.vhost->socks_proxy_port) {
-		if (lws_socks5c_generate_msg(wsi, SOCKS_MSG_GREETING, &plen)) {
-			cce = "socks msg too large";
-			goto oom4;
-		}
-
-		lwsl_client("Sending SOCKS Greeting\n");
-		ads = wsi->a.vhost->socks_proxy_address;
-		port = wsi->a.vhost->socks_proxy_port;
-#endif
-	}
-
-	memset(&sa46, 0, sizeof(sa46));
-
-	if (n || !wsi->dns_results) {
-		/* lws_getaddrinfo46 failed, there is no usable result */
-		lwsl_notice("%s: lws_getaddrinfo46 failed %d\n",
-				__func__, n);
-
-		cce = "ipv6 lws_getaddrinfo46 failed";
-		goto oom4;
-	}
-
-	/*
-	 * Let's try connecting to each of the results in turn until one works
-	 * or we run out of results
-	 */
-
-next_result:
-
-	psa = (const struct sockaddr *)&sa46;
-	n = sizeof(sa46);
-	memset(&sa46, 0, sizeof(sa46));
-
-	switch (wsi->dns_results_next->ai_family) {
-	case AF_INET:
-#if defined(LWS_WITH_IPV6)
-		if (ipv6only) {
-			sa46.sa4.sin_family = AF_INET6;
-
-			/* map IPv4 to IPv6 */
-			memset((char *)&sa46.sa6.sin6_addr, 0,
-						sizeof(sa46.sa6.sin6_addr));
-			sa46.sa6.sin6_addr.s6_addr[10] = 0xff;
-			sa46.sa6.sin6_addr.s6_addr[11] = 0xff;
-			memcpy(&sa46.sa6.sin6_addr.s6_addr[12],
-				&((struct sockaddr_in *)
-				    wsi->dns_results_next->ai_addr)->sin_addr,
-							sizeof(struct in_addr));
-			sa46.sa6.sin6_port = htons(port);
-			ni[0] = '\0';
-			lws_write_numeric_address(sa46.sa6.sin6_addr.s6_addr,
-						  16, ni, sizeof(ni));
-			lwsl_info("%s: %s ipv4->ipv6 %s\n", __func__,
-				  ads ? ads : "(null)", ni);
-			break;
-		}
-#endif
-		sa46.sa4.sin_family = AF_INET;
-		sa46.sa4.sin_addr.s_addr =
-			((struct sockaddr_in *)wsi->dns_results_next->ai_addr)->
-								sin_addr.s_addr;
-		memset(&sa46.sa4.sin_zero, 0, sizeof(sa46.sa4.sin_zero));
-		sa46.sa4.sin_port = htons(port);
-		n = sizeof(struct sockaddr_in);
-		lws_write_numeric_address((uint8_t *)&sa46.sa4.sin_addr.s_addr,
-					  4, ni, sizeof(ni));
-		lwsl_info("%s: %s ipv4 %s\n", __func__,
-					ads ? ads : "(null)", ni);
-		break;
-	case AF_INET6:
-#if defined(LWS_WITH_IPV6)
-		if (!wsi->ipv6)
-			goto try_next_result;
-		sa46.sa4.sin_family = AF_INET6;
-		memcpy(&sa46.sa6.sin6_addr,
-		       &((struct sockaddr_in6 *)
-				       wsi->dns_results_next->ai_addr)->
-				       sin6_addr, sizeof(struct in6_addr));
-		sa46.sa6.sin6_scope_id = ((struct sockaddr_in6 *)
-				wsi->dns_results_next->ai_addr)->sin6_scope_id;
-		sa46.sa6.sin6_flowinfo = ((struct sockaddr_in6 *)
-				wsi->dns_results_next->ai_addr)->sin6_flowinfo;
-		sa46.sa6.sin6_port = htons(port);
-		lws_write_numeric_address((uint8_t *)&sa46.sa6.sin6_addr,
-				16, ni, sizeof(ni));
-		lwsl_info("%s: %s ipv6 %s\n", __func__,
-				ads ? ads : "(null)", ni);
-#else
-		goto try_next_result;	/* ipv4 only can't use this */
-#endif
-		break;
-	}
-
-#if defined(LWS_WITH_UNIX_SOCK)
-ads_known:
-#endif
-
-	/* now we decided on ipv4 or ipv6, set the port and create socket*/
-
-	if (!lws_socket_is_valid(wsi->desc.sockfd)) {
-
-		if (wsi->a.context->event_loop_ops->check_client_connect_ok &&
-		    wsi->a.context->event_loop_ops->check_client_connect_ok(wsi)
-		) {
-			cce = "waiting for event loop watcher to close";
-			goto oom4;
-		}
-
-#if defined(LWS_WITH_UNIX_SOCK)
-		if (wsi->unix_skt)
-			wsi->desc.sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
-		else
-#endif
-			wsi->desc.sockfd = socket(sa46.sa4.sin_family,
-						  SOCK_STREAM, 0);
-
-		if (!lws_socket_is_valid(wsi->desc.sockfd)) {
-			lwsl_warn("Unable to open socket\n");
-			goto try_next_result;
-		}
-
-		if (lws_plat_set_socket_options(wsi->a.vhost, wsi->desc.sockfd,
-#if defined(LWS_WITH_UNIX_SOCK)
-						wsi->unix_skt)) {
-#else
-						0)) {
-#endif
-			lwsl_err("Failed to set wsi socket options\n");
-			goto try_next_result_closesock;
-		}
-
-		lwsl_debug("%s: %p: WAITING_CONNECT\n", __func__, wsi);
-		lwsi_set_state(wsi, LRS_WAITING_CONNECT);
-
-		if (wsi->a.context->event_loop_ops->sock_accept)
-			if (wsi->a.context->event_loop_ops->sock_accept(wsi))
-				goto try_next_result_closesock;
-
-		lws_pt_lock(pt, __func__);
-		if (__insert_wsi_socket_into_fds(wsi->a.context, wsi)) {
-			lws_pt_unlock(pt);
-			goto try_next_result_closesock;
-		}
-		lws_pt_unlock(pt);
-
-		/*
-		 * The fd + wsi combination is entered into the wsi tables
-		 * at this point, with a pollfd
-		 *
-		 * Past here, we can't simply free the structs as error
-		 * handling as oom4 does.
-		 *
-		 * We can run the whole close flow, or unpick the fds inclusion
-		 * and anything else we have done.
-		 */
-
-		if (lws_change_pollfd(wsi, 0, LWS_POLLIN))
-			goto try_next_result_fds;
-
-		if (!wsi->a.protocol)
-			wsi->a.protocol = &wsi->a.vhost->protocols[0];
-
-		lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CONNECT_RESPONSE,
-				wsi->a.vhost->connect_timeout_secs);
-
-		iface = lws_wsi_client_stash_item(wsi, CIS_IFACE,
-						  _WSI_TOKEN_CLIENT_IFACE);
-
-		if (iface && *iface) {
-			m = lws_socket_bind(wsi->a.vhost, wsi->desc.sockfd, 0,
-					    iface, wsi->ipv6);
-			if (m < 0)
-				goto try_next_result_fds;
-		}
-	}
-
-#if defined(LWS_WITH_UNIX_SOCK)
-	if (wsi->unix_skt) {
-		psa = (const struct sockaddr *)&sau;
-		if (sau.sun_path[0])
-			n = (int)(sizeof(uint16_t) + strlen(sau.sun_path));
-		else
-			n = (int)(sizeof(uint16_t) +
-					strlen(&sau.sun_path[1]) + 1);
-	} else
-#endif
-
-	if (!psa) /* coverity */
-		goto try_next_result_fds;
-
-	/*
-	 * The actual connection attempt
-	 */
-
-#if defined(LWS_WITH_DETAILED_LATENCY)
-	wsi->detlat.earliest_write_req =
-		wsi->detlat.earliest_write_req_pre_write = lws_now_usecs();
-#endif
-
-#if defined(LWS_ESP_PLATFORM)
-	errno = 0;
-#endif
-	m = connect(wsi->desc.sockfd, (const struct sockaddr *)psa, n);
-	if (m == -1) {
-		int errno_copy = LWS_ERRNO;
-
-		lwsl_debug("%s: connect says errno: %d\n", __func__,
-								errno_copy);
-
-		if (errno_copy && errno_copy != LWS_EALREADY &&
-		    errno_copy != LWS_EINPROGRESS &&
-		    errno_copy != LWS_EWOULDBLOCK
-#ifdef _WIN32
-			&& errno_copy != WSAEINVAL
-                       && errno_copy != WSAEISCONN
-#endif
-		) {
-#if defined(_DEBUG)
-			char nads[48];
-			lws_sa46_write_numeric_address(&sa46, nads,
-								sizeof(nads));
-			lwsl_info("%s: Connect failed: %s port %d\n",
-				    __func__, nads, port);
-#endif
-			goto try_next_result_fds;
-		}
-
-#if defined(WIN32)
-		if (lws_plat_check_connection_error(wsi))
-			goto try_next_result_fds;
-               if (errno_copy == WSAEISCONN)
-                       goto conn_good;
-#endif
-
-		/*
-		 * Let's set a specialized timeout for this connect attempt
-		 * completion, it uses wsi->sul_connect_timeout just for this
-		 * purpose
-		 */
-
-		lws_sul_schedule(wsi->a.context, 0, &wsi->sul_connect_timeout,
-				 lws_client_conn_wait_timeout,
-				 wsi->a.context->timeout_secs *
-						 LWS_USEC_PER_SEC);
-
-		/*
-		 * must do specifically a POLLOUT poll to hear
-		 * about the connect completion
-		 */
-#if !defined(WIN32)
-		if (lws_change_pollfd(wsi, 0, LWS_POLLOUT))
-			goto try_next_result_fds;
-#endif
-
-		return wsi;
-	}
-
-conn_good:
-	lws_sul_cancel(&wsi->sul_connect_timeout);
-	lwsl_info("%s: Connection started %p\n", __func__, wsi->dns_results);
-
-	/* the tcp connection has happend */
-
-#if defined(LWS_WITH_DETAILED_LATENCY)
-	if (wsi->a.context->detailed_latency_cb) {
-		wsi->detlat.type = LDLT_CONNECTION;
-		wsi->detlat.latencies[LAT_DUR_PROXY_CLIENT_REQ_TO_WRITE] =
-			lws_now_usecs() -
-			wsi->detlat.earliest_write_req_pre_write;
-		wsi->detlat.latencies[LAT_DUR_USERCB] = 0;
-		lws_det_lat_cb(wsi->a.context, &wsi->detlat);
-		wsi->detlat.earliest_write_req =
-			wsi->detlat.earliest_write_req_pre_write =
-							lws_now_usecs();
-	}
-#endif
-
-	lws_addrinfo_clean(wsi);
-
-	if (wsi->a.protocol)
-		wsi->a.protocol->callback(wsi, LWS_CALLBACK_WSI_CREATE,
-					wsi->user_space, NULL, 0);
-
-	lwsl_debug("%s: going into connect_4\n", __func__);
-	return lws_client_connect_4_established(wsi, NULL, plen);
-
-oom4:
-	/*
-	 * We get here if we're trying to clean up a connection attempt that
-	 * didn't make it as far as getting inserted into the wsi / fd tables
-	 */
-
-	if (lwsi_role_client(wsi) && wsi->a.protocol
-				/* && lwsi_state_est(wsi) */)
-		lws_inform_client_conn_fail(wsi,(void *)cce, strlen(cce));
-
-	/* take care that we might be inserted in fds already */
-	if (wsi->position_in_fds_table != LWS_NO_FDS_POS)
-		/* do the full wsi close flow */
-		goto failed1;
-
-	/*
-	 * We can't be an active client connection any more, if we thought
-	 * that was what we were going to be doing.  It should be if we are
-	 * failing by oom4 path, we are still called by
-	 * lws_client_connect_via_info() and will be returning NULL to that,
-	 * so nobody else should have had a chance to queue on us.
-	 */
-	{
-		struct lws_vhost *vhost = wsi->a.vhost;
-		lws_sockfd_type sfd = wsi->desc.sockfd;
-
-		lws_vhost_lock(vhost);
-		__lws_free_wsi(wsi);
-		lws_vhost_unlock(vhost);
-
-		sanity_assert_no_wsi_traces(vhost->context, wsi);
-		sanity_assert_no_sockfd_traces(vhost->context, sfd);
-	}
-
-	return NULL;
-
-connect_to:
-	/*
-	 * It looks like the sul_connect_timeout fired
-	 */
-	lwsl_info("%s: abandoning connect due to timeout\n", __func__);
-
-try_next_result_fds:
-	__remove_wsi_socket_from_fds(wsi);
-
-try_next_result_closesock:
-	/*
-	 * We are killing the socket but leaving
-	 */
-	compatible_close(wsi->desc.sockfd);
-	wsi->desc.sockfd = LWS_SOCK_INVALID;
-
-try_next_result:
-	lws_sul_cancel(&wsi->sul_connect_timeout);
-	if (wsi->dns_results_next) {
-		wsi->dns_results_next = wsi->dns_results_next->ai_next;
-		if (wsi->dns_results_next)
-			goto next_result;
-	}
-	lws_addrinfo_clean(wsi);
-	cce = "Unable to connect";
-
-//failed:
-	lws_inform_client_conn_fail(wsi, (void *)cce, strlen(cce));
-
-failed1:
-	lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "client_connect2");
-
-	return NULL;
-}

+ 0 - 329
Source/ThirdParty/libwebsockets/lib/core-net/client/connect4.c

@@ -1,329 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2020 Andy Green <[email protected]>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "private-lib-core.h"
-
-struct lws *
-lws_client_connect_4_established(struct lws *wsi, struct lws *wsi_piggyback,
-				 ssize_t plen)
-{
-#if defined(LWS_CLIENT_HTTP_PROXYING)
-	struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
-#endif
-	const char *meth;
-	struct lws_pollfd pfd;
-	const char *cce = "";
-	int n, m, rawish = 0;
-
-	meth = lws_wsi_client_stash_item(wsi, CIS_METHOD,
-					 _WSI_TOKEN_CLIENT_METHOD);
-
-	if (meth && (!strcmp(meth, "RAW")
-#if defined(LWS_ROLE_MQTT)
-		     || !strcmp(meth, "MQTT")
-#endif
-	))
-		rawish = 1;
-
-	if (wsi_piggyback)
-		goto send_hs;
-
-#if defined(LWS_CLIENT_HTTP_PROXYING)
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
-	/* we are connected to server, or proxy */
-
-	/* http proxy */
-	if (wsi->a.vhost->http.http_proxy_port) {
-		const char *cpa;
-
-		cpa = lws_wsi_client_stash_item(wsi, CIS_ADDRESS,
-						_WSI_TOKEN_CLIENT_PEER_ADDRESS);
-		if (!cpa)
-			goto failed;
-
-		lwsl_info("%s: going via proxy\n", __func__);
-
-		plen = lws_snprintf((char *)pt->serv_buf, 256,
-			"CONNECT %s:%u HTTP/1.1\x0d\x0a"
-			"Host: %s:%u\x0d\x0a"
-			"User-agent: lws\x0d\x0a", cpa, wsi->ocport,
-						   cpa, wsi->ocport);
-
-#if defined(LWS_WITH_HTTP_BASIC_AUTH)
-		if (wsi->a.vhost->proxy_basic_auth_token[0])
-			plen += lws_snprintf((char *)pt->serv_buf + plen, 256,
-					"Proxy-authorization: basic %s\x0d\x0a",
-					wsi->a.vhost->proxy_basic_auth_token);
-#endif
-
-		plen += lws_snprintf((char *)pt->serv_buf + plen, 5,
-					"\x0d\x0a");
-
-		/* lwsl_hexdump_notice(pt->serv_buf, plen); */
-
-		/*
-		 * OK from now on we talk via the proxy, so connect to that
-		 */
-		if (wsi->stash)
-			wsi->stash->cis[CIS_ADDRESS] =
-				wsi->a.vhost->http.http_proxy_address;
-		else
-			if (lws_hdr_simple_create(wsi,
-					_WSI_TOKEN_CLIENT_PEER_ADDRESS,
-					wsi->a.vhost->http.http_proxy_address))
-			goto failed;
-		wsi->c_port = wsi->a.vhost->http.http_proxy_port;
-
-		n = send(wsi->desc.sockfd, (char *)pt->serv_buf, (int)plen,
-			 MSG_NOSIGNAL);
-		if (n < 0) {
-			lwsl_debug("ERROR writing to proxy socket\n");
-			cce = "proxy write failed";
-			goto failed;
-		}
-
-		lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_PROXY_RESPONSE,
-				wsi->a.context->timeout_secs);
-
-		lwsi_set_state(wsi, LRS_WAITING_PROXY_REPLY);
-
-		return wsi;
-	}
-#endif
-#endif
-
-	/* coverity */
-	if (!wsi->a.protocol)
-		return NULL;
-
-#if defined(LWS_WITH_SOCKS5)
-	if (lwsi_state(wsi) != 	LRS_ESTABLISHED)
-		switch (lws_socks5c_greet(wsi, &cce)) {
-		case -1:
-			goto failed;
-		case 1:
-			return wsi;
-		default:
-			break;
-		}
-#endif
-
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
-send_hs:
-
-	if (wsi_piggyback &&
-	    !lws_dll2_is_detached(&wsi->dll2_cli_txn_queue)) {
-		/*
-		 * We are pipelining on an already-established connection...
-		 * we can skip tls establishment.
-		 *
-		 * Set these queued guys to a state where they won't actually
-		 * send their headers until we decide later.
-		 */
-
-		lwsi_set_state(wsi, LRS_H2_WAITING_TO_SEND_HEADERS);
-
-		/*
-		 * we can't send our headers directly, because they have to
-		 * be sent when the parent is writeable.  The parent will check
-		 * for anybody on his client transaction queue that is in
-		 * LRS_H1C_ISSUE_HANDSHAKE2, and let them write.
-		 *
-		 * If we are trying to do this too early, before the master
-		 * connection has written his own headers, then it will just
-		 * wait in the queue until it's possible to send them.
-		 */
-		lws_callback_on_writable(wsi_piggyback);
-#if defined(LWS_WITH_DETAILED_LATENCY)
-		wsi->detlat.earliest_write_req =
-				wsi->detlat.earliest_write_req_pre_write =
-								lws_now_usecs();
-#endif
-		lwsl_info("%s: wsi %p: waiting to send hdrs (par state 0x%x)\n",
-			    __func__, wsi, lwsi_state(wsi_piggyback));
-	} else {
-		lwsl_info("%s: wsi %p: %s %s client created own conn "
-			  "(raw %d) vh %sm st 0x%x\n",
-			    __func__, wsi, wsi->role_ops->name,
-			    wsi->a.protocol->name, rawish, wsi->a.vhost->name,
-			    lwsi_state(wsi));
-
-		/* we are making our own connection */
-
-		if (!rawish) {
-			if (lwsi_state(wsi) != LRS_H1C_ISSUE_HANDSHAKE2)
-				lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE);
-		} else {
-			/* for a method = "RAW" connection, this makes us
-			 * established */
-
-#if defined(LWS_WITH_TLS) && !defined(LWS_WITH_MBEDTLS)
-
-			/* we have connected if we got here */
-
-			if (lwsi_state(wsi) == LRS_WAITING_CONNECT &&
-			    (wsi->tls.use_ssl & LCCSCF_USE_SSL)) {
-				int result;
-
-				/*
-				 * We can retry this... just cook the SSL BIO
-				 * the first time
-				 */
-
-				result = lws_client_create_tls(wsi, &cce, 1);
-				lwsl_debug("%s: create_tls said %d\n",
-							__func__, result);
-				switch (result) {
-				case CCTLS_RETURN_DONE:
-					break;
-				case CCTLS_RETURN_RETRY:
-					return wsi;
-				default:
-					goto failed;
-				}
-
-				/*
-				 * We succeeded to negotiate a new client tls
-				 * tunnel.  If it's h2 alpn, we have arranged
-				 * to send the h2 prefix and set our state to
-				 * LRS_H2_WAITING_TO_SEND_HEADERS already.
-				 */
-
-				lwsl_notice("%s: wsi %p: "
-					    "tls established st 0x%x\n",
-					    __func__, wsi, lwsi_state(wsi));
-
-				if (lwsi_state(wsi) !=
-						LRS_H2_WAITING_TO_SEND_HEADERS)
-					lwsi_set_state(wsi,
-						LRS_H1C_ISSUE_HANDSHAKE2);
-				lws_set_timeout(wsi,
-					PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND,
-						wsi->a.context->timeout_secs);
-
-				goto provoke_service;
-			}
-#endif
-
-			/* clear his established timeout */
-			lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
-
-			m = wsi->role_ops->adoption_cb[0];
-			if (m) {
-				n = user_callback_handle_rxflow(
-						wsi->a.protocol->callback, wsi,
-						m, wsi->user_space, NULL, 0);
-				if (n < 0) {
-					lwsl_info("RAW_PROXY_CLI_ADOPT err\n");
-					goto failed;
-				}
-			}
-
-			/* service.c pollout processing wants this */
-			wsi->hdr_parsing_completed = 1;
-#if defined(LWS_ROLE_MQTT)
-			if (!strcmp(meth, "MQTT")) {
-#if defined(LWS_WITH_TLS)
-				if (wsi->tls.use_ssl & LCCSCF_USE_SSL) {
-					lwsi_set_state(wsi, LRS_WAITING_SSL);
-					return wsi;
-				}
-#endif
-				lwsl_info("%s: settings LRS_MQTTC_IDLE\n",
-					  __func__);
-				lwsi_set_state(wsi, LRS_MQTTC_IDLE);
-
-				/*
-				 * provoke service to issue the CONNECT
-				 * directly.
-				 */
-				lws_set_timeout(wsi,
-					PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE,
-						wsi->a.context->timeout_secs);
-
-				assert(lws_socket_is_valid(wsi->desc.sockfd));
-
-				pfd.fd = wsi->desc.sockfd;
-				pfd.events = LWS_POLLIN;
-				pfd.revents = LWS_POLLOUT;
-
-				lwsl_info("%s: going to service fd\n",
-						__func__);
-				n = lws_service_fd(wsi->a.context, &pfd);
-				if (n < 0) {
-					cce = "first service failed";
-					goto failed;
-				}
-				if (n)
-					/* returns 1 on fail after close wsi */
-					return NULL;
-				return wsi;
-			}
-#endif
-			lwsl_info("%s: setting ESTABLISHED\n", __func__);
-			lwsi_set_state(wsi, LRS_ESTABLISHED);
-
-			return wsi;
-		}
-
-		/*
-		 * provoke service to issue the handshake directly.
-		 *
-		 * we need to do it this way because in the proxy case, this is
-		 * the next state and executed only if and when we get a good
-		 * proxy response inside the state machine... but notice in
-		 * SSL case this may not have sent anything yet with 0 return,
-		 * and won't until many retries from main loop.  To stop that
-		 * becoming endless, cover with a timeout.
-		 */
-#if defined(LWS_WITH_TLS) && !defined(LWS_WITH_MBEDTLS)
-provoke_service:
-#endif
-		lws_set_timeout(wsi, PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE,
-				wsi->a.context->timeout_secs);
-
-		assert(lws_socket_is_valid(wsi->desc.sockfd));
-
-		pfd.fd = wsi->desc.sockfd;
-		pfd.events = LWS_POLLIN;
-		pfd.revents = LWS_POLLIN;
-
-		n = lws_service_fd(wsi->a.context, &pfd);
-		if (n < 0) {
-			cce = "first service failed";
-			goto failed;
-		}
-		if (n) /* returns 1 on failure after closing wsi */
-			return NULL;
-	}
-#endif
-	return wsi;
-
-failed:
-	lws_inform_client_conn_fail(wsi, (void *)cce, strlen(cce));
-
-	lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "client_connect2");
-
-	return NULL;
-}

+ 1 - 0
Source/ThirdParty/libwebsockets/lib/core-net/close.c

@@ -448,6 +448,7 @@ just_kill_connection:
 		lws_vfs_file_close(&wsi->http.fop_fd);
 		lws_vfs_file_close(&wsi->http.fop_fd);
 #endif
 #endif
 
 
+	lws_sul_cancel(&wsi->sul_connect_timeout);
 #if defined(LWS_WITH_SYS_ASYNC_DNS)
 #if defined(LWS_WITH_SYS_ASYNC_DNS)
 	lws_async_dns_cancel(wsi);
 	lws_async_dns_cancel(wsi);
 #endif
 #endif

+ 6 - 64
Source/ThirdParty/libwebsockets/lib/core-net/client/connect.c → Source/ThirdParty/libwebsockets/lib/core-net/connect.c

@@ -1,7 +1,7 @@
 /*
 /*
  * libwebsockets - small server side websockets and web server implementation
  * libwebsockets - small server side websockets and web server implementation
  *
  *
- * Copyright (C) 2010 - 2020 Andy Green <[email protected]>
+ * Copyright (C) 2010 - 2019 Andy Green <[email protected]>
  *
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to
  * of this software and associated documentation files (the "Software"), to
@@ -22,65 +22,9 @@
  * IN THE SOFTWARE.
  * IN THE SOFTWARE.
  */
  */
 
 
+#include <libwebsockets.h>
 #include "private-lib-core.h"
 #include "private-lib-core.h"
 
 
-static const uint8_t hnames[] = {
-	_WSI_TOKEN_CLIENT_PEER_ADDRESS,
-	_WSI_TOKEN_CLIENT_URI,
-	_WSI_TOKEN_CLIENT_HOST,
-	_WSI_TOKEN_CLIENT_ORIGIN,
-	_WSI_TOKEN_CLIENT_SENT_PROTOCOLS,
-	_WSI_TOKEN_CLIENT_METHOD,
-	_WSI_TOKEN_CLIENT_IFACE,
-	_WSI_TOKEN_CLIENT_ALPN
-};
-
-struct lws *
-lws_http_client_connect_via_info2(struct lws *wsi)
-{
-	struct client_info_stash *stash = wsi->stash;
-	int n;
-
-	lwsl_debug("%s: %p (stash %p)\n", __func__, wsi, stash);
-
-	if (!stash)
-		return wsi;
-
-	wsi->a.opaque_user_data = wsi->stash->opaque_user_data;
-
-	if (stash->cis[CIS_METHOD] && (!strcmp(stash->cis[CIS_METHOD], "RAW") ||
-				      !strcmp(stash->cis[CIS_METHOD], "MQTT")))
-		goto no_ah;
-
-	/*
-	 * we're not necessarily in a position to action these right away,
-	 * stash them... we only need during connect phase so into a temp
-	 * allocated stash
-	 */
-	for (n = 0; n < (int)LWS_ARRAY_SIZE(hnames); n++)
-		if (hnames[n] && stash->cis[n] &&
-		    lws_hdr_simple_create(wsi, hnames[n], stash->cis[n]))
-			goto bail1;
-
-#if defined(LWS_WITH_SOCKS5)
-	if (!wsi->a.vhost->socks_proxy_port)
-		lws_free_set_NULL(wsi->stash);
-#endif
-
-no_ah:
-	wsi->a.context->count_wsi_allocated++;
-
-	return lws_client_connect_2_dnsreq(wsi);
-
-bail1:
-#if defined(LWS_WITH_SOCKS5)
-	if (!wsi->a.vhost->socks_proxy_port)
-		lws_free_set_NULL(wsi->stash);
-#endif
-
-	return NULL;
-}
-
 struct lws *
 struct lws *
 lws_client_connect_via_info(const struct lws_client_connect_info *i)
 lws_client_connect_via_info(const struct lws_client_connect_info *i)
 {
 {
@@ -172,8 +116,8 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i)
 	}
 	}
 
 
 #if LWS_MAX_SMP > 1
 #if LWS_MAX_SMP > 1
-	tid = wsi->a.vhost->protocols[0].callback(wsi,
-				LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0);
+	tid = wsi->a.vhost->protocols[0].callback(wsi, LWS_CALLBACK_GET_THREAD_ID,
+						NULL, NULL, 0);
 #endif
 #endif
 
 
 	/*
 	/*
@@ -231,8 +175,7 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i)
 	wsi->sys_tls_client_cert = i->sys_tls_client_cert;
 	wsi->sys_tls_client_cert = i->sys_tls_client_cert;
 
 
 #if defined(LWS_ROLE_H2)
 #if defined(LWS_ROLE_H2)
-	wsi->txc.manual_initial_tx_credit =
-			(int32_t)i->manual_initial_tx_credit;
+	wsi->txc.manual_initial_tx_credit = (int32_t)i->manual_initial_tx_credit;
 #endif
 #endif
 
 
 	wsi->a.protocol = &wsi->a.vhost->protocols[0];
 	wsi->a.protocol = &wsi->a.vhost->protocols[0];
@@ -251,8 +194,7 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i)
 	}
 	}
 
 
 	if (local) {
 	if (local) {
-		lwsl_info("%s: vh %s protocol binding to %s\n", __func__,
-				wsi->a.vhost->name, local);
+		lwsl_info("%s: vh %s protocol binding to %s\n", __func__, wsi->a.vhost->name, local);
 		p = lws_vhost_name_to_protocol(wsi->a.vhost, local);
 		p = lws_vhost_name_to_protocol(wsi->a.vhost, local);
 		if (p)
 		if (p)
 			lws_bind_protocol(wsi, p, __func__);
 			lws_bind_protocol(wsi, p, __func__);

+ 2 - 25
Source/ThirdParty/libwebsockets/lib/core-net/network.c

@@ -370,8 +370,6 @@ lws_socket_bind(struct lws_vhost *vhost, lws_sockfd_type sockfd, int port,
 	return port;
 	return port;
 }
 }
 
 
-#if defined(LWS_WITH_CLIENT)
-
 unsigned int
 unsigned int
 lws_retry_get_delay_ms(struct lws_context *context,
 lws_retry_get_delay_ms(struct lws_context *context,
 		       const lws_retry_bo_t *retry, uint16_t *ctry,
 		       const lws_retry_bo_t *retry, uint16_t *ctry,
@@ -432,31 +430,10 @@ int
 lws_retry_sul_schedule_retry_wsi(struct lws *wsi, lws_sorted_usec_list_t *sul,
 lws_retry_sul_schedule_retry_wsi(struct lws *wsi, lws_sorted_usec_list_t *sul,
 				 sul_cb_t cb, uint16_t *ctry)
 				 sul_cb_t cb, uint16_t *ctry)
 {
 {
-	char conceal;
-	lws_usec_t us = lws_retry_get_delay_ms(wsi->a.context,
-					       wsi->retry_policy, ctry,
-					       &conceal) * LWS_US_PER_MS;
-
-	if (!conceal)
-		/* if our reties are up, they're up... */
-		return 1;
-
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
-//	if (wsi->role_ops == &role_ops_h1 || wsi->role_ops == &role_ops_h2)
-    if (wsi->role_ops == &role_ops_h1)
-		/*
-		 * Since we're doing it by wsi, we're in a position to check for
-		 * http retry-after, it will increase us accordingly if found
-		 */
-		lws_http_check_retry_after(wsi, &us);
-#endif
-	lws_sul_schedule(wsi->a.context, wsi->tsi, sul, cb, us);
-
-	return 0;
+	return lws_retry_sul_schedule(wsi->a.context, wsi->tsi, sul,
+				      wsi->retry_policy, cb, ctry);
 }
 }
 
 
-#endif
-
 #if defined(LWS_WITH_IPV6)
 #if defined(LWS_WITH_IPV6)
 unsigned long
 unsigned long
 lws_get_addr_scope(const char *ifname_or_ipaddr)
 lws_get_addr_scope(const char *ifname_or_ipaddr)

+ 6 - 8
Source/ThirdParty/libwebsockets/lib/core-net/private-lib-core-net.h

@@ -174,6 +174,7 @@ enum pmd_return {
 	PMDR_HAS_PENDING,
 	PMDR_HAS_PENDING,
 	PMDR_EMPTY_NONFINAL,
 	PMDR_EMPTY_NONFINAL,
 	PMDR_EMPTY_FINAL,
 	PMDR_EMPTY_FINAL,
+	PMDR_NOTHING_WE_SHOULD_DO,
 
 
 	PMDR_FAILED = -1
 	PMDR_FAILED = -1
 };
 };
@@ -409,7 +410,7 @@ struct lws_context_per_thread {
 	struct lws_pollfd *fds;
 	struct lws_pollfd *fds;
 	volatile struct lws_foreign_thread_pollfd * volatile foreign_pfd_list;
 	volatile struct lws_foreign_thread_pollfd * volatile foreign_pfd_list;
 #ifdef _WIN32
 #ifdef _WIN32
-	WSAEVENT events;
+       WSAEVENT events[WSA_MAXIMUM_WAIT_EVENTS];
 	CRITICAL_SECTION interrupt_lock;
 	CRITICAL_SECTION interrupt_lock;
 #endif
 #endif
 	lws_sockfd_type dummy_pipe_fds[2];
 	lws_sockfd_type dummy_pipe_fds[2];
@@ -461,9 +462,6 @@ struct lws_context_per_thread {
 	unsigned char event_loop_destroy_processing_done:1;
 	unsigned char event_loop_destroy_processing_done:1;
 	unsigned char destroy_self:1;
 	unsigned char destroy_self:1;
 	unsigned char is_destroyed:1;
 	unsigned char is_destroyed:1;
-#ifdef _WIN32
-	unsigned char interrupt_requested:1;
-#endif
 };
 };
 
 
 #if defined(LWS_WITH_SERVER_STATUS)
 #if defined(LWS_WITH_SERVER_STATUS)
@@ -1089,11 +1087,11 @@ lws_change_pollfd(struct lws *wsi, int _and, int _or);
 #if defined(LWS_WITH_SERVER)
 #if defined(LWS_WITH_SERVER)
  int _lws_vhost_init_server(const struct lws_context_creation_info *info,
  int _lws_vhost_init_server(const struct lws_context_creation_info *info,
 			      struct lws_vhost *vhost);
 			      struct lws_vhost *vhost);
-struct lws_vhost *
+ LWS_EXTERN struct lws_vhost *
  lws_select_vhost(struct lws_context *context, int port, const char *servername);
  lws_select_vhost(struct lws_context *context, int port, const char *servername);
-int LWS_WARN_UNUSED_RESULT
+ LWS_EXTERN int LWS_WARN_UNUSED_RESULT
  lws_parse_ws(struct lws *wsi, unsigned char **buf, size_t len);
  lws_parse_ws(struct lws *wsi, unsigned char **buf, size_t len);
-void
+ LWS_EXTERN void
  lws_server_get_canonical_hostname(struct lws_context *context,
  lws_server_get_canonical_hostname(struct lws_context *context,
 				   const struct lws_context_creation_info *info);
 				   const struct lws_context_creation_info *info);
 #else
 #else
@@ -1244,7 +1242,7 @@ lws_http_client_connect_via_info2(struct lws *wsi);
 
 
 #if defined(LWS_WITH_CLIENT)
 #if defined(LWS_WITH_CLIENT)
 int
 int
-lws_http_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd);
+lws_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd);
 
 
 int LWS_WARN_UNUSED_RESULT
 int LWS_WARN_UNUSED_RESULT
 lws_http_transaction_completed_client(struct lws *wsi);
 lws_http_transaction_completed_client(struct lws *wsi);

+ 11 - 3
Source/ThirdParty/libwebsockets/lib/core-net/sorted-usec-list.c

@@ -337,10 +337,12 @@ lws_sul_debug_zombies(struct lws_context *ctx, void *po, size_t len,
 				 * indicated as being deleted?
 				 * indicated as being deleted?
 				 */
 				 */
 
 
-				if (sul >= po && lws_ptr_diff(sul, po) < len) {
+				if ((void *)sul >= po &&
+				    (size_t)lws_ptr_diff(sul, po) < len) {
 					lwsl_err("%s: ERROR: Zombie Sul "
 					lwsl_err("%s: ERROR: Zombie Sul "
-						 "(on list %d) %s\n", __func__,
-						 m, destroy_description);
+						 "(on list %d) %s, cb %p\n",
+						 __func__, m,
+						 destroy_description, sul->cb);
 					/*
 					/*
 					 * This assert fires if you have left
 					 * This assert fires if you have left
 					 * a sul scheduled to fire later, but
 					 * a sul scheduled to fire later, but
@@ -350,6 +352,12 @@ lws_sul_debug_zombies(struct lws_context *ctx, void *po, size_t len,
 					 * that may be scheduled before
 					 * that may be scheduled before
 					 * destroying the object the sul lives
 					 * destroying the object the sul lives
 					 * inside.
 					 * inside.
+					 *
+					 * You can look up the cb pointer in
+					 * your mapfile to find out which
+					 * callback function the sul was using
+					 * which usually tells you which sul
+					 * it is.
 					 */
 					 */
 					assert(0);
 					assert(0);
 				}
 				}

+ 6 - 1
Source/ThirdParty/libwebsockets/lib/core-net/wsi-timeout.c

@@ -143,15 +143,17 @@ lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs)
 {
 {
 	struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
 	struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
 
 
+	lws_context_lock(pt->context, __func__);
 	lws_pt_lock(pt, __func__);
 	lws_pt_lock(pt, __func__);
 	lws_dll2_remove(&wsi->sul_timeout.list);
 	lws_dll2_remove(&wsi->sul_timeout.list);
 	lws_pt_unlock(pt);
 	lws_pt_unlock(pt);
 
 
 	if (!secs)
 	if (!secs)
-		return;
+		goto bail;
 
 
 	if (secs == LWS_TO_KILL_SYNC) {
 	if (secs == LWS_TO_KILL_SYNC) {
 		lwsl_debug("synchronously killing %p\n", wsi);
 		lwsl_debug("synchronously killing %p\n", wsi);
+		lws_context_unlock(pt->context);
 		lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS,
 		lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS,
 				   "to sync kill");
 				   "to sync kill");
 		return;
 		return;
@@ -167,6 +169,9 @@ lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs)
 	lws_pt_lock(pt, __func__);
 	lws_pt_lock(pt, __func__);
 	__lws_set_timeout(wsi, reason, secs);
 	__lws_set_timeout(wsi, reason, secs);
 	lws_pt_unlock(pt);
 	lws_pt_unlock(pt);
+
+bail:
+	lws_context_unlock(pt->context);
 }
 }
 
 
 void
 void

+ 10 - 1
Source/ThirdParty/libwebsockets/lib/core-net/wsi.c

@@ -610,8 +610,10 @@ lws_broadcast(struct lws_context_per_thread *pt, int reason, void *in, size_t le
 	lws_fakewsi_def_plwsa(pt);
 	lws_fakewsi_def_plwsa(pt);
 	int n, ret = 0;
 	int n, ret = 0;
 
 
-
 	lws_fakewsi_prep_plwsa_ctx(pt->context);
 	lws_fakewsi_prep_plwsa_ctx(pt->context);
+#if !defined(LWS_PLAT_FREERTOS) && LWS_MAX_SMP > 1
+	((struct lws *)plwsa)->tsi = (int)(pt - &pt->context->pt[0]);
+#endif
 
 
 	while (v) {
 	while (v) {
 		const struct lws_protocols *p = v->protocols;
 		const struct lws_protocols *p = v->protocols;
@@ -638,6 +640,13 @@ lws_wsi_user(struct lws *wsi)
 	return wsi->user_space;
 	return wsi->user_space;
 }
 }
 
 
+int
+lws_wsi_tsi(struct lws *wsi)
+{
+	return wsi->tsi;
+}
+
+
 void
 void
 lws_set_wsi_user(struct lws *wsi, void *data)
 lws_set_wsi_user(struct lws *wsi, void *data)
 {
 {

+ 5 - 8
Source/ThirdParty/libwebsockets/lib/core/context.c

@@ -546,9 +546,6 @@ lws_create_context(const struct lws_context_creation_info *info)
 #if !defined(LWS_PLAT_FREERTOS)
 #if !defined(LWS_PLAT_FREERTOS)
 	context->uid = info->uid;
 	context->uid = info->uid;
 	context->gid = info->gid;
 	context->gid = info->gid;
-	context->gid = -1;
-	context->uid = -1;
-    lwsl_notice("LWS: GID: %d, UID: %d\n", context->gid, context->uid);
 	context->username = info->username;
 	context->username = info->username;
 	context->groupname = info->groupname;
 	context->groupname = info->groupname;
 #endif
 #endif
@@ -570,7 +567,7 @@ lws_create_context(const struct lws_context_creation_info *info)
 	context->pss_policies = info->pss_policies;
 	context->pss_policies = info->pss_policies;
 #endif
 #endif
 
 
-#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) && defined(LWS_WITH_CLIENT)
+#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)
 	context->ss_proxy_bind = info->ss_proxy_bind;
 	context->ss_proxy_bind = info->ss_proxy_bind;
 	context->ss_proxy_port = info->ss_proxy_port;
 	context->ss_proxy_port = info->ss_proxy_port;
 	context->ss_proxy_address = info->ss_proxy_address;
 	context->ss_proxy_address = info->ss_proxy_address;
@@ -1425,7 +1422,7 @@ lws_context_destroy2(struct lws_context *context)
 #endif
 #endif
 #endif
 #endif
 
 
-#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) && defined(LWS_WITH_CLIENT)
+#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)
 		lws_dll2_foreach_safe(&pt->ss_client_owner, NULL, lws_sspc_destroy_dll);
 		lws_dll2_foreach_safe(&pt->ss_client_owner, NULL, lws_sspc_destroy_dll);
 #endif
 #endif
 
 
@@ -1511,14 +1508,14 @@ lws_context_destroy2(struct lws_context *context)
 
 
 	lwsl_debug("%p: post dc2\n", __func__);
 	lwsl_debug("%p: post dc2\n", __func__);
 
 
-	if (!context->pt[0].event_loop_foreign) {
-		int n;
+//	if (!context->pt[0].event_loop_foreign) {
+//		int n;
 		for (n = 0; n < context->count_threads; n++)
 		for (n = 0; n < context->count_threads; n++)
 			if (context->pt[n].inside_service) {
 			if (context->pt[n].inside_service) {
 				lwsl_debug("%p: bailing as inside service\n", __func__);
 				lwsl_debug("%p: bailing as inside service\n", __func__);
 				return;
 				return;
 			}
 			}
-	}
+//	}
 #endif
 #endif
 
 
 	lws_context_destroy3(context);
 	lws_context_destroy3(context);

+ 19 - 45
Source/ThirdParty/libwebsockets/lib/core/private-lib-core.h

@@ -231,32 +231,6 @@ struct lws_foreign_thread_pollfd {
 };
 };
 #endif /* network */
 #endif /* network */
 
 
-#if LWS_MAX_SMP > 1
-
-struct lws_mutex_refcount {
-	pthread_mutex_t lock;
-	pthread_t lock_owner;
-	const char *last_lock_reason;
-	char lock_depth;
-	char metadata;
-};
-
-void
-lws_mutex_refcount_init(struct lws_mutex_refcount *mr);
-
-void
-lws_mutex_refcount_destroy(struct lws_mutex_refcount *mr);
-
-void
-lws_mutex_refcount_lock(struct lws_mutex_refcount *mr, const char *reason);
-
-void
-lws_mutex_refcount_assert_held(struct lws_mutex_refcount *mr);
-
-void
-lws_mutex_refcount_unlock(struct lws_mutex_refcount *mr);
-#endif
-
 #if defined(LWS_WITH_NETWORK)
 #if defined(LWS_WITH_NETWORK)
 #include "private-lib-core-net.h"
 #include "private-lib-core-net.h"
 #endif
 #endif
@@ -570,7 +544,7 @@ lws_vhost_destroy1(struct lws_vhost *vh);
 
 
 
 
 #if defined(LWS_PLAT_FREERTOS)
 #if defined(LWS_PLAT_FREERTOS)
-int
+LWS_EXTERN int
 lws_find_string_in_file(const char *filename, const char *str, int stringlen);
 lws_find_string_in_file(const char *filename, const char *str, int stringlen);
 #endif
 #endif
 
 
@@ -587,22 +561,22 @@ struct lws_buflist {
 	size_t pos;
 	size_t pos;
 };
 };
 
 
-char *
+LWS_EXTERN char *
 lws_strdup(const char *s);
 lws_strdup(const char *s);
 
 
-extern int log_level;
+LWS_EXTERN int log_level;
 
 
-int
+LWS_EXTERN int
 lws_b64_selftest(void);
 lws_b64_selftest(void);
 
 
 
 
 #ifndef LWS_NO_DAEMONIZE
 #ifndef LWS_NO_DAEMONIZE
- pid_t get_daemonize_pid();
+ LWS_EXTERN pid_t get_daemonize_pid();
 #else
 #else
  #define get_daemonize_pid() (0)
  #define get_daemonize_pid() (0)
 #endif
 #endif
 
 
-void lwsl_emit_stderr(int level, const char *line);
+LWS_EXTERN void lwsl_emit_stderr(int level, const char *line);
 
 
 #if !defined(LWS_WITH_TLS)
 #if !defined(LWS_WITH_TLS)
  #define LWS_SSL_ENABLED(context) (0)
  #define LWS_SSL_ENABLED(context) (0)
@@ -657,13 +631,13 @@ lws_vhost_unlock(struct lws_vhost *vhost)
 #define lws_pt_stats_unlock(_a) (void)(_a)
 #define lws_pt_stats_unlock(_a) (void)(_a)
 #endif
 #endif
 
 
-int LWS_WARN_UNUSED_RESULT
+LWS_EXTERN int LWS_WARN_UNUSED_RESULT
 lws_ssl_capable_read_no_ssl(struct lws *wsi, unsigned char *buf, int len);
 lws_ssl_capable_read_no_ssl(struct lws *wsi, unsigned char *buf, int len);
 
 
-int LWS_WARN_UNUSED_RESULT
+LWS_EXTERN int LWS_WARN_UNUSED_RESULT
 lws_ssl_capable_write_no_ssl(struct lws *wsi, unsigned char *buf, int len);
 lws_ssl_capable_write_no_ssl(struct lws *wsi, unsigned char *buf, int len);
 
 
-int LWS_WARN_UNUSED_RESULT
+LWS_EXTERN int LWS_WARN_UNUSED_RESULT
 lws_ssl_pending_no_ssl(struct lws *wsi);
 lws_ssl_pending_no_ssl(struct lws *wsi);
 
 
 int
 int
@@ -688,10 +662,10 @@ lws_find_mount(struct lws *wsi, const char *uri_ptr, int uri_len);
 /*
 /*
  * custom allocator
  * custom allocator
  */
  */
-void *
+LWS_EXTERN void *
 lws_realloc(void *ptr, size_t size, const char *reason);
 lws_realloc(void *ptr, size_t size, const char *reason);
 
 
-void * LWS_WARN_UNUSED_RESULT
+LWS_EXTERN void * LWS_WARN_UNUSED_RESULT
 lws_zalloc(size_t size, const char *reason);
 lws_zalloc(size_t size, const char *reason);
 
 
 #ifdef LWS_PLAT_OPTEE
 #ifdef LWS_PLAT_OPTEE
@@ -716,17 +690,17 @@ lws_vfs_select_fops(const struct lws_plat_file_ops *fops, const char *vfs_path,
 
 
 /* lws_plat_ */
 /* lws_plat_ */
 
 
-int
+LWS_EXTERN int
 lws_plat_context_early_init(void);
 lws_plat_context_early_init(void);
-void
+LWS_EXTERN void
 lws_plat_context_early_destroy(struct lws_context *context);
 lws_plat_context_early_destroy(struct lws_context *context);
-void
+LWS_EXTERN void
 lws_plat_context_late_destroy(struct lws_context *context);
 lws_plat_context_late_destroy(struct lws_context *context);
 
 
-int
+LWS_EXTERN int
 lws_plat_init(struct lws_context *context,
 lws_plat_init(struct lws_context *context,
 	      const struct lws_context_creation_info *info);
 	      const struct lws_context_creation_info *info);
-int
+LWS_EXTERN int
 lws_plat_drop_app_privileges(struct lws_context *context, int actually_drop);
 lws_plat_drop_app_privileges(struct lws_context *context, int actually_drop);
 
 
 #if defined(LWS_WITH_UNIX_SOCK) && !defined(WIN32)
 #if defined(LWS_WITH_UNIX_SOCK) && !defined(WIN32)
@@ -740,11 +714,11 @@ lws_plat_ntpclient_config(struct lws_context *context);
 int
 int
 lws_plat_ifname_to_hwaddr(int fd, const char *ifname, uint8_t *hwaddr, int len);
 lws_plat_ifname_to_hwaddr(int fd, const char *ifname, uint8_t *hwaddr, int len);
 
 
-int
+LWS_EXTERN int
 lws_check_byte_utf8(unsigned char state, unsigned char c);
 lws_check_byte_utf8(unsigned char state, unsigned char c);
-int LWS_WARN_UNUSED_RESULT
+LWS_EXTERN int LWS_WARN_UNUSED_RESULT
 lws_check_utf8(unsigned char *state, unsigned char *buf, size_t len);
 lws_check_utf8(unsigned char *state, unsigned char *buf, size_t len);
-int alloc_file(struct lws_context *context, const char *filename,
+LWS_EXTERN int alloc_file(struct lws_context *context, const char *filename,
 			  uint8_t **buf, lws_filepos_t *amount);
 			  uint8_t **buf, lws_filepos_t *amount);
 
 
 void lws_msleep(unsigned int);
 void lws_msleep(unsigned int);

+ 0 - 1
Source/ThirdParty/libwebsockets/lib/event-libs/CMakeLists.txt

@@ -42,7 +42,6 @@ macro(create_evlib_plugin PLUGIN_NAME MAIN_SRC PLUGIN_HDR EVLIB)
 
 
 	target_link_libraries(websockets-${PLUGIN_NAME} websockets_shared ${EVLIB})
 	target_link_libraries(websockets-${PLUGIN_NAME} websockets_shared ${EVLIB})
 	add_dependencies(websockets-${PLUGIN_NAME} websockets_shared)
 	add_dependencies(websockets-${PLUGIN_NAME} websockets_shared)
-	target_compile_definitions(websockets-${PLUGIN_NAME} PRIVATE LWS_BUILDING_SHARED)
 
 
 	target_include_directories(websockets-${PLUGIN_NAME} PRIVATE
 	target_include_directories(websockets-${PLUGIN_NAME} PRIVATE
 			${PLUGIN_INCLUDE} ${LWS_LIB_BUILD_INC_PATHS})
 			${PLUGIN_INCLUDE} ${LWS_LIB_BUILD_INC_PATHS})

+ 28 - 4
Source/ThirdParty/libwebsockets/lib/event-libs/libuv/libuv.c

@@ -40,6 +40,7 @@ lws_uv_sultimer_cb(uv_timer_t *timer
 	struct lws_context_per_thread *pt = ptpr->pt;
 	struct lws_context_per_thread *pt = ptpr->pt;
 	lws_usec_t us;
 	lws_usec_t us;
 
 
+	lws_context_lock(pt->context, __func__);
 	lws_pt_lock(pt, __func__);
 	lws_pt_lock(pt, __func__);
 	us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS,
 	us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS,
 				    lws_now_usecs());
 				    lws_now_usecs());
@@ -47,6 +48,7 @@ lws_uv_sultimer_cb(uv_timer_t *timer
 		uv_timer_start(&pt_to_priv_uv(pt)->sultimer, lws_uv_sultimer_cb,
 		uv_timer_start(&pt_to_priv_uv(pt)->sultimer, lws_uv_sultimer_cb,
 			       LWS_US_TO_MS(us), 0);
 			       LWS_US_TO_MS(us), 0);
 	lws_pt_unlock(pt);
 	lws_pt_unlock(pt);
+	lws_context_unlock(pt->context);
 }
 }
 
 
 static void
 static void
@@ -62,6 +64,9 @@ lws_uv_idle(uv_idle_t *handle
 
 
 	lws_service_do_ripe_rxflow(pt);
 	lws_service_do_ripe_rxflow(pt);
 
 
+	lws_context_lock(pt->context, __func__);
+	lws_pt_lock(pt, __func__);
+
 	/*
 	/*
 	 * is there anybody with pending stuff that needs service forcing?
 	 * is there anybody with pending stuff that needs service forcing?
 	 */
 	 */
@@ -71,16 +76,17 @@ lws_uv_idle(uv_idle_t *handle
 
 
 	/* account for sultimer */
 	/* account for sultimer */
 
 
-	lws_pt_lock(pt, __func__);
 	us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS,
 	us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS,
 				    lws_now_usecs());
 				    lws_now_usecs());
 	if (us)
 	if (us)
 		uv_timer_start(&pt_to_priv_uv(pt)->sultimer, lws_uv_sultimer_cb,
 		uv_timer_start(&pt_to_priv_uv(pt)->sultimer, lws_uv_sultimer_cb,
 			       LWS_US_TO_MS(us), 0);
 			       LWS_US_TO_MS(us), 0);
-	lws_pt_unlock(pt);
 
 
 	/* there is nobody who needs service forcing, shut down idle */
 	/* there is nobody who needs service forcing, shut down idle */
 	uv_idle_stop(handle);
 	uv_idle_stop(handle);
+
+	lws_pt_unlock(pt);
+	lws_context_unlock(pt->context);
 }
 }
 
 
 static void
 static void
@@ -91,8 +97,11 @@ lws_io_cb(uv_poll_t *watcher, int status, int revents)
 	struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
 	struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
 	struct lws_pollfd eventfd;
 	struct lws_pollfd eventfd;
 
 
+	lws_context_lock(pt->context, __func__);
+	lws_pt_lock(pt, __func__);
+
 	if (pt->is_destroyed)
 	if (pt->is_destroyed)
-		return;
+		goto bail;
 
 
 #if defined(WIN32) || defined(_WIN32)
 #if defined(WIN32) || defined(_WIN32)
 	eventfd.fd = watcher->socket;
 	eventfd.fd = watcher->socket;
@@ -110,7 +119,7 @@ lws_io_cb(uv_poll_t *watcher, int status, int revents)
 		 * You might want to return; instead of servicing the fd in
 		 * You might want to return; instead of servicing the fd in
 		 * some cases */
 		 * some cases */
 		if (status == UV_EAGAIN)
 		if (status == UV_EAGAIN)
-			return;
+			goto bail;
 
 
 		eventfd.events |= LWS_POLLHUP;
 		eventfd.events |= LWS_POLLHUP;
 		eventfd.revents |= LWS_POLLHUP;
 		eventfd.revents |= LWS_POLLHUP;
@@ -124,6 +133,10 @@ lws_io_cb(uv_poll_t *watcher, int status, int revents)
 			eventfd.revents |= LWS_POLLOUT;
 			eventfd.revents |= LWS_POLLOUT;
 		}
 		}
 	}
 	}
+
+	lws_pt_unlock(pt);
+	lws_context_unlock(pt->context);
+
 	lws_service_fd_tsi(context, &eventfd, wsi->tsi);
 	lws_service_fd_tsi(context, &eventfd, wsi->tsi);
 
 
 	if (pt->destroy_self) {
 	if (pt->destroy_self) {
@@ -132,6 +145,11 @@ lws_io_cb(uv_poll_t *watcher, int status, int revents)
 	}
 	}
 
 
 	uv_idle_start(&pt_to_priv_uv(pt)->idle, lws_uv_idle);
 	uv_idle_start(&pt_to_priv_uv(pt)->idle, lws_uv_idle);
+	return;
+
+bail:
+	lws_pt_unlock(pt);
+	lws_context_unlock(pt->context);
 }
 }
 
 
 /*
 /*
@@ -714,6 +732,8 @@ lws_libuv_closewsi(uv_handle_t* handle)
 
 
 	lwsl_info("%s: %p\n", __func__, wsi);
 	lwsl_info("%s: %p\n", __func__, wsi);
 
 
+	lws_context_lock(context, __func__);
+
 	/*
 	/*
 	 * We get called back here for every wsi that closes
 	 * We get called back here for every wsi that closes
 	 */
 	 */
@@ -774,9 +794,13 @@ lws_libuv_closewsi(uv_handle_t* handle)
 		if (!context->count_event_loop_static_asset_handles &&
 		if (!context->count_event_loop_static_asset_handles &&
 		    context->pt[0].event_loop_foreign) {
 		    context->pt[0].event_loop_foreign) {
 			lwsl_info("%s: call lws_context_destroy2\n", __func__);
 			lwsl_info("%s: call lws_context_destroy2\n", __func__);
+			lws_context_unlock(context);
 			lws_context_destroy2(context);
 			lws_context_destroy2(context);
+			return;
 		}
 		}
 	}
 	}
+
+	lws_context_unlock(context);
 }
 }
 
 
 void
 void

+ 2 - 1
Source/ThirdParty/libwebsockets/lib/misc/base64-decode.c

@@ -36,10 +36,11 @@
  * of libwebsockets
  * of libwebsockets
  */
  */
 
 
-#include "private-lib-core.h"
+#include <libwebsockets.h>
 
 
 #include <stdio.h>
 #include <stdio.h>
 #include <string.h>
 #include <string.h>
+#include "private-lib-core.h"
 
 
 static const char encode_orig[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 static const char encode_orig[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 			     "abcdefghijklmnopqrstuvwxyz0123456789+/";
 			     "abcdefghijklmnopqrstuvwxyz0123456789+/";

+ 1 - 0
Source/ThirdParty/libwebsockets/lib/misc/dir.c

@@ -29,6 +29,7 @@
 #define _DARWIN_C_SOURCE
 #define _DARWIN_C_SOURCE
 #endif
 #endif
 
 
+#include <libwebsockets.h>
 #include "private-lib-core.h"
 #include "private-lib-core.h"
 #include <string.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdio.h>

+ 1 - 0
Source/ThirdParty/libwebsockets/lib/misc/lejp.c

@@ -22,6 +22,7 @@
  * IN THE SOFTWARE.
  * IN THE SOFTWARE.
  */
  */
 
 
+#include <libwebsockets.h>
 #include "private-lib-core.h"
 #include "private-lib-core.h"
 #include <string.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdio.h>

+ 1 - 0
Source/ThirdParty/libwebsockets/lib/misc/lws-ring.c

@@ -22,6 +22,7 @@
  * IN THE SOFTWARE.
  * IN THE SOFTWARE.
  */
  */
 
 
+#include <libwebsockets.h>
 #include "private-lib-core.h"
 #include "private-lib-core.h"
 
 
 struct lws_ring *
 struct lws_ring *

+ 1 - 0
Source/ThirdParty/libwebsockets/lib/misc/sha-1.c

@@ -32,6 +32,7 @@
  * implemented by Jun-ichiro itojun Itoh <[email protected]>
  * implemented by Jun-ichiro itojun Itoh <[email protected]>
  */
  */
 
 
+#include <libwebsockets.h>
 #include "private-lib-core.h"
 #include "private-lib-core.h"
 
 
 #ifdef LWS_HAVE_SYS_TYPES_H
 #ifdef LWS_HAVE_SYS_TYPES_H

+ 21 - 2
Source/ThirdParty/libwebsockets/lib/plat/freertos/freertos-pipe.c

@@ -30,11 +30,15 @@ lws_plat_pipe_create(struct lws *wsi)
 	struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
 	struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
 	struct sockaddr_in *si = &wsi->a.context->frt_pipe_si;
 	struct sockaddr_in *si = &wsi->a.context->frt_pipe_si;
 	lws_sockfd_type *fd = pt->dummy_pipe_fds;
 	lws_sockfd_type *fd = pt->dummy_pipe_fds;
+	socklen_t sl;
 
 
 	/*
 	/*
 	 * There's no pipe abstraction on lwip / freertos... use a UDP socket
 	 * There's no pipe abstraction on lwip / freertos... use a UDP socket
-	 * listening on 127.0.0.1:54321 and send a byte to it from a second UDP
+	 * listening on 127.0.0.1:xxxx and send a byte to it from a second UDP
 	 * socket to cancel the wait.
 	 * socket to cancel the wait.
+	 *
+	 * Set the port to 0 at the bind, so lwip will choose a free one in the
+	 * ephemeral range for us.
 	 */
 	 */
 
 
 	fd[0] = socket(AF_INET, SOCK_DGRAM, 0);
 	fd[0] = socket(AF_INET, SOCK_DGRAM, 0);
@@ -53,11 +57,26 @@ lws_plat_pipe_create(struct lws *wsi)
 
 
 	si->sin_family = AF_INET;
 	si->sin_family = AF_INET;
 	si->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
 	si->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-	si->sin_port = htons(54321);
+	si->sin_port = 0;
 
 
 	if (bind(fd[0], (const struct sockaddr *)si, sizeof(*si)) < 0)
 	if (bind(fd[0], (const struct sockaddr *)si, sizeof(*si)) < 0)
 		goto bail;
 		goto bail;
 
 
+	/*
+	 * Query the socket to set context->frt_pipe_si to the full sockaddr it
+	 * wants to be addressed by, including the port that lwip chose.
+	 *
+	 * Afterwards, we can use this prepared sockaddr stashed in the context
+	 * to trigger the "pipe" without any other preliminaries.
+	 */
+
+	sl = sizeof(*si);
+	if (getsockname(fd[0], (struct sockaddr *)si, &sl))
+		goto bail;
+
+	lwsl_info("%s: cancel UDP skt port %d\n", __func__,
+		  ntohs(si->sin_port));
+
 	return 0;
 	return 0;
 
 
 bail:
 bail:

+ 10 - 1
Source/ThirdParty/libwebsockets/lib/plat/unix/unix-spawn.c

@@ -66,6 +66,7 @@ static struct lws *
 lws_create_basic_wsi(struct lws_context *context, int tsi,
 lws_create_basic_wsi(struct lws_context *context, int tsi,
 		     const struct lws_role_ops *ops)
 		     const struct lws_role_ops *ops)
 {
 {
+	size_t s = sizeof(struct lws);
 	struct lws *new_wsi;
 	struct lws *new_wsi;
 
 
 	if (!context->vhost_list)
 	if (!context->vhost_list)
@@ -77,12 +78,20 @@ lws_create_basic_wsi(struct lws_context *context, int tsi,
 		return NULL;
 		return NULL;
 	}
 	}
 
 
-	new_wsi = lws_zalloc(sizeof(*new_wsi), "new wsi");
+#if defined(LWS_WITH_EVENT_LIBS)
+	s += context->event_loop_ops->evlib_size_wsi;
+#endif
+
+	new_wsi = lws_zalloc(s, "new wsi");
 	if (new_wsi == NULL) {
 	if (new_wsi == NULL) {
 		lwsl_err("Out of memory for new connection\n");
 		lwsl_err("Out of memory for new connection\n");
 		return NULL;
 		return NULL;
 	}
 	}
 
 
+#if defined(LWS_WITH_EVENT_LIBS)
+	new_wsi->evlib_wsi = (uint8_t *)new_wsi + sizeof(*new_wsi);
+#endif
+
 	new_wsi->tsi = tsi;
 	new_wsi->tsi = tsi;
 	new_wsi->a.context = context;
 	new_wsi->a.context = context;
 	new_wsi->pending_timeout = NO_PENDING_TIMEOUT;
 	new_wsi->pending_timeout = NO_PENDING_TIMEOUT;

+ 6 - 2
Source/ThirdParty/libwebsockets/lib/plat/windows/windows-init.c

@@ -87,8 +87,10 @@ lws_plat_init(struct lws_context *context,
 	}
 	}
 
 
 	while (n--) {
 	while (n--) {
+               int m;
 		pt->fds_count = 0;
 		pt->fds_count = 0;
-		pt->events = WSACreateEvent(); /* the cancel event */
+               for (m = 0; m < WSA_MAXIMUM_WAIT_EVENTS; m++)
+                       pt->events[m] = WSACreateEvent();
 		InitializeCriticalSection(&pt->interrupt_lock);
 		InitializeCriticalSection(&pt->interrupt_lock);
 
 
 		pt++;
 		pt++;
@@ -113,7 +115,9 @@ lws_plat_context_early_destroy(struct lws_context *context)
 	int n = context->count_threads;
 	int n = context->count_threads;
 
 
 	while (n--) {
 	while (n--) {
-		WSACloseEvent(pt->events);
+		int m;
+		for (m = 0; m < WSA_MAXIMUM_WAIT_EVENTS; m++)
+			WSACloseEvent(pt->events[m]);
 		DeleteCriticalSection(&pt->interrupt_lock);
 		DeleteCriticalSection(&pt->interrupt_lock);
 		pt++;
 		pt++;
 	}
 	}

+ 7 - 2
Source/ThirdParty/libwebsockets/lib/plat/windows/windows-pipe.c

@@ -38,10 +38,15 @@ lws_plat_pipe_signal(struct lws *wsi)
 {
 {
 	struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
 	struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
 
 
+	/*
+	 * We need the critical section so that we are either setting it or
+	 * clearing it, no matter how many threads competing there is a clear
+	 * atomic state for the event
+	 */
+
 	EnterCriticalSection(&pt->interrupt_lock);
 	EnterCriticalSection(&pt->interrupt_lock);
-	pt->interrupt_requested = 1;
+	WSASetEvent(pt->events[0]); /* trigger the cancel event */
 	LeaveCriticalSection(&pt->interrupt_lock);
 	LeaveCriticalSection(&pt->interrupt_lock);
-	WSASetEvent(pt->events); /* trigger the cancel event */
 
 
 	return 0;
 	return 0;
 }
 }

+ 101 - 39
Source/ThirdParty/libwebsockets/lib/plat/windows/windows-service.c

@@ -67,8 +67,6 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
 	unsigned int i;
 	unsigned int i;
 	DWORD ev;
 	DWORD ev;
 	int n;
 	int n;
-	unsigned int eIdx;
-	int interrupt_requested;
 
 
 	/* stay dead once we are dead */
 	/* stay dead once we are dead */
 	if (context == NULL)
 	if (context == NULL)
@@ -148,60 +146,123 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
 	/*
 	/*
 	 * is there anybody with pending stuff that needs service forcing?
 	 * is there anybody with pending stuff that needs service forcing?
 	 */
 	 */
+
 	if (!lws_service_adjust_timeout(context, 1, tsi))
 	if (!lws_service_adjust_timeout(context, 1, tsi))
 		timeout_us = 0;
 		timeout_us = 0;
 
 
+	/*
+	 * WSA cannot actually tell us this from the wait... if anyone wants
+	 * POLLOUT and is not blocked for it, no need to wait since we will want
+	 * to service at least those.   Still enter the wait so we can pick up
+	 * other pending things...
+	 */
+
 	for (n = 0; n < (int)pt->fds_count; n++)
 	for (n = 0; n < (int)pt->fds_count; n++)
-		WSAEventSelect(pt->fds[n].fd, pt->events,
-		       FD_READ | (!!(pt->fds[n].events & LWS_POLLOUT) * FD_WRITE) |
-		       FD_OOB | FD_ACCEPT |
-		       FD_CONNECT | FD_CLOSE | FD_QOS |
-		       FD_ROUTING_INTERFACE_CHANGE |
-		       FD_ADDRESS_LIST_CHANGE);
-
-	ev = WSAWaitForMultipleEvents(1, &pt->events, FALSE,
-				      (DWORD)(timeout_us / LWS_US_PER_MS), FALSE);
-	if (ev != WSA_WAIT_EVENT_0)
+		if (pt->fds[n].fd != LWS_SOCK_INVALID &&
+		    pt->fds[n].events & LWS_POLLOUT &&
+		    !pt->fds[n].write_blocked) {
+			timeout_us = 0;
+			break;
+		}
+
+	// lwsl_notice("%s: to %dms\n", __func__, (int)(timeout_us / 1000));
+	ev = WSAWaitForMultipleEvents(pt->fds_count + 1, pt->events, FALSE,
+				      (DWORD)(timeout_us / LWS_US_PER_MS),
+				      FALSE);
+	//lwsl_notice("%s: ev 0x%x\n", __func__, ev);
+
+	/*
+	 * The wait returns indicating the one event that had something, or
+	 * that we timed out, or something broken.
+	 *
+	 * Amazingly WSA can only handle 64 events, because the errors start
+	 * at ordinal 64.
+	 */
+
+	if (ev >= WSA_MAXIMUM_WAIT_EVENTS &&
+	    ev != WSA_WAIT_TIMEOUT)
+		/* some kind of error */
 		return 0;
 		return 0;
 
 
-	EnterCriticalSection(&pt->interrupt_lock);
-	interrupt_requested = pt->interrupt_requested;
-	pt->interrupt_requested = 0;
-	LeaveCriticalSection(&pt->interrupt_lock);
-	if (interrupt_requested) {
-		lws_broadcast(pt, LWS_CALLBACK_EVENT_WAIT_CANCELLED,
-			      NULL, 0);
+       if (!ev) {
+	       /*
+	        * The zero'th event is the cancel event specifically.  Lock
+	        * the event reset so we are definitely clearing it while we
+	        * try to clear it.
+	        */
+		EnterCriticalSection(&pt->interrupt_lock);
+		WSAResetEvent(pt->events[0]);
+		LeaveCriticalSection(&pt->interrupt_lock);
+		lws_broadcast(pt, LWS_CALLBACK_EVENT_WAIT_CANCELLED, NULL, 0);
+
 		return 0;
 		return 0;
 	}
 	}
 
 
+       /*
+        * Otherwise at least fds[ev - 1] has something to do...
+        */
+
 #if defined(LWS_WITH_TLS)
 #if defined(LWS_WITH_TLS)
 	if (pt->context->tls_ops &&
 	if (pt->context->tls_ops &&
 	    pt->context->tls_ops->fake_POLLIN_for_buffered)
 	    pt->context->tls_ops->fake_POLLIN_for_buffered)
 		pt->context->tls_ops->fake_POLLIN_for_buffered(pt);
 		pt->context->tls_ops->fake_POLLIN_for_buffered(pt);
 #endif
 #endif
 
 
-	for (eIdx = 0; eIdx < pt->fds_count; ++eIdx) {
+	/*
+	 * POLLOUT for any fds that can
+	 */
+
+	for (n = 0; n < (int)pt->fds_count; n++)
+		if (pt->fds[n].fd != LWS_SOCK_INVALID &&
+		    pt->fds[n].events & LWS_POLLOUT &&
+		    !pt->fds[n].write_blocked) {
+			struct timeval tv;
+			fd_set se;
+
+			/*
+			 * We have to check if it is blocked...
+			 * if not, do the POLLOUT handling
+			 */
+
+			FD_ZERO(&se);
+			FD_SET(pt->fds[n].fd, &se);
+			tv.tv_sec = tv.tv_usec = 0;
+			if (select(1, NULL, &se, NULL, &tv) != 1)
+				pt->fds[n].write_blocked = 1;
+			else {
+				pt->fds[n].revents |= LWS_POLLOUT;
+				lws_service_fd_tsi(context, &pt->fds[n], tsi);
+			}
+		}
+
+       if (ev && ev < WSA_MAXIMUM_WAIT_EVENTS) {
 		unsigned int err;
 		unsigned int err;
 
 
-		if (WSAEnumNetworkEvents(pt->fds[eIdx].fd, pt->events,
+		/* handle fds[ev - 1] */
+
+               if (WSAEnumNetworkEvents(pt->fds[ev - 1].fd, pt->events[ev],
 				&networkevents) == SOCKET_ERROR) {
 				&networkevents) == SOCKET_ERROR) {
 			lwsl_err("WSAEnumNetworkEvents() failed "
 			lwsl_err("WSAEnumNetworkEvents() failed "
 				 "with error %d\n", LWS_ERRNO);
 				 "with error %d\n", LWS_ERRNO);
 			return -1;
 			return -1;
 		}
 		}
 
 
-		if (!networkevents.lNetworkEvents)
-			networkevents.lNetworkEvents = LWS_POLLOUT;
-
-		pfd = &pt->fds[eIdx];
+		pfd = &pt->fds[ev - 1];
 		pfd->revents = (short)networkevents.lNetworkEvents;
 		pfd->revents = (short)networkevents.lNetworkEvents;
 
 
+	        if (!pfd->write_blocked && pfd->revents & FD_WRITE)
+	        	 pfd->write_blocked = 0;
+
 		err = networkevents.iErrorCode[FD_CONNECT_BIT];
 		err = networkevents.iErrorCode[FD_CONNECT_BIT];
-               if ((networkevents.lNetworkEvents & FD_CONNECT) && wsi_from_fd(context, pfd->fd) && !wsi_from_fd(context, pfd->fd)->udp) {
-                       lwsl_debug("%s: FD_CONNECT: %p\n", __func__, wsi_from_fd(context, pfd->fd));
+		if ((networkevents.lNetworkEvents & FD_CONNECT) &&
+		    wsi_from_fd(context, pfd->fd) &&
+		    !wsi_from_fd(context, pfd->fd)->udp) {
+                       lwsl_debug("%s: FD_CONNECT: %p\n", __func__,
+                		  wsi_from_fd(context, pfd->fd));
 			pfd->revents &= ~LWS_POLLOUT;
 			pfd->revents &= ~LWS_POLLOUT;
 			if (err && err != LWS_EALREADY &&
 			if (err && err != LWS_EALREADY &&
-			    err != LWS_EINPROGRESS && err != LWS_EWOULDBLOCK &&
+			    err != LWS_EINPROGRESS &&
+			    err != LWS_EWOULDBLOCK &&
 			    err != WSAEINVAL) {
 			    err != WSAEINVAL) {
 				lwsl_debug("Unable to connect errno=%d\n", err);
 				lwsl_debug("Unable to connect errno=%d\n", err);
 
 
@@ -210,10 +271,11 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
 				 * do we have more DNS entries to try?
 				 * do we have more DNS entries to try?
 				 */
 				 */
 				if (wsi_from_fd(context, pfd->fd)->dns_results_next) {
 				if (wsi_from_fd(context, pfd->fd)->dns_results_next) {
-					lws_sul_schedule(context, 0, &wsi_from_fd(context, pfd->fd)->
-									sul_connect_timeout,
-							 lws_client_conn_wait_timeout, 1);
-					continue;
+					lws_sul_schedule(context, 0,
+						&wsi_from_fd(context, pfd->fd)->
+							sul_connect_timeout,
+						lws_client_conn_wait_timeout, 1);
+                                       return 0;
                                } else
                                } else
 					pfd->revents |= LWS_POLLHUP;
 					pfd->revents |= LWS_POLLHUP;
 			} else
 			} else
@@ -221,9 +283,11 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
                                        if (wsi_from_fd(context, pfd->fd)->udp)
                                        if (wsi_from_fd(context, pfd->fd)->udp)
                                                pfd->revents |= LWS_POLLHUP;
                                                pfd->revents |= LWS_POLLHUP;
                                        else
                                        else
-                                               lws_client_connect_3_connect(wsi_from_fd(context, pfd->fd),
-								NULL, NULL, LWS_CONNECT_COMPLETION_GOOD,
-								NULL);
+                                               lws_client_connect_3_connect(
+                                        	  wsi_from_fd(context, pfd->fd),
+						  NULL, NULL,
+						  LWS_CONNECT_COMPLETION_GOOD,
+						  NULL);
                                }
                                }
 		}
 		}
 
 
@@ -232,9 +296,6 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
 			if (wsi)
 			if (wsi)
 				wsi->sock_send_blocking = 0;
 				wsi->sock_send_blocking = 0;
 		}
 		}
-		 /* if something closed, retry this slot */
-		if (pfd->revents & LWS_POLLHUP)
-			--eIdx;
 
 
 		if (pfd->revents) {
 		if (pfd->revents) {
 			/*
 			/*
@@ -243,7 +304,8 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
 			 * on the TCP connection.  But it breaks UDP, so only
 			 * on the TCP connection.  But it breaks UDP, so only
 			 * do it on non-UDP.
 			 * do it on non-UDP.
 			 */
 			 */
-			if (!wsi_from_fd(context, pfd->fd)->udp)
+			wsi = wsi_from_fd(context, pfd->fd);
+			if (wsi && !wsi->udp)
 				recv(pfd->fd, NULL, 0, 0);
 				recv(pfd->fd, NULL, 0, 0);
 
 
 			lws_service_fd_tsi(context, pfd, tsi);
 			lws_service_fd_tsi(context, pfd, tsi);

+ 17 - 15
Source/ThirdParty/libwebsockets/lib/plat/windows/windows-sockets.c

@@ -180,15 +180,15 @@ void
 lws_plat_insert_socket_into_fds(struct lws_context *context, struct lws *wsi)
 lws_plat_insert_socket_into_fds(struct lws_context *context, struct lws *wsi)
 {
 {
 	struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
 	struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
-	int n = LWS_POLLIN | LWS_POLLHUP | FD_CONNECT;
 
 
 	if (wsi->udp) {
 	if (wsi->udp) {
 		lwsl_info("%s: UDP\n", __func__);
 		lwsl_info("%s: UDP\n", __func__);
-		n = LWS_POLLIN;
+		pt->fds[pt->fds_count].events |= LWS_POLLIN;
 	}
 	}
 
 
 	pt->fds[pt->fds_count++].revents = 0;
 	pt->fds[pt->fds_count++].revents = 0;
-	WSAEventSelect(wsi->desc.sockfd, pt->events, n);
+
+	lws_plat_change_pollfd(context, wsi, &pt->fds[pt->fds_count - 1]);
 }
 }
 
 
 void
 void
@@ -219,24 +219,26 @@ lws_plat_check_connection_error(struct lws *wsi)
 }
 }
 
 
 int
 int
-lws_plat_change_pollfd(struct lws_context *context,
-			  struct lws *wsi, struct lws_pollfd *pfd)
+lws_plat_change_pollfd(struct lws_context *context, struct lws *wsi,
+		       struct lws_pollfd *pfd)
 {
 {
 	struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
 	struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
-	long e = LWS_POLLHUP | FD_CONNECT;
-
-	if ((pfd->events & LWS_POLLIN))
-		e |= LWS_POLLIN;
+	long e = LWS_POLLHUP | FD_CONNECT | FD_ACCEPT | FD_CLOSE | FD_WRITE;
 
 
-	if ((pfd->events & LWS_POLLOUT))
-		e |= LWS_POLLOUT;
+	/*
+	 * On windows, FD_WRITE is only coming to indicate that we are writable
+	 * again after being choked.  So we must always listen for it.
+	 */
 
 
-	if (WSAEventSelect(wsi->desc.sockfd, pt->events, e) != SOCKET_ERROR)
-		return 0;
+	if (pfd->events & LWS_POLLIN)
+		e |= FD_READ;
 
 
-	lwsl_err("WSAEventSelect() failed with error %d\n", LWS_ERRNO);
+	if (WSAEventSelect(wsi->desc.sockfd, pt->events[(pfd - pt->fds) + 1], e)) {
+		lwsl_err("WSAEventSelect() failed with error %d\n", LWS_ERRNO);
+		return 1;
+	}
 
 
-	return 1;
+	return 0;
 }
 }
 
 
 const char *
 const char *

+ 3 - 2
Source/ThirdParty/libwebsockets/lib/roles/CMakeLists.txt

@@ -75,9 +75,10 @@ if (NOT LWS_WITHOUT_SERVER OR LWS_WITH_SECURE_STREAMS_PROCESS_API)
 	add_subdir_include_directories(listen)
 	add_subdir_include_directories(listen)
 endif()
 endif()
 
 
-if (LWS_WITH_CLIENT AND (LWS_ROLE_H1 OR LWS_ROLE_H2))
+if (NOT LWS_WITHOUT_CLIENT)
 	list(APPEND SOURCES
 	list(APPEND SOURCES
-		roles/http/client/client-http.c)
+		roles/http/client/client-http.c
+		roles/http/client/client-handshake.c)
 endif()
 endif()
 
 
 #
 #

+ 2 - 2
Source/ThirdParty/libwebsockets/lib/roles/h1/ops-h1.c

@@ -203,7 +203,7 @@ postbody_completion:
 					 */
 					 */
 
 
 					if (lws_http_transaction_completed(wsi))
 					if (lws_http_transaction_completed(wsi))
-						return -1;
+						goto bail;
 					break;
 					break;
 				}
 				}
 #endif
 #endif
@@ -696,7 +696,7 @@ rops_handle_POLLIN_h1(struct lws_context_per_thread *pt, struct lws *wsi,
 		return LWS_HPI_RET_PLEASE_CLOSE_ME;
 		return LWS_HPI_RET_PLEASE_CLOSE_ME;
 	}
 	}
 
 
-	if (lws_http_client_socket_service(wsi, pollfd))
+	if (lws_client_socket_service(wsi, pollfd))
 		return LWS_HPI_RET_WSI_ALREADY_DIED;
 		return LWS_HPI_RET_WSI_ALREADY_DIED;
 #endif
 #endif
 
 

+ 1 - 1
Source/ThirdParty/libwebsockets/lib/roles/h2/ops-h2.c

@@ -132,7 +132,7 @@ rops_handle_POLLIN_h2(struct lws_context_per_thread *pt, struct lws *wsi,
 			return LWS_HPI_RET_PLEASE_CLOSE_ME;
 			return LWS_HPI_RET_PLEASE_CLOSE_ME;
 		}
 		}
 
 
-		n = lws_http_client_socket_service(wsi, pollfd);
+		n = lws_client_socket_service(wsi, pollfd);
 		if (n)
 		if (n)
 			return LWS_HPI_RET_WSI_ALREADY_DIED;
 			return LWS_HPI_RET_WSI_ALREADY_DIED;
 #endif
 #endif

+ 22 - 22
Source/ThirdParty/libwebsockets/lib/roles/h2/private-lib-roles-h2.h

@@ -322,58 +322,58 @@ struct _lws_h2_related {
 int
 int
 lws_h2_rst_stream(struct lws *wsi, uint32_t err, const char *reason);
 lws_h2_rst_stream(struct lws *wsi, uint32_t err, const char *reason);
 struct lws * lws_h2_get_nth_child(struct lws *wsi, int n);
 struct lws * lws_h2_get_nth_child(struct lws *wsi, int n);
-void lws_h2_init(struct lws *wsi);
-int
+LWS_EXTERN void lws_h2_init(struct lws *wsi);
+LWS_EXTERN int
 lws_h2_settings(struct lws *nwsi, struct http2_settings *settings,
 lws_h2_settings(struct lws *nwsi, struct http2_settings *settings,
 		unsigned char *buf, int len);
 		unsigned char *buf, int len);
-int
+LWS_EXTERN int
 lws_h2_parser(struct lws *wsi, unsigned char *in, lws_filepos_t inlen,
 lws_h2_parser(struct lws *wsi, unsigned char *in, lws_filepos_t inlen,
 	      lws_filepos_t *inused);
 	      lws_filepos_t *inused);
-int
+LWS_EXTERN int
 lws_h2_do_pps_send(struct lws *wsi);
 lws_h2_do_pps_send(struct lws *wsi);
-int
+LWS_EXTERN int
 lws_h2_frame_write(struct lws *wsi, int type, int flags, unsigned int sid,
 lws_h2_frame_write(struct lws *wsi, int type, int flags, unsigned int sid,
 		   unsigned int len, unsigned char *buf);
 		   unsigned int len, unsigned char *buf);
-struct lws *
+LWS_EXTERN struct lws *
 lws_wsi_mux_from_id(struct lws *wsi, unsigned int sid);
 lws_wsi_mux_from_id(struct lws *wsi, unsigned int sid);
-int
+LWS_EXTERN int
 lws_hpack_interpret(struct lws *wsi, unsigned char c);
 lws_hpack_interpret(struct lws *wsi, unsigned char c);
-int
+LWS_EXTERN int
 lws_add_http2_header_by_name(struct lws *wsi,
 lws_add_http2_header_by_name(struct lws *wsi,
 			     const unsigned char *name,
 			     const unsigned char *name,
 			     const unsigned char *value, int length,
 			     const unsigned char *value, int length,
 			     unsigned char **p, unsigned char *end);
 			     unsigned char **p, unsigned char *end);
-int
+LWS_EXTERN int
 lws_add_http2_header_by_token(struct lws *wsi,
 lws_add_http2_header_by_token(struct lws *wsi,
 			      enum lws_token_indexes token,
 			      enum lws_token_indexes token,
 			      const unsigned char *value, int length,
 			      const unsigned char *value, int length,
 			      unsigned char **p, unsigned char *end);
 			      unsigned char **p, unsigned char *end);
-int
+LWS_EXTERN int
 lws_add_http2_header_status(struct lws *wsi,
 lws_add_http2_header_status(struct lws *wsi,
 			    unsigned int code, unsigned char **p,
 			    unsigned int code, unsigned char **p,
 			    unsigned char *end);
 			    unsigned char *end);
-void
+LWS_EXTERN void
 lws_hpack_destroy_dynamic_header(struct lws *wsi);
 lws_hpack_destroy_dynamic_header(struct lws *wsi);
-int
+LWS_EXTERN int
 lws_hpack_dynamic_size(struct lws *wsi, int size);
 lws_hpack_dynamic_size(struct lws *wsi, int size);
-int
+LWS_EXTERN int
 lws_h2_goaway(struct lws *wsi, uint32_t err, const char *reason);
 lws_h2_goaway(struct lws *wsi, uint32_t err, const char *reason);
-int
+LWS_EXTERN int
 lws_h2_tx_cr_get(struct lws *wsi);
 lws_h2_tx_cr_get(struct lws *wsi);
-void
+LWS_EXTERN void
 lws_h2_tx_cr_consume(struct lws *wsi, int consumed);
 lws_h2_tx_cr_consume(struct lws *wsi, int consumed);
-int
+LWS_EXTERN int
 lws_hdr_extant(struct lws *wsi, enum lws_token_indexes h);
 lws_hdr_extant(struct lws *wsi, enum lws_token_indexes h);
-void
+LWS_EXTERN void
 lws_pps_schedule(struct lws *wsi, struct lws_h2_protocol_send *pss);
 lws_pps_schedule(struct lws *wsi, struct lws_h2_protocol_send *pss);
 
 
-extern const struct http2_settings lws_h2_defaults;
-int
+LWS_EXTERN const struct http2_settings lws_h2_defaults;
+LWS_EXTERN int
 lws_h2_ws_handshake(struct lws *wsi);
 lws_h2_ws_handshake(struct lws *wsi);
-int lws_h2_issue_preface(struct lws *wsi);
-int
+LWS_EXTERN int lws_h2_issue_preface(struct lws *wsi);
+LWS_EXTERN int
 lws_h2_client_handshake(struct lws *wsi);
 lws_h2_client_handshake(struct lws *wsi);
-struct lws *
+LWS_EXTERN struct lws *
 lws_wsi_h2_adopt(struct lws *parent_wsi, struct lws *wsi);
 lws_wsi_h2_adopt(struct lws *parent_wsi, struct lws *wsi);
 int
 int
 lws_handle_POLLOUT_event_h2(struct lws *wsi);
 lws_handle_POLLOUT_event_h2(struct lws *wsi);

+ 1 - 2
Source/ThirdParty/libwebsockets/lib/roles/http/CMakeLists.txt

@@ -33,7 +33,6 @@ include_directories(. ./compression)
 
 
 list(APPEND SOURCES
 list(APPEND SOURCES
 	roles/http/header.c
 	roles/http/header.c
-	roles/http/date.c
 	roles/http/parsers.c)
 	roles/http/parsers.c)
 	
 	
 if (NOT LWS_WITHOUT_SERVER)
 if (NOT LWS_WITHOUT_SERVER)
@@ -88,4 +87,4 @@ endif()
 # Keep explicit parent scope exports at end
 # Keep explicit parent scope exports at end
 #
 #
 
 
-exports_to_parent_scope()
+exports_to_parent_scope()

+ 1559 - 0
Source/ThirdParty/libwebsockets/lib/roles/http/client/client-handshake.c

@@ -0,0 +1,1559 @@
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010 - 2019 Andy Green <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "private-lib-core.h"
+
+#if !defined(LWS_WITH_SYS_ASYNC_DNS)
+static int
+lws_getaddrinfo46(struct lws *wsi, const char *ads, struct addrinfo **result)
+{
+	struct addrinfo hints;
+	int n;
+
+	memset(&hints, 0, sizeof(hints));
+	*result = NULL;
+
+	hints.ai_socktype = SOCK_STREAM;
+
+#ifdef LWS_WITH_IPV6
+	if (wsi->ipv6) {
+
+#if !defined(__ANDROID__)
+		hints.ai_family = AF_UNSPEC;
+		hints.ai_flags = AI_V4MAPPED;
+#endif
+	} else
+#endif
+	{
+		hints.ai_family = PF_UNSPEC;
+	}
+
+	n = getaddrinfo(ads, NULL, &hints, result);
+
+	lwsl_info("%s: getaddrinfo '%s' says %d\n", __func__, ads, n);
+
+	return n;
+}
+#endif
+
+struct lws *
+lws_client_connect_4_established(struct lws *wsi, struct lws *wsi_piggyback,
+				 ssize_t plen)
+{
+#if defined(LWS_CLIENT_HTTP_PROXYING)
+	struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
+#endif
+	const char *meth;
+	struct lws_pollfd pfd;
+	const char *cce = "";
+	int n, m, rawish = 0;
+
+	meth = lws_wsi_client_stash_item(wsi, CIS_METHOD,
+					 _WSI_TOKEN_CLIENT_METHOD);
+
+	if (meth && (!strcmp(meth, "RAW")
+#if defined(LWS_ROLE_MQTT)
+		     || !strcmp(meth, "MQTT")
+#endif
+	))
+		rawish = 1;
+
+	if (wsi_piggyback)
+		goto send_hs;
+
+#if defined(LWS_CLIENT_HTTP_PROXYING)
+#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
+	/* we are connected to server, or proxy */
+
+	/* http proxy */
+	if (wsi->a.vhost->http.http_proxy_port) {
+		const char *cpa;
+
+		cpa = lws_wsi_client_stash_item(wsi, CIS_ADDRESS,
+						_WSI_TOKEN_CLIENT_PEER_ADDRESS);
+		if (!cpa)
+			goto failed;
+
+		lwsl_info("%s: going via proxy\n", __func__);
+
+		plen = lws_snprintf((char *)pt->serv_buf, 256,
+			"CONNECT %s:%u HTTP/1.1\x0d\x0a"
+			"Host: %s:%u\x0d\x0a"
+			"User-agent: lws\x0d\x0a", cpa, wsi->ocport,
+						   cpa, wsi->ocport);
+
+#if defined(LWS_WITH_HTTP_BASIC_AUTH)
+		if (wsi->a.vhost->proxy_basic_auth_token[0])
+			plen += lws_snprintf((char *)pt->serv_buf + plen, 256,
+					"Proxy-authorization: basic %s\x0d\x0a",
+					wsi->a.vhost->proxy_basic_auth_token);
+#endif
+
+		plen += lws_snprintf((char *)pt->serv_buf + plen, 5, "\x0d\x0a");
+
+		/* lwsl_hexdump_notice(pt->serv_buf, plen); */
+
+		/*
+		 * OK from now on we talk via the proxy, so connect to that
+		 */
+		if (wsi->stash)
+			wsi->stash->cis[CIS_ADDRESS] =
+				wsi->a.vhost->http.http_proxy_address;
+		else
+			if (lws_hdr_simple_create(wsi,
+					_WSI_TOKEN_CLIENT_PEER_ADDRESS,
+					  wsi->a.vhost->http.http_proxy_address))
+			goto failed;
+		wsi->c_port = wsi->a.vhost->http.http_proxy_port;
+
+		n = send(wsi->desc.sockfd, (char *)pt->serv_buf, (int)plen,
+			 MSG_NOSIGNAL);
+		if (n < 0) {
+			lwsl_debug("ERROR writing to proxy socket\n");
+			cce = "proxy write failed";
+			goto failed;
+		}
+
+		lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_PROXY_RESPONSE,
+				wsi->a.context->timeout_secs);
+
+		lwsi_set_state(wsi, LRS_WAITING_PROXY_REPLY);
+
+		return wsi;
+	}
+#endif
+#endif
+
+	/* coverity */
+	if (!wsi->a.protocol)
+		return NULL;
+
+#if defined(LWS_WITH_SOCKS5)
+	if (lwsi_state(wsi) != 	LRS_ESTABLISHED)
+		switch (lws_socks5c_greet(wsi, &cce)) {
+		case -1:
+			goto failed;
+		case 1:
+			return wsi;
+		default:
+			break;
+		}
+#endif
+
+#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
+send_hs:
+
+	if (wsi_piggyback &&
+	    !lws_dll2_is_detached(&wsi->dll2_cli_txn_queue)) {
+		/*
+		 * We are pipelining on an already-established connection...
+		 * we can skip tls establishment.
+		 *
+		 * Set these queued guys to a state where they won't actually
+		 * send their headers until we decide later.
+		 */
+
+		lwsi_set_state(wsi, LRS_H2_WAITING_TO_SEND_HEADERS);
+
+		/*
+		 * we can't send our headers directly, because they have to
+		 * be sent when the parent is writeable.  The parent will check
+		 * for anybody on his client transaction queue that is in
+		 * LRS_H1C_ISSUE_HANDSHAKE2, and let them write.
+		 *
+		 * If we are trying to do this too early, before the master
+		 * connection has written his own headers, then it will just
+		 * wait in the queue until it's possible to send them.
+		 */
+		lws_callback_on_writable(wsi_piggyback);
+#if defined(LWS_WITH_DETAILED_LATENCY)
+		wsi->detlat.earliest_write_req =
+			wsi->detlat.earliest_write_req_pre_write = lws_now_usecs();
+#endif
+		lwsl_info("%s: wsi %p: waiting to send hdrs (par state 0x%x)\n",
+			    __func__, wsi, lwsi_state(wsi_piggyback));
+	} else {
+		lwsl_info("%s: wsi %p: %s %s client created own conn (raw %d) vh %sm st 0x%x\n",
+			    __func__, wsi, wsi->role_ops->name,
+			    wsi->a.protocol->name, rawish, wsi->a.vhost->name,
+			    lwsi_state(wsi));
+
+		/* we are making our own connection */
+
+		if (!rawish) {
+			if (lwsi_state(wsi) != LRS_H1C_ISSUE_HANDSHAKE2)
+				lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE);
+		} else {
+			/* for a method = "RAW" connection, this makes us
+			 * established */
+
+#if defined(LWS_WITH_TLS) && !defined(LWS_WITH_MBEDTLS)
+
+			/* we have connected if we got here */
+
+			if (lwsi_state(wsi) == LRS_WAITING_CONNECT &&
+			    (wsi->tls.use_ssl & LCCSCF_USE_SSL)) {
+				int result;
+
+				/*
+				 * We can retry this... just cook the SSL BIO
+				 * the first time
+				 */
+
+				result = lws_client_create_tls(wsi, &cce, 1);
+				lwsl_debug("%s: create_tls said %d\n", __func__, result);
+				switch (result) {
+				case CCTLS_RETURN_DONE:
+					break;
+				case CCTLS_RETURN_RETRY:
+					return wsi;
+				default:
+					goto failed;
+				}
+
+				/*
+				 * We succeeded to negotiate a new client tls tunnel.
+				 * If it's h2 alpn, we have arranged to send to h2
+				 * prefix and set our state to
+				 * LRS_H2_WAITING_TO_SEND_HEADERS already.
+				 */
+
+				lwsl_notice("%s: wsi %p: tls established st 0x%x\n",
+					    __func__, wsi, lwsi_state(wsi));
+
+				if (lwsi_state(wsi) != LRS_H2_WAITING_TO_SEND_HEADERS)
+					lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE2);
+				lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND,
+						wsi->a.context->timeout_secs);
+
+				goto provoke_service;
+			}
+#endif
+
+			/* clear his established timeout */
+			lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
+
+			m = wsi->role_ops->adoption_cb[0];
+			if (m) {
+				n = user_callback_handle_rxflow(
+						wsi->a.protocol->callback, wsi,
+						m, wsi->user_space, NULL, 0);
+				if (n < 0) {
+					lwsl_info("LWS_CALLBACK_RAW_PROXY_CLI_ADOPT failed\n");
+					goto failed;
+				}
+			}
+
+			/* service.c pollout processing wants this */
+			wsi->hdr_parsing_completed = 1;
+#if defined(LWS_ROLE_MQTT)
+			if (!strcmp(meth, "MQTT")) {
+#if defined(LWS_WITH_TLS)
+				if (wsi->tls.use_ssl & LCCSCF_USE_SSL) {
+					lwsi_set_state(wsi, LRS_WAITING_SSL);
+					return wsi;
+				}
+#endif
+				lwsl_info("%s: settings LRS_MQTTC_IDLE\n",
+					  __func__);
+				lwsi_set_state(wsi, LRS_MQTTC_IDLE);
+
+				/*
+				 * provoke service to issue the CONNECT directly.
+				 */
+				lws_set_timeout(wsi, PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE,
+						wsi->a.context->timeout_secs);
+
+				assert(lws_socket_is_valid(wsi->desc.sockfd));
+
+				pfd.fd = wsi->desc.sockfd;
+				pfd.events = LWS_POLLIN;
+				pfd.revents = LWS_POLLOUT;
+
+				lwsl_info("%s: going to service fd\n", __func__);
+				n = lws_service_fd(wsi->a.context, &pfd);
+				if (n < 0) {
+					cce = "first service failed";
+					goto failed;
+				}
+				if (n) /* returns 1 on failure after closing wsi */
+					return NULL;
+				return wsi;
+			}
+#endif
+			lwsl_info("%s: setting ESTABLISHED\n", __func__);
+			lwsi_set_state(wsi, LRS_ESTABLISHED);
+
+			return wsi;
+		}
+
+		/*
+		 * provoke service to issue the handshake directly.
+		 *
+		 * we need to do it this way because in the proxy case, this is
+		 * the next state and executed only if and when we get a good
+		 * proxy response inside the state machine... but notice in
+		 * SSL case this may not have sent anything yet with 0 return,
+		 * and won't until many retries from main loop.  To stop that
+		 * becoming endless, cover with a timeout.
+		 */
+#if defined(LWS_WITH_TLS) && !defined(LWS_WITH_MBEDTLS)
+provoke_service:
+#endif
+		lws_set_timeout(wsi, PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE,
+				wsi->a.context->timeout_secs);
+
+		assert(lws_socket_is_valid(wsi->desc.sockfd));
+
+		pfd.fd = wsi->desc.sockfd;
+		pfd.events = LWS_POLLIN;
+		pfd.revents = LWS_POLLIN;
+
+		n = lws_service_fd(wsi->a.context, &pfd);
+		if (n < 0) {
+			cce = "first service failed";
+			goto failed;
+		}
+		if (n) /* returns 1 on failure after closing wsi */
+			return NULL;
+	}
+#endif
+	return wsi;
+
+failed:
+	lws_inform_client_conn_fail(wsi, (void *)cce, strlen(cce));
+
+	lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "client_connect2");
+
+	return NULL;
+}
+
+void
+lws_client_conn_wait_timeout(lws_sorted_usec_list_t *sul)
+{
+	struct lws *wsi = lws_container_of(sul, struct lws, sul_connect_timeout);
+
+	/*
+	 * This is used to constrain the time we're willing to wait for a
+	 * connection before giving up on it and retrying.
+	 */
+
+	lwsl_info("%s: connect wait timeout has fired\n", __func__);
+	lws_client_connect_3_connect(wsi, NULL, NULL, 0, NULL);
+}
+
+struct lws *
+lws_client_connect_3_connect(struct lws *wsi, const char *ads,
+			     const struct addrinfo *result, int n, void *opaque)
+{
+#if defined(LWS_WITH_UNIX_SOCK)
+	struct sockaddr_un sau;
+#endif
+#ifdef LWS_WITH_IPV6
+	char ipv6only = lws_check_opt(wsi->a.vhost->options,
+				      LWS_SERVER_OPTION_IPV6_V6ONLY_MODIFY |
+				      LWS_SERVER_OPTION_IPV6_V6ONLY_VALUE);
+#endif
+	struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
+	const struct sockaddr *psa = NULL;
+	uint16_t port = wsi->c_port;
+	const char *cce, *iface;
+	lws_sockaddr46 sa46;
+	ssize_t plen = 0;
+	char ni[48];
+	int m;
+
+       if (n == LWS_CONNECT_COMPLETION_GOOD)
+               goto conn_good;
+
+#if defined(LWS_WITH_IPV6) && defined(__ANDROID__)
+	ipv6only = 0;
+#endif
+
+	/*
+	 * async dns calls back here for everybody who cares when it gets a
+	 * result... but if we are piggybacking, we do not want to connect
+	 * ourselves
+	 */
+
+	if (!lws_dll2_is_detached(&wsi->dll2_cli_txn_queue))
+		return wsi;
+
+	/*
+	* We can check using getsockopt if our connect actually completed.
+	* Posix connect() allows nonblocking to redo the connect to
+	* find out if it succeeded, for win32 we have to use this path
+	* and take WSAEALREADY as a successful connect.
+	*/
+
+	if (lwsi_state(wsi) == LRS_WAITING_CONNECT &&
+	    lws_socket_is_valid(wsi->desc.sockfd)) {
+#if !defined(WIN32)
+		socklen_t sl = sizeof(int);
+		int e = 0;
+#endif
+
+		if (!result && /* no dns results... */
+		    !wsi->sul_connect_timeout.list.owner /* no ongoing connect timeout */)
+			goto connect_to;
+#if defined(WIN32)
+		if (!connect(wsi->desc.sockfd, NULL, 0)) {
+			goto conn_good;
+               } else {
+			if (!LWS_ERRNO || LWS_ERRNO == WSAEINVAL ||
+			    LWS_ERRNO == WSAEWOULDBLOCK || LWS_ERRNO == WSAEALREADY) {
+				lwsl_info("%s: errno %d\n", __func__, errno);
+				return NULL;
+			}
+			lwsl_info("%s: connect check take as FAILED\n", __func__);
+		}
+#else
+		/*
+		* this resets SO_ERROR after reading it.  If there's an error
+		* condition the connect definitively failed.
+		*/
+
+		if (!getsockopt(wsi->desc.sockfd, SOL_SOCKET, SO_ERROR,
+				&e, &sl)) {
+			if (!e) {
+				lwsl_debug("%s: getsockopt check: conn OK errno %d\n",
+					   __func__, errno);
+
+				goto conn_good;
+			}
+
+			lwsl_debug("%s: getsockopt fd %d says err %d\n", __func__,
+					wsi->desc.sockfd, e);
+		}
+#endif
+
+		lwsl_debug("%s: getsockopt check: conn fail: errno %d\n",
+				__func__, LWS_ERRNO);
+		goto try_next_result_fds;
+	}
+
+#if defined(LWS_WITH_UNIX_SOCK)
+	if (ads && *ads == '+') {
+		ads++;
+		memset(&sa46, 0, sizeof(sa46));
+		memset(&sau, 0, sizeof(sau));
+		sau.sun_family = AF_UNIX;
+		strncpy(sau.sun_path, ads, sizeof(sau.sun_path));
+		sau.sun_path[sizeof(sau.sun_path) - 1] = '\0';
+
+		lwsl_info("%s: Unix skt: %s\n", __func__, ads);
+
+		if (sau.sun_path[0] == '@')
+			sau.sun_path[0] = '\0';
+
+		goto ads_known;
+	}
+#endif
+
+#if defined(LWS_WITH_SYS_ASYNC_DNS)
+	if (n == LADNS_RET_FAILED) {
+		lwsl_notice("%s: adns failed %s\n", __func__, ads);
+		/*
+		 * Caller that is giving us LADNS_RET_FAILED will deal
+		 * with cleanup
+		 */
+		return NULL;
+	}
+#endif
+
+	if (!wsi->dns_results) {
+		wsi->dns_results_next = wsi->dns_results = result;
+		if (result)
+			lwsl_debug("%s: result %p result->ai_next %p\n",
+					__func__, result, result->ai_next);
+	}
+
+#if defined(LWS_WITH_DETAILED_LATENCY)
+	if (lwsi_state(wsi) == LRS_WAITING_DNS &&
+	    wsi->a.context->detailed_latency_cb) {
+		wsi->detlat.type = LDLT_NAME_RESOLUTION;
+		wsi->detlat.latencies[LAT_DUR_PROXY_CLIENT_REQ_TO_WRITE] =
+			lws_now_usecs() -
+			wsi->detlat.earliest_write_req_pre_write;
+		wsi->detlat.latencies[LAT_DUR_USERCB] = 0;
+		lws_det_lat_cb(wsi->a.context, &wsi->detlat);
+		wsi->detlat.earliest_write_req_pre_write = lws_now_usecs();
+	}
+#endif
+#if defined(LWS_CLIENT_HTTP_PROXYING) && \
+	(defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2))
+
+	/* Decide what it is we need to connect to:
+	 *
+	 * Priority 1: connect to http proxy */
+
+	if (wsi->a.vhost->http.http_proxy_port) {
+		port = wsi->a.vhost->http.http_proxy_port;
+#else
+		if (0) {
+#endif
+
+#if defined(LWS_WITH_SOCKS5)
+
+	/* Priority 2: Connect to SOCK5 Proxy */
+
+	} else if (wsi->a.vhost->socks_proxy_port) {
+		if (lws_socks5c_generate_msg(wsi, SOCKS_MSG_GREETING, &plen)) {
+			cce = "socks msg too large";
+			goto oom4;
+		}
+
+		lwsl_client("Sending SOCKS Greeting\n");
+		ads = wsi->a.vhost->socks_proxy_address;
+		port = wsi->a.vhost->socks_proxy_port;
+#endif
+	}
+
+	memset(&sa46, 0, sizeof(sa46));
+
+	if (n || !wsi->dns_results) {
+		/* lws_getaddrinfo46 failed, there is no usable result */
+		lwsl_notice("%s: lws_getaddrinfo46 failed %d\n",
+				__func__, n);
+
+		cce = "ipv6 lws_getaddrinfo46 failed";
+		goto oom4;
+	}
+
+	/*
+	 * Let's try connecting to each of the results in turn until one works
+	 * or we run out of results
+	 */
+
+next_result:
+
+	psa = (const struct sockaddr *)&sa46;
+	n = sizeof(sa46);
+	memset(&sa46, 0, sizeof(sa46));
+
+	switch (wsi->dns_results_next->ai_family) {
+	case AF_INET:
+#if defined(LWS_WITH_IPV6)
+		if (ipv6only) {
+			sa46.sa4.sin_family = AF_INET6;
+
+			/* map IPv4 to IPv6 */
+			memset((char *)&sa46.sa6.sin6_addr, 0,
+						sizeof(sa46.sa6.sin6_addr));
+			sa46.sa6.sin6_addr.s6_addr[10] = 0xff;
+			sa46.sa6.sin6_addr.s6_addr[11] = 0xff;
+			memcpy(&sa46.sa6.sin6_addr.s6_addr[12],
+				&((struct sockaddr_in *)
+				    wsi->dns_results_next->ai_addr)->sin_addr,
+							sizeof(struct in_addr));
+			sa46.sa6.sin6_port = htons(port);
+			ni[0] = '\0';
+			lws_write_numeric_address(sa46.sa6.sin6_addr.s6_addr,
+						  16, ni, sizeof(ni));
+			lwsl_info("%s: %s ipv4->ipv6 %s\n", __func__,
+				  ads ? ads : "(null)", ni);
+			break;
+		}
+#endif
+		sa46.sa4.sin_family = AF_INET;
+		sa46.sa4.sin_addr.s_addr =
+			((struct sockaddr_in *)wsi->dns_results_next->ai_addr)->
+								sin_addr.s_addr;
+		memset(&sa46.sa4.sin_zero, 0, sizeof(sa46.sa4.sin_zero));
+		sa46.sa4.sin_port = htons(port);
+		n = sizeof(struct sockaddr_in);
+		lws_write_numeric_address((uint8_t *)&sa46.sa4.sin_addr.s_addr,
+					  4, ni, sizeof(ni));
+		lwsl_info("%s: %s ipv4 %s\n", __func__, ads ? ads : "(null)", ni);
+		break;
+	case AF_INET6:
+#if defined(LWS_WITH_IPV6)
+		if (!wsi->ipv6)
+			goto try_next_result;
+		sa46.sa4.sin_family = AF_INET6;
+		memcpy(&sa46.sa6.sin6_addr,
+		       &((struct sockaddr_in6 *)wsi->dns_results_next->ai_addr)->
+				       sin6_addr, sizeof(struct in6_addr));
+		sa46.sa6.sin6_scope_id = ((struct sockaddr_in6 *)
+				wsi->dns_results_next->ai_addr)->sin6_scope_id;
+		sa46.sa6.sin6_flowinfo = ((struct sockaddr_in6 *)
+				wsi->dns_results_next->ai_addr)->sin6_flowinfo;
+		sa46.sa6.sin6_port = htons(port);
+		lws_write_numeric_address((uint8_t *)&sa46.sa6.sin6_addr,
+				16, ni, sizeof(ni));
+		lwsl_info("%s: %s ipv6 %s\n", __func__, ads ? ads : "(null)", ni);
+#else
+		goto try_next_result;	/* ipv4 only can't use this */
+#endif
+		break;
+	}
+
+#if defined(LWS_WITH_UNIX_SOCK)
+ads_known:
+#endif
+
+	/* now we decided on ipv4 or ipv6, set the port and create socket*/
+
+	if (!lws_socket_is_valid(wsi->desc.sockfd)) {
+
+		if (wsi->a.context->event_loop_ops->check_client_connect_ok &&
+		    wsi->a.context->event_loop_ops->check_client_connect_ok(wsi)) {
+			cce = "waiting for event loop watcher to close";
+			goto oom4;
+		}
+
+#if defined(LWS_WITH_UNIX_SOCK)
+		if (wsi->unix_skt)
+			wsi->desc.sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
+		else
+#endif
+			wsi->desc.sockfd = socket(sa46.sa4.sin_family,
+						  SOCK_STREAM, 0);
+
+		if (!lws_socket_is_valid(wsi->desc.sockfd)) {
+			lwsl_warn("Unable to open socket\n");
+			goto try_next_result;
+		}
+
+		if (lws_plat_set_socket_options(wsi->a.vhost, wsi->desc.sockfd,
+#if defined(LWS_WITH_UNIX_SOCK)
+						wsi->unix_skt)) {
+#else
+						0)) {
+#endif
+			lwsl_err("Failed to set wsi socket options\n");
+			goto try_next_result_closesock;
+		}
+
+		lwsl_debug("%s: %p: WAITING_CONNECT\n", __func__, wsi);
+		lwsi_set_state(wsi, LRS_WAITING_CONNECT);
+
+		if (wsi->a.context->event_loop_ops->sock_accept)
+			if (wsi->a.context->event_loop_ops->sock_accept(wsi))
+				goto try_next_result_closesock;
+
+		lws_pt_lock(pt, __func__);
+		if (__insert_wsi_socket_into_fds(wsi->a.context, wsi)) {
+			lws_pt_unlock(pt);
+			goto try_next_result_closesock;
+		}
+		lws_pt_unlock(pt);
+
+		/*
+		 * The fd + wsi combination is entered into the wsi tables
+		 * at this point, with a pollfd
+		 *
+		 * Past here, we can't simply free the structs as error
+		 * handling as oom4 does.
+		 *
+		 * We can run the whole close flow, or unpick the fds inclusion
+		 * and anything else we have done.
+		 */
+
+		if (lws_change_pollfd(wsi, 0, LWS_POLLIN))
+			goto try_next_result_fds;
+
+		if (!wsi->a.protocol)
+			wsi->a.protocol = &wsi->a.vhost->protocols[0];
+
+		lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CONNECT_RESPONSE,
+				wsi->a.vhost->connect_timeout_secs);
+
+		iface = lws_wsi_client_stash_item(wsi, CIS_IFACE,
+						  _WSI_TOKEN_CLIENT_IFACE);
+
+		if (iface && *iface) {
+			m = lws_socket_bind(wsi->a.vhost, wsi->desc.sockfd, 0,
+					    iface, wsi->ipv6);
+			if (m < 0)
+				goto try_next_result_fds;
+		}
+	}
+
+#if defined(LWS_WITH_UNIX_SOCK)
+	if (wsi->unix_skt) {
+		psa = (const struct sockaddr *)&sau;
+		if (sau.sun_path[0])
+			n = (int)(sizeof(uint16_t) + strlen(sau.sun_path));
+		else
+			n = (int)(sizeof(uint16_t) + strlen(&sau.sun_path[1]) + 1);
+	} else
+#endif
+
+	if (!psa) /* coverity */
+		goto try_next_result_fds;
+
+	/*
+	 * The actual connection attempt
+	 */
+
+#if defined(LWS_WITH_DETAILED_LATENCY)
+	wsi->detlat.earliest_write_req =
+		wsi->detlat.earliest_write_req_pre_write = lws_now_usecs();
+#endif
+
+#if defined(LWS_ESP_PLATFORM)
+	errno = 0;
+#endif
+	m = connect(wsi->desc.sockfd, (const struct sockaddr *)psa, n);
+	if (m == -1) {
+		int errno_copy = LWS_ERRNO;
+
+		lwsl_debug("%s: connect says errno: %d\n", __func__, errno_copy);
+
+		if (errno_copy && errno_copy != LWS_EALREADY &&
+		    errno_copy != LWS_EINPROGRESS &&
+		    errno_copy != LWS_EWOULDBLOCK
+#ifdef _WIN32
+			&& errno_copy != WSAEINVAL
+                       && errno_copy != WSAEISCONN
+#endif
+		) {
+#if defined(_DEBUG)
+			char nads[48];
+			lws_sa46_write_numeric_address(&sa46, nads, sizeof(nads));
+			lwsl_info("%s: Connect failed: %s port %d\n",
+				    __func__, nads, port);
+#endif
+			goto try_next_result_fds;
+		}
+
+#if defined(WIN32)
+		if (lws_plat_check_connection_error(wsi))
+			goto try_next_result_fds;
+               if (errno_copy == WSAEISCONN)
+                       goto conn_good;
+#endif
+
+		/*
+		 * Let's set a specialized timeout for this connect attempt
+		 * completion, it uses wsi->sul_connect_timeout just for this
+		 * purpose
+		 */
+
+		lws_sul_schedule(wsi->a.context, 0, &wsi->sul_connect_timeout,
+				 lws_client_conn_wait_timeout,
+				 wsi->a.context->timeout_secs * LWS_USEC_PER_SEC);
+
+		/*
+		 * must do specifically a POLLOUT poll to hear
+		 * about the connect completion
+		 */
+#if !defined(WIN32)
+		if (lws_change_pollfd(wsi, 0, LWS_POLLOUT))
+			goto try_next_result_fds;
+#endif
+
+		return wsi;
+	}
+
+conn_good:
+	lws_sul_cancel(&wsi->sul_connect_timeout);
+	lwsl_info("%s: Connection started %p\n", __func__, wsi->dns_results);
+
+	/* the tcp connection has happend */
+
+#if defined(LWS_WITH_DETAILED_LATENCY)
+	if (wsi->a.context->detailed_latency_cb) {
+		wsi->detlat.type = LDLT_CONNECTION;
+		wsi->detlat.latencies[LAT_DUR_PROXY_CLIENT_REQ_TO_WRITE] =
+			lws_now_usecs() -
+			wsi->detlat.earliest_write_req_pre_write;
+		wsi->detlat.latencies[LAT_DUR_USERCB] = 0;
+		lws_det_lat_cb(wsi->a.context, &wsi->detlat);
+		wsi->detlat.earliest_write_req =
+			wsi->detlat.earliest_write_req_pre_write =
+							lws_now_usecs();
+	}
+#endif
+
+	lws_addrinfo_clean(wsi);
+
+	if (wsi->a.protocol)
+		wsi->a.protocol->callback(wsi, LWS_CALLBACK_WSI_CREATE,
+					wsi->user_space, NULL, 0);
+
+	lwsl_debug("%s: going into connect_4\n", __func__);
+	return lws_client_connect_4_established(wsi, NULL, plen);
+
+oom4:
+	/*
+	 * We get here if we're trying to clean up a connection attempt that
+	 * didn't make it as far as getting inserted into the wsi / fd tables
+	 */
+
+	if (lwsi_role_client(wsi) && wsi->a.protocol /* && lwsi_state_est(wsi) */)
+		lws_inform_client_conn_fail(wsi,(void *)cce, strlen(cce));
+
+	/* take care that we might be inserted in fds already */
+	if (wsi->position_in_fds_table != LWS_NO_FDS_POS)
+		/* do the full wsi close flow */
+		goto failed1;
+
+	/*
+	 * We can't be an active client connection any more, if we thought
+	 * that was what we were going to be doing.  It should be if we are
+	 * failing by oom4 path, we are still called by
+	 * lws_client_connect_via_info() and will be returning NULL to that,
+	 * so nobody else should have had a chance to queue on us.
+	 */
+	{
+		struct lws_vhost *vhost = wsi->a.vhost;
+		lws_sockfd_type sfd = wsi->desc.sockfd;
+
+		lws_vhost_lock(vhost);
+		__lws_free_wsi(wsi);
+		lws_vhost_unlock(vhost);
+
+		sanity_assert_no_wsi_traces(vhost->context, wsi);
+		sanity_assert_no_sockfd_traces(vhost->context, sfd);
+	}
+
+	return NULL;
+
+connect_to:
+	/*
+	 * It looks like the sul_connect_timeout fired
+	 */
+	lwsl_info("%s: abandoning connect due to timeout\n", __func__);
+
+try_next_result_fds:
+	__remove_wsi_socket_from_fds(wsi);
+
+try_next_result_closesock:
+	/*
+	 * We are killing the socket but leaving
+	 */
+	compatible_close(wsi->desc.sockfd);
+	wsi->desc.sockfd = LWS_SOCK_INVALID;
+
+try_next_result:
+	lws_sul_cancel(&wsi->sul_connect_timeout);
+	if (wsi->dns_results_next) {
+		wsi->dns_results_next = wsi->dns_results_next->ai_next;
+		if (wsi->dns_results_next)
+			goto next_result;
+	}
+	lws_addrinfo_clean(wsi);
+	cce = "Unable to connect";
+
+//failed:
+	lws_inform_client_conn_fail(wsi, (void *)cce, strlen(cce));
+
+failed1:
+	lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "client_connect2");
+
+	return NULL;
+}
+
+struct lws *
+lws_client_connect_2_dnsreq(struct lws *wsi)
+{
+	struct addrinfo *result = NULL;
+	const char *meth = NULL, *ads;
+#if defined(LWS_WITH_IPV6)
+	struct sockaddr_in addr;
+	const char *iface;
+#endif
+	const char *adsin;
+	int n, port = 0;
+	struct lws *w;
+
+	if (lwsi_state(wsi) == LRS_WAITING_DNS ||
+	    lwsi_state(wsi) == LRS_WAITING_CONNECT) {
+		lwsl_info("%s: LRS_WAITING_DNS / CONNECT\n", __func__);
+
+		return wsi;
+	}
+
+	/*
+	 * The first job is figure out if we want to pipeline on or just join
+	 * an existing "active connection" to the same place
+	 */
+
+	meth = lws_wsi_client_stash_item(wsi, CIS_METHOD,
+					 _WSI_TOKEN_CLIENT_METHOD);
+
+	/* we only pipeline connections that said it was okay */
+
+	if (!wsi->client_pipeline) {
+		lwsl_debug("%s: new conn on no pipeline flag\n", __func__);
+
+		goto solo;
+	}
+
+	/* only pipeline things we associate with being a stream */
+
+	if (meth && strcmp(meth, "RAW") && strcmp(meth, "GET") &&
+		    strcmp(meth, "POST") && strcmp(meth, "PUT") &&
+		    strcmp(meth, "UDP") && strcmp(meth, "MQTT"))
+		goto solo;
+
+	/* consult active connections to find out disposition */
+
+	adsin = lws_wsi_client_stash_item(wsi, CIS_ADDRESS,
+					  _WSI_TOKEN_CLIENT_PEER_ADDRESS);
+
+	if (!adsin)
+		/*
+		 * This cannot happen since user code must provide the client
+		 * address to get this far, it's here to satisfy Coverity
+		 */
+		return NULL;
+
+	switch (lws_vhost_active_conns(wsi, &w, adsin)) {
+	case ACTIVE_CONNS_SOLO:
+		break;
+	case ACTIVE_CONNS_MUXED:
+		lwsl_notice("%s: ACTIVE_CONNS_MUXED\n", __func__);
+		if (lwsi_role_h2(wsi)) {
+
+			if (wsi->a.protocol->callback(wsi,
+						    LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP,
+						    wsi->user_space, NULL, 0))
+				goto failed1;
+
+			//lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE2);
+			//lwsi_set_state(w, LRS_ESTABLISHED);
+			lws_callback_on_writable(wsi);
+		}
+
+		return wsi;
+	case ACTIVE_CONNS_QUEUED:
+		lwsl_debug("%s: ACTIVE_CONNS_QUEUED st 0x%x: \n", __func__, lwsi_state(wsi));
+		if (lwsi_state(wsi) == LRS_UNCONNECTED) {
+			if (lwsi_role_h2(w))
+				lwsi_set_state(wsi, LRS_H2_WAITING_TO_SEND_HEADERS);
+			else
+				lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE2);
+		}
+
+		return lws_client_connect_4_established(wsi, w, 0);
+	}
+
+solo:
+	wsi->addrinfo_idx = 0;
+
+	/*
+	 * clients who will create their own fresh connection keep a copy of
+	 * the hostname they originally connected to, in case other connections
+	 * want to use it too
+	 */
+
+	if (!wsi->cli_hostname_copy) {
+		if (wsi->stash && wsi->stash->cis[CIS_HOST])
+			wsi->cli_hostname_copy =
+					lws_strdup(wsi->stash->cis[CIS_HOST]);
+#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
+		else {
+			char *pa = lws_hdr_simple_ptr(wsi,
+					      _WSI_TOKEN_CLIENT_PEER_ADDRESS);
+			if (pa)
+				wsi->cli_hostname_copy = lws_strdup(pa);
+		}
+#endif
+	}
+
+	/*
+	 * If we made our own connection, and we're doing a method that can
+	 * take a pipeline, we are an "active client connection".
+	 *
+	 * Add ourselves to the vhost list of those so that others can
+	 * piggyback on our transaction queue
+	 */
+
+	if (meth && (!strcmp(meth, "RAW") || !strcmp(meth, "GET") ||
+		     !strcmp(meth, "POST") || !strcmp(meth, "PUT") ||
+		     !strcmp(meth, "MQTT")) &&
+	    lws_dll2_is_detached(&wsi->dll2_cli_txn_queue) &&
+	    lws_dll2_is_detached(&wsi->dll_cli_active_conns)) {
+		lws_vhost_lock(wsi->a.vhost);
+		lwsl_info("%s: adding active conn %p\n", __func__, wsi);
+		/* caution... we will have to unpick this on oom4 path */
+		lws_dll2_add_head(&wsi->dll_cli_active_conns,
+				 &wsi->a.vhost->dll_cli_active_conns_owner);
+		lws_vhost_unlock(wsi->a.vhost);
+	}
+
+	/*
+	 * unix socket destination?
+	 */
+
+	if (wsi->stash)
+		ads = wsi->stash->cis[CIS_ADDRESS];
+	else
+		ads = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS);
+
+	/*
+	 * Since address must be given at client creation, should not be
+	 * possible, but necessary to satisfy coverity
+	 */
+	if (!ads)
+		return NULL;
+
+#if defined(LWS_WITH_UNIX_SOCK)
+	if (*ads == '+') {
+		wsi->unix_skt = 1;
+		n = 0;
+		goto next_step;
+	}
+#endif
+
+	/*
+	 * start off allowing ipv6 on connection if vhost allows it
+	 */
+	wsi->ipv6 = LWS_IPV6_ENABLED(wsi->a.vhost);
+#ifdef LWS_WITH_IPV6
+	if (wsi->stash)
+		iface = wsi->stash->cis[CIS_IFACE];
+	else
+		iface = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_IFACE);
+
+	if (wsi->ipv6 && iface &&
+	    inet_pton(AF_INET, iface, &addr.sin_addr) == 1) {
+		lwsl_notice("%s: client connection forced to IPv4\n", __func__);
+		wsi->ipv6 = 0;
+	}
+#endif
+
+#if defined(LWS_WITH_DETAILED_LATENCY)
+	if (lwsi_state(wsi) == LRS_WAITING_DNS &&
+	    wsi->a.context->detailed_latency_cb) {
+		wsi->detlat.type = LDLT_NAME_RESOLUTION;
+		wsi->detlat.latencies[LAT_DUR_PROXY_CLIENT_REQ_TO_WRITE] =
+			lws_now_usecs() -
+			wsi->detlat.earliest_write_req_pre_write;
+		wsi->detlat.latencies[LAT_DUR_USERCB] = 0;
+		lws_det_lat_cb(wsi->a.context, &wsi->detlat);
+		wsi->detlat.earliest_write_req_pre_write = lws_now_usecs();
+	}
+#endif
+
+#if defined(LWS_CLIENT_HTTP_PROXYING) && \
+	(defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2))
+
+	/* Decide what it is we need to connect to:
+	 *
+	 * Priority 1: connect to http proxy */
+
+	if (wsi->a.vhost->http.http_proxy_port) {
+		ads = wsi->a.vhost->http.http_proxy_address;
+		port = wsi->a.vhost->http.http_proxy_port;
+#else
+		if (0) {
+#endif
+
+#if defined(LWS_WITH_SOCKS5)
+
+	/* Priority 2: Connect to SOCK5 Proxy */
+
+	} else if (wsi->a.vhost->socks_proxy_port) {
+		lwsl_client("Sending SOCKS Greeting\n");
+		ads = wsi->a.vhost->socks_proxy_address;
+		port = wsi->a.vhost->socks_proxy_port;
+#endif
+	} else {
+
+		/* Priority 3: Connect directly */
+
+		/* ads already set */
+		port = wsi->c_port;
+	}
+
+	/*
+	 * prepare the actual connection
+	 * to whatever we decided to connect to
+	 */
+	lwsi_set_state(wsi, LRS_WAITING_DNS);
+
+	lwsl_info("%s: %p: lookup %s:%u\n", __func__, wsi, ads, port);
+	(void)port;
+
+#if defined(LWS_WITH_DETAILED_LATENCY)
+	wsi->detlat.earliest_write_req_pre_write = lws_now_usecs();
+#endif
+#if !defined(LWS_WITH_SYS_ASYNC_DNS)
+	if (wsi->dns_results)
+		n = 0;
+	else
+		n = lws_getaddrinfo46(wsi, ads, &result);
+#else
+	lwsi_set_state(wsi, LRS_WAITING_DNS);
+	/* this is either FAILED, CONTINUING, or already called connect_4 */
+
+	n = lws_async_dns_query(wsi->a.context, wsi->tsi, ads, LWS_ADNS_RECORD_A,
+				lws_client_connect_3_connect, wsi, NULL);
+	if (n == LADNS_RET_FAILED_WSI_CLOSED)
+		return NULL;
+
+	if (n == LADNS_RET_FAILED)
+		goto failed1;
+
+	return wsi;
+#endif
+
+#if defined(LWS_WITH_UNIX_SOCK)
+next_step:
+#endif
+	return lws_client_connect_3_connect(wsi, ads, result, n, NULL);
+
+//#if defined(LWS_WITH_SYS_ASYNC_DNS)
+failed1:
+	lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "client_connect2");
+
+	return NULL;
+//#endif
+}
+
+#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
+
+static uint8_t hnames2[] = {
+	_WSI_TOKEN_CLIENT_ORIGIN,
+	_WSI_TOKEN_CLIENT_SENT_PROTOCOLS,
+	_WSI_TOKEN_CLIENT_METHOD,
+	_WSI_TOKEN_CLIENT_IFACE,
+	_WSI_TOKEN_CLIENT_ALPN
+};
+
+/**
+ * lws_client_reset() - retarget a connected wsi to start over with a new
+ * 			connection (ie, redirect)
+ *			this only works if still in HTTP, ie, not upgraded yet
+ * wsi:		connection to reset
+ * address:	network address of the new server
+ * port:	port to connect to
+ * path:	uri path to connect to on the new server
+ * host:	host header to send to the new server
+ */
+struct lws *
+lws_client_reset(struct lws **pwsi, int ssl, const char *address, int port,
+		 const char *path, const char *host, char weak)
+{
+#if defined(LWS_ROLE_WS)
+	struct _lws_websocket_related *ws;
+#endif
+	char *stash, *p;
+	struct lws *wsi;
+	size_t size = 0;
+	int n;
+
+	if (!pwsi)
+		return NULL;
+
+	wsi = *pwsi;
+
+	lwsl_debug("%s: wsi %p: redir %d: %s\n", __func__, wsi, wsi->redirects,
+			address);
+
+	if (wsi->redirects == 3) {
+		lwsl_err("%s: Too many redirects\n", __func__);
+		return NULL;
+	}
+	wsi->redirects++;
+
+	/*
+	 * goal is to close our role part, close the sockfd, detach the ah
+	 * but leave our wsi extant and still bound to whatever vhost it was
+	 */
+
+	for (n = 0; n < (int)LWS_ARRAY_SIZE(hnames2); n++)
+		size += lws_hdr_total_length(wsi, hnames2[n]) + (size_t)1;
+
+	if (size < (size_t)lws_hdr_total_length(wsi, _WSI_TOKEN_CLIENT_URI) + 1)
+		size = lws_hdr_total_length(wsi, _WSI_TOKEN_CLIENT_URI) + (size_t)1;
+
+	/*
+	 * The incoming address and host can be from inside the existing ah
+	 * we are going to detach and reattch
+	 */
+
+	size += strlen(path) + 1 + strlen(address) + 1 + strlen(host) + 1 + 1;
+
+	p = stash = lws_malloc(size, __func__);
+	if (!stash)
+		return NULL;
+
+	/*
+	 * _WSI_TOKEN_CLIENT_ORIGIN,
+	 * _WSI_TOKEN_CLIENT_SENT_PROTOCOLS,
+	 * _WSI_TOKEN_CLIENT_METHOD,
+	 * _WSI_TOKEN_CLIENT_IFACE,
+	 * _WSI_TOKEN_CLIENT_ALPN
+	 * address
+	 * host
+	 * path
+	 */
+
+	for (n = 0; n < (int)LWS_ARRAY_SIZE(hnames2); n++)
+		if (lws_hdr_total_length(wsi, hnames2[n]) &&
+		    lws_hdr_simple_ptr(wsi, hnames2[n])) {
+			memcpy(p, lws_hdr_simple_ptr(wsi, hnames2[n]), (size_t)(
+			       lws_hdr_total_length(wsi, hnames2[n]) + 1));
+			p += (size_t)(lws_hdr_total_length(wsi, hnames2[n]) + 1);
+		} else
+			*p++ = '\0';
+
+	memcpy(p, address, strlen(address) + (size_t)1);
+	address = p;
+	p += strlen(address) + 1;
+	memcpy(p, host, strlen(host) + (size_t)1);
+	host = p;
+	p += strlen(host) + 1;
+	memcpy(p, path, strlen(path) + (size_t)1);
+	path = p;
+
+	if (!port) {
+		lwsl_info("%s: forcing port 443\n", __func__);
+
+		port = 443;
+		ssl = 1;
+	}
+
+	lwsl_info("redirect ads='%s', port=%d, path='%s', ssl = %d, pifds %d\n",
+		   address, port, path, ssl, wsi->position_in_fds_table);
+
+	__remove_wsi_socket_from_fds(wsi);
+#if defined(LWS_ROLE_WS)
+	if (weak) {
+		ws = wsi->ws;
+		wsi->ws = NULL;
+	}
+#endif
+	__lws_reset_wsi(wsi); /* detaches ah here */
+#if defined(LWS_ROLE_WS)
+	if (weak)
+		wsi->ws = ws;
+#endif
+	wsi->client_pipeline = 1;
+
+	/* close the connection by hand */
+
+#if defined(LWS_WITH_TLS)
+	lws_ssl_close(wsi);
+#endif
+
+	if (wsi->role_ops && wsi->role_ops->close_kill_connection)
+		wsi->role_ops->close_kill_connection(wsi, 1);
+
+	if (wsi->a.context->event_loop_ops->close_handle_manually)
+		wsi->a.context->event_loop_ops->close_handle_manually(wsi);
+	else
+		if (wsi->desc.sockfd != LWS_SOCK_INVALID)
+			compatible_close(wsi->desc.sockfd);
+
+#if defined(LWS_WITH_TLS)
+	if (!ssl)
+		wsi->tls.use_ssl &= ~LCCSCF_USE_SSL;
+	else
+		wsi->tls.use_ssl |= LCCSCF_USE_SSL;
+#else
+	if (ssl) {
+		lwsl_err("%s: not configured for ssl\n", __func__);
+		goto bail;
+	}
+#endif
+
+	if (wsi->a.protocol && wsi->role_ops && wsi->protocol_bind_balance) {
+		wsi->a.protocol->callback(wsi,
+				wsi->role_ops->protocol_unbind_cb[
+				       !!lwsi_role_server(wsi)],
+				       wsi->user_space, (void *)__func__, 0);
+
+		wsi->protocol_bind_balance = 0;
+	}
+
+	wsi->desc.sockfd = LWS_SOCK_INVALID;
+	lws_role_transition(wsi, LWSIFR_CLIENT, LRS_UNCONNECTED, &role_ops_h1);
+//	wsi->a.protocol = NULL;
+	if (wsi->a.protocol)
+		lws_bind_protocol(wsi, wsi->a.protocol, "client_reset");
+	wsi->pending_timeout = NO_PENDING_TIMEOUT;
+	wsi->c_port = port;
+	wsi->hdr_parsing_completed = 0;
+
+	if (lws_header_table_attach(wsi, 0)) {
+		lwsl_err("%s: failed to get ah\n", __func__);
+		goto bail;
+	}
+	//_lws_header_table_reset(wsi->http.ah);
+
+	if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS, address))
+		goto bail;
+
+	if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_HOST, host))
+		goto bail;
+
+	/*
+	 * _WSI_TOKEN_CLIENT_ORIGIN,
+	 * _WSI_TOKEN_CLIENT_SENT_PROTOCOLS,
+	 * _WSI_TOKEN_CLIENT_METHOD,
+	 * _WSI_TOKEN_CLIENT_IFACE,
+	 * _WSI_TOKEN_CLIENT_ALPN
+	 * address
+	 * host
+	 * path
+	 */
+
+	p = stash;
+	for (n = 0; n < (int)LWS_ARRAY_SIZE(hnames2); n++) {
+		if (lws_hdr_simple_create(wsi, hnames2[n], p))
+			goto bail;
+		p += lws_hdr_total_length(wsi, hnames2[n]) + (size_t)1;
+	}
+
+	stash[0] = '/';
+	memmove(&stash[1], path, size - 1 < strlen(path) + 1 ?
+					size - 1 : strlen(path) + (size_t)1);
+	if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_URI, stash))
+		goto bail;
+
+	lws_free_set_NULL(stash);
+
+#if defined(LWS_WITH_HTTP2)
+	if (wsi->client_mux_substream)
+		wsi->h2.END_STREAM = wsi->h2.END_HEADERS = 0;
+#endif
+
+	*pwsi = lws_client_connect_2_dnsreq(wsi);
+
+	return *pwsi;
+
+bail:
+	lws_free_set_NULL(stash);
+
+	return NULL;
+}
+
+#if defined(LWS_WITH_HTTP_PROXY) && defined(LWS_WITH_HUBBUB)
+hubbub_error
+html_parser_cb(const hubbub_token *token, void *pw)
+{
+	struct lws_rewrite *r = (struct lws_rewrite *)pw;
+	char buf[1024], *start = buf + LWS_PRE, *p = start,
+	     *end = &buf[sizeof(buf) - 1], dotstar[128];
+	size_t i;
+
+	switch (token->type) {
+	case HUBBUB_TOKEN_DOCTYPE:
+
+		lws_strnncpy(dotstar, token->data.doctype.name.ptr,
+			     token->data.doctype.name.len, sizeof(dotstar));
+
+		p += lws_snprintf(p, end - p, "<!DOCTYPE %s %s ",
+				  dotstar, token->data.doctype.force_quirks ?
+						"(force-quirks) " : "");
+
+		if (token->data.doctype.public_missing)
+			lwsl_debug("\tpublic: missing\n");
+		else {
+			lws_strnncpy(dotstar, token->data.doctype.public_id.ptr,
+				     token->data.doctype.public_id.len,
+				     sizeof(dotstar));
+			p += lws_snprintf(p, end - p, "PUBLIC \"%s\"\n",
+					  dotstar);
+		}
+
+		if (token->data.doctype.system_missing)
+			lwsl_debug("\tsystem: missing\n");
+		else {
+			lws_strnncpy(dotstar, token->data.doctype.system_id.ptr,
+				     token->data.doctype.system_id.len,
+				     sizeof(dotstar));
+			p += lws_snprintf(p, end - p, " \"%s\">\n", dotstar);
+		}
+
+		break;
+	case HUBBUB_TOKEN_START_TAG:
+		lws_strnncpy(dotstar, token->data.tag.name.ptr,
+			     token->data.tag.name.len, sizeof(dotstar));
+		p += lws_snprintf(p, end - p, "<%s", dotstar);
+
+/*				(token->data.tag.self_closing) ?
+						"(self-closing) " : "",
+				(token->data.tag.n_attributes > 0) ?
+						"attributes:" : "");
+*/
+		for (i = 0; i < token->data.tag.n_attributes; i++) {
+			if (!hstrcmp(&token->data.tag.attributes[i].name, "href", 4) ||
+			    !hstrcmp(&token->data.tag.attributes[i].name, "action", 6) ||
+			    !hstrcmp(&token->data.tag.attributes[i].name, "src", 3)) {
+				const char *pp = (const char *)token->data.tag.attributes[i].value.ptr;
+				int plen = (int) token->data.tag.attributes[i].value.len;
+
+				if (strncmp(pp, "http:", 5) && strncmp(pp, "https:", 6)) {
+
+					if (!hstrcmp(&token->data.tag.attributes[i].value,
+						     r->from, r->from_len)) {
+						pp += r->from_len;
+						plen -= r->from_len;
+					}
+					lws_strnncpy(dotstar,
+						token->data.tag.attributes[i].name.ptr,
+						token->data.tag.attributes[i].name.len,
+						sizeof(dotstar));
+
+					p += lws_snprintf(p, end - p, " %s=\"%s",
+							  dotstar, r->to);
+					lws_strnncpy(dotstar, pp, plen, sizeof(dotstar));
+					p += lws_snprintf(p, end - p, " /%s\"", dotstar);
+					continue;
+				}
+			}
+
+			lws_strnncpy(dotstar,
+				token->data.tag.attributes[i].name.ptr,
+				token->data.tag.attributes[i].name.len,
+				sizeof(dotstar));
+
+			p += lws_snprintf(p, end - p, " %s=\"", dotstar);
+			lws_strnncpy(dotstar,
+				token->data.tag.attributes[i].value.ptr,
+				token->data.tag.attributes[i].value.len,
+				sizeof(dotstar));
+			p += lws_snprintf(p, end - p, "%s\"", dotstar);
+		}
+		p += lws_snprintf(p, end - p, ">");
+		break;
+	case HUBBUB_TOKEN_END_TAG:
+		lws_strnncpy(dotstar, token->data.tag.name.ptr,
+			     token->data.tag.name.len, sizeof(dotstar));
+		p += lws_snprintf(p, end - p, "</%s", dotstar);
+/*
+				(token->data.tag.self_closing) ?
+						"(self-closing) " : "",
+				(token->data.tag.n_attributes > 0) ?
+						"attributes:" : "");
+*/
+		for (i = 0; i < token->data.tag.n_attributes; i++) {
+			lws_strnncpy(dotstar,
+				     token->data.tag.attributes[i].name.ptr,
+				     token->data.tag.attributes[i].name.len,
+				     sizeof(dotstar));
+			p += lws_snprintf(p, end - p, " %s='", dotstar);
+			lws_strnncpy(dotstar,
+				     token->data.tag.attributes[i].value.ptr,
+				     token->data.tag.attributes[i].value.len,
+				     sizeof(dotstar));
+			p += lws_snprintf(p, end - p, "%s'\n", dotstar);
+		}
+		p += lws_snprintf(p, end - p, ">");
+		break;
+	case HUBBUB_TOKEN_COMMENT:
+		lws_strnncpy(dotstar, token->data.comment.ptr,
+			     token->data.comment.len, sizeof(dotstar));
+		p += lws_snprintf(p, end - p, "<!-- %s -->\n",  dotstar);
+		break;
+	case HUBBUB_TOKEN_CHARACTER:
+		if (token->data.character.len == 1) {
+			if (*token->data.character.ptr == '<') {
+				p += lws_snprintf(p, end - p, "&lt;");
+				break;
+			}
+			if (*token->data.character.ptr == '>') {
+				p += lws_snprintf(p, end - p, "&gt;");
+				break;
+			}
+			if (*token->data.character.ptr == '&') {
+				p += lws_snprintf(p, end - p, "&amp;");
+				break;
+			}
+		}
+		lws_strnncpy(dotstar, token->data.character.ptr,
+			     token->data.character.len, sizeof(dotstar));
+		p += lws_snprintf(p, end - p, "%s", dotstar);
+		break;
+	case HUBBUB_TOKEN_EOF:
+		p += lws_snprintf(p, end - p, "\n");
+		break;
+	}
+
+	if (r->wsi->a.protocol_bind_balance &&
+	    user_callback_handle_rxflow(r->wsi->a.protocol->callback,
+			r->wsi, LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ,
+			r->wsi->user_space, start, p - start))
+		return -1;
+
+	return HUBBUB_OK;
+}
+#endif
+
+#endif
+
+static const uint8_t hnames[] = {
+	_WSI_TOKEN_CLIENT_PEER_ADDRESS,
+	_WSI_TOKEN_CLIENT_URI,
+	_WSI_TOKEN_CLIENT_HOST,
+	_WSI_TOKEN_CLIENT_ORIGIN,
+	_WSI_TOKEN_CLIENT_SENT_PROTOCOLS,
+	_WSI_TOKEN_CLIENT_METHOD,
+	_WSI_TOKEN_CLIENT_IFACE,
+	_WSI_TOKEN_CLIENT_ALPN
+};
+
+struct lws *
+lws_http_client_connect_via_info2(struct lws *wsi)
+{
+	struct client_info_stash *stash = wsi->stash;
+	int n;
+
+	lwsl_debug("%s: %p (stash %p)\n", __func__, wsi, stash);
+
+	if (!stash)
+		return wsi;
+
+	wsi->a.opaque_user_data = wsi->stash->opaque_user_data;
+
+	if (stash->cis[CIS_METHOD] && (!strcmp(stash->cis[CIS_METHOD], "RAW") ||
+				      !strcmp(stash->cis[CIS_METHOD], "MQTT")))
+		goto no_ah;
+
+	/*
+	 * we're not necessarily in a position to action these right away,
+	 * stash them... we only need during connect phase so into a temp
+	 * allocated stash
+	 */
+	for (n = 0; n < (int)LWS_ARRAY_SIZE(hnames); n++)
+		if (hnames[n] && stash->cis[n]) {
+			if (lws_hdr_simple_create(wsi, hnames[n], stash->cis[n]))
+				goto bail1;
+		}
+
+#if defined(LWS_WITH_SOCKS5)
+	if (!wsi->a.vhost->socks_proxy_port)
+		lws_free_set_NULL(wsi->stash);
+#endif
+
+no_ah:
+	wsi->a.context->count_wsi_allocated++;
+
+	return lws_client_connect_2_dnsreq(wsi);
+
+bail1:
+#if defined(LWS_WITH_SOCKS5)
+	if (!wsi->a.vhost->socks_proxy_port)
+		lws_free_set_NULL(wsi->stash);
+#endif
+
+	return NULL;
+}

+ 67 - 218
Source/ThirdParty/libwebsockets/lib/roles/http/client/client-http.c

@@ -24,6 +24,72 @@
 
 
 #include "private-lib-core.h"
 #include "private-lib-core.h"
 
 
+#if defined(LWS_WITH_TLS)
+int
+lws_client_create_tls(struct lws *wsi, const char **pcce, int do_c1)
+{
+
+	/* we can retry this... just cook the SSL BIO the first time */
+
+	if (wsi->tls.use_ssl & LCCSCF_USE_SSL) {
+		int n;
+
+		if (!wsi->tls.ssl) {
+			if (lws_ssl_client_bio_create(wsi) < 0) {
+				*pcce = "bio_create failed";
+				return CCTLS_RETURN_ERROR;
+			}
+
+#if defined(LWS_WITH_TLS)
+			if (!wsi->transaction_from_pipeline_queue &&
+			    lws_tls_restrict_borrow(wsi->a.context)) {
+				*pcce = "tls restriction limit";
+				return CCTLS_RETURN_ERROR;
+			}
+#endif
+		}
+
+		if (!do_c1)
+			return 0;
+
+		n = lws_ssl_client_connect1(wsi, (char *)wsi->a.context->pt[(int)wsi->tsi].serv_buf,
+					    wsi->a.context->pt_serv_buf_size);
+		lwsl_debug("%s: lws_ssl_client_connect1: %d\n", __func__, n);
+		if (!n)
+			return CCTLS_RETURN_RETRY; /* caller should return 0 */
+		if (n < 0) {
+			*pcce = (const char *)wsi->a.context->pt[(int)wsi->tsi].serv_buf;
+			return CCTLS_RETURN_ERROR;
+		}
+	} else
+		wsi->tls.ssl = NULL;
+
+#if defined (LWS_WITH_HTTP2)
+	if (wsi->client_h2_alpn) {
+		/*
+		 * We connected to the server and set up tls, and
+		 * negotiated "h2".
+		 *
+		 * So this is it, we are an h2 master client connection
+		 * now, not an h1 client connection.
+		 */
+#if defined(LWS_WITH_TLS)
+		lws_tls_server_conn_alpn(wsi);
+#endif
+
+		/* send the H2 preface to legitimize the connection */
+		if (lws_h2_issue_preface(wsi)) {
+			*pcce = "error sending h2 preface";
+			return CCTLS_RETURN_ERROR;
+		}
+	}
+#endif
+
+	return CCTLS_RETURN_DONE; /* OK */
+}
+
+#endif
+
 void
 void
 lws_client_http_body_pending(struct lws *wsi, int something_left_to_send)
 lws_client_http_body_pending(struct lws *wsi, int something_left_to_send)
 {
 {
@@ -31,7 +97,7 @@ lws_client_http_body_pending(struct lws *wsi, int something_left_to_send)
 }
 }
 
 
 int
 int
-lws_http_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd)
+lws_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd)
 {
 {
 	struct lws_context *context = wsi->a.context;
 	struct lws_context *context = wsi->a.context;
 	struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
 	struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
@@ -1440,220 +1506,3 @@ account_and_ret:
 }
 }
 
 
 #endif
 #endif
-
-static uint8_t hnames2[] = {
-	_WSI_TOKEN_CLIENT_ORIGIN,
-	_WSI_TOKEN_CLIENT_SENT_PROTOCOLS,
-	_WSI_TOKEN_CLIENT_METHOD,
-	_WSI_TOKEN_CLIENT_IFACE,
-	_WSI_TOKEN_CLIENT_ALPN
-};
-
-/**
- * lws_client_reset() - retarget a connected wsi to start over with a new
- * 			connection (ie, redirect)
- *			this only works if still in HTTP, ie, not upgraded yet
- * wsi:		connection to reset
- * address:	network address of the new server
- * port:	port to connect to
- * path:	uri path to connect to on the new server
- * host:	host header to send to the new server
- */
-struct lws *
-lws_client_reset(struct lws **pwsi, int ssl, const char *address, int port,
-		 const char *path, const char *host, char weak)
-{
-#if defined(LWS_ROLE_WS)
-	struct _lws_websocket_related *ws;
-#endif
-	char *stash, *p;
-	struct lws *wsi;
-	size_t size = 0;
-	int n;
-
-	if (!pwsi)
-		return NULL;
-
-	wsi = *pwsi;
-
-	lwsl_debug("%s: wsi %p: redir %d: %s\n", __func__, wsi, wsi->redirects,
-			address);
-
-	if (wsi->redirects == 3) {
-		lwsl_err("%s: Too many redirects\n", __func__);
-		return NULL;
-	}
-	wsi->redirects++;
-
-	/*
-	 * goal is to close our role part, close the sockfd, detach the ah
-	 * but leave our wsi extant and still bound to whatever vhost it was
-	 */
-
-	for (n = 0; n < (int)LWS_ARRAY_SIZE(hnames2); n++)
-		size += lws_hdr_total_length(wsi, hnames2[n]) + (size_t)1;
-
-	if (size < (size_t)lws_hdr_total_length(wsi, _WSI_TOKEN_CLIENT_URI) + 1)
-		size = lws_hdr_total_length(wsi, _WSI_TOKEN_CLIENT_URI) + (size_t)1;
-
-	/*
-	 * The incoming address and host can be from inside the existing ah
-	 * we are going to detach and reattch
-	 */
-
-	size += strlen(path) + 1 + strlen(address) + 1 + strlen(host) + 1 + 1;
-
-	p = stash = lws_malloc(size, __func__);
-	if (!stash)
-		return NULL;
-
-	/*
-	 * _WSI_TOKEN_CLIENT_ORIGIN,
-	 * _WSI_TOKEN_CLIENT_SENT_PROTOCOLS,
-	 * _WSI_TOKEN_CLIENT_METHOD,
-	 * _WSI_TOKEN_CLIENT_IFACE,
-	 * _WSI_TOKEN_CLIENT_ALPN
-	 * address
-	 * host
-	 * path
-	 */
-
-	for (n = 0; n < (int)LWS_ARRAY_SIZE(hnames2); n++)
-		if (lws_hdr_total_length(wsi, hnames2[n]) &&
-		    lws_hdr_simple_ptr(wsi, hnames2[n])) {
-			memcpy(p, lws_hdr_simple_ptr(wsi, hnames2[n]), (size_t)(
-			       lws_hdr_total_length(wsi, hnames2[n]) + 1));
-			p += (size_t)(lws_hdr_total_length(wsi, hnames2[n]) + 1);
-		} else
-			*p++ = '\0';
-
-	memcpy(p, address, strlen(address) + (size_t)1);
-	address = p;
-	p += strlen(address) + 1;
-	memcpy(p, host, strlen(host) + (size_t)1);
-	host = p;
-	p += strlen(host) + 1;
-	memcpy(p, path, strlen(path) + (size_t)1);
-	path = p;
-
-	if (!port) {
-		lwsl_info("%s: forcing port 443\n", __func__);
-
-		port = 443;
-		ssl = 1;
-	}
-
-	lwsl_info("redirect ads='%s', port=%d, path='%s', ssl = %d, pifds %d\n",
-		   address, port, path, ssl, wsi->position_in_fds_table);
-
-	__remove_wsi_socket_from_fds(wsi);
-#if defined(LWS_ROLE_WS)
-	if (weak) {
-		ws = wsi->ws;
-		wsi->ws = NULL;
-	}
-#endif
-	__lws_reset_wsi(wsi); /* detaches ah here */
-#if defined(LWS_ROLE_WS)
-	if (weak)
-		wsi->ws = ws;
-#endif
-	wsi->client_pipeline = 1;
-
-	/* close the connection by hand */
-
-#if defined(LWS_WITH_TLS)
-	lws_ssl_close(wsi);
-#endif
-
-	if (wsi->role_ops && wsi->role_ops->close_kill_connection)
-		wsi->role_ops->close_kill_connection(wsi, 1);
-
-	if (wsi->a.context->event_loop_ops->close_handle_manually)
-		wsi->a.context->event_loop_ops->close_handle_manually(wsi);
-	else
-		if (wsi->desc.sockfd != LWS_SOCK_INVALID)
-			compatible_close(wsi->desc.sockfd);
-
-#if defined(LWS_WITH_TLS)
-	if (!ssl)
-		wsi->tls.use_ssl &= ~LCCSCF_USE_SSL;
-	else
-		wsi->tls.use_ssl |= LCCSCF_USE_SSL;
-#else
-	if (ssl) {
-		lwsl_err("%s: not configured for ssl\n", __func__);
-		goto bail;
-	}
-#endif
-
-	if (wsi->a.protocol && wsi->role_ops && wsi->protocol_bind_balance) {
-		wsi->a.protocol->callback(wsi,
-				wsi->role_ops->protocol_unbind_cb[
-				       !!lwsi_role_server(wsi)],
-				       wsi->user_space, (void *)__func__, 0);
-
-		wsi->protocol_bind_balance = 0;
-	}
-
-	wsi->desc.sockfd = LWS_SOCK_INVALID;
-	lws_role_transition(wsi, LWSIFR_CLIENT, LRS_UNCONNECTED, &role_ops_h1);
-//	wsi->a.protocol = NULL;
-	if (wsi->a.protocol)
-		lws_bind_protocol(wsi, wsi->a.protocol, "client_reset");
-	wsi->pending_timeout = NO_PENDING_TIMEOUT;
-	wsi->c_port = port;
-	wsi->hdr_parsing_completed = 0;
-
-	if (lws_header_table_attach(wsi, 0)) {
-		lwsl_err("%s: failed to get ah\n", __func__);
-		goto bail;
-	}
-	//_lws_header_table_reset(wsi->http.ah);
-
-	if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS, address))
-		goto bail;
-
-	if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_HOST, host))
-		goto bail;
-
-	/*
-	 * _WSI_TOKEN_CLIENT_ORIGIN,
-	 * _WSI_TOKEN_CLIENT_SENT_PROTOCOLS,
-	 * _WSI_TOKEN_CLIENT_METHOD,
-	 * _WSI_TOKEN_CLIENT_IFACE,
-	 * _WSI_TOKEN_CLIENT_ALPN
-	 * address
-	 * host
-	 * path
-	 */
-
-	p = stash;
-	for (n = 0; n < (int)LWS_ARRAY_SIZE(hnames2); n++) {
-		if (lws_hdr_simple_create(wsi, hnames2[n], p))
-			goto bail;
-		p += lws_hdr_total_length(wsi, hnames2[n]) + (size_t)1;
-	}
-
-	stash[0] = '/';
-	memmove(&stash[1], path, size - 1 < strlen(path) + 1 ?
-					size - 1 : strlen(path) + (size_t)1);
-	if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_URI, stash))
-		goto bail;
-
-	lws_free_set_NULL(stash);
-
-#if defined(LWS_WITH_HTTP2)
-	if (wsi->client_mux_substream)
-		wsi->h2.END_STREAM = wsi->h2.END_HEADERS = 0;
-#endif
-
-	*pwsi = lws_client_connect_2_dnsreq(wsi);
-
-	return *pwsi;
-
-bail:
-	lws_free_set_NULL(stash);
-
-	return NULL;
-}

+ 0 - 209
Source/ThirdParty/libwebsockets/lib/roles/http/date.c

@@ -1,209 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2020 Andy Green <[email protected]>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * RFC7231 date string generation and parsing
- */
-
-#include "private-lib-core.h"
-
-/*
- * To avoid needless pointers, we encode these in one string using the fact
- * they're 3 chars each to index it
- */
-
-static const char *const s =
-		"JanFebMarAprMayJunJulAugSepOctNovDecMonTueWedThuFriSatSun";
-
-static int
-lws_http_date_render(char *buf, size_t len, const struct tm *tm)
-{
-	const char *w = s + 36 + (3 * tm->tm_wday), *m = s + (3 * tm->tm_mon);
-
-	if (len < 29)
-		return -1;
-
-	lws_snprintf(buf, len, "%c%c%c, %02d %c%c%c %d %02d:%02d:%02d GMT",
-		     w[0], w[1], w[2], tm->tm_mday, m[0], m[1], m[2],
-		     1900 + tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec);
-
-	return 0;
-}
-
-
-int
-lws_http_date_render_from_unix(char *buf, size_t len, const time_t *t)
-{
-	struct tm *tm = gmtime(t);
-
-	if (lws_http_date_render(buf, len, tm))
-		return -1;
-
-	return 0;
-}
-
-static int
-lws_http_date_parse(const char *b, size_t len, struct tm *tm)
-{
-	int n;
-
-	if (len < 29)
-		return -1;
-
-	/*
-	 * We reject anything that isn't a properly-formatted RFC7231 date, eg
-	 *
-	 *     Tue, 15 Nov 1994 08:12:31 GMT
-	 */
-
-	if (b[3] != ','  || b[4] != ' '  || b[7] != ' '  || b[11] != ' ' ||
-	    b[16] != ' ' || b[19] != ':' || b[22] != ':' || b[25] != ' ' ||
-	    b[26] != 'G' || b[27] != 'M' || b[28] != 'T')
-		return -1;
-
-	memset(tm, 0, sizeof(*tm));
-
-	for (n = 36; n < 57; n += 3)
-		if (b[0] == s[n] && b[1] == s[n + 1] && b[2] == s[n + 2])
-			break;
-		else
-			tm->tm_wday++;
-
-	if (n == 57)
-		return -1;
-
-	for (n = 0; n < 36; n += 3)
-		if (b[8] == s[n] && b[9] == s[n + 1] && b[10] == s[n + 2])
-			break;
-		else
-			tm->tm_mon++;
-
-	if (n == 36)
-		return -1;
-
-	tm->tm_mday = atoi(b + 5);
-	n = atoi(b + 12);
-	if (n < 1900)
-		return -1;
-	tm->tm_year = n - 1900;
-
-	n = atoi(b + 17);
-	if (n < 0 || n > 23)
-		return -1;
-	tm->tm_hour = n;
-
-	n = atoi(b + 20);
-	if (n < 0 || n > 60)
-		return -1;
-	tm->tm_min = n;
-
-	n = atoi(b + 23);
-	if (n < 0 || n > 61) /* leap second */
-		return -1;
-	tm->tm_sec = n;
-
-	return 0;
-}
-
-int
-lws_http_date_parse_unix(const char *b, size_t len, time_t *t)
-{
-	struct tm tm;
-
-	if (lws_http_date_parse(b, len, &tm))
-		return -1;
-
-	*t = mktime(&tm);
-
-	return (int)*t == -1 ? -1 : 0;
-}
-
-#if defined(LWS_WITH_CLIENT)
-
-int
-lws_http_check_retry_after(struct lws *wsi, lws_usec_t *us_interval_in_out)
-{
-	size_t len = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_RETRY_AFTER);
-	char *p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_RETRY_AFTER);
-	lws_usec_t u;
-	time_t t, td;
-
-	if (!p)
-		return 1;
-
-	/*
-	 * There are two arg styles for RETRY_AFTER specified in RFC7231 7.1.3,
-	 * either a full absolute second-resolution date/time, or an integer
-	 * interval
-	 *
-	 *      Retry-After: Fri, 31 Dec 1999 23:59:59 GMT
-         *      Retry-After: 120
-	 */
-
-	if (len < 9)
-		u = ((lws_usec_t)(time_t)atoi(p)) * LWS_USEC_PER_SEC;
-	else {
-
-		if (lws_http_date_parse_unix(p, len, &t))
-			return 1;
-
-		/*
-		 * If possible, look for DATE from the server as well, so we
-		 * can calculate the interval it thinks it is giving us,
-		 * eliminating problems from server - client clock skew
-		 */
-
-		time(&td);
-		len = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_DATE);
-		if (len) {
-			p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_DATE);
-			/* if this fails, it leaves td as client time */
-			(void)lws_http_date_parse_unix(p, len, &td);
-		}
-
-		if (td >= t)
-			/*
-			 * if he's effectively giving us a 0 or negative
-			 * interval, just ignore the whole thing and keep the
-			 * incoming interval
-			 */
-			return 1;
-
-		u = ((lws_usec_t)(t - td)) * LWS_USEC_PER_SEC;
-	}
-
-	/*
-	 * We are only willing to increase the incoming interval, not
-	 * decrease it
-	 */
-
-	if (u < *us_interval_in_out)
-		/* keep the incoming interval */
-		return 1;
-
-	/* use the computed interval */
-	*us_interval_in_out = u;
-
-	return 0;
-}
-
-#endif

+ 1 - 17
Source/ThirdParty/libwebsockets/lib/roles/http/header.c

@@ -1,7 +1,7 @@
 /*
 /*
  * libwebsockets - small server side websockets and web server implementation
  * libwebsockets - small server side websockets and web server implementation
  *
  *
- * Copyright (C) 2010 - 2020 Andy Green <[email protected]>
+ * Copyright (C) 2010 - 2019 Andy Green <[email protected]>
  *
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to
  * of this software and associated documentation files (the "Software"), to
@@ -35,22 +35,6 @@ lws_token_to_string(enum lws_token_indexes token)
 	return (unsigned char *)set[token];
 	return (unsigned char *)set[token];
 }
 }
 
 
-/*
- * Return http header index if one matches slen chars of s, or -1
- */
-
-int
-lws_http_string_to_known_header(const char *s, size_t slen)
-{
-	int n;
-
-	for (n = 0; n < (int)LWS_ARRAY_SIZE(set); n++)
-		if (!strncmp(set[n], s, slen))
-			return n;
-
-	return -1;
-}
-
 int
 int
 lws_add_http_header_by_name(struct lws *wsi, const unsigned char *name,
 lws_add_http_header_by_name(struct lws *wsi, const unsigned char *name,
 			    const unsigned char *value, int length,
 			    const unsigned char *value, int length,

+ 0 - 9
Source/ThirdParty/libwebsockets/lib/roles/http/private-lib-roles-http.h

@@ -327,15 +327,6 @@ lws_sul_http_ah_lifecheck(lws_sorted_usec_list_t *sul);
 uint8_t *
 uint8_t *
 lws_http_multipart_headers(struct lws *wsi, uint8_t *p);
 lws_http_multipart_headers(struct lws *wsi, uint8_t *p);
 
 
-int
-lws_http_string_to_known_header(const char *s, size_t slen);
-
-int
-lws_http_date_render_from_unix(char *buf, size_t len, const time_t *t);
-
-int
-lws_http_date_parse_unix(const char *b, size_t len, time_t *t);
-
 enum {
 enum {
 	CCTLS_RETURN_ERROR		= -1,
 	CCTLS_RETURN_ERROR		= -1,
 	CCTLS_RETURN_DONE		= 0,
 	CCTLS_RETURN_DONE		= 0,

+ 1 - 1
Source/ThirdParty/libwebsockets/lib/roles/private-lib-roles.h

@@ -291,7 +291,7 @@ extern const struct lws_role_ops role_ops_raw_skt, role_ops_raw_file,
 #endif
 #endif
 
 
 #if defined(LWS_ROLE_H2)
 #if defined(LWS_ROLE_H2)
- #include "h2/private-lib-roles-h2.h"
+ #include "private-lib-roles-h2.h"
 #else
 #else
  #define lwsi_role_h2(wsi) (0)
  #define lwsi_role_h2(wsi) (0)
 #endif
 #endif

+ 1 - 1
Source/ThirdParty/libwebsockets/lib/roles/raw-proxy/ops-raw-proxy.c

@@ -111,7 +111,7 @@ try_pollout:
 	}
 	}
 
 
 #if defined(LWS_WITH_CLIENT)
 #if defined(LWS_WITH_CLIENT)
-	if (lws_http_client_socket_service(wsi, pollfd))
+	if (lws_client_socket_service(wsi, pollfd))
 		return LWS_HPI_RET_WSI_ALREADY_DIED;
 		return LWS_HPI_RET_WSI_ALREADY_DIED;
 #endif
 #endif
 
 

+ 1 - 0
Source/ThirdParty/libwebsockets/lib/roles/ws/client-parser-ws.c

@@ -554,6 +554,7 @@ drain_extension:
 				return -1;
 				return -1;
 			}
 			}
 			if (n == PMDR_DID_NOTHING)
 			if (n == PMDR_DID_NOTHING)
+				/* ie, not PMDR_NOTHING_WE_SHOULD_DO */
 				break;
 				break;
 #endif
 #endif
 			lwsl_ext("%s: post inflate ebuf in len %d / out len %d\n",
 			lwsl_ext("%s: post inflate ebuf in len %d / out len %d\n",

+ 12 - 2
Source/ThirdParty/libwebsockets/lib/roles/ws/ext/extension-permessage-deflate.c

@@ -192,10 +192,20 @@ lws_extension_callback_pm_deflate(struct lws_context *context,
 		lwsl_ext(" %s: LWS_EXT_CB_PAYLOAD_RX: in %d, existing in %d\n",
 		lwsl_ext(" %s: LWS_EXT_CB_PAYLOAD_RX: in %d, existing in %d\n",
 			 __func__, pmdrx->eb_in.len, priv->rx.avail_in);
 			 __func__, pmdrx->eb_in.len, priv->rx.avail_in);
 
 
-		/* if this frame is not marked as compressed, we ignore it */
+		/*
+		 * If this frame is not marked as compressed,
+		 * there is nothing we should do with it
+		 */
 
 
 		if (!(wsi->ws->rsv_first_msg & 0x40) || (wsi->ws->opcode & 8))
 		if (!(wsi->ws->rsv_first_msg & 0x40) || (wsi->ws->opcode & 8))
-			return PMDR_DID_NOTHING;
+			/*
+			 * This is a bit different than DID_NOTHING... we have
+			 * identified using ext-private bits in the packet, or
+			 * by it being a control fragment that we SHOULD not do
+			 * anything to it, parent should continue as if we
+			 * processed it
+			 */
+			return PMDR_NOTHING_WE_SHOULD_DO;
 
 
 		/*
 		/*
 		 * we shouldn't come back in here if we already applied the
 		 * we shouldn't come back in here if we already applied the

+ 4 - 2
Source/ThirdParty/libwebsockets/lib/roles/ws/ops-ws.c

@@ -633,6 +633,7 @@ drain_extension:
 				return -1;
 				return -1;
 			}
 			}
 			if (n == PMDR_DID_NOTHING)
 			if (n == PMDR_DID_NOTHING)
+				/* ie, not PMDR_NOTHING_WE_SHOULD_DO */
 				break;
 				break;
 #endif
 #endif
 			lwsl_debug("%s: post ext ret %d, ebuf in %d / out %d\n",
 			lwsl_debug("%s: post ext ret %d, ebuf in %d / out %d\n",
@@ -691,7 +692,8 @@ utf8_fail:
 
 
 			/* if pmd not enabled, in == out */
 			/* if pmd not enabled, in == out */
 
 
-			if (n == PMDR_DID_NOTHING
+			if (n == PMDR_DID_NOTHING ||
+			    n == PMDR_NOTHING_WE_SHOULD_DO
 #if !defined(LWS_WITHOUT_EXTENSIONS)
 #if !defined(LWS_WITHOUT_EXTENSIONS)
 				       	||
 				       	||
 			    n == PMDR_UNKNOWN
 			    n == PMDR_UNKNOWN
@@ -979,7 +981,7 @@ rops_handle_POLLIN_ws(struct lws_context_per_thread *pt, struct lws *wsi,
 			return LWS_HPI_RET_PLEASE_CLOSE_ME;
 			return LWS_HPI_RET_PLEASE_CLOSE_ME;
 		}
 		}
 
 
-		n = lws_http_client_socket_service(wsi, pollfd);
+		n = lws_client_socket_service(wsi, pollfd);
 		if (n)
 		if (n)
 			return LWS_HPI_RET_WSI_ALREADY_DIED;
 			return LWS_HPI_RET_WSI_ALREADY_DIED;
 #endif
 #endif

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.