diff -Nru libwebsockets-4.0.20/appveyor.yml libwebsockets-4.1.6/appveyor.yml --- libwebsockets-4.0.20/appveyor.yml 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/appveyor.yml 1970-01-01 00:00:00.000000000 +0000 @@ -1,77 +0,0 @@ -environment: - matrix: - - LWS_METHOD: jose - CMAKE_ARGS: -DLWS_WITH_JOSE=1 - - - LWS_METHOD: x64 - CMAKE_ARGS: -DCMAKE_GENERATOR_PLATFORM=x64 -DLWS_WITH_HTTP2=1 -DLWS_WITH_PLUGINS=1 -DLIBUV_INCLUDE_DIRS=C:\assets\libuv64\include -DLIBUV_LIBRARIES=C:\assets\libuv64\libuv.lib - - - LWS_METHOD: lwsws - CMAKE_ARGS: -DLWS_WITH_LWSWS=1 -DSQLITE3_INCLUDE_DIRS=C:\assets\sqlite3 -DSQLITE3_LIBRARIES=C:\assets\sqlite3\sqlite3.lib -DLIBUV_INCLUDE_DIRS=C:\assets\libuv\include -DLIBUV_LIBRARIES=C:\assets\libuv\libuv.lib - - - LWS_METHOD: default - - - LWS_METHOD: noserver - CMAKE_ARGS: -DLWS_WITHOUT_SERVER=ON - - - LWS_METHOD: noclient - CMAKE_ARGS: -DLWS_WITHOUT_CLIENT=ON - - - LWS_METHOD: noext - CMAKE_ARGS: -DLWS_WITHOUT_EXTENSIONS=ON - - - LWS_METHOD: nossl - CMAKE_ARGS: -DLWS_WITH_SSL=OFF - -install: - - appveyor DownloadFile https://libwebsockets.org:444/win-libuv.zip - - mkdir c:\assets - - mkdir c:\assets\libuv - - 7z x -oc:\assets\libuv win-libuv.zip - - appveyor DownloadFile https://libwebsockets.org:444/win-libuv64.zip - - mkdir c:\assets\libuv64 - - 7z x -oc:\assets\libuv64 win-libuv64.zip - - appveyor DownloadFile https://libwebsockets.org:444/nsis-3.0rc1-setup.exe - - cmd /c start /wait nsis-3.0rc1-setup.exe /S /D=C:\nsis - - appveyor DownloadFile https://libwebsockets.org:444/sqlite-dll-win32-x86-3130000.zip - - mkdir c:\assets\sqlite3 - - 7z x -oc:\assets\sqlite3 sqlite-dll-win32-x86-3130000.zip - - SET PATH=C:\Program Files\NSIS\;C:\Program Files (x86)\NSIS\;c:\nsis;%PATH% - -build_script: - - md build - - cd build - - cmake -DCMAKE_BUILD_TYPE=Release %CMAKE_ARGS% .. - - cmake --build . --config Release - -after_build: - - cd %APPVEYOR_BUILD_FOLDER% - - mkdir staging - - mkdir staging\include - - cp -r %APPVEYOR_BUILD_FOLDER%\build\bin %APPVEYOR_BUILD_FOLDER%\build\lib staging - - if EXIST staging\bin\share mv staging\bin\share staging - - if NOT EXIST staging\share\libwebsockets-test-server mkdir staging\share\libwebsockets-test-server - - IF EXIST %APPVEYOR_BUILD_FOLDER%\build\libwebsockets-test-server.pem cp %APPVEYOR_BUILD_FOLDER%\build\libwebsockets-test-server.pem staging\share\libwebsockets-test-server - - IF EXIST %APPVEYOR_BUILD_FOLDER%\build\libwebsockets-test-server.key.pem cp %APPVEYOR_BUILD_FOLDER%\build\libwebsockets-test-server.key.pem staging\share\libwebsockets-test-server - - IF EXIST %APPVEYOR_BUILD_FOLDER%\build\lws_config.h cp %APPVEYOR_BUILD_FOLDER%\build\lws_config.h staging\include - - cp %APPVEYOR_BUILD_FOLDER%\include\libwebsockets.h staging\include - - cp -r %APPVEYOR_BUILD_FOLDER%\include\libwebsockets staging\include - - 7z a build\lws-%LWS_METHOD%-%APPVEYOR_BUILD_ID%.zip %APPVEYOR_BUILD_FOLDER%\staging\* - -artifacts: - - path: build\lws-%LWS_METHOD%-%APPVEYOR_BUILD_ID%.zip - -#deploy: -#- provider: BinTray -# username: lws-team -# api_key: -# secure: nDpZ7P/wrk98DwJPMC6KpCC23QrVP8f3RxvKzBaqOmb9LiVrg1IyO1cc5vcgShZC -# subject: lws-team -# repo: libwebsockets -# package: windows -# publish: true -# override: true -# explode: false - -matrix: - fast_finish: true diff -Nru libwebsockets-4.0.20/bug_report.md libwebsockets-4.1.6/bug_report.md --- libwebsockets-4.0.20/bug_report.md 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/bug_report.md 2020-12-01 17:40:26.000000000 +0000 @@ -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. + diff -Nru libwebsockets-4.0.20/changelog libwebsockets-4.1.6/changelog --- libwebsockets-4.0.20/changelog 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/changelog 2020-12-01 17:40:26.000000000 +0000 @@ -1,6 +1,98 @@ Changelog --------- +v4.1.0 +====== + + - NEW: travis / appveyor / bintray are replaced by Sai + https://libwebsockets.org/sai/ which for lws currently does 193 builds per + git push on 16 platforms, all self-hosted. The homebrew bash scripts used + to select Minimal examples are replaced by CTest. Platforms currently + include Fedora/AMD/GCC, Windows/AMD/mingw32, Windows/AMD/mingw64, Android/ + aarch64/LLVM, esp-idf (on WROVER-KIT and HELTEC physical boards), Fedora/ + RISCV (on QEMU)/GCC, CentOS8/AMD/GCC, Gentoo/AMD/GCC, Bionic/AMD/GCC, + Linkit 7697, Focal/AMD/GCC, Windows (on QEMU)/AMD/MSVC, + Focal/aarch64-RPI4/GCC, iOS/aarch64/LLVM and OSX/AMD/LLVM. + + - NEW: The single CMakeLists.txt has been refactored and modernized into smaller + CMakeLists.txt in the subdirectory along with the code that is being managed + for build by it. Build options are still listed in the top level as before + but the new way is much more maintainable. + + - NEW: event lib support on Unix is now built into dynamically loaded plugins + and brought in at runtime, allowing all of the support to be built in + isolation without conflicts, and separately packaged with individual + dependencies. See ./READMEs/event-libs.md for details and how to force + the old static build into lws method. + + - NEW: Captive Portal Detection. Lws can determine if the active default + route is able to connect to the internet, or is in a captive portal type + situation, by trying to connect to a remote server that will respond in an + unusual way, like provide a 204. + + - NEW: Secure streams: Support system trust store if it exists + Build on Windows + Support lws raw socket protocol in SS + Support Unix Domain Socket transport + + - NEW: Windows: Support Unix Domain Sockets same as other platforms + + - NEW: Windows: Build using native pthreads, async dns, ipv6 on MSVC + + - NEW: lws_struct: BLOB support + + - NEW: lws_sul: Now provides two sorted timer domains, a default one as + before, and another whose scheduled events are capable to wake the system from suspend + + - NEW: System Message Distribution: lws_smd provides a very lightweight way + to pass short messages between subsystems both in RTOS type case where the + subsystems are all on the lws event loop, and in the case participants are in + different processes, using Secure Streams proxying. Participants register a bitmap + of message classes they care about; if no particpant cares about a particular message, + it is rejected at allocation time for the sender, making it cheap to provide messages + speculatively. See lib/system/smd/README.md for full details. + + - NEW: lws_drivers: wrappers for SDK driver abstractions (or actual drivers) + See lib/drivers/README.md, example implementations + minimal-examples/embedded/esp32/esp-wrover-kit + - generic gpio + - generic LED (by name) lib/drivers/led/README.md + - generic PWM, sophisticated interpolated table + sequencers with crossfade + - generic button (by name), with debounce and press classification + emitting rich SMD click, long-click, double-click, + down, repeat, up JSON messages + lib/drivers/button/README.md + - bitbang i2c on generic gpio (hw support can use same + abstract API) + - bitbang spi on generic gpio (hw support can use same + abstract API) + - generic display object, can be wired up to controller + drivers that hook up by generic i2c or spi, + generic backlight PWM sequencing and + blanking timer support + - generic settings storage: get and set blobs by name + - generic network device: netdev abstract class with + WIFI / Ethernet implementations + using underlying SDK APIs; + generic 80211 Scan managements + and credentials handling via + lws_settings + This is the new way to provide embedded platform + functionality that was in the past done like + esp32-factory. Unlike the old way, the new way has no + native apis in it and can be built on other SDK / SoCs + the same. + + - NEW: Security-aware JWS JWT (JSON Web Tokens) apis are provided on top of the existing + JOSE / JWS apis. All the common algorithms are available along with some + high level apis like lws http cookie -> JWT struct -> lws http cookie. + + - REMOVED: esp32-helper and friends used by esp32-factory now lws_drivers + exists + + - REMOVED: generic sessions and friends now JWT is provided + v4.0.0 ====== diff -Nru libwebsockets-4.0.20/cmake/FindLibWebSockets.cmake libwebsockets-4.1.6/cmake/FindLibWebSockets.cmake --- libwebsockets-4.0.20/cmake/FindLibWebSockets.cmake 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/cmake/FindLibWebSockets.cmake 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -# This module tries to find libWebsockets library and include files -# -# LIBWEBSOCKETS_INCLUDE_DIR, path where to find libwebsockets.h -# LIBWEBSOCKETS_LIBRARY_DIR, path where to find libwebsockets.so -# LIBWEBSOCKETS_LIBRARIES, the library to link against -# LIBWEBSOCKETS_FOUND, If false, do not try to use libWebSockets -# -# This currently works probably only for Linux - -FIND_PATH ( LIBWEBSOCKETS_INCLUDE_DIR libwebsockets.h - /usr/local/include - /usr/include -) - -FIND_LIBRARY ( LIBWEBSOCKETS_LIBRARIES websockets - /usr/local/lib - /usr/lib -) - -GET_FILENAME_COMPONENT( LIBWEBSOCKETS_LIBRARY_DIR ${LIBWEBSOCKETS_LIBRARIES} PATH ) - -SET ( LIBWEBSOCKETS_FOUND "NO" ) -IF ( LIBWEBSOCKETS_INCLUDE_DIR ) - IF ( LIBWEBSOCKETS_LIBRARIES ) - SET ( LIBWEBSOCKETS_FOUND "YES" ) - ENDIF ( LIBWEBSOCKETS_LIBRARIES ) -ENDIF ( LIBWEBSOCKETS_INCLUDE_DIR ) - -MARK_AS_ADVANCED( - LIBWEBSOCKETS_LIBRARY_DIR - LIBWEBSOCKETS_INCLUDE_DIR - LIBWEBSOCKETS_LIBRARIES -) \ No newline at end of file diff -Nru libwebsockets-4.0.20/cmake/FindOpenSSLbins.cmake libwebsockets-4.1.6/cmake/FindOpenSSLbins.cmake --- libwebsockets-4.0.20/cmake/FindOpenSSLbins.cmake 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/cmake/FindOpenSSLbins.cmake 2020-12-01 17:40:26.000000000 +0000 @@ -1,42 +1,102 @@ - -if(OPENSSL_FOUND) - - find_program(OPENSSL_EXECUTABLE openssl openssl.exe bin/openssl.exe - HINTS ${_OPENSSL_ROOT_HINTS} - PATH - /usr/bin/ - bin/ - DOC "Openssl executable") - - mark_as_advanced(OPENSSL_EXECUTABLE) - - # On Windows, we need to copy the OpenSSL dlls - # to the output directory. - if(WIN32) - set(OPENSSL_BIN_FOUND 0) - - find_file(LIBEAY_BIN - NAMES - libeay32.dll - HINTS - ${_OPENSSL_ROOT_HINTS} - PATH_SUFFIXES - bin) - - find_file(SSLEAY_BIN - NAMES - ssleay32.dll - HINTS - ${_OPENSSL_ROOT_HINTS} - PATH_SUFFIXES - bin) - - if(LIBEAY_BIN) - if(SSLEAY_BIN) - set(OPENSSL_BIN_FOUND 1) - endif(SSLEAY_BIN) - endif(LIBEAY_BIN) - endif(WIN32) - -endif(OPENSSL_FOUND) - + +if(OPENSSL_FOUND) + + find_program(OPENSSL_EXECUTABLE openssl openssl.exe bin/openssl.exe + HINTS ${_OPENSSL_ROOT_HINTS} + PATH + /usr/bin/ + bin/ + DOC "Openssl executable") + + mark_as_advanced(OPENSSL_EXECUTABLE) + + # On Windows, we need to copy the OpenSSL dlls + # to the output directory. + # BUT only if non-static libs (referencing dlls) are used + # In this case + # ** we only want to find dlls that are compatible with the libs + # the assumption is that these are part of the same OpenSSL package + # and typically reside in the same or in a close by directory as the executable + # ** we do NOT want to find dlls in general dll directories such as C:\Windows\systemXX + # because these IN GENERAL are not compatible with the libs + if(WIN32 AND OPENSSL_VERSION) + set(OPENSSL_BIN_FOUND 0) + + # we check for OpenSSL versioning, as described in https://wiki.openssl.org/index.php/Versioning + string(REGEX MATCH "^([0-9]+)\\.([0-9]+)\\.(.*)$" REGEX_MATCH ${OPENSSL_VERSION}) + + if (NOT ${REGEX_MATCH} EQUAL "") + + message(DEBUG "Assuming OpenSSL release ${OPENSSL_VERSION} >= 1.1.0 for dll discovery") + + # the regex matched - so we assume OpenSSL release >= 1.1 + set(OVNR "${CMAKE_MATCH_1}") # OpenSSL version number + set(ORNR "${CMAKE_MATCH_2}") # OpenSSL release number + set(CRYPTO32_NAME "libcrypto-${OVNR}_${ORNR}.dll") + set(CRYPTO64_NAME "libcrypto-${OVNR}_${ORNR}-x64.dll") + message(VERBOSE "CRYPTO32_NAME=${CRYPTO32_NAME}") + message(VERBOSE "CRYPTO64_NAME=${CRYPTO64_NAME}") + set(SSL32_NAME "libssl-${OVNR}_${ORNR}.dll") + set(SSL64_NAME "libssl-${OVNR}_${ORNR}-x64.dll") + message(VERBOSE "SSL32_NAME=${SSL32_NAME}") + message(VERBOSE "SSL64_NAME=${SSL64_NAME}") + + get_filename_component(OPENSSL_EXECUTABLE_PATH ${OPENSSL_EXECUTABLE} DIRECTORY) + message(VERBOSE "OPENSSL_EXECUTABLE_PATH=${OPENSSL_EXECUTABLE_PATH}") + set(OPENSSL_EXECUTABLE_BIN_PATH "") + string(REGEX MATCH "^(.*)/tools/openssl$" REGEX_MATCH ${OPENSSL_EXECUTABLE_PATH}) + message(DEBUG "REGEX_MATCH=\"${REGEX_MATCH}\"") + message(DEBUG "CMAKE_MATCH_1=\"${CMAKE_MATCH_1}\"") + if (NOT ${REGEX_MATCH} EQUAL "") + set(OPENSSL_EXECUTABLE_BIN_PATH "${CMAKE_MATCH_1}/bin") # bin path of this openssl variant + endif() + message(VERBOSE "OPENSSL_EXECUTABLE_BIN_PATH=${OPENSSL_EXECUTABLE_BIN_PATH}") + + unset(LIBCRYPTO_BIN) # clear + unset(LIBCRYPTO_BIN CACHE) # clear as well, because otherwise find_file might use it + find_file(LIBCRYPTO_BIN + NO_DEFAULT_PATH + NAMES ${CRYPTO32_NAME} ${CRYPTO64_NAME} + PATHS ${OPENSSL_EXECUTABLE_PATH} ${OPENSSL_EXECUTABLE_BIN_PATH} + ) + message(VERBOSE "LIBCRYPTO_BIN=${LIBCRYPTO_BIN}") + + unset(LIBSSL_BIN) # clear + unset(LIBSSL_BIN CACHE) # clear as well, because otherwise find_file might use it + find_file(LIBSSL_BIN + NO_DEFAULT_PATH + NAMES ${SSL32_NAME} ${SSL64_NAME} + PATHS ${OPENSSL_EXECUTABLE_PATH} ${OPENSSL_EXECUTABLE_BIN_PATH} + ) + message(VERBOSE "LIBSSL_BIN=${LIBSSL_BIN}") + + else() # the version regex did not match + + # as a fallback, we check for "old" OpenSSL library (used before OpenSSL 1.1.0) + + find_file(LIBCRYPTO_BIN + NAMES + libeay32.dll + HINTS + ${_OPENSSL_ROOT_HINTS} + PATH_SUFFIXES + bin) + + find_file(LIBSSL_BIN + NAMES + ssleay32.dll + HINTS + ${_OPENSSL_ROOT_HINTS} + PATH_SUFFIXES + bin) + + endif() + + if(LIBCRYPTO_BIN AND LIBSSL_BIN) + set(OPENSSL_BIN_FOUND 1) + endif() + + endif(WIN32) + +endif(OPENSSL_FOUND) + diff -Nru libwebsockets-4.0.20/cmake/libwebsockets-config.cmake.in libwebsockets-4.1.6/cmake/libwebsockets-config.cmake.in --- libwebsockets-4.0.20/cmake/libwebsockets-config.cmake.in 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/cmake/libwebsockets-config.cmake.in 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,23 @@ +# - Config file for lws + +# It defines the following variables +# LIBWEBSOCKETS_INCLUDE_DIRS - include directories for FooBar +# LIBWEBSOCKETS_LIBRARIES - libraries to link against + +# Get the path of the current file. +get_filename_component(LWS_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) + +# Set the include directories. +set(LIBWEBSOCKETS_INCLUDE_DIRS "@LWS__INCLUDE_DIRS@") + +# Include the project Targets file, this contains definitions for IMPORTED targets. +include(${LWS_CMAKE_DIR}/LibwebsocketsTargets.cmake) + +# IMPORTED targets from LibwebsocketsTargets.cmake +set(LIBWEBSOCKETS_LIBRARIES websockets websockets_shared) + +# These are additional libs that lws wants your app to also link to +foreach(item "@LIB_LIST_AT_END@") + list(APPEND LIBWEBSOCKETS_DEP_LIBS ${item}) +endforeach() + diff -Nru libwebsockets-4.0.20/cmake/LibwebsocketsConfig.cmake.in libwebsockets-4.1.6/cmake/LibwebsocketsConfig.cmake.in --- libwebsockets-4.0.20/cmake/LibwebsocketsConfig.cmake.in 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/cmake/LibwebsocketsConfig.cmake.in 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -# - Config file for the Libevent package -# It defines the following variables -# LIBWEBSOCKETS_INCLUDE_DIRS - include directories for FooBar -# LIBWEBSOCKETS_LIBRARIES - libraries to link against - -# Get the path of the current file. -get_filename_component(LWS_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) - -# Set the include directories. -set(LIBWEBSOCKETS_INCLUDE_DIRS "@LWS__INCLUDE_DIRS@") - -# Include the project Targets file, this contains definitions for IMPORTED targets. -include(${LWS_CMAKE_DIR}/LibwebsocketsTargets.cmake) - -# IMPORTED targets from LibwebsocketsTargets.cmake -set(LIBWEBSOCKETS_LIBRARIES websockets websockets_shared) - diff -Nru libwebsockets-4.0.20/cmake/libwebsockets-config-version.cmake.in libwebsockets-4.1.6/cmake/libwebsockets-config-version.cmake.in --- libwebsockets-4.0.20/cmake/libwebsockets-config-version.cmake.in 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/cmake/libwebsockets-config-version.cmake.in 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,11 @@ +set(PACKAGE_VERSION "@CPACK_PACKAGE_VERSION@") + +# Check whether the requested PACKAGE_FIND_VERSION is compatible +if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}") + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else() + set(PACKAGE_VERSION_COMPATIBLE TRUE) + if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}") + set(PACKAGE_VERSION_EXACT TRUE) + endif() +endif() diff -Nru libwebsockets-4.0.20/cmake/LibwebsocketsConfigVersion.cmake.in libwebsockets-4.1.6/cmake/LibwebsocketsConfigVersion.cmake.in --- libwebsockets-4.0.20/cmake/LibwebsocketsConfigVersion.cmake.in 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/cmake/LibwebsocketsConfigVersion.cmake.in 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -set(PACKAGE_VERSION "@CPACK_PACKAGE_VERSION@") - -# Check whether the requested PACKAGE_FIND_VERSION is compatible -if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}") - set(PACKAGE_VERSION_COMPATIBLE FALSE) -else() - set(PACKAGE_VERSION_COMPATIBLE TRUE) - if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}") - set(PACKAGE_VERSION_EXACT TRUE) - endif() -endif() diff -Nru libwebsockets-4.0.20/cmake/LwsCheckRequirements.cmake libwebsockets-4.1.6/cmake/LwsCheckRequirements.cmake --- libwebsockets-4.0.20/cmake/LwsCheckRequirements.cmake 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/cmake/LwsCheckRequirements.cmake 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,76 @@ +# If we are being built as part of lws, confirm current build config supports +# reqconfig, else skip building ourselves. +# +# If we are being built externally, confirm installed lws was configured to +# support reqconfig, else error out with a helpful message about the problem. +# +MACRO(require_lws_config reqconfig _val result) + + if (DEFINED ${reqconfig}) + if (${reqconfig}) + set (rq 1) + else() + set (rq 0) + endif() + else() + set(rq 0) + endif() + + if (${_val} EQUAL ${rq}) + set(SAME 1) + else() + set(SAME 0) + endif() + + if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) + if (${_val}) + message("${SAMP}: skipping as lws being built without ${reqconfig}") + else() + message("${SAMP}: skipping as lws built with ${reqconfig}") + endif() + set(${result} 0) + else() + if (LWS_WITH_MINIMAL_EXAMPLES) + set(MET ${SAME}) + else() + CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) + if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) + set(HAS_${reqconfig} 0) + else() + set(HAS_${reqconfig} 1) + endif() + if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) + set(MET 1) + else() + set(MET 0) + endif() + endif() + if (NOT MET) + if (${_val}) + message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") + else() + message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") + endif() + endif() + + endif() +ENDMACRO() + +MACRO(require_pthreads result) + CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) + if (NOT LWS_HAVE_PTHREAD_H) + if (LWS_WITH_MINIMAL_EXAMPLES) + set(${result} 0) + message("${SAMP}: skipping as no pthreads") + else() + message(FATAL_ERROR "threading support requires pthreads") + endif() + else() + if (WIN32) + set(PTHREAD_LIB ${LWS_EXT_PTHREAD_LIBRARIES}) + else() + set(PTHREAD_LIB pthread) + endif() + endif() +ENDMACRO() + diff -Nru libwebsockets-4.0.20/cmake/lws_config.h.in libwebsockets-4.1.6/cmake/lws_config.h.in --- libwebsockets-4.0.20/cmake/lws_config.h.in 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/cmake/lws_config.h.in 2020-12-01 17:40:26.000000000 +0000 @@ -7,17 +7,23 @@ #endif #define LWS_INSTALL_DATADIR "${CMAKE_INSTALL_PREFIX}/share" +#define LWS_INSTALL_LIBDIR "${CMAKE_INSTALL_PREFIX}/${LWS_INSTALL_LIB_DIR}${LIB_SUFFIX}" #define LWS_LIBRARY_VERSION_MAJOR ${LWS_LIBRARY_VERSION_MAJOR} #define LWS_LIBRARY_VERSION_MINOR ${LWS_LIBRARY_VERSION_MINOR} +#define LWS_LIBRARY_VERSION_PATCH_ELABORATED ${LWS_LIBRARY_VERSION_PATCH_ELABORATED} #define LWS_LIBRARY_VERSION_PATCH ${LWS_LIBRARY_VERSION_PATCH} + /* LWS_LIBRARY_VERSION_NUMBER looks like 1005001 for e.g. version 1.5.1 */ #define LWS_LIBRARY_VERSION_NUMBER (LWS_LIBRARY_VERSION_MAJOR * 1000000) + \ (LWS_LIBRARY_VERSION_MINOR * 1000) + \ LWS_LIBRARY_VERSION_PATCH #define LWS_MAX_SMP ${LWS_MAX_SMP} +#cmakedefine LWS_ESP_PLATFORM #cmakedefine LWS_LIBRARY_VERSION_NUMBER +#cmakedefine LWS_EXT_PTHREAD_LIBRARIES + #cmakedefine LWS_AVOID_SIGPIPE_IGN #cmakedefine LWS_BUILD_HASH "${LWS_BUILD_HASH}" #cmakedefine LWS_BUILTIN_GETIFADDRS @@ -41,13 +47,17 @@ #cmakedefine LWS_HAVE_EVP_aes_256_cfb8 #cmakedefine LWS_HAVE_EVP_aes_256_cfb128 #cmakedefine LWS_HAVE_EVP_aes_128_xts +#cmakedefine LWS_HAVE_EVP_PKEY_new_raw_private_key #cmakedefine LWS_HAVE_EXECVPE #cmakedefine LWS_HAVE_LIBCAP #cmakedefine LWS_HAVE_HMAC_CTX_new #cmakedefine LWS_HAVE_MALLOC_H #cmakedefine LWS_HAVE_MALLOC_TRIM #cmakedefine LWS_HAVE_MALLOC_USABLE_SIZE +#cmakedefine LWS_HAVE_mbedtls_md_setup #cmakedefine LWS_HAVE_mbedtls_net_init +#cmakedefine LWS_HAVE_mbedtls_rsa_complete +#cmakedefine LWS_HAVE_mbedtls_internal_aes_encrypt #cmakedefine LWS_HAVE_mbedtls_ssl_conf_alpn_protocols #cmakedefine LWS_HAVE_mbedtls_ssl_get_alpn_protocol #cmakedefine LWS_HAVE_mbedtls_ssl_conf_sni @@ -63,6 +73,8 @@ #cmakedefine LWS_HAVE_RSA_SET0_KEY #cmakedefine LWS_HAVE_RSA_verify_pss_mgf1 #cmakedefine LWS_HAVE_SSL_CTX_get0_certificate +#cmakedefine LWS_HAVE_SSL_CTX_load_verify_file +#cmakedefine LWS_HAVE_SSL_CTX_load_verify_dir #cmakedefine LWS_HAVE_SSL_CTX_set1_param #cmakedefine LWS_HAVE_SSL_CTX_set_ciphersuites #cmakedefine LWS_HAVE_SSL_EXTRA_CHAIN_CERTS @@ -113,6 +125,7 @@ #cmakedefine LWS_WITH_DEPRECATED_LWS_DLL #cmakedefine LWS_WITH_DETAILED_LATENCY #cmakedefine LWS_WITH_DIR +#cmakedefine LWS_WITH_DRIVERS #cmakedefine LWS_WITH_ESP32 #cmakedefine LWS_HAVE_EVBACKEND_LINUXAIO #cmakedefine LWS_HAVE_EVBACKEND_IOURING @@ -127,6 +140,7 @@ #cmakedefine LWS_WITH_HTTP2 #cmakedefine LWS_WITH_HTTP_BASIC_AUTH #cmakedefine LWS_WITH_HTTP_BROTLI +#cmakedefine LWS_HTTP_HEADERS_ALL #cmakedefine LWS_WITH_HTTP_PROXY #cmakedefine LWS_WITH_HTTP_STREAM_COMPRESSION #cmakedefine LWS_WITH_HTTP_UNCOMMON_HEADERS @@ -154,18 +168,22 @@ #cmakedefine LWS_WITH_SECURE_STREAMS #cmakedefine LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM #cmakedefine LWS_WITH_SECURE_STREAMS_PROXY_API +#cmakedefine LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY #cmakedefine LWS_WITH_SELFTESTS #cmakedefine LWS_WITH_SEQUENCER #cmakedefine LWS_WITH_SERVER_STATUS +#cmakedefine LWS_WITH_SYS_SMD #cmakedefine LWS_WITH_SMTP #cmakedefine LWS_WITH_SOCKS5 #cmakedefine LWS_WITH_STATEFUL_URLDECODE #cmakedefine LWS_WITH_STATS #cmakedefine LWS_WITH_STRUCT_SQLITE3 #cmakedefine LWS_WITH_STRUCT_JSON +#cmakedefine LWS_WITH_SUL_DEBUGGING #cmakedefine LWS_WITH_SQLITE3 #cmakedefine LWS_WITH_SYS_NTPCLIENT #cmakedefine LWS_WITH_SYS_DHCP_CLIENT +#cmakedefine LWS_WITH_SYS_STATE #cmakedefine LWS_WITH_THREADPOOL #cmakedefine LWS_WITH_TLS #cmakedefine LWS_WITH_UDP @@ -173,5 +191,8 @@ #cmakedefine LWS_WITH_ZIP_FOPS #cmakedefine USE_OLD_CYASSL #cmakedefine USE_WOLFSSL +#cmakedefine LWS_WITH_EVENT_LIBS +#cmakedefine LWS_WITH_EVLIB_PLUGINS +#cmakedefine LWS_WITH_LIBUV_INTERNAL +#cmakedefine LWS_WITH_PLUGINS_API -${LWS_SIZEOFPTR_CODE} diff -Nru libwebsockets-4.0.20/cmake/lws_config_private.h.in libwebsockets-4.1.6/cmake/lws_config_private.h.in --- libwebsockets-4.0.20/cmake/lws_config_private.h.in 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/cmake/lws_config_private.h.in 2020-12-01 17:40:26.000000000 +0000 @@ -5,17 +5,12 @@ #define _DEBUG #endif #endif +#cmakedefine LWIP_PROVIDE_ERRNO /* Define to 1 to use CyaSSL as a replacement for OpenSSL. * LWS_OPENSSL_SUPPORT needs to be set also for this to work. */ #cmakedefine USE_CYASSL -/* Define to 1 if you have the header file. */ -#cmakedefine LWS_HAVE_DLFCN_H - -/* Define to 1 if you have the header file. */ -#cmakedefine LWS_HAVE_FCNTL_H - /* Define to 1 if you have the `fork' function. */ #cmakedefine LWS_HAVE_FORK @@ -32,19 +27,9 @@ /* Define to 1 if you have the header file. */ #cmakedefine LWS_HAVE_MEMORY_H -/* Define to 1 if you have the `memset' function. */ -#cmakedefine LWS_HAVE_MEMSET - /* Define to 1 if you have the header file. */ #cmakedefine LWS_HAVE_NETINET_IN_H -/* Define to 1 if your system has a GNU libc compatible `realloc' function, - and to 0 otherwise. */ -#cmakedefine LWS_HAVE_REALLOC - -/* Define to 1 if you have the `socket' function. */ -#cmakedefine LWS_HAVE_SOCKET - /* Define to 1 if you have the header file. */ #cmakedefine LWS_HAVE_STDINT_H @@ -63,6 +48,9 @@ /* Define to 1 if you have the header file. */ #cmakedefine LWS_HAVE_SYS_PRCTL_H +/* Define to 1 if you have the header file. */ +#cmakedefine LWS_HAVE_SYS_RESOURCE_H + /* Define to 1 if you have the header file. */ #cmakedefine LWS_HAVE_SYS_SOCKET_H diff -Nru libwebsockets-4.0.20/CMakeLists-implied-options.txt libwebsockets-4.1.6/CMakeLists-implied-options.txt --- libwebsockets-4.0.20/CMakeLists-implied-options.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/CMakeLists-implied-options.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,418 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# This part of the CMakeLists.txt defines internal logic between options + +if(IOS) + set(LWS_DETECTED_PLAT_IOS 1) +endif() + +# Workaround for ESP-IDF +# Detect ESP_PLATFORM environment flag, if exist, set LWS_WITH_ESP32. +# Otherwise the user may not be able to run configuration ESP-IDF in the first time. +if (ESP_PLATFORM) + message(STATUS "ESP-IDF enabled") + set(LWS_WITH_ESP32 ON) + set(LWS_WITH_ZLIB OFF) + set(LWS_HAVE_mbedtls_ssl_get_alpn_protocol 1) +else() + set(LWS_WITH_ESP32_HELPER OFF) +endif() + +if (LWS_WITH_ESP32) + set(LWS_PLAT_FREERTOS 1) +endif() + +if (LWS_PLAT_OPTEE) + set(LWS_WITH_UDP 0) +endif() + +if (LWS_PLAT_FREERTOS) + message(STATUS "No LWS_WITH_DIR or LWS_WITH_LEJP_CONF") + set(LWS_WITH_DIR OFF) + set(LWS_WITH_LEJP_CONF OFF) + message("LWS_WITH_DIR ${LWS_WITH_DIR}") +else() + message(STATUS "Compiled with LWS_WITH_DIR and LWS_WITH_LEJP_CONF") + set(LWS_WITH_DIR ON) + set(LWS_WITH_LEJP_CONF ON) +endif() + +if (LWS_FOR_GITOHASHI) + set(LWS_WITH_THREADPOOL 1) + set(LWS_WITH_HTTP2 1) + set(LWS_UNIX_SOCK 1) + set(LWS_WITH_HTTP_PROXY 1) + set(LWS_WITH_FTS 1) + set(LWS_WITH_DISKCACHE 1) + set(LWS_WITH_LWSAC 1) + set(LWS_WITH_LEJP_CONF 1) + set(LWS_WITH_SPAWN 1) + set(LWS_WITH_FSMOUNT 1) + set(LWS_WITH_STRUCT_JSON 1) + set(LWS_WITH_STRUCT_SQLITE3 1) +endif() + +if(LWS_WITH_DISTRO_RECOMMENDED) + set(LWS_WITH_HTTP2 1) # selfcontained + set(LWS_WITH_LWSWS 1) # libuv + set(LWS_WITH_CGI 1) # selfcontained + set(LWS_IPV6 1) # selfcontained + set(LWS_WITH_ZIP_FOPS 1) # libz + set(LWS_WITH_SOCKS5 1) # selfcontained + set(LWS_WITH_RANGES 1) # selfcontained + set(LWS_WITH_ACME 1) # selfcontained / tls + set(LWS_WITH_SERVER_STATUS 1) # selfcontained + set(LWS_WITH_GLIB 1) # glib + set(LWS_WITH_LIBUV 1) # libuv + set(LWS_WITH_LIBEV 1) # libev + set(LWS_WITH_LIBEVENT 1) # libevent + set(LWS_WITH_EVLIB_PLUGINS 1) # event libraries created as plugins / individual packages + set(LWS_WITHOUT_EXTENSIONS 0) # libz + set(LWS_ROLE_DBUS 1) # dbus-related libs + set(LWS_WITH_FTS 1) # selfcontained + set(LWS_WITH_THREADPOOL 1) # pthreads + set(LWS_UNIX_SOCK 1) # selfcontained + set(LWS_WITH_HTTP_PROXY 1) # selfcontained + set(LWS_WITH_DISKCACHE 1) # selfcontained + set(LWS_WITH_LWSAC 1) # selfcontained + set(LWS_WITH_LEJP_CONF 1) # selfcontained + set(LWS_WITH_PLUGINS 1) # libdl + set(LWS_ROLE_RAW_PROXY 1) # selfcontained + set(LWS_WITH_GENCRYPTO 1) # selfcontained / tls + set(LWS_WITH_JOSE 1) # selfcontained + set(LWS_WITH_STRUCT_JSON 1) # selfcontained + set(LWS_WITH_STRUCT_SQLITE3 1) # sqlite3 + set(LWS_WITH_SPAWN 1) # selfcontained +# libmount is problematic on Centos 8 / RHEL 8 +# set(LWS_WITH_FSMOUNT 1) + set(LWS_ROLE_MQTT 1) # selfcontained + set(LWS_WITH_SECURE_STREAMS 1) # selfcontained + set(LWS_WITH_SECURE_STREAMS_PROXY_API 1) # selfcontained + set(LWS_WITH_DIR 1) # selfcontained +endif() + +# LWS_WITH_EVENT_LIBS is set if any event lib selected + +if (LWS_WITH_LIBEV OR + LWS_WITH_LIBUV OR + LWS_WITH_LIBEVENT OR + LWS_WITH_GLIB) + set(LWS_WITH_EVENT_LIBS 1) +else() + unset(LWS_WITH_EVENT_LIBS) +endif() + +if (LWS_WITH_SECURE_STREAMS_PROXY_API) + set(LWS_WITH_LWS_DSH 1) + set(LWS_WITH_UNIX_SOCK 1) +endif() + +if (NOT LWS_WITH_NETWORK) + set(LWS_ROLE_MQTT 0) + set(LWS_ROLE_H1 0) + set(LWS_ROLE_WS 0) + set(LWS_ROLE_RAW 0) + set(LWS_WITHOUT_EXTENSIONS 1) + set(LWS_WITHOUT_SERVER 1) + set(LWS_WITHOUT_CLIENT 1) + set(LWS_WITH_HTTP2 0) + set(LWS_WITH_SOCKS5 0) + set(LWS_UNIX_SOCK 0) + set(LWS_WITH_HTTP_PROXY 0) + set(LWS_WITH_PLUGINS 0) + set(LWS_WITH_LWSWS 0) + set(LWS_WITH_CGI 0) + set(LWS_ROLE_RAW_PROXY 0) + set(LWS_WITH_PEER_LIMITS 0) + set(LWS_WITH_HTTP_STREAM_COMPRESSION 0) + set(LWS_WITH_HTTP_BROTLI 0) + set(LWS_WITH_POLL 0) + set(LWS_WITH_SEQUENCER 0) + set(LWS_ROLE_DBUS 0) + set(LWS_WITH_LWS_DSH 0) + set(LWS_WITH_THREADPOOL 0) + set(LWS_WITH_SYS_SMD 0) +endif() + +if (LWS_WITH_CGI) + set(LWS_WITH_SPAWN 1) +endif() + +if (LWS_WITH_STRUCT_SQLITE3) + set(LWS_WITH_SQLITE3 1) +endif() + +if (LWS_WITH_HTTP_BASIC_AUTH) + # WWW_AUTHENTICATE used by basic auth is an "uncommon header" + set(LWS_WITH_HTTP_UNCOMMON_HEADERS 1) +endif() + +if (APPLE) + set(LWS_ROLE_DBUS 0) +endif() + +if(NOT DEFINED CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type") +endif() + +if (LWS_PLAT_FREERTOS) + set(LWS_UNIX_SOCK 0) +endif() + +if (LWS_PLAT_FREERTOS) + set(LWS_WITH_FTS 0) +endif() + +if (LWS_WITH_HTTP2) + set(LWS_ROLE_H2 1) +endif() +if (LWS_WITH_CGI) + set(LWS_ROLE_CGI 1) +endif() + +if (NOT LWS_ROLE_WS) + set(LWS_WITHOUT_EXTENSIONS 1) +endif() + +unset(LWS_WITH_LIBUV_INTERNAL) + +if (LWS_WITH_LWSWS) + message(STATUS "LWS_WITH_LWSWS --> Enabling LWS_WITH_PLUGINS and LWS_WITH_LIBUV") + set(LWS_WITH_PLUGINS 1) + set(LWS_WITH_LIBUV 1) + set(LWS_WITH_LIBUV_INTERNAL 1) + set(LWS_WITH_EVENT_LIBS 1) # implied by LIBUV_INTERNAL + set(LWS_WITH_ACCESS_LOG 1) + set(LWS_WITH_SERVER_STATUS 1) + set(LWS_WITH_LEJP 1) + set(LWS_WITH_LEJP_CONF 1) + set(LWS_WITH_PEER_LIMITS 1) + set(LWS_ROLE_RAW_PROXY 1) +endif() + +# sshd plugin +if (LWS_WITH_PLUGINS) + set(LWS_WITH_GENCRYPTO 1) +endif() + +if (LWS_ROLE_RAW_PROXY) + set (LWS_WITH_CLIENT 1) + set (LWS_WITH_SERVER 1) +endif() + +if (LWS_WITH_ACME) + set (LWS_WITH_CLIENT 1) + set (LWS_WITH_SERVER 1) + set (LWS_WITH_JOSE 1) +endif() + +if (LWS_WITH_JOSE) + set(LWS_WITH_LEJP 1) + set(LWS_WITH_GENCRYPTO 1) +endif() + +if (LWS_WITH_PLUGINS AND NOT LWS_WITH_LIBUV) +message(STATUS "LWS_WITH_PLUGINS --> Enabling LWS_WITH_LIBUV") + set(LWS_WITH_LIBUV 1) + set(LWS_WITH_EVENT_LIBS 1) +endif() + +if (LWS_WITH_PLUGINS OR LWS_WITH_CGI) + # sshd plugin + set(LWS_WITH_GENCRYPTO 1) +endif() + +if (LWS_PLAT_FREERTOS) + set(LWS_WITH_SHARED OFF) + if (LWS_WITH_SSL) + set(LWS_WITH_MBEDTLS ON) + endif() + # set(LWS_WITHOUT_CLIENT ON) + set(LWS_WITHOUT_TESTAPPS ON) + set(LWS_WITHOUT_EXTENSIONS ON) + set(LWS_WITH_PLUGINS OFF) + set(LWS_WITH_RANGES ON) + # this implies no pthreads in the lib + set(LWS_MAX_SMP 1) + set(LWS_HAVE_MALLOC 1) + set(LWS_HAVE_REALLOC 1) + set(LWS_HAVE_GETIFADDRS 1) + set(LWS_WITH_CUSTOM_HEADERS 0) +endif() + +#if (LWS_WITH_ESP32) +# set(LWS_WITH_ZIP_FOPS 1) +#endif() + +if (WIN32) +set(LWS_MAX_SMP 1) +if (LWS_WITH_PLUGINS) +set(LWS_WITH_LIBUV_INTERNAL 1) +endif() +endif() + +if (LWS_WITHOUT_SERVER) +set(LWS_WITH_LWSWS OFF) +endif() + +if (LWS_WITH_LEJP_CONF) + set(LWS_WITH_DIR 1) +endif() + +# confirm H1 relationships + +if (NOT LWS_ROLE_H1 AND LWS_ROLE_H2) + message(FATAL_ERROR "H2 requires LWS_ROLE_H1") +endif() + +if (NOT LWS_ROLE_H1 AND LWS_ROLE_WS) + message(FATAL_ERROR "WS requires LWS_ROLE_H1") +endif() + +if (NOT LWS_ROLE_H1 AND LWS_ROLE_CGI) + message(FATAL_ERROR "CGI requires LWS_ROLE_H1") +endif() + +# confirm HTTP relationships + +if (NOT LWS_ROLE_H1 AND NOT LWS_ROLE_H2 AND LWS_WITH_HTTP_PROXY) + message(FATAL_ERROR "LWS_WITH_LWSWS requires LWS_ROLE_H1") +endif() + +if (NOT LWS_ROLE_H1 AND NOT LWS_ROLE_H2 AND LWS_WITH_HTTP_PROXY) + message(FATAL_ERROR "LWS_WITH_HTTP_PROXY requires LWS_ROLE_H1") +endif() + +if (NOT LWS_ROLE_H1 AND NOT LWS_ROLE_H2 AND LWS_WITH_RANGES) + message(FATAL_ERROR "LWS_WITH_RANGES requires LWS_ROLE_H1") +endif() + +if (NOT LWS_ROLE_H1 AND NOT LWS_ROLE_H2 AND LWS_WITH_ACCESS_LOG) + message(FATAL_ERROR "LWS_WITH_ACCESS_LOG requires LWS_ROLE_H1") +endif() + +if (LWS_WITH_HTTP_PROXY AND (LWS_WITHOUT_CLIENT OR LWS_WITHOUT_SERVER)) + message("You have to enable both client and server for http proxy") + set(LWS_WITH_HTTP_PROXY 0) +endif() + +if (NOT LWS_WITHOUT_EXTENSIONS OR LWS_WITH_ZIP_FOPS) + set(LWS_WITH_ZLIB 1) +endif() + +if (LWS_WITH_SECURE_STREAMS) + set(LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM 1) +endif() + +if (NOT (LWS_WITH_STATIC OR LWS_WITH_SHARED)) + message(FATAL_ERROR "Makes no sense to compile with neither static nor shared libraries.") +endif() + +if (LWS_WITHOUT_DAEMONIZE OR WIN32) + set(LWS_NO_DAEMONIZE 1) +endif() + +if (LWS_WITH_LIBEV) + set(LWS_WITH_LIBEV 1) +endif() + +if (LWS_WITH_LIBUV) + set(LWS_WITH_LIBUV 1) +endif() + +if (LWS_WITH_LIBEVENT) + set(LWS_WITH_LIBEVENT 1) +endif() + +if (LWS_IPV6) + set(LWS_WITH_IPV6 1) +endif() + +if (LWS_UNIX_SOCK) + set(LWS_WITH_UNIX_SOCK 1) +endif() + +if (NOT LWS_MAX_SMP) + set(LWS_MAX_SMP 1) +endif() +if ("${LWS_MAX_SMP}" STREQUAL "") + set(LWS_MAX_SMP 1) +endif() + +set(LWS_WITH_CLIENT 1) +if (LWS_WITHOUT_CLIENT) + set(LWS_WITH_CLIENT) + set(LWS_WITH_SECURE_STREAMS 0) +endif() +set(LWS_WITH_SERVER 1) +if (LWS_WITHOUT_SERVER) + set(LWS_WITH_SERVER) +endif() + +# using any abstract protocol enables LWS_WITH_ABSTRACT + +#if (LWS_WITH_SMTP) +# set(LWS_WITH_ABSTRACT 1) +#endif() + +if (NOT LWS_WITH_EVLIB_PLUGINS AND (LWS_WITH_LIBEV AND LWS_WITH_LIBEVENT)) + message(FATAL_ERROR "Sorry libev and libevent conflict with each others' namespace, you can only have one or the other") +endif() + +if (LWS_SSL_SERVER_WITH_ECDH_CERT) + set(LWS_SSL_SERVER_WITH_ECDH_CERT 1) +endif() + +# LWS_OPENSSL_SUPPORT deprecated... use LWS_WITH_TLS +if (LWS_WITH_SSL OR LWS_WITH_MBEDTLS) + set(LWS_OPENSSL_SUPPORT 1) + set(LWS_WITH_TLS 1) +endif() + +if (NOT LWS_WITH_SSL) + set(LWS_WITHOUT_BUILTIN_SHA1 OFF) +endif() +# protocol plugins dont make any sense either +if (LWS_WITH_PLUGINS AND NOT LWS_WITH_SHARED) + message("Deselecting PLUGINS since building static") + set(LWS_WITH_PLUGINS 0) +endif() + + +# if we're only building static, we don't want event lib plugins +# +if (LWS_WITH_EVLIB_PLUGINS AND NOT LWS_WITH_SHARED) + message("Deselecting EVLIB_PLUGINS since building static") + set(LWS_WITH_EVLIB_PLUGINS 0) +endif() + +if (LWS_WITH_PLUGINS OR (LWS_WITH_EVLIB_PLUGINS AND LWS_WITH_EVENT_LIBS)) + set(LWS_WITH_PLUGINS_API 1) +endif() + +if (WIN32 AND NOT LWS_EXT_PTHREAD_LIBRARIES) + message("SMD requires pthreads") + set(LWS_WITH_SYS_SMD 0) +endif() + diff -Nru libwebsockets-4.0.20/CMakeLists.txt libwebsockets-4.1.6/CMakeLists.txt --- libwebsockets-4.0.20/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,9 +1,48 @@ -cmake_minimum_required(VERSION 2.8.9) +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# + +cmake_minimum_required(VERSION 2.8.12) +include(CheckFunctionExists) +include(CheckSymbolExists) +include(CheckIncludeFile) +include(CheckIncludeFiles) +include(CheckLibraryExists) +include(CheckTypeSize) +include(CheckCSourceCompiles) -if(POLICY CMP0048) +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 @@ -17,8 +56,15 @@ set(LWS_ROLE_RAW 1) set(LWS_WITH_POLL 1) +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) # # Select features recommended for PC distro packaging @@ -27,6 +73,11 @@ option(LWS_FOR_GITOHASHI "Enable features recommended for use with gitohashi" OFF) # +# Compiler features +# +option(DISABLE_WERROR "Avoid treating compiler warnings as fatal errors" OFF) + +# # Major individual features # option(LWS_WITH_NETWORK "Compile with network-related code" ON) @@ -40,12 +91,11 @@ option(LWS_WITH_LWSWS "Libwebsockets Webserver" OFF) option(LWS_WITH_CGI "Include CGI (spawn process with network-connected stdin/out/err) APIs" OFF) option(LWS_IPV6 "Compile with support for ipv6" OFF) -option(LWS_UNIX_SOCK "Compile with support for UNIX domain socket" OFF) -option(LWS_WITH_PLUGINS "Support plugins for protocols and extensions" OFF) +option(LWS_UNIX_SOCK "Compile with support for UNIX domain socket if OS supports it" ON) +option(LWS_WITH_PLUGINS "Support plugins for protocols and extensions (implies LWS_WITH_PLUGINS_API)" OFF) option(LWS_WITH_HTTP_PROXY "Support for active HTTP proxying" OFF) option(LWS_WITH_ZIP_FOPS "Support serving pre-zipped files" OFF) option(LWS_WITH_SOCKS5 "Allow use of SOCKS5 proxy on client connections" OFF) -option(LWS_WITH_GENERIC_SESSIONS "With the Generic Sessions plugin" OFF) option(LWS_WITH_PEER_LIMITS "Track peers and restrict resources a single peer can allocate" OFF) option(LWS_WITH_ACCESS_LOG "Support generating Apache-compatible access logs" OFF) option(LWS_WITH_RANGES "Support http ranges (RFC7233)" OFF) @@ -63,6 +113,8 @@ option(LWS_WITH_SYS_DHCP_CLIENT "Build in tiny DHCP client" OFF) option(LWS_WITH_HTTP_BASIC_AUTH "Support Basic Auth" ON) option(LWS_WITH_HTTP_UNCOMMON_HEADERS "Include less common http header support" ON) +option(LWS_WITH_SYS_STATE "lws_system state support" ON) +option(LWS_WITH_SYS_SMD "Lws System Message Distribution" ON) # # Secure Streams @@ -70,6 +122,19 @@ option(LWS_WITH_SECURE_STREAMS "Secure Streams protocol-agnostic API" OFF) option(LWS_WITH_SECURE_STREAMS_PROXY_API "Secure Streams support to work across processes" OFF) option(LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM "Auth support for api.amazon.com" OFF) +option(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY "Secure Streams Policy is hardcoded only" OFF) + +# +# CTest options +# +# +# If you build with LWS_WITH_MINIMAL_EXAMPLES, you can use CTest / make test to run +# examples that can give a pass/fail response. By default it runs tests both against +# a local server peer and warmcat.com, if your CI wants to do the tests but does not +# have internet routing, then you can still run a subset of tests with CTest / make +# test that only does local tests by disabling this option. +# +option(LWS_CTEST_INTERNET_AVAILABLE "CTest will performs tests that need the Internet" ON) # # TLS library options... all except mbedTLS are basically OpenSSL variants. @@ -88,6 +153,19 @@ option(LWS_WITH_LIBEVENT "Compile with support for libevent" OFF) option(LWS_WITH_GLIB "Compile with support for glib event loop" OFF) +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() +# +# LWS Drivers +# + +option(LWS_WITH_DRIVERS "With generic drivers for gpio, i2c, display etc" OFF) + # # Static / Dynamic build options # @@ -99,7 +177,6 @@ # Specific platforms # option(LWS_WITH_ESP32 "Build for ESP32" OFF) -option(LWS_WITH_ESP32_HELPER "Build ESP32 helper" OFF) option(LWS_PLAT_OPTEE "Build for OPTEE" OFF) option(LWS_PLAT_FREERTOS "Build for FreeRTOS" OFF) option(LWS_PLAT_ANDROID "Android flavour of unix platform" OFF) @@ -132,7 +209,7 @@ option(LWS_WITH_STRUCT_SQLITE3 "Generic struct serialization to and from SQLITE3" OFF) # broken atm #option(LWS_WITH_SMTP "Provide SMTP support" OFF) -if (WIN32 OR 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) else() @@ -156,13 +233,12 @@ option(LWS_WITH_CUSTOM_HEADERS "Store and allow querying custom HTTP headers (H1 only)" ON) option(LWS_WITH_DISKCACHE "Hashed cache directory with lazy LRU deletion to size limit" OFF) option(LWS_WITH_ASAN "Build with gcc runtime sanitizer options enabled (needs libasan)" OFF) -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_ZLIB "Include zlib support (required for extensions)" OFF) option(LWS_WITH_BUNDLED_ZLIB "Use bundled zlib version (Windows only)" ${LWS_WITH_BUNDLED_ZLIB_DEFAULT}) option(LWS_WITH_MINIZ "Use miniz instead of zlib" OFF) -option(LWS_WITH_DEPRECATED_LWS_DLL "Migrate to lws_dll2 instead ASAP" OFF) -option(LWS_WITH_SEQUENCER "lws_seq_t support" ON) +option(LWS_WITH_DEPRECATED_THINGS "Temporary workaround for deprecated apis" OFF) +option(LWS_WITH_SEQUENCER "lws_seq_t support" OFF) option(LWS_WITH_EXTERNAL_POLL "Support external POLL integration using callback messages (not recommended)" OFF) option(LWS_WITH_LWS_DSH "Support lws_dsh_t Disordered Shared Heap" OFF) option(LWS_CLIENT_HTTP_PROXYING "Support external http proxies for client connections" ON) @@ -171,7 +247,10 @@ option(LWS_WITH_UDP "Platform supports UDP" ON) option(LWS_WITH_SPAWN "Spawn subprocesses with piped stdin/out/stderr" OFF) option(LWS_WITH_FSMOUNT "Overlayfs and fallback mounting apis" OFF) - +option(LWS_WITH_FANALYZER "Enable gcc -fanalyzer if compiler supports" OFF) +option(LWS_HTTP_HEADERS_ALL "Override header reduction optimization and include all like older lws versions" OFF) +option(LWS_WITH_SUL_DEBUGGING "Enable zombie lws_sul checking on object deletion" OFF) +option(LWS_WITH_PLUGINS_API "Build generic lws_plugins apis (see LWS_WITH_PLUGINS to also build protocol plugins)" OFF) # # to use miniz, enable both LWS_WITH_ZLIB and LWS_WITH_MINIZ @@ -179,189 +258,50 @@ # End of user settings # -if(IOS) - set(LWS_DETECTED_PLAT_IOS 1) -endif() - -# Workaround for ESP-IDF -# Detect ESP_PLATFORM environment flag, if exist, set LWS_WITH_ESP32. -# Otherwise the user may not be able to run configuration ESP-IDF in the first time. -if(ESP_PLATFORM) - message(STATUS "ESP-IDF enabled") - set(LWS_WITH_ESP32 ON) -else() - set(LWS_WITH_ESP32_HELPER OFF) -endif() - -if (LWS_WITH_ESP32) - set(LWS_PLAT_FREERTOS 1) -endif() - -if (LWS_PLAT_FREERTOS OR LWS_PLAT_OPTEE) - set(LWS_WITH_UDP 0) -endif() - -if (WIN32 OR LWS_PLAT_FREERTOS) - message(STATUS "No LWS_WITH_DIR or LWS_WITH_LEJP_CONF") - set(LWS_WITH_DIR OFF) - set(LWS_WITH_LEJP_CONF OFF) - message("LWS_WITH_DIR ${LWS_WITH_DIR}") -else() - message(STATUS "Compiled with LWS_WITH_DIR and LWS_WITH_LEJP_CONF") - set(LWS_WITH_DIR ON) - set(LWS_WITH_LEJP_CONF ON) -endif() - -if (LWS_FOR_GITOHASHI) - set(LWS_WITH_THREADPOOL 1) - set(LWS_WITH_HTTP2 1) - set(LWS_UNIX_SOCK 1) - set(LWS_WITH_HTTP_PROXY 1) - set(LWS_WITH_FTS 1) - set(LWS_WITH_DISKCACHE 1) - set(LWS_WITH_LWSAC 1) - set(LWS_WITH_LEJP_CONF 1) - set(LWS_WITH_SPAWN 1) - set(LWS_WITH_FSMOUNT 1) - set(LWS_WITH_STRUCT_JSON 1) - set(LWS_WITH_STRUCT_SQLITE3 1) -endif() - -if(LWS_WITH_DISTRO_RECOMMENDED) - set(LWS_WITH_HTTP2 1) - set(LWS_WITH_LWSWS 1) - set(LWS_WITH_CGI 1) - set(LWS_IPV6 1) - set(LWS_WITH_ZIP_FOPS 1) - set(LWS_WITH_SOCKS5 1) - set(LWS_WITH_RANGES 1) - set(LWS_WITH_ACME 1) - set(LWS_WITH_SERVER_STATUS 1) - set(LWS_WITH_GLIB 1) - set(LWS_WITH_LIBUV 1) - set(LWS_WITH_LIBEV 1) - # libev + libevent cannot coexist at build-time - set(LWS_WITH_LIBEVENT 0) - set(LWS_WITHOUT_EXTENSIONS 0) - set(LWS_ROLE_DBUS 1) - set(LWS_WITH_FTS 1) - set(LWS_WITH_THREADPOOL 1) - set(LWS_UNIX_SOCK 1) - set(LWS_WITH_HTTP_PROXY 1) - set(LWS_WITH_DISKCACHE 1) - set(LWS_WITH_LWSAC 1) - set(LWS_WITH_LEJP_CONF 1) - set(LWS_WITH_PLUGINS 1) - set(LWS_ROLE_RAW_PROXY 1) - set(LWS_WITH_GENCRYPTO 1) - set(LWS_WITH_JOSE 1) - set(LWS_WITH_STRUCT_JSON 1) - set(LWS_WITH_STRUCT_SQLITE3 1) - set(LWS_WITH_SPAWN 1) - set(LWS_WITH_FSMOUNT 1) - set(LWS_ROLE_MQTT 1) -endif() - -if (LWS_WITH_SECURE_STREAMS_PROXY_API) - set(LWS_WITH_LWS_DSH 1) - set(LWS_WITH_UNIX_SOCK 1) -endif() - -if (NOT LWS_WITH_NETWORK) - set(LWS_ROLE_MQTT 0) - set(LWS_ROLE_H1 0) - set(LWS_ROLE_WS 0) - set(LWS_ROLE_RAW 0) - set(LWS_WITHOUT_EXTENSIONS 1) - set(LWS_WITHOUT_SERVER 1) - set(LWS_WITHOUT_CLIENT 1) - set(LWS_WITH_HTTP2 0) - set(LWS_WITH_SOCKS5 0) - set(LWS_UNIX_SOCK 0) - set(LWS_WITH_HTTP_PROXY 0) - set(LWS_WITH_PLUGINS 0) - set(LWS_WITH_LWSWS 0) - set(LWS_WITH_CGI 0) - set(LWS_ROLE_RAW_PROXY 0) - set(LWS_WITH_PEER_LIMITS 0) - set(LWS_WITH_GENERIC_SESSIONS 0) - set(LWS_WITH_HTTP_STREAM_COMPRESSION 0) - set(LWS_WITH_HTTP_BROTLI 0) - set(LWS_WITH_POLL 0) - set(LWS_WITH_SEQUENCER 0) - set(LWS_ROLE_DBUS 0) - set(LWS_WITH_LWS_DSH 0) - set(LWS_WITH_THREADPOOL 0) -endif() - -if (LWS_WITH_CGI) - set(LWS_WITH_SPAWN 1) -endif() - -if (LWS_WITH_STRUCT_SQLITE3) - set(LWS_WITH_SQLITE3 1) -endif() - -# do you care about this? Then send me a patch where it disables it on travis -# but allows it on APPLE -if (APPLE) - set(LWS_ROLE_DBUS 0) -endif() - -if(NOT DEFINED CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type") -endif() - -# microsoft... that's why you can't have nice things - -if (WIN32 OR LWS_PLAT_FREERTOS) - set(LWS_UNIX_SOCK 0) -endif() - -if (LWS_PLAT_FREERTOS) - set(LWS_WITH_LWSAC 0) - set(LWS_WITH_FTS 0) -endif() - -set(PACKAGE "libwebsockets") -set(CPACK_PACKAGE_NAME "${PACKAGE}") -set(CPACK_PACKAGE_VERSION_MAJOR "4") -set(CPACK_PACKAGE_VERSION_MINOR "0") -set(CPACK_PACKAGE_VERSION_PATCH "20") -set(CPACK_PACKAGE_RELEASE 1) -set(CPACK_GENERATOR "RPM") -set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") -set(CPACK_PACKAGE_VENDOR "andy@warmcat.com") -set(CPACK_PACKAGE_CONTACT "andy@warmcat.com") -set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PACKAGE} ${PACKAGE_VERSION}") -set(SOVERSION "16") -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}") +# sets of sub-options implied by other options +# +set(LIB_LIST "") +set(LIB_LIST_AT_END) +set(LWS_LIBRARIES) +set(LWS_OPENSSL_SUPPORT 0) +include(CMakeLists-implied-options.txt) -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}) +# +# Structural helpers for cmake in subdirs +# -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/") +macro(add_subdir_include_directories arg1) + add_subdirectory(${arg1}) + include_directories(${_CMAKE_INC_LIST}) +endmacro() +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() +endmacro() -message(STATUS "CMAKE_TOOLCHAIN_FILE='${CMAKE_TOOLCHAIN_FILE}'") +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() -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() +# +# Try to find the current Git hash +# -# Try to find the current Git hash. find_package(Git) if(GIT_EXECUTABLE) execute_process( @@ -373,7 +313,7 @@ set(LWS_BUILD_HASH ${GIT_HASH}) # append the build user and hostname - if(NOT LWS_REPRODUCIBLE) + if (NOT LWS_REPRODUCIBLE) execute_process( WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" COMMAND "whoami" @@ -393,167 +333,74 @@ message("Git commit hash: ${LWS_BUILD_HASH}") endif() -# translate old functionality enables to set up ROLE enables so nothing changes -if (LWS_WITH_HTTP2 AND LWS_WITHOUT_SERVER) - set(LWS_WITH_HTTP2 0) - message("HTTP2 disabled due to LWS_WITHOUT_SERVER") -endif() - -if (LWS_WITH_HTTP2) - set(LWS_ROLE_H2 1) -endif() -if (LWS_WITH_CGI) - set(LWS_ROLE_CGI 1) -endif() - -if (NOT LWS_ROLE_WS) - set(LWS_WITHOUT_EXTENSIONS 1) -endif() - -if (LWS_WITH_MBEDTLS) - include_directories(lib/tls/mbedtls/wrapper/include) -endif() - -include_directories(include plugins lib/core lib/core-net lib/event-libs include/abstract lib/tls lib/roles lib/event-libs/libuv lib/event-libs/poll lib/event-libs/libevent lib/event-libs/glib lib/event-libs/libev lib/jose/jwe lib/jose/jws lib/jose lib/misc lib/roles/http lib/roles/http/compression lib/roles/h1 lib/roles/h2 lib/roles/ws lib/roles/cgi lib/roles/dbus lib/roles/raw-proxy lib/abstract lib/system/async-dns lib/roles/mqtt) - -if (LWS_WITH_SECURE_STREAMS) - set(LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM 1) -endif() - -if (LWS_PLAT_FREERTOS) - include_directories(lib/plat/freertos lib/plat/freertos/esp32) -else() - if (WIN32) - include_directories(lib/plat/windows) - else() - if (LWS_WITH_OPTEE) - include_directories(lib/plat/optee) - else() - include_directories(lib/plat/unix) - endif() - endif() -endif() - - -if (LWS_WITH_LWSWS) - message(STATUS "LWS_WITH_LWSWS --> Enabling LWS_WITH_PLUGINS and LWS_WITH_LIBUV") - set(LWS_WITH_PLUGINS 1) - set(LWS_WITH_LIBUV 1) - set(LWS_WITH_ACCESS_LOG 1) - set(LWS_WITH_SERVER_STATUS 1) - set(LWS_WITH_LEJP 1) - set(LWS_WITH_LEJP_CONF 1) - set(LWS_WITH_PEER_LIMITS 1) - set(LWS_ROLE_RAW_PROXY 1) -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 "6") -# sshd plugin -if (LWS_WITH_PLUGINS) - set(LWS_WITH_GENCRYPTO 1) -endif() +set(CPACK_PACKAGE_VERSION_PATCH "${CPACK_PACKAGE_VERSION_PATCH_NUMBER}-${LWS_BUILD_HASH}") +set(CPACK_PACKAGE_RELEASE 1) -if (LWS_ROLE_RAW_PROXY) - set (LWS_WITH_CLIENT 1) - set (LWS_WITH_SERVER 1) +set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") +set(CPACK_PACKAGE_VENDOR "andy@warmcat.com") +set(CPACK_PACKAGE_CONTACT "andy@warmcat.com") +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}") -if (LWS_WITH_ACME) - set (LWS_WITH_CLIENT 1) - set (LWS_WITH_SERVER 1) - set (LWS_WITH_JOSE 1) -endif() +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) -if (LWS_WITH_JOSE) - set(LWS_WITH_LEJP 1) - set(LWS_WITH_GENCRYPTO 1) -endif() -if (LWS_WITH_PLUGINS AND NOT LWS_WITH_LIBUV) -message(STATUS "LWS_WITH_PLUGINS --> Enabling LWS_WITH_LIBUV") - set(LWS_WITH_LIBUV 1) -endif() +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 (LWS_WITH_PLUGINS OR LWS_WITH_CGI) - # sshd plugin - set(LWS_WITH_GENCRYPTO 1) +if (NOT CMAKE_MODULE_PATH) + set(CMAKE_MODULE_PATH "") endif() +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/") -if (LWS_WITH_GENERIC_SESSIONS) - set(LWS_WITH_SQLITE3 1) - # set(LWS_WITH_SMTP 1) - set(LWS_WITH_STRUCT_SQLITE3 1) -endif() -if (LWS_PLAT_FREERTOS) - set(LWS_WITH_SHARED OFF) - set(LWS_WITH_MBEDTLS ON) - # set(LWS_WITHOUT_CLIENT ON) - set(LWS_WITHOUT_TESTAPPS ON) - set(LWS_WITHOUT_EXTENSIONS ON) - set(LWS_WITH_PLUGINS OFF) - set(LWS_WITH_RANGES ON) - # this implies no pthreads in the lib - set(LWS_MAX_SMP 1) - set(LWS_HAVE_MALLOC 1) - set(LWS_HAVE_REALLOC 1) - set(LWS_HAVE_GETIFADDRS 1) - set(LWS_WITH_CUSTOM_HEADERS 0) +if (CMAKE_TOOLCHAIN_FILE) + message(STATUS "CMAKE_TOOLCHAIN_FILE='${CMAKE_TOOLCHAIN_FILE}'") endif() -if (LWS_WITH_ESP32) - set(LWS_WITH_ZIP_FOPS 1) +if (NOT LIB_SUFFIX) + set(LIB_SUFFIX "") endif() if (WIN32) -set(LWS_MAX_SMP 1) -set(LWS_WITH_THREADPOOL 0) -endif() - -if (LWS_WITHOUT_SERVER) -set(LWS_WITH_LWSWS OFF) -endif() - -if (LWS_WITH_LEJP_CONF) - set(LWS_WITH_DIR 1) -endif() - -# confirm H1 relationships - -if (NOT LWS_ROLE_H1 AND LWS_ROLE_H2) - message(FATAL_ERROR "H2 requires LWS_ROLE_H1") -endif() - -if (NOT LWS_ROLE_H1 AND LWS_ROLE_WS) - message(FATAL_ERROR "WS requires LWS_ROLE_H1") -endif() - -if (NOT LWS_ROLE_H1 AND LWS_ROLE_CGI) - message(FATAL_ERROR "CGI requires LWS_ROLE_H1") -endif() - -# confirm HTTP relationships - -if (NOT LWS_ROLE_H1 AND NOT LWS_ROLE_H2 AND LWS_WITH_HTTP_PROXY) - message(FATAL_ERROR "LWS_WITH_LWSWS requires LWS_ROLE_H1") -endif() - -if (NOT LWS_ROLE_H1 AND NOT LWS_ROLE_H2 AND LWS_WITH_HTTP_PROXY) - message(FATAL_ERROR "LWS_WITH_HTTP_PROXY requires LWS_ROLE_H1") -endif() - -if (NOT LWS_ROLE_H1 AND NOT LWS_ROLE_H2 AND LWS_WITH_RANGES) - message(FATAL_ERROR "LWS_WITH_RANGES requires LWS_ROLE_H1") -endif() - -if (NOT LWS_ROLE_H1 AND NOT LWS_ROLE_H2 AND LWS_WITH_ACCESS_LOG) - message(FATAL_ERROR "LWS_WITH_ACCESS_LOG requires LWS_ROLE_H1") + 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() - -if (LWS_WITH_HTTP_PROXY AND (LWS_WITHOUT_CLIENT OR LWS_WITHOUT_SERVER)) - message("You have to enable both client and server for http proxy") - set(LWS_WITH_HTTP_PROXY 0) -endif() +include_directories(include) # Allow the user to override installation directories. set(LWS_INSTALL_LIB_DIR lib CACHE PATH "Installation directory for libraries") @@ -561,137 +408,25 @@ 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") -# Allow the user to use the old CyaSSL options/library in stead of wolfSSL -if (LWS_WITH_CYASSL AND LWS_WITH_WOLFSSL) - message(FATAL_ERROR "LWS_WITH_CYASSL and LWS_WITH_WOLFSSL are mutually exclusive!") -endif() -if (LWS_WITH_CYASSL) - # Copy CyaSSL options to the wolfSSL options - set(LWS_WITH_WOLFSSL ${LWS_WITH_CYASSL} CACHE BOOL "Use wolfSSL/CyaSSL instead of OpenSSL" FORCE) - set(LWS_WOLFSSL_LIBRARIES ${LWS_CYASSL_LIBRARIES} CACHE PATH "Path to wolfSSL/CyaSSL libraries" FORCE) - set(LWS_WOLFSSL_INCLUDE_DIRS ${LWS_CYASSL_INCLUDE_DIRS} CACHE PATH "Path to wolfSSL/CyaSSL header files" FORCE) -endif() - -if (NOT (LWS_WITH_STATIC OR LWS_WITH_SHARED)) - message(FATAL_ERROR "Makes no sense to compile with neither static nor shared libraries.") -endif() - -if (NOT LWS_WITHOUT_EXTENSIONS OR LWS_WITH_ZIP_FOPS) - set(LWS_WITH_ZLIB 1) -endif() - # 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_OPENSSL_LIBRARIES CACHE PATH "Path to the OpenSSL library") -set(LWS_OPENSSL_INCLUDE_DIRS CACHE PATH "Path to the OpenSSL include directory") -set(LWS_WOLFSSL_LIBRARIES CACHE PATH "Path to the wolfSSL library") -set(LWS_WOLFSSL_INCLUDE_DIRS CACHE PATH "Path to the wolfSSL include directory") -set(LWS_LIBEV_LIBRARIES CACHE PATH "Path to the libev library") -set(LWS_LIBEV_INCLUDE_DIRS CACHE PATH "Path to the libev include directory") -set(LWS_LIBUV_LIBRARIES CACHE PATH "Path to the libuv library") -set(LWS_LIBUV_INCLUDE_DIRS CACHE PATH "Path to the libuv 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_LIBEVENT_INCLUDE_DIRS CACHE PATH "Path to the libevent include directory") -set(LWS_LIBEVENT_LIBRARIES CACHE PATH "Path to the libevent library") -set(LWS_GLIB_INCLUDE_DIRS CACHE PATH "Path to the glib include directory") -set(LWS_GLIB_LIBRARIES CACHE PATH "Path to the glib library") 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 (NOT LWS_WITH_SSL) - set(LWS_WITHOUT_BUILTIN_SHA1 OFF) -endif() - -if (LWS_WITH_BORINGSSL) - # boringssl deprecated EVP_PKEY - set (LWS_WITH_GENHASH OFF) -endif() - -if (LWS_WITH_SSL AND NOT LWS_WITH_WOLFSSL AND NOT LWS_WITH_MBEDTLS) - if ("${LWS_OPENSSL_LIBRARIES}" STREQUAL "" OR "${LWS_OPENSSL_INCLUDE_DIRS}" STREQUAL "") - else() - if (NOT LWS_PLAT_FREERTOS) - set(OPENSSL_LIBRARIES ${LWS_OPENSSL_LIBRARIES}) - endif() - set(OPENSSL_INCLUDE_DIRS ${LWS_OPENSSL_INCLUDE_DIRS}) - set(OPENSSL_FOUND 1) - endif() -endif() - -if (LWS_WITH_SSL AND LWS_WITH_WOLFSSL) - if ("${LWS_WOLFSSL_LIBRARIES}" STREQUAL "" OR "${LWS_WOLFSSL_INCLUDE_DIRS}" STREQUAL "") - if (NOT WOLFSSL_FOUND) - if (LWS_WITH_CYASSL) - message(FATAL_ERROR "You must set LWS_CYASSL_LIBRARIES and LWS_CYASSL_INCLUDE_DIRS when LWS_WITH_CYASSL is turned on.") - else() - message(FATAL_ERROR "You must set LWS_WOLFSSL_LIBRARIES and LWS_WOLFSSL_INCLUDE_DIRS when LWS_WITH_WOLFSSL is turned on.") - endif() - endif() - else() - set(WOLFSSL_LIBRARIES ${LWS_WOLFSSL_LIBRARIES}) - set(WOLFSSL_INCLUDE_DIRS ${LWS_WOLFSSL_INCLUDE_DIRS}) - set(WOLFSSL_FOUND 1) - endif() - set(USE_WOLFSSL 1) - set(LWS_WITH_TLS 1) - if (LWS_WITH_CYASSL) - set(USE_OLD_CYASSL 1) - endif() -endif() - -if (LWS_WITH_SSL AND LWS_WITH_MBEDTLS) - if ("${LWS_MBEDTLS_LIBRARIES}" STREQUAL "" OR "${LWS_MBEDTLS_INCLUDE_DIRS}" STREQUAL "" AND NOT LWS_PLAT_FREERTOS) - - find_path(LWS_MBEDTLS_INCLUDE_DIRS mbedtls/ssl.h) - - find_library(MBEDTLS_LIBRARY mbedtls) - find_library(MBEDX509_LIBRARY mbedx509) - find_library(MBEDCRYPTO_LIBRARY mbedcrypto) - - set(LWS_MBEDTLS_LIBRARIES "${MBEDTLS_LIBRARY}" "${MBEDX509_LIBRARY}" "${MBEDCRYPTO_LIBRARY}") - - include(FindPackageHandleStandardArgs) - find_package_handle_standard_args(MBEDTLS DEFAULT_MSG - LWS_MBEDTLS_INCLUDE_DIRS MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY) - - mark_as_advanced(LWS_MBEDTLS_INCLUDE_DIRS MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY) - - if ("${LWS_MBEDTLS_LIBRARIES}" STREQUAL "" OR "${LWS_MBEDTLS_INCLUDE_DIRS}" STREQUAL "") - message(FATAL_ERROR "You must set LWS_MBEDTLS_LIBRARIES and LWS_MBEDTLS_INCLUDE_DIRS when LWS_WITH_MBEDTLS is turned on.") - endif() - endif() - set(MBEDTLS_LIBRARIES ${LWS_MBEDTLS_LIBRARIES}) - set(MBEDTLS_INCLUDE_DIRS ${LWS_MBEDTLS_INCLUDE_DIRS}) - set(MBEDTLS_FOUND 1) - set(USE_MBEDTLS 1) -endif() - if (LWS_WITH_HTTP_STREAM_COMPRESSION) set(LWS_WITH_ZLIB 1) endif() -if (LWS_WITH_FSMOUNT AND ${CMAKE_SYSTEM_NAME} STREQUAL "Linux") - if ("${LWS_LIBMOUNT_LIBRARIES}" STREQUAL "" OR "${LWS_LIBMOUNT_INCLUDE_DIRS}" STREQUAL "") - - # libmount paths (this is only on Linux) - # - find_path( LIBMOUNT_INC_PATH NAMES "libmount/libmount.h") - find_library(LIBMOUNT_LIB_PATH NAMES "mount") - else() - set(LIBMOUNT_INC_PATH ${LWS_LIBMOUNT_INCLUDE_DIRS}) - set(LIBMOUNT_LIB_PATH ${LWS_LIBMOUNT_LIBRARIES}) - endif() - - if (NOT LIBMOUNT_INC_PATH OR NOT LIBMOUNT_LIB_PATH) - message(FATAL_ERROR " Unable to find libmount") - endif() -endif() - if (LWS_WITH_ZLIB AND NOT LWS_WITH_BUNDLED_ZLIB) if ("${LWS_ZLIB_LIBRARIES}" STREQUAL "" OR "${LWS_ZLIB_INCLUDE_DIRS}" STREQUAL "") else() @@ -701,41 +436,6 @@ endif() endif() -if (LWS_WITH_LIBEV) - if ("${LWS_LIBEV_LIBRARIES}" STREQUAL "" OR "${LWS_LIBEV_INCLUDE_DIRS}" STREQUAL "") - else() - set(LIBEV_LIBRARIES ${LWS_LIBEV_LIBRARIES}) - set(LIBEV_INCLUDE_DIRS ${LWS_LIBEV_INCLUDE_DIRS}) - set(LIBEV_FOUND 1) - endif() -endif() - -if (LWS_WITH_LIBUV) - if ("${LWS_LIBUV_LIBRARIES}" STREQUAL "" OR "${LWS_LIBUV_INCLUDE_DIRS}" STREQUAL "") - else() - set(LIBUV_LIBRARIES ${LWS_LIBUV_LIBRARIES}) - set(LIBUV_INCLUDE_DIRS ${LWS_LIBUV_INCLUDE_DIRS}) - set(LIBUV_FOUND 1) - endif() -endif() - -if (LWS_WITH_LIBEVENT) - if ("${LWS_LIBEVENT_LIBRARIES}" STREQUAL "" OR "${LWS_LIBEVENT_INCLUDE_DIRS}" STREQUAL "") - else() - set(LIBEVENT_LIBRARIES ${LWS_LIBEVENT_LIBRARIES}) - set(LIBEVENT_INCLUDE_DIRS ${LWS_LIBEVENT_INCLUDE_DIRS}) - set(LIBEVENT_FOUND 1) - endif() -endif() - -if (LWS_WITH_GLIB) - if ("${LWS_GLIB_LIBRARIES}" STREQUAL "" OR "${LWS_GLIB_INCLUDE_DIRS}" STREQUAL "") - else() - set(LIBGLIB_LIBRARIES ${LWS_GLIB_LIBRARIES}) - set(LIBGLIB_INCLUDE_DIRS ${LWS_GLIB_INCLUDE_DIRS}) - set(LIBGLIB_FOUND 1) - endif() -endif() if (LWS_WITH_SQLITE3) if ("${LWS_SQLITE3_LIBRARIES}" STREQUAL "" OR "${LWS_SQLITE3_INCLUDE_DIRS}" STREQUAL "") @@ -746,152 +446,51 @@ endif() endif() +include_directories("${PROJECT_BINARY_DIR}") -if (LWS_WITH_LIBEV AND LWS_WITH_LIBEVENT) - message(FATAL_ERROR "Sorry libev and libevent conflict with each others' namespace, you can only have one or the other") -endif() - -# The base dir where the test-apps look for the SSL certs. -set(LWS_OPENSSL_CLIENT_CERTS ../share CACHE PATH "Server SSL certificate directory") -if (WIN32) - set(LWS_OPENSSL_CLIENT_CERTS . CACHE PATH "Client SSL certificate directory") +# Check for different inline keyword versions. +foreach(KEYWORD "inline" "__inline__" "__inline") + set(CMAKE_REQUIRED_DEFINITIONS "-DKEYWORD=${KEYWORD}") + CHECK_C_SOURCE_COMPILES( + " + #include + static KEYWORD void a() {} + int main(int argc, char **argv) { a(); return 0; } + " LWS_HAVE_${KEYWORD}) +endforeach() - if (LWS_UNIX_SOCK) - set(LWS_UNIX_SOCK OFF) - message(WARNING "Windows does not support UNIX domain sockets") +if (NOT LWS_HAVE_inline) + if (LWS_HAVE___inline__) + set(inline __inline__) + elseif(LWS_HAVE___inline) + set(inline __inline) endif() -else() - set(LWS_OPENSSL_CLIENT_CERTS /etc/pki/tls/certs/ CACHE PATH "Client SSL certificate directory") -endif() - -# LWS_OPENSSL_SUPPORT deprecated... use LWS_WITH_TLS -if (LWS_WITH_SSL OR LWS_WITH_MBEDTLS) - set(LWS_OPENSSL_SUPPORT 1) - set(LWS_WITH_TLS 1) endif() -if (LWS_SSL_CLIENT_USE_OS_CA_CERTS) - set(LWS_SSL_CLIENT_USE_OS_CA_CERTS 1) -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") -if (LWS_WITHOUT_DAEMONIZE OR WIN32) - set(LWS_NO_DAEMONIZE 1) -endif() +SET(LWS_INSTALL_PATH "${CMAKE_INSTALL_PREFIX}") -if (LWS_WITH_LIBEV) - set(LWS_WITH_LIBEV 1) -endif() +# 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_WITH_LIBUV) - set(LWS_WITH_LIBUV 1) +if (LWS_WITHOUT_BUILTIN_SHA1) + set(LWS_SHA1_USE_OPENSSL_NAME 1) endif() -if (LWS_WITH_LIBEVENT) - set(LWS_WITH_LIBEVENT 1) -endif() - -if (LWS_IPV6) - set(LWS_WITH_IPV6 1) -endif() - -if (LWS_UNIX_SOCK) - set(LWS_WITH_UNIX_SOCK 1) -endif() - -if (LWS_WITH_HTTP2) - set(LWS_WITH_HTTP2 1) -endif() - -if ("${LWS_MAX_SMP}" STREQUAL "") - set(LWS_MAX_SMP 1) -endif() - -set(LWS_WITH_CLIENT 1) -if (LWS_WITHOUT_CLIENT) - set(LWS_WITH_CLIENT) -endif() -set(LWS_WITH_SERVER 1) -if (LWS_WITHOUT_SERVER) - set(LWS_WITH_SERVER) -endif() - -# using any abstract protocol enables LWS_WITH_ABSTRACT - -#if (LWS_WITH_SMTP) -# set(LWS_WITH_ABSTRACT 1) -#endif() - - - -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 (LWS_SSL_SERVER_WITH_ECDH_CERT) - set(LWS_SSL_SERVER_WITH_ECDH_CERT 1) -endif() - -include_directories("${PROJECT_BINARY_DIR}") - -include(CheckCSourceCompiles) - -# Check for different inline keyword versions. -foreach(KEYWORD "inline" "__inline__" "__inline") - set(CMAKE_REQUIRED_DEFINITIONS "-DKEYWORD=${KEYWORD}") - CHECK_C_SOURCE_COMPILES( - " - #include - 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}") - -include(CheckFunctionExists) -include(CheckSymbolExists) -include(CheckIncludeFile) -include(CheckIncludeFiles) -include(CheckLibraryExists) -include(CheckTypeSize) -include(CheckCSourceCompiles) - -if (LWS_WITHOUT_BUILTIN_SHA1) - set(LWS_SHA1_USE_OPENSSL_NAME 1) -endif() - -if (HAIKU) - set(CMAKE_REQUIRED_LIBRARIES network) -endif() - -CHECK_C_SOURCE_COMPILES( - "#include - int main(int argc, char **argv) { return malloc_trim(0); } - " LWS_HAVE_MALLOC_TRIM) -CHECK_C_SOURCE_COMPILES( - "#include - int main(int argc, char **argv) { return (int)malloc_usable_size((void *)0); } - " LWS_HAVE_MALLOC_USABLE_SIZE) +CHECK_C_SOURCE_COMPILES( + "#include + int main(int argc, char **argv) { return malloc_trim(0); } + " LWS_HAVE_MALLOC_TRIM) +CHECK_C_SOURCE_COMPILES( + "#include + 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) @@ -911,7 +510,7 @@ CHECK_FUNCTION_EXISTS(_atoi64 LWS_HAVE__ATOI64) CHECK_FUNCTION_EXISTS(_stat32i64 LWS_HAVE__STAT32I64) CHECK_FUNCTION_EXISTS(clock_gettime LWS_HAVE_CLOCK_GETTIME) -CHECK_FUNCTION_EXISTS(eventfd LWS_HAVE_EVENTFD) + if (NOT LWS_HAVE_GETIFADDRS) if (LWS_WITHOUT_BUILTIN_GETIFADDRS) @@ -920,8 +519,31 @@ set(LWS_BUILTIN_GETIFADDRS 1) endif() -CHECK_INCLUDE_FILE(dlfcn.h LWS_HAVE_DLFCN_H) -CHECK_INCLUDE_FILE(fcntl.h LWS_HAVE_FCNTL_H) +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) @@ -940,66 +562,20 @@ 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) +CHECK_INCLUDE_FILE(sys/resource.h LWS_HAVE_SYS_RESOURCE_H) -CHECK_LIBRARY_EXISTS(cap cap_set_flag "" LWS_HAVE_LIBCAP) - -if (LWS_ROLE_DBUS) - - if (NOT LWS_DBUS_LIB) - set(LWS_DBUS_LIB "dbus-1") - endif() - - CHECK_LIBRARY_EXISTS(${LWS_DBUS_LIB} dbus_connection_set_watch_functions "" LWS_HAVE_LIBDBUS) - if (NOT LWS_HAVE_LIBDBUS) - message(FATAL_ERROR "Install dbus-devel, or libdbus-1-dev etc") - endif() - - if (NOT LWS_DBUS_INCLUDE1) - # look in fedora and debian / ubuntu place - if (EXISTS "/usr/include/dbus-1.0") - set(LWS_DBUS_INCLUDE1 "/usr/include/dbus-1.0") - else() - message(FATAL_ERROR "Set LWS_DBUS_INCLUDE1 to /usr/include/dbus-1.0 or wherever the main dbus includes are") - endif() - endif() - - if (NOT LWS_DBUS_INCLUDE2) - # look in fedora... debian / ubuntu has the ARCH in the path... - if (EXISTS "/usr/lib64/dbus-1.0/include") - set(LWS_DBUS_INCLUDE2 "/usr/lib64/dbus-1.0/include") - else() - message(FATAL_ERROR "Set LWS_DBUS_INCLUDE2 to /usr/lib/ARCH-linux-gnu/dbus-1.0/include or wherever dbus-arch-deps.h is on your system") - endif() +if (WIN32 OR MSVC) + CHECK_C_SOURCE_COMPILES("#include + #include + 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() - - set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES};${LWS_DBUS_INCLUDE1};${LWS_DBUS_INCLUDE2}) - - CHECK_C_SOURCE_COMPILES("#include - int main(void) { - return 0; - }" LWS_DBUS_CHECK_OK) -endif() - -if (LWS_WITH_LIBUV) -CHECK_INCLUDE_FILE(uv-version.h LWS_HAVE_UV_VERSION_H) - # libuv changed the location in 1.21.0. Retain both - # checks temporarily to ensure a smooth transition. - if (NOT LWS_HAVE_UV_VERSION_H) - CHECK_INCLUDE_FILE(uv/version.h LWS_HAVE_NEW_UV_VERSION_H) - endif() endif() -if (LWS_WITH_LIBEV) - CHECK_C_SOURCE_COMPILES( - "#include - int main(int argc, char **argv) { return EVBACKEND_LINUXAIO; } - " LWS_HAVE_EVBACKEND_LINUXAIO) - CHECK_C_SOURCE_COMPILES( - "#include - int main(int argc, char **argv) { return EVBACKEND_IOURING; } - " LWS_HAVE_EVBACKEND_IOURING) - -endif() +CHECK_LIBRARY_EXISTS(cap cap_set_flag "" LWS_HAVE_LIBCAP) if (LWS_WITH_ZLIB AND NOT LWS_WITH_BUNDLED_ZLIB) @@ -1010,11 +586,17 @@ endif() endif() -# TODO: These can also be tested to see whether they actually work... -set(LWS_HAVE_WORKING_FORK LWS_HAVE_FORK) -set(LWS_HAVE_WORKING_VFORK LWS_HAVE_VFORK) +CHECK_INCLUDE_FILES("stdlib.h;stdarg.h;string.h" STDC_HEADERS) -CHECK_INCLUDE_FILES("stdlib.h;stdarg.h;string.h;float.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 int main(void) { @@ -1022,13 +604,12 @@ return 0; }" LWS_HAS_INTPTR_T) -if (LWS_HAVE_PTHREAD_H) - if ((CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) - set(CMAKE_REQUIRED_FLAGS "-pthread -Wno-error=unused-command-line-argument") - else() - set(CMAKE_REQUIRED_FLAGS "-pthread") - endif() +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 int main(void) { @@ -1062,1044 +643,149 @@ set(realloc rpl_realloc) endif() -if (UNIX) - execute_process( COMMAND grep -c illumos /lib/ld.so.1 - OUTPUT_VARIABLE ILLUMOS ERROR_QUIET ) - # Chomp the \n at end of output. - string(REGEX REPLACE "[\n]+" "" ILLUMOS "${ILLUMOS}") - - if(NOT ${ILLUMOS} MATCHES "0") - add_definitions( "-D__illumos__" ) - set(ILLUMOS 1) - endif() -endif() - -if (MSVC) - # Turn off stupid microsoft security warnings. - add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE) -endif(MSVC) - -include_directories("${PROJECT_SOURCE_DIR}/lib") - -# Group headers and sources. -# Some IDEs use this for nicer file structure. -set(HDR_PRIVATE - lib/core/private-lib-core.h) - -set(HDR_PUBLIC - "${PROJECT_SOURCE_DIR}/include/libwebsockets.h" - "${PROJECT_BINARY_DIR}/lws_config.h" - "${PROJECT_SOURCE_DIR}/plugins/ssh-base/include/lws-plugin-ssh.h" - ) - -set(SOURCES - lib/core/alloc.c - lib/core/buflist.c - lib/core/context.c - lib/core/lws_dll2.c - lib/core/libwebsockets.c - lib/core/logs.c - lib/system/system.c - lib/misc/base64-decode.c - lib/misc/lws-ring.c -) - -if (LWS_WITH_SPAWN) - list(APPEND SOURCES lib/misc/spawn.c) -endif() - -if (LWS_WITH_FSMOUNT AND ${CMAKE_SYSTEM_NAME} STREQUAL "Linux") - list(APPEND SOURCES lib/misc/fsmount.c) -endif() - - - -if (LWS_WITH_FILE_OPS) - list(APPEND SOURCES lib/core/vfs.c) -endif() -if (LWS_WITH_DEPRECATED_LWS_DLL) - list(APPEND SOURCES - lib/core/lws_dll.c) -endif() - -if (LWS_WITH_NETWORK) - list(APPEND SOURCES - lib/core-net/dummy-callback.c - lib/core-net/output.c - lib/core-net/close.c - lib/core-net/network.c - lib/core-net/vhost.c - lib/core-net/pollfd.c - lib/core-net/service.c - lib/core-net/sorted-usec-list.c - lib/core-net/state.c - lib/core-net/stats.c - lib/core-net/wsi.c - lib/core-net/wsi-timeout.c - lib/core-net/adopt.c - lib/roles/pipe/ops-pipe.c - ) - if (LWS_WITH_SYS_ASYNC_DNS) - list(APPEND SOURCES - lib/system/async-dns/async-dns.c - lib/system/async-dns/async-dns-parse.c) - endif() - if (LWS_WITH_SYS_NTPCLIENT) - list(APPEND SOURCES - lib/system/ntpclient/ntpclient.c) - 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) + endif() + if (LWS_WITH_GCOV) + set (GCOV_FLAGS "-fprofile-arcs -ftest-coverage ") + else() + set(GCOV_FLAGS "") + endif() - if (LWS_WITH_SYS_DHCP_CLIENT) - list(APPEND SOURCES - lib/system/dhcpclient/dhcpclient.c) + 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_WITH_DETAILED_LATENCY) - list(APPEND SOURCES - lib/core-net/detailed-latency.c) - endif() - - if (LWS_WITH_LWS_DSH) - list(APPEND SOURCES - lib/core-net/lws-dsh.c) + if (LWS_GCC_HAS_IGNORED_QUALIFIERS) + set(CMAKE_C_FLAGS "-Wignored-qualifiers ${CMAKE_C_FLAGS}" ) endif() - if (LWS_WITH_SEQUENCER) - list(APPEND SOURCES - lib/core-net/sequencer.c) + if (LWS_GCC_HAS_TYPE_LIMITS) + set(CMAKE_C_FLAGS "-Wtype-limits ${CMAKE_C_FLAGS}" ) endif() - if (LWS_WITH_ABSTRACT) - list(APPEND SOURCES - lib/abstract/abstract.c - ) - if (LWS_WITH_SEQUENCER) - list(APPEND SOURCES - lib/abstract/test-sequencer.c) - endif() + if (LWS_WITH_FANALYZER AND LWS_HAVE_FANALYZER) + set(CMAKE_C_FLAGS "-fanalyzer ${CMAKE_C_FLAGS}" ) endif() - if (LWS_WITH_SECURE_STREAMS) - list(APPEND SOURCES - lib/secure-streams/secure-streams.c - lib/secure-streams/policy.c - lib/secure-streams/system/fetch-policy/fetch-policy.c - ) - if (LWS_ROLE_H1) - list(APPEND SOURCES - lib/secure-streams/protocols/ss-h1.c - ) - endif() - if (LWS_ROLE_H2) - list(APPEND SOURCES - lib/secure-streams/protocols/ss-h2.c - ) - endif() - if (LWS_ROLE_WS) - list(APPEND SOURCES - lib/secure-streams/protocols/ss-ws.c - ) - endif() - if (LWS_ROLE_MQTT) - list(APPEND SOURCES - lib/secure-streams/protocols/ss-mqtt.c - ) - endif() - - if (LWS_WITH_SECURE_STREAMS_PROXY_API) - list(APPEND SOURCES - lib/secure-streams/secure-streams-serialize.c - lib/secure-streams/secure-streams-client.c - ) - endif() - - if (LWS_WITH_SECURE_STREAMS_PROXY_API) - list(APPEND SOURCES - lib/secure-streams/secure-streams-process.c - ) - endif() - - if (LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM) - list(APPEND SOURCES - lib/secure-streams/system/auth-api.amazon.com/auth.c - ) - endif() + if (CMAKE_COMPILER_IS_CLANG OR CMAKE_C_COMPILER_VERSION VERSION_GREATER 4.4) + set(CMAKE_C_FLAGS "-Wuninitialized ${CMAKE_C_FLAGS}") endif() - if (LWS_WITH_STATS) - list(APPEND SOURCES - lib/core-net/stats.c - ) + # always warn all and generate debug info + if (UNIX AND NOT LWS_PLAT_FREERTOS) + set(CMAKE_C_FLAGS "-Wall -Wsign-compare -Wstrict-aliasing ${VISIBILITY_FLAG} -Wundef ${GCOV_FLAGS} ${CMAKE_C_FLAGS} ${ASAN_FLAGS}" ) + else() + set(CMAKE_C_FLAGS "-Wall -Wsign-compare ${VISIBILITY_FLAG} ${GCOV_FLAGS} ${CMAKE_C_FLAGS}" ) endif() -endif() - -if (LWS_WITH_DIR) - list(APPEND SOURCES lib/misc/dir.c) -endif() -if (LWS_ROLE_MQTT AND LWS_WITH_CLIENT) - list(APPEND SOURCES - lib/roles/mqtt/mqtt.c - lib/roles/mqtt/ops-mqtt.c - lib/roles/mqtt/primitives.c - lib/roles/mqtt/client/client-mqtt.c - lib/roles/mqtt/client/client-mqtt-handshake.c - ) -endif() - -if (LWS_WITH_THREADPOOL AND UNIX AND LWS_HAVE_PTHREAD_H) - list(APPEND SOURCES lib/misc/threadpool/threadpool.c) -endif() - -if (LWS_ROLE_H1 OR LWS_ROLE_H2) - list(APPEND SOURCES - lib/roles/http/header.c - lib/roles/http/parsers.c) - if (LWS_WITH_HTTP_STREAM_COMPRESSION) - list(APPEND SOURCES - lib/roles/http/compression/stream.c - lib/roles/http/compression/deflate/deflate.c) - if (LWS_WITH_HTTP_BROTLI) - list(APPEND SOURCES - lib/roles/http/compression/brotli/brotli.c) - endif() + if ("${DISABLE_WERROR}" STREQUAL "OFF") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") endif() -endif() +endif () -if (LWS_ROLE_H1) - list(APPEND SOURCES - lib/roles/h1/ops-h1.c) +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 (LWS_ROLE_WS) - list(APPEND SOURCES - lib/roles/ws/ops-ws.c) - if (NOT LWS_WITHOUT_CLIENT) - list(APPEND SOURCES - lib/roles/ws/client-ws.c - lib/roles/ws/client-parser-ws.c) - endif() - if (NOT LWS_WITHOUT_SERVER) - list(APPEND SOURCES - lib/roles/ws/server-ws.c) - endif() -endif() +if (COMPILER_IS_CLANG) -if (LWS_ROLE_RAW) - list(APPEND SOURCES - lib/roles/raw-skt/ops-raw-skt.c) - if (LWS_ROLE_RAW_FILE) - list(APPEND SOURCES lib/roles/raw-file/ops-raw-file.c) - endif() - - if (LWS_WITH_ABSTRACT) - list(APPEND SOURCES - lib/abstract/transports/raw-skt.c) + # 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 (LWS_ROLE_RAW_PROXY) - list(APPEND SOURCES - lib/roles/raw-proxy/ops-raw-proxy.c) +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 (LWS_ROLE_CGI) - list(APPEND SOURCES - lib/roles/cgi/cgi-server.c - lib/roles/cgi/ops-cgi.c) -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 (LWS_ROLE_DBUS) - list(APPEND SOURCES - lib/roles/dbus/dbus.c) +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 (LWS_WITH_ACCESS_LOG) - list(APPEND SOURCES - lib/roles/http/server/access-log.c) +if (HDR_PRIVATE) + source_group("Headers Private" FILES ${HDR_PRIVATE}) endif() - -if (LWS_WITH_PEER_LIMITS) - list(APPEND SOURCES - lib/misc/peer-limits.c) +if (HDR_PUBLIC) + source_group("Headers Public" FILES ${HDR_PUBLIC}) endif() - -if (LWS_WITH_LWSAC) - list(APPEND SOURCES - lib/misc/lwsac/lwsac.c - lib/misc/lwsac/cached-file.c) +if (SOURCES) + source_group("Sources" FILES ${SOURCES}) endif() - -if (LWS_WITH_FTS) - list(APPEND SOURCES - lib/misc/fts/trie.c - lib/misc/fts/trie-fd.c) +if (RESOURCES) + source_group("Resources" FILES ${RESOURCES}) endif() -if (LWS_WITH_DISKCACHE) - list(APPEND SOURCES - lib/misc/diskcache.c) -endif() -if (LWS_WITH_STRUCT_JSON) - list(APPEND SOURCES - lib/misc/lws-struct-lejp.c) +# +# 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_STRUCT_SQLITE3) - list(APPEND SOURCES - lib/misc/lws-struct-sqlite.c) -endif() -if (NOT LWS_WITHOUT_CLIENT) - list(APPEND SOURCES - lib/core-net/connect.c - lib/core-net/client.c - lib/roles/http/client/client-http.c - lib/roles/http/client/client-handshake.c) -endif() - -if (NOT LWS_WITHOUT_SERVER) - list(APPEND SOURCES - lib/core-net/server.c) -endif() - -if (NOT LWS_WITHOUT_SERVER OR LWS_WITH_SECURE_STREAMS_PROCESS_API) - list(APPEND SOURCES - lib/roles/listen/ops-listen.c) -endif() - -if (LWS_WITH_MBEDTLS) - set(LWS_WITH_SSL ON) - - include_directories(lib/tls/mbedtls/wrapper/include) - include_directories(lib/tls/mbedtls/wrapper/include/platform) - include_directories(lib/tls/mbedtls/wrapper/include/internal) - include_directories(lib/tls/mbedtls/wrapper/include/openssl) - - if (LWS_WITH_NETWORK) - list(APPEND HDR_PRIVATE - lib/tls/mbedtls/wrapper/include/internal/ssl3.h - lib/tls/mbedtls/wrapper/include/internal/ssl_cert.h - lib/tls/mbedtls/wrapper/include/internal/ssl_code.h - lib/tls/mbedtls/wrapper/include/internal/ssl_dbg.h - lib/tls/mbedtls/wrapper/include/internal/ssl_lib.h - lib/tls/mbedtls/wrapper/include/internal/ssl_methods.h - lib/tls/mbedtls/wrapper/include/internal/ssl_pkey.h - lib/tls/mbedtls/wrapper/include/internal/ssl_stack.h - lib/tls/mbedtls/wrapper/include/internal/ssl_types.h - lib/tls/mbedtls/wrapper/include/internal/ssl_x509.h - lib/tls/mbedtls/wrapper/include/internal/tls1.h - lib/tls/mbedtls/wrapper/include/internal/x509_vfy.h) - - list(APPEND HDR_PRIVATE - lib/tls/mbedtls/wrapper/include/openssl/ssl.h) - - list(APPEND HDR_PRIVATE - lib/tls/mbedtls/wrapper/include/platform/ssl_pm.h - lib/tls/mbedtls/wrapper/include/platform/ssl_port.h) - - list(APPEND SOURCES - lib/tls/mbedtls/wrapper/library/ssl_cert.c - lib/tls/mbedtls/wrapper/library/ssl_lib.c - lib/tls/mbedtls/wrapper/library/ssl_methods.c - lib/tls/mbedtls/wrapper/library/ssl_pkey.c - lib/tls/mbedtls/wrapper/library/ssl_stack.c - lib/tls/mbedtls/wrapper/library/ssl_x509.c) - - list(APPEND SOURCES - lib/tls/mbedtls/wrapper/platform/ssl_pm.c - lib/tls/mbedtls/wrapper/platform/ssl_port.c) - endif() -endif() - -if (LWS_WITH_SSL) - list(APPEND SOURCES - lib/tls/tls.c - ) - if (LWS_WITH_NETWORK) - list(APPEND SOURCES - lib/tls/tls-network.c - ) - endif() - - if (LWS_WITH_MBEDTLS) - list(APPEND SOURCES - lib/tls/mbedtls/mbedtls-tls.c - lib/tls/mbedtls/mbedtls-x509.c - ) - if (LWS_WITH_NETWORK) - list(APPEND SOURCES - lib/tls/mbedtls/mbedtls-ssl.c - ) - endif() - if (LWS_WITH_GENCRYPTO) - list(APPEND SOURCES - lib/tls/mbedtls/lws-genhash.c - lib/tls/mbedtls/lws-genrsa.c - lib/tls/mbedtls/lws-genaes.c - lib/tls/lws-genec-common.c - lib/tls/mbedtls/lws-genec.c - lib/tls/mbedtls/lws-gencrypto.c - ) - endif() - else() - list(APPEND SOURCES - lib/tls/openssl/openssl-tls.c - lib/tls/openssl/openssl-x509.c - ) - if (LWS_WITH_NETWORK) - list(APPEND SOURCES - lib/tls/openssl/openssl-ssl.c - ) - endif() - if (LWS_WITH_GENCRYPTO) - list(APPEND SOURCES - lib/tls/openssl/lws-genhash.c - lib/tls/openssl/lws-genrsa.c - lib/tls/openssl/lws-genaes.c - lib/tls/lws-genec-common.c - lib/tls/openssl/lws-genec.c - lib/tls/openssl/lws-gencrypto.c - ) - endif() - endif() - - if (NOT LWS_WITHOUT_SERVER) - list(APPEND SOURCES - lib/tls/tls-server.c) - if (LWS_WITH_MBEDTLS) - list(APPEND SOURCES - lib/tls/mbedtls/mbedtls-server.c) - else() - list(APPEND SOURCES - lib/tls/openssl/openssl-server.c) - endif() - endif() - if (NOT LWS_WITHOUT_CLIENT) - list(APPEND SOURCES - lib/tls/tls-client.c) - if (LWS_WITH_MBEDTLS) - list(APPEND SOURCES - lib/tls/mbedtls/mbedtls-client.c) - else() - list(APPEND SOURCES - lib/tls/openssl/openssl-client.c) - endif() - - endif() -endif() - -if (NOT LWS_WITHOUT_BUILTIN_SHA1) - list(APPEND SOURCES - lib/misc/sha-1.c) -endif() - -if (LWS_WITH_HTTP2 AND NOT LWS_WITHOUT_SERVER) - list(APPEND SOURCES - lib/roles/h2/http2.c - lib/roles/h2/hpack.c - lib/roles/h2/ops-h2.c) -endif() -# select the active platform files - -if (WIN32) - list(APPEND SOURCES - lib/plat/windows/windows-fds.c - lib/plat/windows/windows-file.c - lib/plat/windows/windows-init.c - lib/plat/windows/windows-misc.c - lib/plat/windows/windows-pipe.c - lib/plat/windows/windows-plugins.c - lib/plat/windows/windows-service.c - lib/plat/windows/windows-sockets.c - ) - if (LWS_WITH_SYS_ASYNC_DNS) - list(APPEND SOURCES lib/plat/windows/windows-resolv.c) - endif() -else() - - if (LWS_PLAT_OPTEE) - list(APPEND SOURCES - lib/plat/optee/lws-plat-optee.c - ) - if (LWS_WITH_NETWORK) - list(APPEND SOURCES - lib/plat/optee/network.c - ) - endif() - else() - if (LWS_PLAT_FREERTOS) - list(APPEND SOURCES - lib/plat/freertos/freertos-fds.c - lib/plat/freertos/freertos-init.c - lib/plat/freertos/freertos-misc.c - lib/plat/freertos/freertos-pipe.c - lib/plat/freertos/freertos-service.c - lib/plat/freertos/freertos-sockets.c - lib/misc/romfs.c) - if (LWS_WITH_ESP32_HELPER) - list(APPEND SOURCES lib/plat/freertos/esp32/esp32-helpers.c) - endif() - if (LWS_WITH_FILE_OPS) - list(APPEND SOURCES lib/plat/freertos/freertos-file.c) - endif() - if (LWS_WITH_SYS_ASYNC_DNS) - list(APPEND SOURCES lib/plat/freertos/freertos-resolv.c) - endif() - else() - set(LWS_PLAT_UNIX 1) - list(APPEND SOURCES - lib/plat/unix/unix-caps.c - lib/plat/unix/unix-misc.c - lib/plat/unix/unix-init.c - ) - if (LWS_WITH_FILE_OPS) - list(APPEND SOURCES lib/plat/unix/unix-file.c) - endif() - if (LWS_WITH_NETWORK) - list(APPEND SOURCES - lib/plat/unix/unix-pipe.c - lib/plat/unix/unix-service.c - lib/plat/unix/unix-sockets.c - lib/plat/unix/unix-fds.c - ) - if (LWS_WITH_SYS_ASYNC_DNS) - if (LWS_PLAT_ANDROID) - list(APPEND SOURCES lib/plat/unix/android/android-resolv.c) - else() - list(APPEND SOURCES lib/plat/unix/unix-resolv.c) - endif() - endif() - endif() - - if (LWS_WITH_PLUGINS AND LWS_WITH_LIBUV) - list(APPEND SOURCES lib/plat/unix/unix-plugins.c) - endif() - endif() - endif() -endif() - -if (LWS_WITH_SOCKS5 AND NOT LWS_WITHOUT_CLIENT) - list(APPEND SOURCES - lib/core-net/socks5-client.c) -endif() - -if ((LWS_ROLE_H1 OR LWS_ROLE_H2) AND NOT LWS_WITHOUT_SERVER) - list(APPEND SOURCES - lib/roles/http/server/server.c - lib/roles/http/server/lws-spa.c) -endif() - -if (LWS_ROLE_WS AND NOT LWS_WITHOUT_EXTENSIONS) - list(APPEND HDR_PRIVATE - lib/roles/ws/ext/extension-permessage-deflate.h) - list(APPEND SOURCES - lib/roles/ws/ext/extension.c - lib/roles/ws/ext/extension-permessage-deflate.c) -endif() - -if (LWS_WITH_HTTP_PROXY) - list(APPEND SOURCES - lib/roles/http/server/rewrite.c) -endif() - -if (LWS_WITH_POLL AND LWS_WITH_NETWORK) - list(APPEND SOURCES - lib/event-libs/poll/poll.c) -endif() - -if (LWS_WITH_LIBUV AND LWS_WITH_NETWORK) - list(APPEND SOURCES - lib/event-libs/libuv/libuv.c) -endif() - -if (LWS_WITH_LIBEVENT AND LWS_WITH_NETWORK) - list(APPEND SOURCES - lib/event-libs/libevent/libevent.c) -endif() - -if (LWS_WITH_GLIB AND LWS_WITH_NETWORK) - list(APPEND SOURCES - lib/event-libs/glib/glib.c) -endif() - - -if (LWS_WITH_LIBEV AND LWS_WITH_NETWORK) - list(APPEND SOURCES - lib/event-libs/libev/libev.c) - # libev generates a big mess of warnings with gcc, maintainer claims gcc to blame - set_source_files_properties( lib/event-libs/libev/libev.c PROPERTIES COMPILE_FLAGS "-Wno-error" ) -endif() - -if (LWS_WITH_LEJP) - list(APPEND SOURCES - lib/misc/lejp.c) -endif() -if (LWS_WITH_LEJP_CONF AND LWS_WITH_NETWORK AND NOT LWS_PLAT_OPTEE) - list(APPEND SOURCES - "lib/roles/http/server/lejp-conf.c" - ) -endif() - -if (LWS_WITH_ABSTRACT) - list(APPEND SOURCES - lib/abstract/transports/unit-test.c) -endif() - -#if (LWS_WITH_SMTP) -# list(APPEND SOURCES -# lib/abstract/protocols/smtp/smtp.c -# lib/abstract/protocols/smtp/smtp-sequencer.c -# ) -#endif() - -if (LWS_WITH_RANGES) - list(APPEND SOURCES - lib/roles/http/server/ranges.c) -endif() - -if (LWS_WITH_ZIP_FOPS) - if (LWS_WITH_ZLIB) - list(APPEND SOURCES - lib/roles/http/server/fops-zip.c) - else() - message(FATAL_ERROR "Pre-zipped file support (LWS_WITH_ZIP_FOPS) requires ZLIB (LWS_WITH_ZLIB)") - endif() -endif() - -if (LWS_WITH_JOSE) - list(APPEND SOURCES - lib/jose/jwk/jwk.c - lib/jose/jws/jose.c - lib/jose/jws/jws.c - lib/jose/jwe/jwe.c - lib/jose/jwe/enc/aescbc.c - lib/jose/jwe/enc/aesgcm.c - lib/jose/jwe/enc/aeskw.c - lib/jose/jwe/jwe-rsa-aescbc.c - lib/jose/jwe/jwe-rsa-aesgcm.c - lib/jose/jwe/jwe-ecdh-es-aeskw.c - ) -endif() - -if (LWS_WITH_TLS AND (LWS_WITH_JOSE OR LWS_WITH_GENCRYPTO)) - list(APPEND SOURCES - lib/tls/lws-gencrypto-common.c) -endif() - -# Add helper files for Windows. -if (WIN32) - set(WIN32_HELPERS_PATH win32port/win32helpers) - include_directories(${WIN32_HELPERS_PATH}) - - if (WIN32) - list(APPEND SOURCES - ${WIN32_HELPERS_PATH}/gettimeofday.c - ) - - list(APPEND HDR_PRIVATE - ${WIN32_HELPERS_PATH}/gettimeofday.h - ) - endif(WIN32) - -else() - # Unix. - if (NOT LWS_WITHOUT_DAEMONIZE) - list(APPEND SOURCES - lib/misc/daemonize.c) - endif() -endif() - -if (UNIX) - if (NOT LWS_HAVE_GETIFADDRS) - list(APPEND HDR_PRIVATE lib/misc/getifaddrs.h) - list(APPEND SOURCES lib/misc/getifaddrs.c) - endif() -endif() - -if ((CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) - set(COMPILER_IS_CLANG ON) -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_HAVE_VISIBILITY) - set(VISIBILITY_FLAG -fvisibility=hidden) - endif() - if (LWS_WITH_GCOV) - set (GCOV_FLAGS "-fprofile-arcs -ftest-coverage ") - endif() - - 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") - 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 (UNIX AND NOT LWS_PLAT_FREERTOS) - set(CMAKE_C_FLAGS "-Wall -Wsign-compare -Wstrict-aliasing -Wuninitialized -Werror ${VISIBILITY_FLAG} -Wundef ${GCOV_FLAGS} ${CMAKE_C_FLAGS} ${ASAN_FLAGS}" ) - else() - set(CMAKE_C_FLAGS "-Wall -Wsign-compare -Wuninitialized -Werror ${VISIBILITY_FLAG} ${GCOV_FLAGS} ${CMAKE_C_FLAGS}" ) - endif() -endif () - -if (LWS_PLAT_OPTEE) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --sysroot ../../../../lib/libutils/isoc/include -I../../../../lib/libutils/isoc/include -I../../../../lib/libutils/ext/include" ) -endif() - -if ((CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) AND NOT LWS_WITHOUT_TESTAPPS) - if (UNIX AND LWS_HAVE_PTHREAD_H) - # 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() - -source_group("Headers Private" FILES ${HDR_PRIVATE}) -source_group("Headers Public" FILES ${HDR_PUBLIC}) -source_group("Sources" FILES ${SOURCES}) -source_group("Resources" FILES ${RESOURCES}) - -# -# Create the lib. -# -set(LWS_LIBRARIES) - -if (LWS_WITH_STATIC) - if (LWS_STATIC_PIC) - set(CMAKE_POSITION_INDEPENDENT_CODE ON) - endif() - add_library(websockets STATIC - ${HDR_PRIVATE} - ${HDR_PUBLIC} - ${SOURCES}) - list(APPEND LWS_LIBRARIES websockets) - - if (WIN32) - # Windows uses the same .lib ending for static libraries and shared - # library linker files, so rename the static library. - set_target_properties(websockets - PROPERTIES - OUTPUT_NAME websockets_static) - endif() - add_custom_command( - TARGET websockets - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/include/libwebsockets.h - ${CMAKE_CURRENT_BINARY_DIR}/include/libwebsockets.h - ) - - add_custom_command( - TARGET websockets - COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/include/libwebsockets/ - ${CMAKE_CURRENT_BINARY_DIR}/include/libwebsockets - ) - - add_custom_command( - TARGET websockets - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/lws_config.h - ${CMAKE_CURRENT_BINARY_DIR}/include/lws_config.h - ) - -endif() - -if (LWS_WITH_SHARED) - add_library(websockets_shared SHARED - ${HDR_PRIVATE} - ${HDR_PUBLIC} - ${SOURCES} - ${RESOURCES}) - list(APPEND LWS_LIBRARIES websockets_shared) - - # We want the shared lib to be named "libwebsockets" - # not "libwebsocket_shared". - set_target_properties(websockets_shared - PROPERTIES - OUTPUT_NAME websockets) - - if (WIN32) - # Compile as DLL (export function declarations) - set_property( - TARGET websockets_shared - PROPERTY COMPILE_DEFINITIONS - LWS_DLL - LWS_INTERNAL) - endif() - - if (APPLE) - set_property(TARGET websockets_shared PROPERTY MACOSX_RPATH YES) - endif() - - add_custom_command( - TARGET websockets_shared - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/include/libwebsockets.h - ${CMAKE_CURRENT_BINARY_DIR}/include/libwebsockets.h - ) - - add_custom_command( - TARGET websockets - COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/include/libwebsockets - ${CMAKE_CURRENT_BINARY_DIR}/include/libwebsockets - ) - - add_custom_command( - TARGET websockets_shared - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/lws_config.h - ${CMAKE_CURRENT_BINARY_DIR}/include/lws_config.h - ) - - -endif() - -# Set the so version of the lib. -# Equivalent to LDFLAGS=-version-info x:x:x -if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR COMPILER_IS_CLANG) - foreach(lib ${LWS_LIBRARIES}) - set_target_properties(${lib} - PROPERTIES - SOVERSION ${SOVERSION}) - endforeach() -endif() - -set(LIB_LIST) - -# -# Find libraries. -# - -# -# ZLIB (needed for deflate extension and if LWS_WITH_HTTP_STREAM_COMPRESSION) -# -if (LWS_WITH_ZLIB) - if (LWS_WITH_BUNDLED_ZLIB) - if (WIN32) - set(WIN32_ZLIB_PATH "win32port/zlib") - set(ZLIB_SRCS - ${WIN32_ZLIB_PATH}/adler32.c - ${WIN32_ZLIB_PATH}/compress.c - ${WIN32_ZLIB_PATH}/crc32.c - ${WIN32_ZLIB_PATH}/deflate.c - ${WIN32_ZLIB_PATH}/gzlib.c - ${WIN32_ZLIB_PATH}/gzread.c - ${WIN32_ZLIB_PATH}/gzwrite.c - ${WIN32_ZLIB_PATH}/infback.c - ${WIN32_ZLIB_PATH}/inffast.c - ${WIN32_ZLIB_PATH}/inflate.c - ${WIN32_ZLIB_PATH}/inftrees.c - ${WIN32_ZLIB_PATH}/trees.c - ${WIN32_ZLIB_PATH}/uncompr.c - ${WIN32_ZLIB_PATH}/zutil.c) - add_library(zlib_internal STATIC ${ZLIB_SRCS}) - set(ZLIB_INCLUDE_DIRS ${WIN32_ZLIB_PATH}) - get_property(ZLIB_LIBRARIES TARGET zlib_internal PROPERTY LOCATION) - set(ZLIB_FOUND 1) - # Make sure zlib_internal is compiled before the libs. - foreach (lib ${LWS_LIBRARIES}) - add_dependencies(${lib} zlib_internal) - endforeach() - else() - message(FATAL_ERROR "Don't have bundled zlib for that platform") - endif() - elseif (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}) -endif() - -if (LWS_WITH_HTTP_BROTLI) - list(APPEND LIB_LIST brotlienc brotlidec brotlidec) -endif() - -# -# OpenSSL -# -if (LWS_WITH_SSL) - message("Compiling with SSL support") - set(chose_ssl 0) - if (LWS_WITH_WOLFSSL) - # Use wolfSSL as OpenSSL replacement. - # TODO: Add a find_package command for this also. - message("wolfSSL include dir: ${WOLFSSL_INCLUDE_DIRS}") - message("wolfSSL libraries: ${WOLFSSL_LIBRARIES}") - - # Additional to the root directory we need to include - # the wolfssl/ subdirectory which contains the OpenSSL - # compatibility layer headers. - - if (LWS_WITH_CYASSL) - foreach(inc ${WOLFSSL_INCLUDE_DIRS}) - set(OPENSSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIRS} ${inc} ${inc}/cyassl) - include_directories("${inc}" "${inc}/cyassl") - endforeach() - else() - foreach(inc ${WOLFSSL_INCLUDE_DIRS}) - set(OPENSSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIRS} ${inc} ${inc}/wolfssl) - include_directories("${inc}" "${inc}/wolfssl") - endforeach() - endif() - set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS}) - set(VARIA wolfSSL_) - - list(APPEND LIB_LIST "${WOLFSSL_LIBRARIES}") - set(chose_ssl 1) - endif() - - if (LWS_WITH_MBEDTLS) - message("MBEDTLS include dir: ${MBEDTLS_INCLUDE_DIRS}") - message("MBEDTLS libraries: ${MBEDTLS_LIBRARIES}") - - foreach(inc ${MBEDTLS_INCLUDE_DIRS}) - include_directories("${inc}" "${inc}/mbedtls") - endforeach() - - list(APPEND LIB_LIST "${MBEDTLS_LIBRARIES}") - set(chose_ssl 1) - endif() - - if (NOT chose_ssl) - if (NOT OPENSSL_FOUND AND NOT LWS_WITH_BORINGSSL) - # TODO: Add support for STATIC also. - if (NOT LWS_PLAT_FREERTOS) - find_package(PkgConfig QUIET) - pkg_check_modules(PC_OPENSSL openssl QUIET) - find_package(OpenSSL REQUIRED) - list(APPEND OPENSSL_LIBRARIES ${PC_OPENSSL_LIBRARIES}) - endif() - set(OPENSSL_INCLUDE_DIRS "${OPENSSL_INCLUDE_DIR}") - endif() - - message("OpenSSL include dir: ${OPENSSL_INCLUDE_DIRS}") - if (NOT LWS_PLAT_FREERTOS) - message("OpenSSL libraries: ${OPENSSL_LIBRARIES}") - endif() - - include_directories("${OPENSSL_INCLUDE_DIRS}") - if (NOT LWS_PLAT_FREERTOS) - list(APPEND LIB_LIST ${OPENSSL_LIBRARIES}) - endif() - - if (NOT LWS_WITH_MBEDTLS) - # older (0.98) Openssl lacks this - set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS}) - check_include_file(openssl/ecdh.h LWS_HAVE_OPENSSL_ECDH_H) - - if (LWS_SSL_SERVER_WITH_ECDH_CERT AND NOT LWS_HAVE_OPENSSL_ECDH_H) - message(FATAL_ERROR "Missing openssl/ecdh.h, so cannot use LWS_SSL_SERVER_WITH_ECDH_CERT") - endif() - else() - unset(LWS_HAVE_OPENSSL_ECDH_H) - endif(NOT LWS_WITH_MBEDTLS) - endif() - -endif(LWS_WITH_SSL) - -if (LWS_WITH_LIBEV) - if (NOT LIBEV_FOUND) - find_path(LIBEV_INCLUDE_DIRS NAMES ev.h) - find_library(LIBEV_LIBRARIES NAMES ev) - if(LIBEV_INCLUDE_DIRS AND LIBEV_LIBRARIES) - set(LIBEV_FOUND 1) - endif() - endif() - message("libev include dir: ${LIBEV_INCLUDE_DIRS}") - message("libev libraries: ${LIBEV_LIBRARIES}") - include_directories("${LIBEV_INCLUDE_DIRS}") - list(APPEND LIB_LIST ${LIBEV_LIBRARIES}) -endif(LWS_WITH_LIBEV) - -if (LWS_WITH_LIBUV) - if (NOT LIBUV_FOUND) - find_path(LIBUV_INCLUDE_DIRS NAMES uv.h) - find_library(LIBUV_LIBRARIES NAMES uv) - if(LIBUV_INCLUDE_DIRS AND LIBUV_LIBRARIES) - set(LIBUV_FOUND 1) - endif() - endif() - message("libuv include dir: ${LIBUV_INCLUDE_DIRS}") - message("libuv libraries: ${LIBUV_LIBRARIES}") - include_directories("${LIBUV_INCLUDE_DIRS}") - list(APPEND LIB_LIST ${LIBUV_LIBRARIES}) -endif() - -if (LWS_WITH_LIBEVENT) - if (NOT LIBEVENT_FOUND) - find_path(LIBEVENT_INCLUDE_DIRS NAMES event2/event.h) - find_library(LIBEVENT_LIBRARIES NAMES event) - if(LIBEVENT_INCLUDE_DIRS AND LIBEVENT_LIBRARIES) - set(LIBEVENT_FOUND 1) - endif() - endif() - message("libevent include dir: ${LIBEVENT_INCLUDE_DIRS}") - message("libevent libraries: ${LIBEVENT_LIBRARIES}") - include_directories("${LIBEVENT_INCLUDE_DIRS}") - list(APPEND LIB_LIST ${LIBEVENT_LIBRARIES}) -endif(LWS_WITH_LIBEVENT) - -if (LWS_WITH_GLIB) - include (FindPkgConfig) - if (NOT GLIB_FOUND) - find_path(GLIB_INCLUDE_DIRS NAMES glib-2.0/glib.h) - find_library(GLIB_LIBRARIES NAMES glib-2.0) - if(GLIB_INCLUDE_DIRS AND GLIB_LIBRARIES) - set(GLIB_FOUND 1) - endif() - if (GLIB_INCLUDE_DIRS) - set(GLIB_INCLUDE_DIRS "${GLIB_INCLUDE_DIRS}/glib-2.0") - endif() - endif() - PKG_SEARCH_MODULE(LWS_GLIB2 glib-2.0) - if (LWS_GLIB2_FOUND) - list(APPEND GLIB_INCLUDE_DIRS "${LWS_GLIB2_INCLUDE_DIRS}") - endif() - message("glib include dir: ${GLIB_INCLUDE_DIRS}") - message("glib libraries: ${GLIB_LIBRARIES}") - include_directories("${GLIB_INCLUDE_DIRS}") - list(APPEND LIB_LIST ${GLIB_LIBRARIES}) -endif(LWS_WITH_GLIB) - -if (LWS_WITH_FSMOUNT AND ${CMAKE_SYSTEM_NAME} STREQUAL "Linux") - message("libmount include dir: ${LIBMOUNT_INC_PATH}") - message("libmount libraries: ${LIBMOUNT_LIB_PATH}") - - include_directories("${LIBMOUNT_INC_PATH}") - list(APPEND LIB_LIST ${LIBMOUNT_LIB_PATH}) +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() @@ -2123,752 +809,126 @@ list(APPEND LIB_LIST ${LIBHUBBUB_LIBRARIES} ) endif() -if (LWS_ROLE_DBUS) - message("dbus include dir 1: ${LWS_DBUS_INCLUDE1}") - message("dbus include dir 2: ${LWS_DBUS_INCLUDE2}") - include_directories("${LWS_DBUS_INCLUDE1}") - include_directories("${LWS_DBUS_INCLUDE2}") - list(APPEND LIB_LIST ${LWS_DBUS_LIB}) +if (LWS_HAVE_LIBCAP) + find_library(LIBCAP_LIBRARIES NAMES cap) + list(APPEND LIB_LIST ${LIBCAP_LIBRARIES} ) endif() + # -# Platform specific libs. +# Append the "at end" pieces to the lib list # -if (WINCE) - list(APPEND LIB_LIST ws2.lib) -elseif (WIN32) - list(APPEND LIB_LIST ws2_32.lib userenv.lib psapi.lib iphlpapi.lib) -endif() - -if (${CMAKE_SYSTEM_NAME} MATCHES "QNX") - list(APPEND LIB_LIST socket) -endif() +list(APPEND LIB_LIST ${LIB_LIST_AT_END}) # -# add libs here that need to be at the end of the link order +# Second-level CMakeLists # -if (UNIX) - list(APPEND LIB_LIST m) -endif() - -if(ILLUMOS) - list(APPEND LIB_LIST socket) -endif() - -if (HAIKU) - list(APPEND LIB_LIST network) -endif() +include_directories("${PROJECT_SOURCE_DIR}/lib") +add_subdirectory(lib) -if (LWS_HAVE_LIBCAP) - list(APPEND LIB_LIST cap ) -endif() -if (UNIX) - list(APPEND LIB_LIST dl) -endif() -if (LWS_WITH_ZLIB AND NOT LWS_WITH_BUNDLED_ZLIB) - list(APPEND LIB_LIST "${ZLIB_LIBRARIES}") +if(WIN32 AND NOT CYGWIN) + set(DEF_INSTALL_CMAKE_DIR cmake) +else() + set(DEF_INSTALL_CMAKE_DIR lib${LIB_SUFFIX}/cmake/libwebsockets) endif() -# Setup the linking for all libs. -foreach (lib ${LWS_LIBRARIES}) - target_link_libraries(${lib} ${LIB_LIST}) -endforeach() +if (DEFINED REL_INCLUDE_DIR) + set(LWS__INCLUDE_DIRS "\${LWS_CMAKE_DIR}/${REL_INCLUDE_DIR}") +endif() -set (temp ${CMAKE_REQUIRED_LIBRARIES}) -set(CMAKE_REQUIRED_LIBRARIES ${LIB_LIST}) +configure_file(${PROJECT_SOURCE_DIR}/cmake/libwebsockets-config.cmake.in + ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/libwebsockets-config.cmake + @ONLY) -if (LWS_WITH_ZLIB) - if (LWS_WITH_BUNDLED_ZLIB) - if (WIN32) - # it's trying to delete internal zlib entry - LIST(REMOVE_AT CMAKE_REQUIRED_LIBRARIES 0 ) - endif() - endif() -endif() +# 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) -CHECK_FUNCTION_EXISTS(${VARIA}SSL_CTX_set1_param LWS_HAVE_SSL_CTX_set1_param) -CHECK_FUNCTION_EXISTS(${VARIA}SSL_set_info_callback LWS_HAVE_SSL_SET_INFO_CALLBACK) -CHECK_FUNCTION_EXISTS(${VARIA}X509_VERIFY_PARAM_set1_host LWS_HAVE_X509_VERIFY_PARAM_set1_host) -CHECK_FUNCTION_EXISTS(${VARIA}RSA_set0_key LWS_HAVE_RSA_SET0_KEY) -CHECK_FUNCTION_EXISTS(${VARIA}X509_get_key_usage LWS_HAVE_X509_get_key_usage) -CHECK_FUNCTION_EXISTS(${VARIA}EVP_PKEY_new_raw_private_key LWS_HAVE_SSL_CTX_EVP_PKEY_new_raw_private_key) -CHECK_FUNCTION_EXISTS(${VARIA}SSL_CTX_get0_certificate LWS_HAVE_SSL_CTX_get0_certificate) -CHECK_FUNCTION_EXISTS(${VARIA}SSL_get0_alpn_selected LWS_HAVE_SSL_get0_alpn_selected) -CHECK_FUNCTION_EXISTS(${VARIA}SSL_set_alpn_protos LWS_HAVE_SSL_set_alpn_protos) -CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_128_cfb8 LWS_HAVE_EVP_aes_128_cfb8) -CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_128_cfb128 LWS_HAVE_EVP_aes_128_cfb128) -CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_192_cfb8 LWS_HAVE_EVP_aes_192_cfb8) -CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_192_cfb128 LWS_HAVE_EVP_aes_192_cfb128) -CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_256_cfb8 LWS_HAVE_EVP_aes_256_cfb8) -CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_256_cfb128 LWS_HAVE_EVP_aes_256_cfb128) -CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_128_xts LWS_HAVE_EVP_aes_128_xts) -CHECK_FUNCTION_EXISTS(${VARIA}RSA_verify_pss_mgf1 LWS_HAVE_RSA_verify_pss_mgf1) -CHECK_FUNCTION_EXISTS(${VARIA}HMAC_CTX_new LWS_HAVE_HMAC_CTX_new) -CHECK_FUNCTION_EXISTS(${VARIA}SSL_CTX_set_ciphersuites LWS_HAVE_SSL_CTX_set_ciphersuites) -if (LWS_WITH_SSL AND NOT LWS_WITH_MBEDTLS) - if (UNIX) - set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} dl) - endif() -CHECK_C_SOURCE_COMPILES("#include \nint main(void) { STACK_OF(X509) *c = NULL; SSL_CTX *ctx = NULL; return (int)SSL_CTX_get_extra_chain_certs_only(ctx, &c); }\n" LWS_HAVE_SSL_EXTRA_CHAIN_CERTS) -CHECK_C_SOURCE_COMPILES("#include \nint main(void) { EVP_MD_CTX *md_ctx = NULL; EVP_MD_CTX_free(md_ctx); return 0; }\n" LWS_HAVE_EVP_MD_CTX_free) -CHECK_FUNCTION_EXISTS(${VARIA}ECDSA_SIG_set0 LWS_HAVE_ECDSA_SIG_set0) -CHECK_FUNCTION_EXISTS(${VARIA}BN_bn2binpad LWS_HAVE_BN_bn2binpad) -CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_128_wrap LWS_HAVE_EVP_aes_128_wrap) -CHECK_FUNCTION_EXISTS(${VARIA}EC_POINT_get_affine_coordinates LWS_HAVE_EC_POINT_get_affine_coordinates) -endif() -if (LWS_WITH_MBEDTLS) - set(LWS_HAVE_TLS_CLIENT_METHOD 1) - if (NOT LWS_PLAT_FREERTOS) - # not supported in esp-idf openssl wrapper yet, but is in our version - set(LWS_HAVE_X509_VERIFY_PARAM_set1_host 1) - endif() - - CHECK_FUNCTION_EXISTS(mbedtls_ssl_conf_alpn_protocols LWS_HAVE_mbedtls_ssl_conf_alpn_protocols) - CHECK_FUNCTION_EXISTS(mbedtls_ssl_get_alpn_protocol LWS_HAVE_mbedtls_ssl_get_alpn_protocol) - CHECK_FUNCTION_EXISTS(mbedtls_ssl_conf_sni LWS_HAVE_mbedtls_ssl_conf_sni) - CHECK_FUNCTION_EXISTS(mbedtls_ssl_set_hs_ca_chain LWS_HAVE_mbedtls_ssl_set_hs_ca_chain) - CHECK_FUNCTION_EXISTS(mbedtls_ssl_set_hs_own_cert LWS_HAVE_mbedtls_ssl_set_hs_own_cert) - CHECK_FUNCTION_EXISTS(mbedtls_ssl_set_hs_authmode LWS_HAVE_mbedtls_ssl_set_hs_authmode) - CHECK_FUNCTION_EXISTS(mbedtls_net_init LWS_HAVE_mbedtls_net_init) +# 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") -else() -CHECK_FUNCTION_EXISTS(${VARIA}TLS_client_method LWS_HAVE_TLS_CLIENT_METHOD) -CHECK_FUNCTION_EXISTS(${VARIA}TLSv1_2_client_method LWS_HAVE_TLSV1_2_CLIENT_METHOD) +# 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() -# ideally we want to use pipe2() -CHECK_C_SOURCE_COMPILES("#define _GNU_SOURCE\n#include \nint main(void) {int fd[2];\n return pipe2(fd, 0);\n}\n" LWS_HAVE_PIPE2) -# old mbedtls has everything in mbedtls/net.h +set(libwebsockets_DIR ${PROJECT_BINARY_DIR}) +set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") +message("DIR ${libwebsockets_DIR} CMP ${CMAKE_MODULE_PATH}") -CHECK_C_SOURCE_COMPILES("#include \nint main(void) { return 0;}\n" LWS_HAVE_MBEDTLS_NET_SOCKETS) +if (LWS_WITH_MINIMAL_EXAMPLES) + add_subdirectory(minimal-examples) +endif() -# tcp keepalive needs this on linux to work practically... but it only exists -# after kernel 2.6.37 +if (NOT LWS_WITHOUT_TESTAPPS) + add_subdirectory(test-apps) +endif() -CHECK_C_SOURCE_COMPILES("#include \nint main(void) { return TCP_USER_TIMEOUT; }\n" LWS_HAVE_TCP_USER_TIMEOUT) +add_subdirectory(plugins) +add_subdirectory(lwsws) -set(CMAKE_REQUIRED_LIBRARIES ${temp}) # Generate the lws_config.h that includes all the public compilation settings. configure_file( "${PROJECT_SOURCE_DIR}/cmake/lws_config.h.in" "${PROJECT_BINARY_DIR}/lws_config.h") + +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 +) -# 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") +add_custom_target(GENHDR DEPENDS ${PROJECT_BINARY_DIR}/include/lws_config.h) -# Generate self-signed SSL certs for the test-server. +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}) -if (LWS_WITH_SSL AND NOT LWS_WITH_WOLFSSL) - message("Searching for OpenSSL executable and dlls") - find_package(OpenSSLbins) - message("OpenSSL executable: ${OPENSSL_EXECUTABLE}") - if (OPENSSL_EXECUTABLE MATCHES "^$") - set(OPENSSL_EXECUTABLE openssl) - endif() - if (NOT OPENSSL_EXECUTABLE) - set(OPENSSL_EXECUTABLE openssl) - endif() +set_source_files_properties(${HDR_PUBLIC} PROPERTIES GENERATED 1) +if (LWS_WITH_STATIC) + add_dependencies(websockets GENHDR) endif() - -set(GENCERTS 0) - -if (LWS_WITH_SSL AND OPENSSL_EXECUTABLE AND NOT LWS_WITHOUT_TEST_SERVER AND NOT LWS_WITHOUT_SERVER AND NOT LWS_WITHOUT_TESTAPPS) - set(GENCERTS 1) -endif() -if (LWS_PLAT_FREERTOS) - set(GENCERTS 1) -endif() -message(" GENCERTS = ${GENCERTS}") -if (GENCERTS) - message("Generating SSL Certificates for the test-server...") - - set(TEST_SERVER_SSL_KEY "${PROJECT_BINARY_DIR}/libwebsockets-test-server.key.pem") - set(TEST_SERVER_SSL_CERT "${PROJECT_BINARY_DIR}/libwebsockets-test-server.pem") - - if (WIN32) - if (MINGW) - message("cmd = \"${OPENSSL_EXECUTABLE}\" req -new -newkey rsa:1024 -days 10000 -nodes -x509 -subj \"/C=GB/ST=Erewhon/L=All around/O=libwebsockets-test/CN=localhost\" -keyout \"${TEST_SERVER_SSL_KEY}\" -out \"${TEST_SERVER_SSL_CERT}\"") - execute_process( - COMMAND "${OPENSSL_EXECUTABLE}" req -new -newkey rsa:1024 -days 10000 -nodes -x509 -subj "/C=GB/ST=Erewhon/L=All around/O=libwebsockets-test/CN=localhost" -keyout "${TEST_SERVER_SSL_KEY}" -out "${TEST_SERVER_SSL_CERT}" - RESULT_VARIABLE OPENSSL_RETURN_CODE) - else() - file(WRITE "${PROJECT_BINARY_DIR}/openssl_input.txt" - "GB\n" - "Erewhon\n" - "All around\n" - "libwebsockets-test\n" - "localhost\n" - "none@invalid.org\n\n" - ) - - # The "type" command is a bit picky with paths. - file(TO_NATIVE_PATH "${PROJECT_BINARY_DIR}/openssl_input.txt" OPENSSL_INPUT_WIN_PATH) - message("OPENSSL_INPUT_WIN_PATH = ${OPENSSL_INPUT_WIN_PATH}") - message("cmd = \"${OPENSSL_EXECUTABLE}\" req -new -newkey rsa:1024 -days 10000 -nodes -x509 -keyout \"${TEST_SERVER_SSL_KEY}\" -out \"${TEST_SERVER_SSL_CERT}\"") - - execute_process( - COMMAND cmd /c type "${OPENSSL_INPUT_WIN_PATH}" - COMMAND "${OPENSSL_EXECUTABLE}" req -new -newkey rsa:1024 -days 10000 -nodes -x509 -keyout "${TEST_SERVER_SSL_KEY}" -out "${TEST_SERVER_SSL_CERT}" - RESULT_VARIABLE OPENSSL_RETURN_CODE - OUTPUT_QUIET ERROR_QUIET) - - message("\n") - endif() - - if (OPENSSL_RETURN_CODE) - message(WARNING "!!! Failed to generate SSL certificate for Test Server using cmd.exe !!!:\nOpenSSL return code = ${OPENSSL_RETURN_CODE}") - else() - message("SUCCSESFULLY generated SSL certificate") - endif() - else() - # Unix. - execute_process( - COMMAND printf "GB\\nErewhon\\nAll around\\nlibwebsockets-test\\n\\nlocalhost\\nnone@invalid.org\\n" - COMMAND "${OPENSSL_EXECUTABLE}" - req -new -newkey rsa:1024 -days 10000 -nodes -x509 -keyout "${TEST_SERVER_SSL_KEY}" -out "${TEST_SERVER_SSL_CERT}" - RESULT_VARIABLE OPENSSL_RETURN_CODE - # OUTPUT_QUIET ERROR_QUIET - ) - - if (OPENSSL_RETURN_CODE) - message(WARNING "!!! Failed to generate SSL certificate for Test Server!!!:\nOpenSSL return code = ${OPENSSL_RETURN_CODE}") - else() - message("SUCCESSFULLY generated SSL certificate") - endif() - endif() - - list(APPEND TEST_SERVER_DATA - "${TEST_SERVER_SSL_KEY}" - "${TEST_SERVER_SSL_CERT}") +if (LWS_WITH_SHARED) + add_dependencies(websockets_shared GENHDR) endif() - -# -# Test applications # -set(TEST_APP_LIST) -if ((LWS_ROLE_H1 OR LWS_ROLE_H2) AND NOT LWS_WITHOUT_TESTAPPS) - # - # Helper function for adding a test app. - # - macro(create_test_app TEST_NAME MAIN_SRC S2 S3 S4 S5 S6) - - set(TEST_SRCS ${MAIN_SRC}) - set(TEST_HDR) - if ("${S2}" STREQUAL "") - else() - list(APPEND TEST_SRCS ${S2}) - endif() - if ("${S3}" STREQUAL "") - else() - list(APPEND TEST_SRCS ${S3}) - endif() - if ("${S4}" STREQUAL "") - else() - list(APPEND TEST_SRCS ${S4}) - endif() - if ("${S5}" STREQUAL "") - else() - list(APPEND TEST_SRCS ${S5}) - endif() - if ("${S6}" STREQUAL "") - else() - list(APPEND TEST_SRCS ${S6}) - endif() - if (WIN32) - list(APPEND TEST_SRCS - ${WIN32_HELPERS_PATH}/getopt.c - ${WIN32_HELPERS_PATH}/getopt_long.c - ${WIN32_HELPERS_PATH}/gettimeofday.c - ) - - list(APPEND TEST_HDR - ${WIN32_HELPERS_PATH}/getopt.h - ${WIN32_HELPERS_PATH}/gettimeofday.h - ) - endif(WIN32) - - source_group("Headers Private" FILES ${TEST_HDR}) - source_group("Sources" FILES ${TEST_SRCS}) - add_executable(${TEST_NAME} ${TEST_SRCS} ${TEST_HDR}) - - if (LWS_LINK_TESTAPPS_DYNAMIC) - if (NOT LWS_WITH_SHARED) - message(FATAL_ERROR "Build of the shared library is disabled. LWS_LINK_TESTAPPS_DYNAMIC must be combined with LWS_WITH_SHARED.") - endif() - target_link_libraries(${TEST_NAME} websockets_shared) - add_dependencies(${TEST_NAME} websockets_shared) - else() - if (NOT LWS_WITH_STATIC) - message(FATAL_ERROR "Build of the static library is disabled. Disabled LWS_LINK_TESTAPPS_DYNAMIC must be combined with LWS_WITH_STATIC.") - endif() - target_link_libraries(${TEST_NAME} websockets) - add_dependencies(${TEST_NAME} websockets) - if (UNIX AND LWS_WITH_SSL AND NOT LWS_WITH_MBEDTLS) - target_link_libraries(${TEST_NAME} dl) - endif() - endif() - - if (LWS_WITH_HTTP_STREAM_COMPRESSION) - target_link_libraries(${TEST_NAME} z) - endif() - - # Set test app specific defines. - set_property(TARGET ${TEST_NAME} - PROPERTY COMPILE_DEFINITIONS - INSTALL_DATADIR="${CMAKE_INSTALL_PREFIX}/share" - ) - - # Prefix the binary names with libwebsockets. - set_target_properties(${TEST_NAME} - PROPERTIES - OUTPUT_NAME libwebsockets-${TEST_NAME}) - - # Add to the list of tests. - list(APPEND TEST_APP_LIST ${TEST_NAME}) - endmacro() - - if (UNIX AND LWS_WITH_PLUGINS) - set(CMAKE_C_FLAGS "-fPIC ${CMAKE_C_FLAGS}") - if(NOT((${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") OR (${CMAKE_SYSTEM_NAME} MATCHES "QNX"))) - target_link_libraries(websockets dl) - endif() - endif() - - if (NOT LWS_WITHOUT_SERVER) - # - # test-server - # - if (NOT LWS_WITHOUT_TEST_SERVER) - create_test_app(test-server "test-apps/test-server.c" - "" - "" - "" - "" - "") - - if (LWS_WITH_CGI AND LWS_WITH_TLS) - create_test_app(test-sshd "test-apps/test-sshd.c" - "" - "" - "" - "" - "") - target_include_directories(test-sshd PRIVATE "${PROJECT_SOURCE_DIR}/plugins/ssh-base/include") - - endif() - - endif() - - # - # test-server-extpoll - # - if (NOT LWS_WITHOUT_TEST_SERVER_EXTPOLL AND NOT WIN32) - create_test_app(test-server-extpoll - "test-apps/test-server.c" - "" - "" - "" - "" - "") - # Set defines for this executable only. - set_property( - TARGET test-server-extpoll - PROPERTY COMPILE_DEFINITIONS - EXTERNAL_POLL - INSTALL_DATADIR="${CMAKE_INSTALL_PREFIX}/share" - ) - - # We need to link against winsock code. - if (WIN32) - target_link_libraries(test-server-extpoll ws2_32.lib) - endif(WIN32) - endif() - - if (LWS_WITH_LEJP) - create_test_app( - test-lejp - "test-apps/test-lejp.c" - "" - "" - "" - "" - "") - endif() - - # Data files for running the test server. - list(APPEND TEST_SERVER_DATA - "${PROJECT_SOURCE_DIR}/test-apps/favicon.ico" - "${PROJECT_SOURCE_DIR}/test-apps/leaf.jpg" - "${PROJECT_SOURCE_DIR}/test-apps/candide.zip" - "${PROJECT_SOURCE_DIR}/test-apps/libwebsockets.org-logo.svg" - "${PROJECT_SOURCE_DIR}/test-apps/http2.png" - "${PROJECT_SOURCE_DIR}/test-apps/wss-over-h2.png" - "${PROJECT_SOURCE_DIR}/test-apps/lws-common.js" - "${PROJECT_SOURCE_DIR}/test-apps/test.html" - "${PROJECT_SOURCE_DIR}/test-apps/test.css" - "${PROJECT_SOURCE_DIR}/test-apps/test.js") - - add_custom_command(TARGET test-server - POST_BUILD - COMMAND "${CMAKE_COMMAND}" -E make_directory "$/../share/libwebsockets-test-server") - - # Copy the file needed to run the server so that the test apps can - # reach them from their default output location - foreach (TEST_FILE ${TEST_SERVER_DATA}) - if (EXISTS ${TEST_FILE}) - add_custom_command(TARGET test-server - POST_BUILD - COMMAND "${CMAKE_COMMAND}" -E copy "${TEST_FILE}" "$/../share/libwebsockets-test-server" VERBATIM) - endif() - endforeach() - endif(NOT LWS_WITHOUT_SERVER) - - if (NOT LWS_WITHOUT_CLIENT) - # - # test-client - # - if (NOT LWS_WITHOUT_TEST_CLIENT) - create_test_app(test-client "test-apps/test-client.c" "" "" "" "" "") - endif() - - endif(NOT LWS_WITHOUT_CLIENT) - - - if (LWS_WITH_PLUGINS AND LWS_WITH_SHARED) - macro(create_plugin PLUGIN_NAME PLUGIN_INCLUDE MAIN_SRC S2 S3) - - set(PLUGIN_SRCS ${MAIN_SRC}) - - if ("${S2}" STREQUAL "") - else() - list(APPEND PLUGIN_SRCS ${S2}) - endif() - if ("${S3}" STREQUAL "") - else() - list(APPEND PLUGIN_SRCS ${S3}) - endif() - - if (WIN32) - list(APPEND PLUGIN_SRCS - ${WIN32_HELPERS_PATH}/getopt.c - ${WIN32_HELPERS_PATH}/getopt_long.c - ${WIN32_HELPERS_PATH}/gettimeofday.c - ) - - list(APPEND PLUGIN_HDR - ${WIN32_HELPERS_PATH}/getopt.h - ${WIN32_HELPERS_PATH}/gettimeofday.h - ) - endif(WIN32) - - source_group("Headers Private" FILES ${PLUGIN_HDR}) - source_group("Sources" FILES ${PLUGIN_SRCS}) - add_library(${PLUGIN_NAME} SHARED ${PLUGIN_SRCS} ${PLUGIN_HDR}) - - target_link_libraries(${PLUGIN_NAME} websockets_shared) - add_dependencies(${PLUGIN_NAME} websockets_shared) - include_directories(${PLUGIN_INCLUDE}) - - # Set test app specific defines. - set_property(TARGET ${PLUGIN_NAME} - PROPERTY COMPILE_DEFINITIONS - INSTALL_DATADIR="${CMAKE_INSTALL_PREFIX}/plugins" - ) - - SET_TARGET_PROPERTIES(${PLUGIN_NAME} - PROPERTIES COMPILE_FLAGS ${CMAKE_C_FLAGS}) - -# set_target_properties(${PLUGIN_NAME} -# PROPERTIES -# OUTPUT_NAME ${PLUGIN_NAME}) - - list(APPEND PLUGINS_LIST ${PLUGIN_NAME}) - - endmacro() - -if (LWS_ROLE_WS) - create_plugin(protocol_dumb_increment "" - "plugins/protocol_dumb_increment.c" "" "") - create_plugin(protocol_lws_mirror "" - "plugins/protocol_lws_mirror.c" "" "") - create_plugin(protocol_lws_status "" - "plugins/protocol_lws_status.c" "" "") - create_plugin(protocol_lws_table_dirlisting "" - "plugins/generic-table/protocol_table_dirlisting.c" "" "") - if (NOT WIN32) - create_plugin(protocol_lws_raw_test "" - "plugins/protocol_lws_raw_test.c" "" "") - - if (UNIX AND LWS_HAVE_PTHREAD_H) - create_plugin(protocol_deaddrop "" - "plugins/deaddrop/protocol_lws_deaddrop.c" "" "") - endif() - endif() - - if (LWS_WITH_SERVER_STATUS) - create_plugin(protocol_lws_server_status "" - "plugins/protocol_lws_server_status.c" "" "") - endif() - - if (NOT LWS_WITHOUT_CLIENT) - create_plugin(protocol_client_loopback_test "" - "plugins/protocol_client_loopback_test.c" "" "") - endif() - -endif(LWS_ROLE_WS) - - create_plugin(protocol_post_demo "" - "plugins/protocol_post_demo.c" "" "") - -if (LWS_ROLE_RAW_PROXY) - create_plugin(protocol_lws_raw_proxy "" - "plugins/raw-proxy/protocol_lws_raw_proxy.c" "" "") -endif() - -if (LWS_WITH_FTS) - create_plugin(protocol_fulltext_demo "" - "plugins/protocol_fulltext_demo.c" "" "") -endif() - - -if (LWS_WITH_SSL) - create_plugin(protocol_lws_ssh_base "plugins/ssh-base/include" - "plugins/ssh-base/sshd.c;plugins/ssh-base/telnet.c;plugins/ssh-base/kex-25519.c" "plugins/ssh-base/crypto/chacha.c;plugins/ssh-base/crypto/ed25519.c;plugins/ssh-base/crypto/fe25519.c;plugins/ssh-base/crypto/ge25519.c;plugins/ssh-base/crypto/poly1305.c;plugins/ssh-base/crypto/sc25519.c;plugins/ssh-base/crypto/smult_curve25519_ref.c" "") - create_plugin(protocol_lws_sshd_demo "plugins/ssh-base/include" "plugins/protocol_lws_sshd_demo.c" "" "") - - include_directories("${PROJECT_SOURCE_DIR}/plugins/ssh-base/include") -endif() - - - -if (LWS_WITH_ACME) - create_plugin(protocol_lws_acme_client "" - "plugins/acme-client/protocol_lws_acme_client.c" "" "") -endif() - -if (LWS_WITH_GENERIC_SESSIONS AND LWS_ROLE_WS AND LWS_WITH_TLS) - create_plugin(protocol_generic_sessions "" - "plugins/generic-sessions/protocol_generic_sessions.c" - "plugins/generic-sessions/utils.c" - "plugins/generic-sessions/handlers.c") - - if (WIN32) - target_link_libraries(protocol_generic_sessions ${LWS_SQLITE3_LIBRARIES}) - else() - target_link_libraries(protocol_generic_sessions sqlite3 ) - endif(WIN32) - - create_plugin(protocol_lws_messageboard "" - "plugins/generic-sessions/protocol_lws_messageboard.c" "" "") - if (WIN32) - target_link_libraries(protocol_lws_messageboard ${LWS_SQLITE3_LIBRARIES}) - else() - target_link_libraries(protocol_lws_messageboard sqlite3 ) - endif(WIN32) - -endif(LWS_WITH_GENERIC_SESSIONS AND LWS_ROLE_WS AND LWS_WITH_TLS) - - - endif(LWS_WITH_PLUGINS AND LWS_WITH_SHARED) - - # - # Copy OpenSSL dlls to the output directory on Windows. - # (Otherwise we'll get an error when trying to run) - # - if (WIN32 AND LWS_WITH_SSL AND NOT LWS_WITH_WOLFSSL) - if(OPENSSL_BIN_FOUND) - message("OpenSSL dlls found:") - message(" Libeay: ${LIBEAY_BIN}") - message(" SSLeay: ${SSLEAY_BIN}") - - foreach(TARGET_BIN ${TEST_APP_LIST}) - add_custom_command(TARGET ${TARGET_BIN} - POST_BUILD - COMMAND "${CMAKE_COMMAND}" -E copy "${LIBEAY_BIN}" "$" VERBATIM) - add_custom_command(TARGET ${TARGET_BIN} - POST_BUILD - COMMAND "${CMAKE_COMMAND}" -E copy "${SSLEAY_BIN}" "$" VERBATIM) - - # - # Win32: if we are using libuv, also need to copy it in the output dir - # - if (WIN32 AND LWS_WITH_LIBUV) - STRING(REPLACE ".lib" ".dll" LIBUV_BIN ${LIBUV_LIBRARIES}) - add_custom_command(TARGET ${TARGET_BIN} - POST_BUILD - COMMAND "${CMAKE_COMMAND}" -E copy "${LIBUV_BIN}" "$" VERBATIM) - endif() - endforeach() - endif() - endif() -endif((LWS_ROLE_H1 OR LWS_ROLE_H2) AND NOT LWS_WITHOUT_TESTAPPS) - -if (LWS_WITH_LWSWS) - list(APPEND LWSWS_SRCS - "lwsws/main.c" - ) - - if (WIN32) - list(APPEND LWSWS_SRCS - ${WIN32_HELPERS_PATH}/getopt.c - ${WIN32_HELPERS_PATH}/getopt_long.c - ${WIN32_HELPERS_PATH}/gettimeofday.c - ) - - list(APPEND LWSWS_HDR - ${WIN32_HELPERS_PATH}/getopt.h - ${WIN32_HELPERS_PATH}/gettimeofday.h - ) - endif(WIN32) - - source_group("Headers Private" FILES ${LWSWS_HDR}) - source_group("Sources" FILES ${LWSWS_SRCS}) - add_executable("lwsws" ${LWSWS_SRCS} ${LWSWS_HDR}) - - target_link_libraries("lwsws" websockets_shared) - add_dependencies("lwsws" websockets_shared) - - # Set test app specific defines. - set_property(TARGET "lwsws" - PROPERTY COMPILE_DEFINITIONS - INSTALL_DATADIR="${CMAKE_INSTALL_PREFIX}/share" - ) -endif (LWS_WITH_LWSWS) - -# secure streams plugins - -if (LWS_WITH_SECURE_STREAMS) - # - # Helper function for adding a secure stream plugin - # - macro(create_ss_plugin NAME S2 S3 S4 S5 S6) - - set(SSP_SRCS) - set(SSP_PUBLIC_HDR) - set(SSP_HDR) - - if ("${S2}" STREQUAL "") - else() - list(APPEND SSP_SRCS - lib/secure-streams/plugins/${NAME}/${S2}) - endif() - if ("${S3}" STREQUAL "") - else() - list(APPEND SSP_SRCS - lib/secure-streams/plugins/${NAME}/${S3}) - endif() - if ("${S4}" STREQUAL "") - else() - list(APPEND SSP_SRCS - lib/secure-streams/plugins/${NAME}/${S4}) - endif() - if ("${S5}" STREQUAL "") - else() - list(APPEND SSP_SRCS - lib/secure-streams/plugins/${NAME}/${S5}) - endif() - if ("${S6}" STREQUAL "") - else() - list(APPEND SSP_SRCS - lib/secure-streams/plugins/${NAME}/${S6}) - endif() - - source_group("Headers Private" FILES ${SSP_HDR}) - source_group("Sources" FILES ${SSP_SRCS}) - - add_library( ${NAME} STATIC - ${SSP_HDR} ${SSP_PUBLIC_HDR} ${SSP_SRCS} ) - - add_dependencies(${NAME} websockets_shared) - list(APPEND SS_PLUGINS_LIST ${NAME}) - endmacro() - - include_directories(lib/secure-streams) - - create_ss_plugin(ssp-h1url "h1url.c" "" "" "" "") -endif() - -if (UNIX) - -# Generate and install pkgconfig. -# (This is not indented, because the tabs will be part of the output) -file(WRITE "${PROJECT_BINARY_DIR}/libwebsockets.pc" -"prefix=\"${CMAKE_INSTALL_PREFIX}\" -exec_prefix=\${prefix} -libdir=\${exec_prefix}/lib${LIB_SUFFIX} -includedir=\${prefix}/include - -Name: libwebsockets -Description: Websockets server and client library -Version: ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH} - -Libs: -L\${libdir} -lwebsockets -Cflags: -I\${includedir}" -) - - install(FILES "${PROJECT_BINARY_DIR}/libwebsockets.pc" - DESTINATION lib${LIB_SUFFIX}/pkgconfig) - -file(WRITE "${PROJECT_BINARY_DIR}/libwebsockets_static.pc" -"prefix=\"${CMAKE_INSTALL_PREFIX}\" -exec_prefix=\${prefix} -libdir=\${exec_prefix}/lib${LIB_SUFFIX} -includedir=\${prefix}/include - -Name: libwebsockets_static -Description: Websockets server and client static library -Version: ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH} - -Libs: -L\${libdir} -lwebsockets_static -Libs.private: -Cflags: -I\${includedir}" -) - - install(FILES "${PROJECT_BINARY_DIR}/libwebsockets_static.pc" - DESTINATION lib${LIB_SUFFIX}/pkgconfig) - - -endif(UNIX) - # # Installation preparations. # -if(WIN32 AND NOT CYGWIN) - set(DEF_INSTALL_CMAKE_DIR cmake) -else() - set(DEF_INSTALL_CMAKE_DIR lib${LIB_SUFFIX}/cmake/libwebsockets) -endif() - -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() - export(PACKAGE libwebsockets) -# 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/LibwebsocketsConfig.cmake.in - ${PROJECT_BINARY_DIR}/LibwebsocketsConfig.cmake - @ONLY) +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) @@ -2878,139 +938,14 @@ "${LWS_ABSOLUTE_INSTALL_CMAKE_DIR}" "${LWS_ABSOLUTE_INSTALL_INCLUDE_DIR}") # Calculate the relative directory from the cmake dir. -# Note the EVENT_CMAKE_DIR is defined in JanssonConfig.cmake.in, -# we escape it here so it's evaluated when it is included instead -# so that the include dirs are given relative to where the -# config file is located. -set(LWS__INCLUDE_DIRS - "\${LWS_CMAKE_DIR}/${REL_INCLUDE_DIR}") -configure_file(${PROJECT_SOURCE_DIR}/cmake/LibwebsocketsConfig.cmake.in - ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/LibwebsocketsConfig.cmake - @ONLY) - -# Generate version info for both build-tree and install-tree. -configure_file(${PROJECT_SOURCE_DIR}/cmake/LibwebsocketsConfigVersion.cmake.in - ${PROJECT_BINARY_DIR}/LibwebsocketsConfigVersion.cmake - @ONLY) - - set_target_properties(${LWS_LIBRARIES} - PROPERTIES PUBLIC_HEADER "${HDR_PUBLIC}") - -# -# Installation. -# - -install(DIRECTORY include/libwebsockets - DESTINATION "${LWS_INSTALL_INCLUDE_DIR}" COMPONENT dev_headers) - -# Install libs and headers. -install(TARGETS ${LWS_LIBRARIES} - EXPORT LibwebsocketsTargets - LIBRARY DESTINATION "${LWS_INSTALL_LIB_DIR}${LIB_SUFFIX}" COMPONENT libraries - ARCHIVE DESTINATION "${LWS_INSTALL_LIB_DIR}${LIB_SUFFIX}" COMPONENT libraries - RUNTIME DESTINATION "${LWS_INSTALL_BIN_DIR}" COMPONENT libraries # Windows DLLs - PUBLIC_HEADER DESTINATION "${LWS_INSTALL_INCLUDE_DIR}" COMPONENT dev) - -set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries") -set(CPACK_COMPONENT_DEV_DISPLAY_NAME "Development files") - -# Install test apps. -if (NOT LWS_WITHOUT_TESTAPPS) - install(TARGETS ${TEST_APP_LIST} - RUNTIME DESTINATION ${LWS_INSTALL_EXAMPLES_DIR} - COMPONENT examples) - set(CPACK_COMPONENT_EXAMPLES_DISPLAY_NAME "Example files") -endif() - -# lwsws -if (LWS_WITH_LWSWS) - install(TARGETS lwsws - RUNTIME DESTINATION "${LWS_INSTALL_BIN_DIR}" COMPONENT lwsws ) -endif() - -# Programs shared files used by the test-server. -if (NOT LWS_WITHOUT_TESTAPPS AND NOT LWS_WITHOUT_SERVER) - install(FILES ${TEST_SERVER_DATA} - DESTINATION share/libwebsockets-test-server - COMPONENT examples) - - install(FILES "${PROJECT_SOURCE_DIR}/test-apps/private/index.html" - DESTINATION share/libwebsockets-test-server/private - COMPONENT examples) -if (LWS_WITH_CGI) - set(CGI_TEST_SCRIPT "${PROJECT_SOURCE_DIR}/test-apps/lws-cgi-test.sh") - install(FILES ${CGI_TEST_SCRIPT} - PERMISSIONS OWNER_EXECUTE GROUP_EXECUTE WORLD_EXECUTE OWNER_READ GROUP_READ WORLD_READ - DESTINATION share/libwebsockets-test-server - COMPONENT examples) - endif() -endif() - - -if (NOT LWS_WITHOUT_TEST_SERVER AND NOT LWS_WITHOUT_SERVER AND NOT LWS_WITHOUT_TESTAPPS) - install(FILES test-apps/lws-ssh-test-keys;test-apps/lws-ssh-test-keys.pub - DESTINATION share/libwebsockets-test-server - COMPONENT examples) -endif() - -# plugins - -if (LWS_WITH_PLUGINS) - install(TARGETS ${PLUGINS_LIST} - PERMISSIONS OWNER_WRITE OWNER_EXECUTE GROUP_EXECUTE WORLD_EXECUTE OWNER_READ GROUP_READ WORLD_READ - DESTINATION share/libwebsockets-test-server/plugins - COMPONENT plugins) - - if (NOT WIN32) - install(FILES plugins/deaddrop/assets/index.html;plugins/deaddrop/assets/deaddrop.js;plugins/deaddrop/assets/deaddrop.css;plugins/deaddrop/assets/drop.svg - DESTINATION share/libwebsockets-test-server/deaddrop - COMPONENT plugins) - endif() - - -if (LWS_WITH_SERVER_STATUS) - install(FILES plugins/server-status.html;plugins/server-status.js;plugins/server-status.css;plugins/lwsws-logo.png - DESTINATION share/libwebsockets-test-server/server-status - COMPONENT examples) -endif() -if (LWS_WITH_GENERIC_SESSIONS) - install(FILES - plugins/generic-sessions/assets/lwsgs-logo.png - plugins/generic-sessions/assets/seats.jpg - plugins/generic-sessions/assets/failed-login.html - plugins/generic-sessions/assets/lwsgs.js - plugins/generic-sessions/assets/lwsgs.css - plugins/generic-sessions/assets/post-register-fail.html - plugins/generic-sessions/assets/post-register-ok.html - plugins/generic-sessions/assets/post-verify-ok.html - plugins/generic-sessions/assets/post-verify-fail.html - plugins/generic-sessions/assets/sent-forgot-ok.html - plugins/generic-sessions/assets/sent-forgot-fail.html - plugins/generic-sessions/assets/post-forgot-ok.html - plugins/generic-sessions/assets/post-forgot-fail.html - plugins/generic-sessions/assets/index.html - DESTINATION share/libwebsockets-test-server/generic-sessions - COMPONENT examples) - install(FILES plugins/generic-sessions/assets/successful-login.html - DESTINATION share/libwebsockets-test-server/generic-sessions/needauth - COMPONENT examples) - install(FILES plugins/generic-sessions/assets/admin-login.html - DESTINATION share/libwebsockets-test-server/generic-sessions/needadmin - COMPONENT examples) -endif() - - install(FILES - plugins/generic-table/assets/lwsgt.js - plugins/generic-table/assets/index.html - DESTINATION share/libwebsockets-test-server/generic-table - COMPONENT examples) - -endif() +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}/LibwebsocketsConfig.cmake" - "${PROJECT_BINARY_DIR}/LibwebsocketsConfigVersion.cmake" + "${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. @@ -3025,116 +960,7 @@ # Most people are more used to "make dist" compared to "make package_source" add_custom_target(dist COMMAND "${CMAKE_MAKE_PROGRAM}" package_source) -include(UseRPMTools) -if (RPMTools_FOUND) - RPMTools_ADD_RPM_TARGETS(libwebsockets scripts/libwebsockets.spec) -endif() - -message("---------------------------------------------------------------------") -message(" Settings: (For more help do cmake -LH )") -message("---------------------------------------------------------------------") -message(" LWS_WITH_STATIC = ${LWS_WITH_STATIC}") -message(" LWS_WITH_SHARED = ${LWS_WITH_SHARED}") -message(" LWS_WITH_SSL = ${LWS_WITH_SSL} (SSL Support)") -message(" LWS_SSL_CLIENT_USE_OS_CA_CERTS = ${LWS_SSL_CLIENT_USE_OS_CA_CERTS}") -message(" LWS_WITH_WOLFSSL = ${LWS_WITH_WOLFSSL} (wolfSSL/CyaSSL replacement for OpenSSL)") -if (LWS_WITH_WOLFSSL) - message(" LWS_WOLFSSL_LIBRARIES = ${LWS_WOLFSSL_LIBRARIES}") - message(" LWS_WOLFSSL_INCLUDE_DIRS = ${LWS_WOLFSSL_INCLUDE_DIRS}") -endif() -message(" LWS_WITH_MBEDTLS = ${LWS_WITH_MBEDTLS} (mbedTLS replacement for OpenSSL)") -message(" LWS_WITHOUT_BUILTIN_SHA1 = ${LWS_WITHOUT_BUILTIN_SHA1}") -message(" LWS_WITHOUT_BUILTIN_GETIFADDRS = ${LWS_WITHOUT_BUILTIN_GETIFADDRS}") -message(" LWS_WITHOUT_CLIENT = ${LWS_WITHOUT_CLIENT}") -message(" LWS_WITHOUT_SERVER = ${LWS_WITHOUT_SERVER}") -message(" LWS_LINK_TESTAPPS_DYNAMIC = ${LWS_LINK_TESTAPPS_DYNAMIC}") -message(" LWS_WITHOUT_TESTAPPS = ${LWS_WITHOUT_TESTAPPS}") -message(" LWS_WITHOUT_TEST_SERVER = ${LWS_WITHOUT_TEST_SERVER}") -message(" LWS_WITHOUT_TEST_SERVER_EXTPOLL = ${LWS_WITHOUT_TEST_SERVER_EXTPOLL}") -message(" LWS_WITHOUT_TEST_PING = ${LWS_WITHOUT_TEST_PING}") -message(" LWS_WITHOUT_TEST_CLIENT = ${LWS_WITHOUT_TEST_CLIENT}") -message(" LWS_WITHOUT_EXTENSIONS = ${LWS_WITHOUT_EXTENSIONS}") -message(" LWS_WITHOUT_DAEMONIZE = ${LWS_WITHOUT_DAEMONIZE}") -message(" LWS_WITH_LIBEV = ${LWS_WITH_LIBEV}") -message(" LWS_WITH_LIBUV = ${LWS_WITH_LIBUV}") -message(" LWS_WITH_LIBEVENT = ${LWS_WITH_LIBEVENT}") -message(" LWS_WITH_GLIB = ${LWS_WITH_GLIB}") -message(" LWS_IPV6 = ${LWS_IPV6}") -message(" LWS_UNIX_SOCK = ${LWS_UNIX_SOCK}") -message(" LWS_WITH_HTTP2 = ${LWS_WITH_HTTP2}") -message(" LWS_ROLE_MQTT = ${LWS_ROLE_MQTT}") -message(" LWS_SSL_SERVER_WITH_ECDH_CERT = ${LWS_SSL_SERVER_WITH_ECDH_CERT}") -message(" LWS_MAX_SMP = ${LWS_MAX_SMP}") -message(" LWS_HAVE_PTHREAD_H = ${LWS_HAVE_PTHREAD_H}") -message(" LWS_WITH_CGI = ${LWS_WITH_CGI}") -message(" LWS_HAVE_OPENSSL_ECDH_H = ${LWS_HAVE_OPENSSL_ECDH_H}") -message(" LWS_HAVE_SSL_CTX_set1_param = ${LWS_HAVE_SSL_CTX_set1_param}") -message(" LWS_HAVE_RSA_SET0_KEY = ${LWS_HAVE_RSA_SET0_KEY}") -message(" LWS_WITH_HTTP_PROXY = ${LWS_WITH_HTTP_PROXY}") -message(" LIBHUBBUB_LIBRARIES = ${LIBHUBBUB_LIBRARIES}") -message(" PLUGINS = ${PLUGINS_LIST}") -message(" LWS_WITH_ACCESS_LOG = ${LWS_WITH_ACCESS_LOG}") -message(" LWS_WITH_SERVER_STATUS = ${LWS_WITH_SERVER_STATUS}") -message(" LWS_WITH_LEJP = ${LWS_WITH_LEJP}") -message(" LWS_WITH_LEJP_CONF = ${LWS_WITH_LEJP_CONF}") -# this is broken atm -#message(" LWS_WITH_SMTP = ${LWS_WITH_SMTP}") -message(" LWS_WITH_GENERIC_SESSIONS = ${LWS_WITH_GENERIC_SESSIONS}") -message(" LWS_STATIC_PIC = ${LWS_STATIC_PIC}") -message(" LWS_WITH_RANGES = ${LWS_WITH_RANGES}") -message(" LWS_PLAT_OPTEE = ${LWS_PLAT_OPTEE}") -message(" LWS_PLAT_FREERTOS = ${LWS_PLAT_FREERTOS}") -message(" LWS_WITH_ZIP_FOPS = ${LWS_WITH_ZIP_FOPS}") -message(" LWS_AVOID_SIGPIPE_IGN = ${LWS_AVOID_SIGPIPE_IGN}") -message(" LWS_WITH_STATS = ${LWS_WITH_STATS}") -message(" LWS_WITH_SOCKS5 = ${LWS_WITH_SOCKS5}") -message(" LWS_HAVE_SYS_CAPABILITY_H = ${LWS_HAVE_SYS_CAPABILITY_H}") -message(" LWS_HAVE_LIBCAP = ${LWS_HAVE_LIBCAP}") -message(" LWS_WITH_PEER_LIMITS = ${LWS_WITH_PEER_LIMITS}") -message(" LWS_HAVE_ATOLL = ${LWS_HAVE_ATOLL}") -message(" LWS_HAVE__ATOI64 = ${LWS_HAVE__ATOI64}") -message(" LWS_HAVE_STAT32I64 = ${LWS_HAVE_STAT32I64}") -message(" LWS_HAS_INTPTR_T = ${LWS_HAS_INTPTR_T}") -message(" LWS_WITH_EXPORT_LWSTARGETS = ${LWS_WITH_EXPORT_LWSTARGETS}") -message(" LWS_WITH_ABSTRACT = ${LWS_WITH_ABSTRACT}") -message("---------------------------------------------------------------------") - -# These will be available to parent projects including libwebsockets using add_subdirectory() -set(LIBWEBSOCKETS_LIBRARIES ${LWS_LIBRARIES} CACHE STRING "Libwebsocket libraries") -if (LWS_WITH_STATIC) - set(LIBWEBSOCKETS_LIBRARIES_STATIC websockets CACHE STRING "Libwebsocket static library") -endif() -if (LWS_WITH_SHARED) - set(LIBWEBSOCKETS_LIBRARIES_SHARED websockets_shared CACHE STRING "Libwebsocket shared library") -endif() - -if (LWS_WITH_MINIMAL_EXAMPLES) - MACRO(SUBDIRLIST result curdir) - FILE(GLOB children RELATIVE ${curdir} ${curdir}/*) - SET(dirlist "") - - FOREACH(child ${children}) - IF(IS_DIRECTORY ${curdir}/${child}) - LIST(APPEND dirlist ${child}) - ENDIF() - ENDFOREACH() - - SET(${result} ${dirlist}) - ENDMACRO() - - SUBDIRLIST(SUBDIRS "${PROJECT_SOURCE_DIR}/minimal-examples") - FOREACH(subdir ${SUBDIRS}) - - SUBDIRLIST(SUBDIRS2 "${PROJECT_SOURCE_DIR}/minimal-examples/${subdir}") - FOREACH(subdir2 ${SUBDIRS2}) - if (EXISTS "${PROJECT_SOURCE_DIR}/minimal-examples/${subdir}/${subdir2}/CMakeLists.txt") - message("Processing ${PROJECT_SOURCE_DIR}/minimal-examples/${subdir}/${subdir2}") - add_subdirectory("${PROJECT_SOURCE_DIR}/minimal-examples/${subdir}/${subdir2}") - endif() - ENDFOREACH() - ENDFOREACH() -ENDIF() # This must always be last! include(CPack) diff -Nru libwebsockets-4.0.20/contrib/android-make-script.sh libwebsockets-4.1.6/contrib/android-make-script.sh --- libwebsockets-4.0.20/contrib/android-make-script.sh 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/contrib/android-make-script.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,116 +0,0 @@ -#!/bin/bash - -# -# Build libwebsockets static library for Android -# - -# path to NDK -export NDK=/opt/ndk_r17/android-ndk-r17-beta2-linux-x86_64/android-ndk-r17-beta2 -export ANDROID_NDK=${NDK} -export TOOLCHAIN=${NDK}/toolchain -export CORSS_SYSROOT=${NDK}/sysroot -export SYSROOT=${NDK}/platforms/android-22/arch-arm -set -e - -# Download packages libz, libuv, mbedtls and libwebsockets -#zlib-1.2.8 -#libuv-1.x -#mbedtls-2.11.0 -#libwebsockets-3.0.0 - - -# create a local android toolchain -API=${3:-24} - -$NDK/build/tools/make-standalone-toolchain.sh \ - --toolchain=arm-linux-androideabi-4.9 \ - --arch=arm \ - --install-dir=`pwd`/android-toolchain-arm \ - --platform=android-$API \ - --stl=libc++ \ - --force \ - --verbose - -# setup environment to use the gcc/ld from the android toolchain -export INSTALL_PATH=/opt/libwebsockets_android/android-toolchain-arm -export TOOLCHAIN_PATH=`pwd`/android-toolchain-arm -export TOOL=arm-linux-androideabi -export NDK_TOOLCHAIN_BASENAME=${TOOLCHAIN_PATH}/bin/${TOOL} -export PATH=`pwd`/android-toolchain-arm/bin:$PATH -export CC=$NDK_TOOLCHAIN_BASENAME-gcc -export CXX=$NDK_TOOLCHAIN_BASENAME-g++ -export LINK=${CXX} -export LD=$NDK_TOOLCHAIN_BASENAME-ld -export AR=$NDK_TOOLCHAIN_BASENAME-ar -export RANLIB=$NDK_TOOLCHAIN_BASENAME-ranlib -export STRIP=$NDK_TOOLCHAIN_BASENAME-strip -export PLATFORM=android -export CFLAGS="D__ANDROID_API__=$API" - -# configure and build libuv -[ ! -f ./android-toolchain-arm/lib/libuv.so ] && { -cd libuv -echo "=============================================>> build libuv" - -PATH=$TOOLCHAIN_PATH:$PATH make clean -PATH=$TOOLCHAIN_PATH:$PATH make -PATH=$TOOLCHAIN_PATH:$PATH make install -echo "<<============================================= build libuv" -cd .. -} - -# configure and build zlib -[ ! -f ./android-toolchain-arm/lib/libz.so ] && { -cd zlib-1.2.8 -echo "=============================================>> build libz" - -PATH=$TOOLCHAIN_PATH:$PATH make clean -PATH=$TOOLCHAIN_PATH:$PATH make -PATH=$TOOLCHAIN_PATH:$PATH make install -echo "<<============================================= build libz" -cd .. -} - -# configure and build mbedtls -[ ! -f ./android-toolchain-arm/lib/libmbedtls.so ] && { -echo "=============================================>> build mbedtls" -PREFIX=$TOOLCHAIN_PATH -cd mbedtls-2.11.0 -[ ! -d build ] && mkdir build -cd build -export CFLAGS="$CFLAGS -fomit-frame-pointer" - -PATH=$TOOLCHAIN_PATH:$PATH cmake .. -DCMAKE_TOOLCHAIN_FILE=`pwd`/../cross-arm-android-gnueabi.cmake \ - -DCMAKE_INSTALL_PREFIX:PATH=${INSTALL_PATH} \ - -DCMAKE_BUILD_TYPE=RELEASE -DUSE_SHARED_MBEDTLS_LIBRARY=On - -PATH=$TOOLCHAIN_PATH:$PATH make clean -PATH=$TOOLCHAIN_PATH:$PATH make SHARED=1 -PATH=$TOOLCHAIN_PATH:$PATH make install -echo "<<============================================= build mbedtls" -cd ../.. -} - -# configure and build libwebsockets -[ ! -f ./android-toolchain-arm/lib/libwebsockets.so ] && { -cd libwebsockets -[ ! -d build ] && mkdir build -cd build -echo "=============================================>> build libwebsockets" - -PATH=$TOOLCHAIN_PATH:$PATH cmake .. -DCMAKE_TOOLCHAIN_FILE=`pwd`/../cross-arm-android-gnueabi.cmake \ - -DCMAKE_INSTALL_PREFIX:PATH=${INSTALL_PATH} \ - -DLWS_WITH_LWSWS=1 \ - -DLWS_WITH_MBEDTLS=1 \ - -DLWS_WITHOUT_TESTAPPS=1 \ - -DLWS_MBEDTLS_LIBRARIES="${INSTALL_PATH}/lib/libmbedcrypto.a;${INSTALL_PATH}/lib/libmbedtls.a;${INSTALL_PATH}/lib/libmbedx509.a" \ - -DLWS_MBEDTLS_INCLUDE_DIRS=${INSTALL_PATH}/include \ - -DLWS_LIBUV_LIBRARIES=${INSTALL_PATH}/lib/libuv.so \ - -DLWS_LIBUV_INCLUDE_DIRS=${INSTALL_PATH}/include \ - -DLWS_ZLIB_LIBRARIES=${INSTALL_PATH}/lib/libz.so \ - -DLWS_ZLIB_INCLUDE_DIRS=${INSTALL_PATH}/include -PATH=$TOOLCHAIN_PATH:$PATH make -PATH=$TOOLCHAIN_PATH:$PATH make install -echo "<<============================================= build libwebsockets" -cd ../.. -} diff -Nru libwebsockets-4.0.20/contrib/cross-aarch64-android.cmake libwebsockets-4.1.6/contrib/cross-aarch64-android.cmake --- libwebsockets-4.0.20/contrib/cross-aarch64-android.cmake 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/contrib/cross-aarch64-android.cmake 2020-12-01 17:40:26.000000000 +0000 @@ -3,16 +3,27 @@ # # This can be used when running cmake in the following way: # cd build/ -# cmake .. -DCMAKE_TOOLCHAIN_FILE=../cross-aarch64-android.cmake +# cmake .. -DCMAKE_TOOLCHAIN_FILE=contrib/cross-aarch64-android.cmake # -# Target operating system name. -set(CMAKE_SYSTEM_NAME Linux) + +set(ANDROID_API_VER 24) +set(ABARCH1 arm64) set(CMAKE_SYSTEM_PROCESSOR aarch64) +set(NDK /opt/android/ndk/21.1.6352462/) +set(CROSS_SYSROOT "${NDK}/platforms/android-${ANDROID_API_VER}/arch-${ABARCH1}") +set(BUILD_ARCH linux-x86_64) -# Name of C compiler. -set(CMAKE_C_COMPILER "aarch64-linux-android-gcc") -set(CMAKE_CXX_COMPILER "aarch64-linux-android-g++") +# +# Rest should be computed from the above +# +set(TC_PATH ${NDK}/toolchains/llvm/prebuilt/${BUILD_ARCH}) +set(TC_BASE ${TC_PATH}/bin/${CMAKE_SYSTEM_PROCESSOR}-linux-android) +set(PLATFORM android) +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_C_COMPILER "${TC_BASE}${ANDROID_API_VER}-clang") +set(CMAKE_CXX_COMPILER "${TC_BASE}${ANDROID_API_VER}-clang++") +set(CMAKE_STAGING_PREFIX "${CROSS_SYSROOT}") # # Different build system distros set release optimization level to different @@ -31,11 +42,10 @@ endif() #-nostdlib -SET(CMAKE_C_FLAGS "-DGCC_VER=\"\\\"$(GCC_VER)\\\"\" -DARM64=1 -D__LP64__=1 -Os -g3 -fpie -mstrict-align -fPIC -ffunction-sections -fdata-sections " CACHE STRING "" FORCE) +SET(CMAKE_C_FLAGS "-DGCC_VER=\"\\\"$(GCC_VER)\\\"\" -DARM64=1 -D__LP64__=1 -Os -g3 -fpie -mstrict-align -fPIC -ffunction-sections -fdata-sections -D__ANDROID_API__=${ANDROID_API_VER} -Wno-pointer-sign" CACHE STRING "" FORCE) -# Where to look for the target environment. (More paths can be added here) -#set(CMAKE_FIND_ROOT_PATH "") +set(CMAKE_FIND_ROOT_PATH "${CROSS_SYSROOT}") # Adjust the default behavior of the FIND_XXX() commands: # search programs in the host environment only. diff -Nru libwebsockets-4.0.20/contrib/cross-atmel.cmake libwebsockets-4.1.6/contrib/cross-atmel.cmake --- libwebsockets-4.0.20/contrib/cross-atmel.cmake 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/contrib/cross-atmel.cmake 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,119 @@ +# +# CMake Toolchain file for crosscompiling on Atmel Arm products +# +# To build without tls +# +# cd build/ +# cmake .. -DCMAKE_INSTALL_PREFIX:PATH=/opt/atmel/cross-root \ +# -DCMAKE_TOOLCHAIN_FILE=../contrib/cross-atmel.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=0 \ +# -DLWS_WITH_SSL=0 \ +# -DLWS_WITH_FILE_OPS=0 +# + +# I had to edit /opt/xdk-asf-3.48.0/thirdparty/lwip/lwip-port-1.4.1-dev/sam/include/arch/cc.h +# to comment out #define LWIP_PROVIDE_ERRNO + +# if your sdk lives somewhere else, this is the only place that should need changing + +set(CROSS_BASE /opt/arm-none-eabi) +set(SDK_BASE /opt/xdk-asf-3.48.0) +set(CROSS_PATH ${CROSS_BASE}/bin/arm-none-eabi) + +set(LWIP_VER 1.4.1-dev) +set(FREERTOS_VER 10.0.0) + +# +# Target operating system name. +set(CMAKE_SYSTEM_NAME Generic) + +# Name of C compiler. +set(CMAKE_C_COMPILER "${CROSS_PATH}-gcc") + +# +# cmake believes we should link a NOP test program OK, but since we're +# baremetal, that's not true in our case. It tries to build this test +# with the cross compiler, but with no args on it, and it fails. +# So disable this test for this toolchain (we'll find out soon enough +# if we actually can't compile anything) + +set(CMAKE_C_COMPILER_WORKS 1) +set(CMAKE_CXX_COMPILER_WORKS 1) + +# +# similarly we're building a .a like this, we can't actually build +# complete test programs to probe api availability... so force some +# key ones + +set(LWS_HAVE_mbedtls_ssl_conf_alpn_protocols 1) +set(LWS_HAVE_mbedtls_ssl_conf_alpn_protocols 1) +set(LWS_HAVE_mbedtls_ssl_get_alpn_protocol 1) +set(LWS_HAVE_mbedtls_ssl_conf_sni 1) +set(LWS_HAVE_mbedtls_ssl_set_hs_ca_chain 1) +set(LWS_HAVE_mbedtls_ssl_set_hs_own_cert 1) +set(LWS_HAVE_mbedtls_ssl_set_hs_authmode 1) +set(LWS_HAVE_mbedtls_net_init 1) +set(LWS_HAVE_mbedtls_md_setup 1) # not on xenial 2.2 +set(LWS_HAVE_mbedtls_rsa_complete 1) # not on xenial 2.2 +set(LWS_HAVE_mbedtls_internal_aes_encrypt 1) +# +# Different build system distros set release optimization level to different +# things according to their local policy, eg, Fedora is -O2 and Ubuntu is -O3 +# here. Actually the build system's local policy is completely unrelated to +# our desire for cross-build release optimization policy for code built to run +# on a completely different target than the build system itself. +# +# Since this goes last on the compiler commandline we have to override it to a +# sane value for cross-build here. Notice some gcc versions enable broken +# optimizations with -O3. +# +if (CMAKE_BUILD_TYPE MATCHES RELEASE OR CMAKE_BUILD_TYPE MATCHES Release OR CMAKE_BUILD_TYPE MATCHES release) + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O2") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2") +endif() + +set(PLAT_ARCH ARM_CM4F) +set(PLAT_ARCH_CMSIS sam4e) +set(PLAT_SOC __SAM4E16E__) +set(PLAT_BOARD SAM4E_XPLAINED_PRO) + +set(CF_LWIP "${CF_LWIP} -I${SDK_BASE}/thirdparty/lwip/lwip-${LWIP_VER}/src/include/lwip") +set(CF_LWIP "${CF_LWIP} -I${SDK_BASE}/thirdparty/lwip/lwip-${LWIP_VER}/src/include/posix") +set(CF_LWIP "${CF_LWIP} -I${SDK_BASE}/thirdparty/lwip/lwip-${LWIP_VER}/src/include") +set(CF_LWIP "${CF_LWIP} -I${SDK_BASE}/thirdparty/lwip/lwip-${LWIP_VER}/src/module_config") +set(CF_LWIP "${CF_LWIP} -I${SDK_BASE}/thirdparty/lwip/lwip-port-${LWIP_VER}/sam/include") +set(CF_LWIP "${CF_LWIP} -I${SDK_BASE}/thirdparty/lwip/lwip-${LWIP_VER}/src/include/ipv4") + +set(CF_FREERTOS "${CF_FREERTOS} -I${SDK_BASE}/thirdparty/freertos/freertos-${FREERTOS_VER}/Source/include") +set(CF_FREERTOS "${CF_FREERTOS} -I${SDK_BASE}/thirdparty/freertos/freertos-${FREERTOS_VER}/module_config") +set(CF_FREERTOS "${CF_FREERTOS} -I${SDK_BASE}/thirdparty/freertos/freertos-${FREERTOS_VER}/Source/portable/GCC/${PLAT_ARCH}") + +set(CF_SDK_GLUE "${CF_SDK_GLUE} -I${SDK_BASE}/common/boards") +set(CF_SDK_GLUE "${CF_SDK_GLUE} -I${SDK_BASE}/common/utils") +set(CF_SDK_GLUE "${CF_SDK_GLUE} -I${SDK_BASE}/sam/utils/") +set(CF_SDK_GLUE "${CF_SDK_GLUE} -I${SDK_BASE}/sam/utils/preprocessor") +set(CF_SDK_GLUE "${CF_SDK_GLUE} -I${SDK_BASE}/sam/utils/header_files") +set(CF_SDK_GLUE "${CF_SDK_GLUE} -I${SDK_BASE}/sam/boards") +set(CF_SDK_GLUE "${CF_SDK_GLUE} -I${SDK_BASE}/sam/utils/cmsis/${PLAT_ARCH_CMSIS}/source/templates") +set(CF_SDK_GLUE "${CF_SDK_GLUE} -I${SDK_BASE}/sam/utils/cmsis/${PLAT_ARCH_CMSIS}/include") +set(CF_SDK_GLUE "${CF_SDK_GLUE} -I${SDK_BASE}/thirdparty/CMSIS/Include") +set(CF_SDK_GLUE "${CF_SDK_GLUE} -I${SDK_BASE}/common/utils/osprintf") + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -lnosys -nostartfiles ${CF_LWIP} ${CF_FREERTOS} ${CF_SDK_GLUE} -DBOARD=${PLAT_BOARD} -D${PLAT_SOC} -DLWIP_TIMEVAL_PRIVATE=0 -DLWS_AMAZON_RTOS=1 -DLWIP_SOCKET_OFFSET=0 -DLWIP_COMPAT_SOCKETS -DLWIP_DNS=1 -DLWIP_SOCKETS=1 " CACHE STRING "" FORCE) + +# Where to look for the target environment. (More paths can be added here) +set(CMAKE_FIND_ROOT_PATH "${CROSS_PATH}") + +# Adjust the default behavior of the FIND_XXX() commands: +# search programs in the host environment only. +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + +# Search headers and libraries in the target environment only. +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + diff -Nru libwebsockets-4.0.20/contrib/cross-esp32.cmake libwebsockets-4.1.6/contrib/cross-esp32.cmake --- libwebsockets-4.0.20/contrib/cross-esp32.cmake 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/contrib/cross-esp32.cmake 2020-12-01 17:40:26.000000000 +0000 @@ -9,11 +9,13 @@ # Target operating system name. set(CMAKE_SYSTEM_NAME Linux) -# Name of C compiler. -set(CMAKE_C_COMPILER "${CROSS_PATH}/bin/xtensa-esp32-elf-gcc${EXECUTABLE_EXT}") -set(CMAKE_AR "${CROSS_PATH}/bin/xtensa-esp32-elf-ar${EXECUTABLE_EXT}") -set(CMAKE_RANLIB "${CROSS_PATH}/bin/xtensa-esp32-elf-ranlib${EXECUTABLE_EXT}") -set(CMAKE_LINKER "${CROSS_PATH}/bin/xtensa-esp32-elf-ld${EXECUTABLE_EXT}") +# assumed these are set up on the $PATH +set(TC xtensa-esp32-elf) + +set(CMAKE_C_COMPILER "${TC}-gcc${EXECUTABLE_EXT}") +set(CMAKE_AR "${TC}-ar${EXECUTABLE_EXT}") +set(CMAKE_RANLIB "${TC}-ranlib${EXECUTABLE_EXT}") +set(CMAKE_LINKER "${TC}-ld${EXECUTABLE_EXT}") # # Different build system distros set release optimization level to different diff -Nru libwebsockets-4.0.20/contrib/cross-linkit.cmake libwebsockets-4.1.6/contrib/cross-linkit.cmake --- libwebsockets-4.0.20/contrib/cross-linkit.cmake 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/contrib/cross-linkit.cmake 2020-12-01 17:40:26.000000000 +0000 @@ -1,10 +1,10 @@ # # CMake Toolchain file for crosscompiling on Mediatek Linkit 7967 # -# This can be used like this (with Linkit sdk unpacked to /projects/linkit/sdk) +# This can be used like this (with Linkit sdk unpacked to /opt/linkit) # # cd build/ -# cmake .. -DCMAKE_INSTALL_PREFIX:PATH=/projects/linkit/cross-root \ +# cmake .. -DCMAKE_INSTALL_PREFIX:PATH=/opt/linkit/cross-root \ # -DCMAKE_TOOLCHAIN_FILE=../contrib/cross-linkit.cmake \ # -DLWS_PLAT_FREERTOS=1 \ # -DLWS_WITH_ZLIB=0 \ @@ -16,7 +16,7 @@ # # if your sdk lives somewhere else, this is the only place that should need changing -set(CROSS_BASE /projects/linkit/sdk) +set(CROSS_BASE /opt/linkit/sdk) set(CROSS_PATH ${CROSS_BASE}/tools/gcc/gcc-arm-none-eabi) # @@ -38,6 +38,22 @@ set(CMAKE_CXX_COMPILER_WORKS 1) # +# similarly we're building a .a like this, we can't actually build +# complete test programs to probe api availability... so force some +# key ones + +set(LWS_HAVE_mbedtls_ssl_conf_alpn_protocols 1) +set(LWS_HAVE_mbedtls_ssl_conf_alpn_protocols 1) +set(LWS_HAVE_mbedtls_ssl_get_alpn_protocol 1) +set(LWS_HAVE_mbedtls_ssl_conf_sni 1) +set(LWS_HAVE_mbedtls_ssl_set_hs_ca_chain 1) +set(LWS_HAVE_mbedtls_ssl_set_hs_own_cert 1) +set(LWS_HAVE_mbedtls_ssl_set_hs_authmode 1) +set(LWS_HAVE_mbedtls_net_init 1) +set(LWS_HAVE_mbedtls_md_setup 1) # not on xenial 2.2 +set(LWS_HAVE_mbedtls_rsa_complete 1) # not on xenial 2.2 +set(LWS_HAVE_mbedtls_internal_aes_encrypt 1) +# # Different build system distros set release optimization level to different # things according to their local policy, eg, Fedora is -O2 and Ubuntu is -O3 # here. Actually the build system's local policy is completely unrelated to @@ -53,7 +69,7 @@ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2") endif() -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -nostartfiles -I${CROSS_BASE}/middleware/third_party/lwip/src/include/lwip -I${CROSS_BASE}/middleware/third_party/lwip/src/include -I${CROSS_BASE}/project/mt7687_hdk/apps/httpd/inc/ -I${CROSS_BASE}/kernel/service/inc/ -I${CROSS_BASE}/driver/chip/inc -I${CROSS_BASE}/driver/chip/mt7687/inc/ -I${CROSS_BASE}/driver/CMSIS/Device/MTK/mt7687/Include/ -I${CROSS_BASE}/driver/CMSIS/Include -I${CROSS_BASE}/middleware/third_party/lwip/ports/include/ -I${CROSS_BASE}/middleware/third_party/lwip/src/include/posix/ -I${CROSS_BASE}/kernel/rtos/FreeRTOS/Source/include/ -I${CROSS_BASE}/middleware/third_party/mbedtls/include/ -I${CROSS_BASE}/kernel/rtos/FreeRTOS/Source/portable/GCC/ARM_CM4F/ -I${CROSS_BASE}/middleware/third_party/sntp/inc/ -DLWS_AMAZON_RTOS=1" CACHE STRING "" FORCE) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -lnosys -nostartfiles -I${CROSS_BASE}/middleware/third_party/lwip/src/include/lwip -I${CROSS_BASE}/middleware/third_party/lwip/src/include -I${CROSS_BASE}/project/mt7687_hdk/apps/httpd/inc/ -I${CROSS_BASE}/kernel/service/inc/ -I${CROSS_BASE}/driver/chip/inc -I${CROSS_BASE}/driver/chip/mt7687/inc/ -I${CROSS_BASE}/driver/CMSIS/Device/MTK/mt7687/Include/ -I${CROSS_BASE}/driver/CMSIS/Include -I${CROSS_BASE}/middleware/third_party/lwip/ports/include/ -I${CROSS_BASE}/middleware/third_party/lwip/src/include/posix/ -I${CROSS_BASE}/kernel/rtos/FreeRTOS/Source/include/ -I${CROSS_BASE}/middleware/third_party/mbedtls/include/ -I${CROSS_BASE}/kernel/rtos/FreeRTOS/Source/portable/GCC/ARM_CM4F/ -I${CROSS_BASE}/middleware/third_party/sntp/inc/ -DLWS_AMAZON_RTOS=1" CACHE STRING "" FORCE) # Where to look for the target environment. (More paths can be added here) set(CMAKE_FIND_ROOT_PATH "${CROSS_PATH}") diff -Nru libwebsockets-4.0.20/contrib/cross-w32.cmake libwebsockets-4.1.6/contrib/cross-w32.cmake --- libwebsockets-4.0.20/contrib/cross-w32.cmake 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/contrib/cross-w32.cmake 2020-12-01 17:40:26.000000000 +0000 @@ -6,7 +6,11 @@ # cmake .. -DCMAKE_TOOLCHAIN_FILE=../contrib/cross-w32.cmake -DLWS_WITH_SSL=0 # -set(CROSS_PATH /opt/mingw32) +# the outermost path to your cross toolchain +#set(CROSS_PATH /opt/mingw32) +set(CROSS_PATH /usr) +# your cross root +set(CROSS_ROOT ${CROSS_PATH}/i686-w64-mingw32/sys-root/) # Target operating system name. set(CMAKE_SYSTEM_NAME Windows) @@ -15,7 +19,6 @@ set(CMAKE_C_COMPILER "${CROSS_PATH}/bin/i686-w64-mingw32-gcc") set(CMAKE_CXX_COMPILER "${CROSS_PATH}/bin/i686-w64-mingw32-g++") set(CMAKE_RC_COMPILER "${CROSS_PATH}/bin/i686-w64-mingw32-windres") -set(CMAKE_C_FLAGS "-Wno-error") # # Different build system distros set release optimization level to different @@ -34,7 +37,8 @@ endif() # Where to look for the target environment. (More paths can be added here) -set(CMAKE_FIND_ROOT_PATH "${CROSS_PATH}") +set(CMAKE_FIND_ROOT_PATH "${CROSS_ROOT}/mingw") +set(CMAKE_SYSROOT ${CROSS_ROOT}) # Adjust the default behavior of the FIND_XXX() commands: # search programs in the host environment only. diff -Nru libwebsockets-4.0.20/contrib/cross-w64.cmake libwebsockets-4.1.6/contrib/cross-w64.cmake --- libwebsockets-4.0.20/contrib/cross-w64.cmake 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/contrib/cross-w64.cmake 2020-12-01 17:40:26.000000000 +0000 @@ -3,13 +3,18 @@ # # This can be used when running cmake in the following way: # cd build/ -# cmake .. -DCMAKE_TOOLCHAIN_FILE=../contrib/cross-w64.cmake -DLWS_WITH_SSL=0 +# cmake .. -DCMAKE_TOOLCHAIN_FILE=../contrib/cross-w64.cmake # -set(CROSS_PATH /opt/mingw64) +# the outermost path to your cross toolchain +#set(CROSS_PATH /opt/mingw64) +set(CROSS_PATH /usr) +# your cross root +set(CROSS_ROOT ${CROSS_PATH}/x86_64-w64-mingw32/sys-root/) # Target operating system name. set(CMAKE_SYSTEM_NAME Windows) +set(CMAKE_SYSROOT ${CROSS_ROOT}) # Name of C compiler. set(CMAKE_C_COMPILER "${CROSS_PATH}/bin/x86_64-w64-mingw32-gcc") @@ -34,7 +39,7 @@ endif() # Where to look for the target environment. (More paths can be added here) -set(CMAKE_FIND_ROOT_PATH "${CROSS_PATH}") +set(CMAKE_FIND_ROOT_PATH "${CROSS_ROOT}/mingw") # Adjust the default behavior of the FIND_XXX() commands: # search programs in the host environment only. diff -Nru libwebsockets-4.0.20/contrib/iOS.cmake libwebsockets-4.1.6/contrib/iOS.cmake --- libwebsockets-4.0.20/contrib/iOS.cmake 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/contrib/iOS.cmake 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,229 @@ +# This file is based off of the Platform/Darwin.cmake and Platform/UnixPaths.cmake +# files which are included with CMake 2.8.4 +# It has been altered for iOS development + +# Options: +# +# IOS_PLATFORM = OS (default) or OS32 or SIMULATOR or SIMULATOR64 +# This decides if SDKS will be selected from the iPhoneOS.platform or iPhoneSimulator.platform folders +# OS - the default, used to build for iPhone and iPad physical devices, which have an arm arch. +# SIMULATOR - used to build for the Simulator platforms, which have an x86 arch. +# +# CMAKE_IOS_DEVELOPER_ROOT = automatic(default) or /path/to/platform/Developer folder +# By default this location is automatcially chosen based on the IOS_PLATFORM value above. +# If set manually, it will override the default location and force the user of a particular Developer Platform +# +# CMAKE_IOS_SDK_ROOT = automatic(default) or /path/to/platform/Developer/SDKs/SDK folder +# By default this location is automatcially chosen based on the CMAKE_IOS_DEVELOPER_ROOT value. +# In this case it will always be the most up-to-date SDK found in the CMAKE_IOS_DEVELOPER_ROOT path. +# If set manually, this will force the use of a specific SDK version +# +# IOS_BITCODE = 1/0: Enable bitcode or not. Only iOS >= 6.0 device build can enable bitcode. Default is enabled. + +# Macros: +# +# set_xcode_property (TARGET XCODE_PROPERTY XCODE_VALUE) +# A convenience macro for setting xcode specific properties on targets +# example: set_xcode_property (myioslib IPHONEOS_DEPLOYMENT_TARGET "3.1") +# +# find_host_package (PROGRAM ARGS) +# A macro used to find executable programs on the host system, not within the iOS environment. +# Thanks to the android-cmake project for providing the command + +# Standard settings +set (CMAKE_SYSTEM_NAME Darwin) +set (CMAKE_SYSTEM_VERSION 1) +set(CMAKE_CROSSCOMPILING TRUE) +set (UNIX TRUE) +set (APPLE TRUE) +set (IOS TRUE) + +if(NOT DEFINED IOS_BITCODE) # check xcode/clang version? since xcode 7 + set(IOS_BITCODE 1) +endif() +set(IOS_BITCODE_MARKER 0) + +# Required as of cmake 2.8.10 +set (CMAKE_OSX_DEPLOYMENT_TARGET "" CACHE STRING "Force unset of the deployment target for iOS" FORCE) + +# Determine the cmake host system version so we know where to find the iOS SDKs +find_program (CMAKE_UNAME uname /bin /usr/bin /usr/local/bin) +if (CMAKE_UNAME) + exec_program(uname ARGS -r OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_VERSION) + string (REGEX REPLACE "^([0-9]+)\\.([0-9]+).*$" "\\1" DARWIN_MAJOR_VERSION "${CMAKE_HOST_SYSTEM_VERSION}") +endif (CMAKE_UNAME) + +# Force the compilers to gcc for iOS +include (CMakeForceCompiler) +set (CMAKE_C_COMPILER /usr/bin/clang) +set (CMAKE_CXX_COMPILER /usr/bin/clang++) +set(CMAKE_AR ar CACHE FILEPATH "" FORCE) + +# Skip the platform compiler checks for cross compiling +set (CMAKE_CXX_COMPILER_WORKS TRUE) +set (CMAKE_C_COMPILER_WORKS TRUE) + +# All iOS/Darwin specific settings - some may be redundant +set (CMAKE_SHARED_LIBRARY_PREFIX "lib") +set (CMAKE_SHARED_LIBRARY_SUFFIX ".dylib") +set (CMAKE_SHARED_MODULE_PREFIX "lib") +set (CMAKE_SHARED_MODULE_SUFFIX ".so") +set (CMAKE_MODULE_EXISTS 1) +set (CMAKE_DL_LIBS "") + +if(IOS_BITCODE) + set(BITCODE_FLAGS "-fembed-bitcode") + elseif(IOS_BITCODE_MARKER) + set(BITCODE_FLAGS "-fembed-bitcode-marker") + endif() + +set (CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG "-compatibility_version ") +set (CMAKE_C_OSX_CURRENT_VERSION_FLAG "-current_version ") +set (CMAKE_CXX_OSX_COMPATIBILITY_VERSION_FLAG "${CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG}") +set (CMAKE_CXX_OSX_CURRENT_VERSION_FLAG "${CMAKE_C_OSX_CURRENT_VERSION_FLAG}") + +# Hidden visibilty is required for cxx on iOS +set (CMAKE_C_FLAGS_INIT "${BITCODE_FLAGS}") +set (CMAKE_CXX_FLAGS_INIT "-fvisibility=hidden -fvisibility-inlines-hidden ${BITCODE_FLAGS}") + +set (CMAKE_C_LINK_FLAGS "-Wl,-search_paths_first ${CMAKE_C_LINK_FLAGS}") +set (CMAKE_CXX_LINK_FLAGS "-Wl,-search_paths_first ${CMAKE_CXX_LINK_FLAGS}") + +set (CMAKE_PLATFORM_HAS_INSTALLNAME 1) +set (CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-dynamiclib -headerpad_max_install_names") +set (CMAKE_SHARED_MODULE_CREATE_C_FLAGS "-bundle -headerpad_max_install_names") +set (CMAKE_SHARED_MODULE_LOADER_C_FLAG "-Wl,-bundle_loader,") +set (CMAKE_SHARED_MODULE_LOADER_CXX_FLAG "-Wl,-bundle_loader,") +set (CMAKE_FIND_LIBRARY_SUFFIXES ".dylib" ".so" ".a") + +# hack: if a new cmake (which uses CMAKE_INSTALL_NAME_TOOL) runs on an old build tree +# (where install_name_tool was hardcoded) and where CMAKE_INSTALL_NAME_TOOL isn't in the cache +# and still cmake didn't fail in CMakeFindBinUtils.cmake (because it isn't rerun) +# hardcode CMAKE_INSTALL_NAME_TOOL here to install_name_tool, so it behaves as it did before, Alex +if (NOT DEFINED CMAKE_INSTALL_NAME_TOOL) + find_program(CMAKE_INSTALL_NAME_TOOL install_name_tool) +endif () + +# Setup iOS platform unless specified manually with IOS_PLATFORM +if (NOT DEFINED IOS_PLATFORM) + set (IOS_PLATFORM "OS") +endif () +set (IOS_PLATFORM ${IOS_PLATFORM} CACHE STRING "Type of iOS Platform") + +# Setup building for arm64 or not +if (NOT DEFINED BUILD_ARM64) + set (BUILD_ARM64 true) +endif () +set (BUILD_ARM64 ${BUILD_ARM64} CACHE STRING "Build arm64 arch or not") + +# Check the platform selection and setup for developer root +if (${IOS_PLATFORM} STREQUAL "OS") + set (IOS_PLATFORM_LOCATION "iPhoneOS.platform") + + # This causes the installers to properly locate the output libraries + set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphoneos") +elseif (${IOS_PLATFORM} STREQUAL "OS32") + set (IOS_PLATFORM_LOCATION "iPhoneOS.platform") + + # This causes the installers to properly locate the output libraries + set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphoneos") +elseif (${IOS_PLATFORM} STREQUAL "SIMULATOR") + set (IS_SIMULATOR true) + set (IOS_PLATFORM_LOCATION "iPhoneSimulator.platform") + + # This causes the installers to properly locate the output libraries + set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphonesimulator") +elseif (${IOS_PLATFORM} STREQUAL "SIMULATOR64") + set (IS_SIMULATOR true) + set (IOS_PLATFORM_LOCATION "iPhoneSimulator.platform") + + # This causes the installers to properly locate the output libraries + set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphonesimulator") +else () + message (FATAL_ERROR "Unsupported IOS_PLATFORM value selected. Please choose OS or SIMULATOR") +endif () + +# Setup iOS developer location unless specified manually with CMAKE_IOS_DEVELOPER_ROOT +# Note Xcode 4.3 changed the installation location, choose the most recent one available +exec_program(/usr/bin/xcode-select ARGS -print-path OUTPUT_VARIABLE CMAKE_XCODE_DEVELOPER_DIR) +set (XCODE_POST_43_ROOT "${CMAKE_XCODE_DEVELOPER_DIR}/Platforms/${IOS_PLATFORM_LOCATION}/Developer") +set (XCODE_PRE_43_ROOT "/Developer/Platforms/${IOS_PLATFORM_LOCATION}/Developer") +if (NOT DEFINED CMAKE_IOS_DEVELOPER_ROOT) + if (EXISTS ${XCODE_POST_43_ROOT}) + set (CMAKE_IOS_DEVELOPER_ROOT ${XCODE_POST_43_ROOT}) + elseif(EXISTS ${XCODE_PRE_43_ROOT}) + set (CMAKE_IOS_DEVELOPER_ROOT ${XCODE_PRE_43_ROOT}) + endif (EXISTS ${XCODE_POST_43_ROOT}) +endif () +set (CMAKE_IOS_DEVELOPER_ROOT ${CMAKE_IOS_DEVELOPER_ROOT} CACHE PATH "Location of iOS Platform") + +# Find and use the most recent iOS sdk unless specified manually with CMAKE_IOS_SDK_ROOT +if (NOT DEFINED CMAKE_IOS_SDK_ROOT) + file (GLOB _CMAKE_IOS_SDKS "${CMAKE_IOS_DEVELOPER_ROOT}/SDKs/*") + if (_CMAKE_IOS_SDKS) + list (SORT _CMAKE_IOS_SDKS) + list (REVERSE _CMAKE_IOS_SDKS) + list (GET _CMAKE_IOS_SDKS 0 CMAKE_IOS_SDK_ROOT) + else (_CMAKE_IOS_SDKS) + message (FATAL_ERROR "No iOS SDK's found in default search path ${CMAKE_IOS_DEVELOPER_ROOT}. Manually set CMAKE_IOS_SDK_ROOT or install the iOS SDK.") + endif (_CMAKE_IOS_SDKS) + message (STATUS "Toolchain using default iOS SDK: ${CMAKE_IOS_SDK_ROOT}") +endif () +set (CMAKE_IOS_SDK_ROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Location of the selected iOS SDK") + +# Set the sysroot default to the most recent SDK +set (CMAKE_OSX_SYSROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Sysroot used for iOS support") + +# set the architecture for iOS +if (${IOS_PLATFORM} STREQUAL "OS") + set (IOS_ARCH arm64) +elseif (${IOS_PLATFORM} STREQUAL "OS32") + set (IOS_ARCH armv7) +elseif (${IOS_PLATFORM} STREQUAL "SIMULATOR") + set (IOS_ARCH i386) +elseif (${IOS_PLATFORM} STREQUAL "SIMULATOR64") + set (IOS_ARCH x86_64) +endif () + +set (CMAKE_OSX_ARCHITECTURES ${IOS_ARCH} CACHE STRING "Build architecture for iOS") + +# Set the find root to the iOS developer roots and to user defined paths +set (CMAKE_FIND_ROOT_PATH ${CMAKE_IOS_DEVELOPER_ROOT} ${CMAKE_IOS_SDK_ROOT} ${CMAKE_PREFIX_PATH} CACHE STRING "iOS find search path root") + +# default to searching for frameworks first +set (CMAKE_FIND_FRAMEWORK FIRST) + +# set up the default search directories for frameworks +set (CMAKE_SYSTEM_FRAMEWORK_PATH + ${CMAKE_IOS_SDK_ROOT}/System/Library/Frameworks + ${CMAKE_IOS_SDK_ROOT}/System/Library/PrivateFrameworks + ${CMAKE_IOS_SDK_ROOT}/Developer/Library/Frameworks +) + +# only search the iOS sdks, not the remainder of the host filesystem +set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY) +set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + + +# This little macro lets you set any XCode specific property +macro (set_xcode_property TARGET XCODE_PROPERTY XCODE_VALUE) + set_property (TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY} ${XCODE_VALUE}) +endmacro (set_xcode_property) + + +# This macro lets you find executable programs on the host system +macro (find_host_package) + set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER) + set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER) + set (IOS FALSE) + + find_package(${ARGN}) + + set (IOS TRUE) + set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY) + set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +endmacro (find_host_package) + diff -Nru libwebsockets-4.0.20/debian/changelog libwebsockets-4.1.6/debian/changelog --- libwebsockets-4.0.20/debian/changelog 2021-12-01 17:40:37.000000000 +0000 +++ libwebsockets-4.1.6/debian/changelog 2023-07-24 12:56:35.000000000 +0000 @@ -1,21 +1,63 @@ -libwebsockets (4.0.20-2ubuntu1) jammy; urgency=medium +libwebsockets (4.1.6-3.1~bpo22.04.1~ppa1) jammy; urgency=medium + * No-change backport to jammy. + + -- Gianfranco Costamagna Mon, 24 Jul 2023 14:56:35 +0200 + +libwebsockets (4.1.6-3.1) unstable; urgency=medium + + * Non-maintainer upload. + * debian/patches/f9d1f25abe896b9fa1de780e4a5cb41116926a29.patch: + - cherry-pick upstream patch to fix a build failure with gcc-13 + (Closes: #1037747) + + -- Gianfranco Costamagna Thu, 20 Jul 2023 17:27:19 +0200 + +libwebsockets (4.1.6-3) unstable; urgency=medium + + * Update self-testing. + + -- Laszlo Boszormenyi (GCS) Sun, 07 Aug 2022 10:46:31 +0200 + +libwebsockets (4.1.6-2) unstable; urgency=medium + + * Update -dev dependency. + * Upload to Sid. + + [ Simon Chopin ] * d/rules: downgrade deprecation errors into warnings to fix the build - against OpenSSL3 + against OpenSSL3 (closes: #1006245). + + -- Laszlo Boszormenyi (GCS) Sat, 06 Aug 2022 07:42:00 +0200 + +libwebsockets (4.1.6-1) experimental; urgency=medium + + * New upstream release. + + -- Laszlo Boszormenyi (GCS) Fri, 11 Dec 2020 17:00:18 +0100 + +libwebsockets (4.1.4-1) experimental; urgency=medium + + * New upstream release. - -- Simon Chopin Wed, 01 Dec 2021 18:40:37 +0100 + -- Laszlo Boszormenyi (GCS) Thu, 29 Oct 2020 22:44:45 +0100 -libwebsockets (4.0.20-2build1) jammy; urgency=medium +libwebsockets (4.1.3-1) experimental; urgency=medium - * No-change rebuild against openssl3 + * New upstream release. + * Update library symbols for this release. - -- Simon Chopin Mon, 29 Nov 2021 13:45:23 +0100 + -- Laszlo Boszormenyi (GCS) Wed, 14 Oct 2020 18:05:17 +0200 -libwebsockets (4.0.20-2) unstable; urgency=medium +libwebsockets (4.1.2-1) experimental; urgency=medium - * Enable LWS_WITH_EXTERNAL_POLL support (closes: #977637). + * New upstream release: + - package ev, uv and glib event loops as plugins. + * Library transition from libwebsockets16 to libwebsockets17 . + * Update library symbols for this release. + * Update debhelper level to 12 . - -- Laszlo Boszormenyi (GCS) Thu, 11 Feb 2021 20:30:30 +0100 + -- Laszlo Boszormenyi (GCS) Sun, 27 Sep 2020 17:53:20 +0200 libwebsockets (4.0.20-1) unstable; urgency=medium diff -Nru libwebsockets-4.0.20/debian/control libwebsockets-4.1.6/debian/control --- libwebsockets-4.0.20/debian/control 2021-12-01 17:40:37.000000000 +0000 +++ libwebsockets-4.1.6/debian/control 2022-08-06 05:42:00.000000000 +0000 @@ -1,16 +1,16 @@ Source: libwebsockets Section: libs Priority: optional -Maintainer: Ubuntu Developers -XSBC-Original-Maintainer: Laszlo Boszormenyi (GCS) +Maintainer: Laszlo Boszormenyi (GCS) Uploaders: Peter Pentchev -Build-Depends: debhelper-compat (= 11), cmake, libcap-dev [linux-any], - libev-dev, libssl-dev, libuv1-dev, openssl, zlib1g-dev +Build-Depends: debhelper-compat (= 12), pkg-config, cmake, + libcap-dev [linux-any], libev-dev, libuv1-dev, libglib2.0-dev, zlib1g-dev, + libssl-dev, openssl Standards-Version: 4.5.0 Homepage: https://libwebsockets.org/ Rules-Requires-Root: no -Package: libwebsockets16 +Package: libwebsockets17 Architecture: any Multi-Arch: same Depends: ${shlibs:Depends}, ${misc:Depends} @@ -19,14 +19,54 @@ clients and servers built to use minimal CPU and memory resources and provide fast throughput in both directions. . - This package contains the shared library. + This package contains the main shared library. + +Package: libwebsockets-evlib-ev +Architecture: any +Multi-Arch: same +Depends: libwebsockets17 (= ${binary:Version}), + ${shlibs:Depends}, ${misc:Depends} +Description: lightweight C websockets library + Libwebsockets is a lightweight pure C library for both websockets + clients and servers built to use minimal CPU and memory resources + and provide fast throughput in both directions. + . + This package contains the shared library for evlib_ev plugin. + +Package: libwebsockets-evlib-uv +Architecture: any +Multi-Arch: same +Depends: libwebsockets17 (= ${binary:Version}), + ${shlibs:Depends}, ${misc:Depends} +Description: lightweight C websockets library + Libwebsockets is a lightweight pure C library for both websockets + clients and servers built to use minimal CPU and memory resources + and provide fast throughput in both directions. + . + This package contains the shared library for evlib_uv plugin. + +Package: libwebsockets-evlib-glib +Architecture: any +Multi-Arch: same +Depends: libwebsockets17 (= ${binary:Version}), + ${shlibs:Depends}, ${misc:Depends} +Description: lightweight C websockets library + Libwebsockets is a lightweight pure C library for both websockets + clients and servers built to use minimal CPU and memory resources + and provide fast throughput in both directions. + . + This package contains the shared library for evlib_glib plugin. Package: libwebsockets-dev Section: libdevel Architecture: any Multi-Arch: same -Depends: libwebsockets16 (= ${binary:Version}), libev-dev, libssl-dev, - libuv1-dev, zlib1g-dev, libcap-dev [linux-any], ${misc:Depends} +Depends: libwebsockets17 (= ${binary:Version}), + libwebsockets-evlib-ev (= ${binary:Version}), + libwebsockets-evlib-uv (= ${binary:Version}), + libwebsockets-evlib-glib (= ${binary:Version}), + libev-dev, libssl-dev, libuv1-dev, zlib1g-dev, + libcap-dev [linux-any], ${misc:Depends} Description: lightweight C websockets library - development files Libwebsockets is a lightweight pure C library for both websockets clients and servers built to use minimal CPU and memory resources @@ -39,7 +79,7 @@ Section: utils Architecture: any Multi-Arch: foreign -Depends: libwebsockets16 (= ${binary:Version}), +Depends: libwebsockets17 (= ${binary:Version}), libwebsockets-test-server-common (= ${source:Version}), ${shlibs:Depends}, ${misc:Depends} Description: lightweight C websockets library - test servers diff -Nru libwebsockets-4.0.20/debian/libwebsockets16.install libwebsockets-4.1.6/debian/libwebsockets16.install --- libwebsockets-4.0.20/debian/libwebsockets16.install 2018-03-02 18:39:44.000000000 +0000 +++ libwebsockets-4.1.6/debian/libwebsockets16.install 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -usr/lib/*/lib*.so.* diff -Nru libwebsockets-4.0.20/debian/libwebsockets16.symbols libwebsockets-4.1.6/debian/libwebsockets16.symbols --- libwebsockets-4.0.20/debian/libwebsockets16.symbols 2020-06-27 15:33:41.000000000 +0000 +++ libwebsockets-4.1.6/debian/libwebsockets16.symbols 1970-01-01 00:00:00.000000000 +0000 @@ -1,330 +0,0 @@ -libwebsockets.so.16 libwebsockets16 #MINVER# - __lws_sul_insert@Base 4.0.0 - __lws_sul_service_ripe@Base 4.0.0 - __lws_system_attach@Base 4.0.0 - _lws_log@Base 1.2 - _lws_logv@Base 1.4 - _lws_plat_file_close@Base 2.4.1 - _lws_plat_file_open@Base 2.4.1 - _lws_plat_file_read@Base 2.4.1 - _lws_plat_file_seek_cur@Base 2.4.1 - _lws_plat_file_write@Base 2.4.1 - _lws_plat_service_tsi@Base 2.4.1 - humanize_schema_si@Base 3.2.0 - humanize_schema_si_bytes@Base 3.2.0 - humanize_schema_us@Base 3.2.0 - lejp_change_callback@Base 3.2.0 - lejp_check_path_match@Base 3.2.0 - lejp_construct@Base 3.2.0 - lejp_destruct@Base 3.2.0 - lejp_error_to_string@Base 3.2.0 - lejp_get_wildcard@Base 3.2.0 - lejp_parse@Base 3.2.0 - lejp_parser_pop@Base 3.2.0 - lejp_parser_push@Base 3.2.0 - lws_SHA1@Base 1.6.0 - lws_add_http_common_headers@Base 3.2.0 - lws_add_http_header_by_name@Base 1.4 - lws_add_http_header_by_token@Base 1.4 - lws_add_http_header_content_length@Base 1.4 - lws_add_http_header_status@Base 1.4 - lws_adjust_protocol_psds@Base 2.4.1 - lws_adopt_descriptor_vhost@Base 2.4.1 - lws_adopt_descriptor_vhost_via_info@Base 4.0.0 - lws_adopt_socket@Base 1.7.0 - lws_adopt_socket_readbuf@Base 2.0.2 - lws_adopt_socket_vhost@Base 2.4.1 - lws_adopt_socket_vhost_readbuf@Base 2.4.1 - lws_b64_decode_state_init@Base 4.0.0 - lws_b64_decode_stateful@Base 4.0.0 - lws_b64_decode_string@Base 1.4 - lws_b64_decode_string_len@Base 3.2.0 - lws_b64_encode_string@Base 1.2 - lws_b64_encode_string_url@Base 3.2.0 - lws_buflist_append_segment@Base 3.2.0 - lws_buflist_describe@Base 4.0.0 - lws_buflist_destroy_all_segments@Base 3.2.0 - lws_buflist_linear_copy@Base 4.0.0 - lws_buflist_next_segment_len@Base 3.2.0 - lws_buflist_total_len@Base 4.0.0 - lws_buflist_use_segment@Base 3.2.0 - lws_callback_all_protocol@Base 1.6.0 - lws_callback_all_protocol_vhost@Base 2.0.2 - lws_callback_all_protocol_vhost_args@Base 2.4.1 - lws_callback_http_dummy@Base 2.4.1 - lws_callback_on_writable@Base 1.6.0 - lws_callback_on_writable_all_protocol@Base 1.6.0 - lws_callback_on_writable_all_protocol_vhost@Base 2.0.2 - lws_callback_vhost_protocols@Base 2.4.1 - lws_callback_vhost_protocols_vhost@Base 3.2.0 - lws_cancel_service@Base 1.6.0 - lws_cancel_service_pt@Base 1.7.0 - lws_canonical_hostname@Base 1.6.0 - lws_chunked_html_process@Base 2.4.1 - lws_clear_child_pending_on_writable@Base 2.4.1 - lws_client_connect_via_info@Base 1.7.0 - lws_client_http_body_pending@Base 2.4.1 - lws_client_http_multipart@Base 4.0.0 - lws_client_reset@Base 1.7.0 - lws_close_reason@Base 1.7.0 - lws_cmdline_option@Base 3.2.0 - lws_cmdline_option_handle_builtin@Base 4.0.0 - lws_context_deprecate@Base 2.4.1 - lws_context_destroy@Base 1.6.0 - lws_context_init_extensions@Base 4.0.19 - lws_context_is_deprecated@Base 2.4.1 - lws_context_user@Base 1.6.0 - lws_create_adopt_udp@Base 3.2.0 - lws_create_context@Base 1.6.0 - lws_create_vhost@Base 2.0.2 - lws_daemonize@Base 1.2 - lws_dir@Base 3.2.0 - lws_dll2_add_before@Base 3.2.0 - lws_dll2_add_head@Base 3.2.0 - lws_dll2_add_sorted@Base 3.2.0 - lws_dll2_add_tail@Base 3.2.0 - lws_dll2_clear@Base 3.2.0 - lws_dll2_foreach_safe@Base 3.2.0 - lws_dll2_owner_clear@Base 3.2.0 - lws_dll2_remove@Base 3.2.0 - lws_explicit_bzero@Base 3.2.0 - lws_ext_parse_options@Base 4.0.19 - lws_extension_callback_pm_deflate@Base 4.0.19 - lws_filename_purify_inplace@Base 3.2.0 - lws_finalize_http_header@Base 1.4 - lws_finalize_startup@Base 2.0.2 - lws_finalize_write_http_header@Base 3.2.0 - lws_frame_is_binary@Base 1.2 - lws_get_child@Base 2.0.2 - lws_get_child_pending_on_writable@Base 2.4.1 - lws_get_close_length@Base 2.4.1 - lws_get_close_payload@Base 2.4.1 - lws_get_context@Base 1.6.0 - lws_get_count_threads@Base 1.7.0 - lws_get_effective_uid_gid@Base 3.2.0 - lws_get_fops@Base 1.6.0 - lws_get_library_version@Base 1.2 - lws_get_mimetype@Base 2.4.1 - lws_get_network_wsi@Base 2.4.1 - lws_get_opaque_parent_data@Base 2.4.1 - lws_get_opaque_user_data@Base 3.2.0 - lws_get_parent@Base 2.0.2 - lws_get_peer_addresses@Base 1.6.0 - lws_get_peer_simple@Base 2.4.1 - lws_get_peer_simple_fd@Base 4.0.0 - lws_get_peer_write_allowance@Base 1.4 - lws_get_protocol@Base 1.6.0 - lws_get_random@Base 1.6.0 - lws_get_reserved_bits@Base 1.6.0 - lws_get_socket_fd@Base 1.6.0 - lws_get_ssl@Base 2.4.1 - lws_get_tsi@Base 4.0.0 - lws_get_udp@Base 3.2.0 - lws_get_urlarg_by_name@Base 2.4.1 - lws_get_vhost@Base 2.4.1 - lws_get_vhost_by_name@Base 3.2.0 - lws_get_vhost_iface@Base 3.2.0 - lws_get_vhost_listen_port@Base 3.2.0 - lws_get_vhost_name@Base 3.2.0 - lws_get_vhost_port@Base 3.2.0 - lws_get_vhost_user@Base 3.2.0 - lws_h2_client_stream_long_poll_rxonly@Base 4.0.0 - lws_h2_get_peer_txcredit_estimate@Base 4.0.0 - lws_h2_update_peer_txcredit@Base 4.0.0 - lws_handle_POLLOUT_event@Base 2.4.1 - lws_hdr_copy@Base 1.2 - lws_hdr_copy_fragment@Base 1.6.0 - lws_hdr_custom_copy@Base 3.2.0 - lws_hdr_custom_length@Base 3.2.0 - lws_hdr_fragment_length@Base 1.7.0 - lws_hdr_total_length@Base 1.2 - lws_hex_to_byte_array@Base 3.2.0 - lws_http_basic_auth_gen@Base 4.0.0 - lws_http_client_http_response@Base 2.4.1 - lws_http_client_read@Base 2.0.2 - lws_http_compression_apply@Base 3.2.0 - lws_http_get_uri_and_method@Base 3.2.0 - lws_http_headers_detach@Base 3.2.0 - lws_http_is_redirected_to_get@Base 4.0.0 - lws_http_mark_sse@Base 3.2.0 - lws_http_redirect@Base 2.0.2 - lws_http_transaction_completed@Base 1.4 - lws_humanize@Base 3.2.0 - lws_init_vhost_client_ssl@Base 2.4.1 - lws_interface_to_sa@Base 1.7.0 - lws_is_cgi@Base 2.0.2 - lws_is_final_fragment@Base 1.6.0 - lws_is_first_fragment@Base 2.4.1 - lws_is_ssl@Base 1.4 - lws_json_purify@Base 2.4.1 - lws_json_purify_len@Base 4.0.0 - lws_libuv_static_refcount_add@Base 3.2.0 - lws_libuv_static_refcount_del@Base 3.2.0 - lws_list_ptr_insert@Base 3.2.0 - lws_now_secs@Base 2.4.1 - lws_now_usecs@Base 3.2.0 - lws_open@Base 3.2.0 - lws_parse_numeric_address@Base 4.0.0 - lws_parse_uri@Base 1.7.0 - lws_partial_buffered@Base 1.4 - lws_plat_read_file@Base 3.2.0 - lws_plat_recommended_rsa_bits@Base 3.2.0 - lws_plat_write_cert@Base 3.2.0 - lws_plat_write_file@Base 3.2.0 - lws_protocol_get@Base 2.0.2 - lws_protocol_init@Base 2.4.1 - lws_protocol_vh_priv_get@Base 2.0.2 - lws_protocol_vh_priv_zalloc@Base 2.0.2 - lws_pvo_get_str@Base 3.2.0 - lws_pvo_search@Base 3.2.0 - lws_raw_transaction_completed@Base 3.2.0 - lws_remaining_packet_payload@Base 1.6.0 - lws_retry_get_delay_ms@Base 3.2.0 - lws_retry_sul_schedule@Base 4.0.0 - lws_retry_sul_schedule_retry_wsi@Base 4.0.0 - lws_return_http_status@Base 1.6.0 - lws_ring_bump_head@Base 2.4.1 - lws_ring_consume@Base 2.4.1 - lws_ring_create@Base 2.4.1 - lws_ring_destroy@Base 2.4.1 - lws_ring_dump@Base 3.2.0 - lws_ring_get_count_free_elements@Base 2.4.1 - lws_ring_get_count_waiting_elements@Base 2.4.1 - lws_ring_get_element@Base 2.4.1 - lws_ring_get_oldest_tail@Base 2.4.1 - lws_ring_insert@Base 2.4.1 - lws_ring_next_linear_insert_range@Base 2.4.1 - lws_ring_update_oldest_tail@Base 2.4.1 - lws_rx_flow_allow_all_protocol@Base 1.6.0 - lws_rx_flow_control@Base 1.6.0 - lws_sa46_compare_ads@Base 4.0.0 - lws_sa46_parse_numeric_address@Base 4.0.0 - lws_sa46_write_numeric_address@Base 4.0.0 - lws_send_pipe_choked@Base 1.2 - lws_seq_check_wsi@Base 3.2.0 - lws_seq_create@Base 3.2.0 - lws_seq_destroy@Base 3.2.0 - lws_seq_from_user@Base 3.2.0 - lws_seq_get_context@Base 3.2.0 - lws_seq_name@Base 3.2.0 - lws_seq_queue_event@Base 3.2.0 - lws_seq_timeout_us@Base 3.2.0 - lws_seq_us_since_creation@Base 3.2.0 - lws_ser_ru16be@Base 4.0.0 - lws_ser_ru32be@Base 4.0.0 - lws_ser_ru64be@Base 4.0.0 - lws_ser_wu16be@Base 4.0.0 - lws_ser_wu32be@Base 4.0.0 - lws_ser_wu64be@Base 4.0.0 - lws_serve_http_file@Base 1.6.0 - lws_serve_http_file_fragment@Base 1.6.0 - lws_service@Base 1.6.0 - lws_service_adjust_timeout@Base 2.4.1 - lws_service_fd@Base 1.6.0 - lws_service_fd_tsi@Base 1.7.0 - lws_service_tsi@Base 1.7.0 - lws_set_allocator@Base 1.4 - lws_set_extension_option@Base 2.0.2 - lws_set_fops@Base 2.4.1 - lws_set_log_level@Base 1.2 - lws_set_opaque_parent_data@Base 2.4.1 - lws_set_opaque_user_data@Base 3.2.0 - lws_set_proxy@Base 1.6.0 - lws_set_timeout@Base 1.6.0 - lws_set_timer_usecs@Base 3.2.0 - lws_set_wsi_user@Base 2.4.1 - lws_snprintf@Base 2.0.3 - lws_spa_create@Base 2.4.1 - lws_spa_create_via_info@Base 3.2.0 - lws_spa_destroy@Base 2.4.1 - lws_spa_finalize@Base 2.4.1 - lws_spa_get_length@Base 2.4.1 - lws_spa_get_string@Base 2.4.1 - lws_spa_process@Base 2.4.1 - lws_sql_purify@Base 2.4.1 - lws_ssl_remove_wsi_from_buffered_list@Base 1.4 - lws_state_reg_deregister@Base 4.0.0 - lws_state_reg_notifier@Base 4.0.0 - lws_state_reg_notifier_list@Base 4.0.0 - lws_state_transition@Base 4.0.0 - lws_state_transition_steps@Base 4.0.0 - lws_strexp_expand@Base 4.0.0 - lws_strexp_init@Base 4.0.0 - lws_strexp_reset_out@Base 4.0.0 - lws_strncpy@Base 3.2.0 - lws_sul_schedule@Base 3.2.0 - lws_system_blob_destroy@Base 4.0.0 - lws_system_blob_direct_set@Base 4.0.0 - lws_system_blob_get@Base 4.0.0 - lws_system_blob_get_single_ptr@Base 4.0.0 - lws_system_blob_get_size@Base 4.0.0 - lws_system_blob_heap_append@Base 4.0.0 - lws_system_blob_heap_empty@Base 4.0.0 - lws_system_context_from_system_mgr@Base 4.0.0 - lws_system_get_blob@Base 4.0.0 - lws_system_get_ops@Base 4.0.0 - lws_system_get_state_manager@Base 4.0.0 - lws_timed_callback_vh_protocol@Base 3.2.0 - lws_timed_callback_vh_protocol_us@Base 3.2.0 - lws_timingsafe_bcmp@Base 3.2.0 - lws_tls_cert_updated@Base 3.2.0 - lws_tls_client_vhost_extra_cert_mem@Base 4.0.0 - lws_tls_peer_cert_info@Base 3.2.0 - lws_tls_vhost_cert_info@Base 3.2.0 - lws_token_to_string@Base 1.4 - lws_tokenize@Base 3.2.0 - lws_tokenize_cstr@Base 3.2.0 - lws_tokenize_init@Base 3.2.0 - lws_urldecode@Base 2.4.1 - lws_urlencode@Base 2.0.2 - lws_uv_getloop@Base 1.7.0 - lws_validity_confirmed@Base 4.0.0 - lws_vbi_decode@Base 4.0.0 - lws_vbi_encode@Base 4.0.0 - lws_vfs_file_open@Base 2.4.1 - lws_vfs_file_seek_end@Base 2.4.1 - lws_vfs_file_seek_set@Base 2.4.1 - lws_vfs_get_length@Base 2.4.1 - lws_vfs_get_mod_time@Base 2.4.1 - lws_vfs_tell@Base 2.4.1 - lws_vhost_destroy@Base 2.4.1 - lws_vhost_name_to_protocol@Base 2.4.1 - lws_vhost_user@Base 2.4.1 - lws_write@Base 1.6.0 - lws_write_numeric_address@Base 4.0.0 - lws_wsi_tx_credit@Base 4.0.0 - lws_wsi_user@Base 1.6.0 - lws_x509_create@Base 3.2.0 - lws_x509_destroy@Base 3.2.0 - lws_x509_info@Base 3.2.0 - lws_x509_parse_from_pem@Base 3.2.0 - lws_x509_verify@Base 3.2.0 - lwsac_align@Base 3.2.0 - lwsac_cached_file@Base 3.2.0 - lwsac_detach@Base 3.2.0 - lwsac_extend@Base 4.0.0 - lwsac_free@Base 3.2.0 - lwsac_get_next@Base 3.2.0 - lwsac_get_tail_pos@Base 3.2.0 - lwsac_info@Base 3.2.0 - lwsac_reference@Base 3.2.0 - lwsac_scan_extant@Base 4.0.0 - lwsac_sizeof@Base 3.2.0 - lwsac_total_alloc@Base 3.2.0 - lwsac_total_overhead@Base 4.0.0 - lwsac_unreference@Base 3.2.0 - lwsac_use@Base 3.2.0 - lwsac_use_backfill@Base 4.0.0 - lwsac_use_cached_file_detach@Base 3.2.0 - lwsac_use_cached_file_end@Base 3.2.0 - lwsac_use_cached_file_start@Base 3.2.0 - lwsac_use_zero@Base 3.2.0 - lwsl_emit_stderr@Base 1.3 - lwsl_emit_stderr_notimestamp@Base 3.2.0 - lwsl_emit_syslog@Base 1.2 - lwsl_hexdump@Base 1.2 - lwsl_hexdump_level@Base 2.4.1 - lwsl_timestamp@Base 2.0.2 - lwsl_visible@Base 2.4.1 - lwsws_get_config_globals@Base 3.2.0 - lwsws_get_config_vhosts@Base 3.2.0 diff -Nru libwebsockets-4.0.20/debian/libwebsockets17.install libwebsockets-4.1.6/debian/libwebsockets17.install --- libwebsockets-4.0.20/debian/libwebsockets17.install 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/debian/libwebsockets17.install 2018-03-02 18:39:44.000000000 +0000 @@ -0,0 +1 @@ +usr/lib/*/lib*.so.* diff -Nru libwebsockets-4.0.20/debian/libwebsockets17.symbols libwebsockets-4.1.6/debian/libwebsockets17.symbols --- libwebsockets-4.0.20/debian/libwebsockets17.symbols 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/debian/libwebsockets17.symbols 2020-10-14 16:05:17.000000000 +0000 @@ -0,0 +1,349 @@ +libwebsockets.so.17 libwebsockets17 #MINVER# + __lws_close_free_wsi_final@Base 4.1.0 + __lws_sul_insert@Base 4.0.0 + __lws_sul_service_ripe@Base 4.0.0 + __lws_system_attach@Base 4.0.0 + _lws_dll2_search_sz_pl@Base 4.1.0 + _lws_log@Base 1.2 + _lws_logv@Base 1.4 + _lws_plat_file_close@Base 2.4.1 + _lws_plat_file_open@Base 2.4.1 + _lws_plat_file_read@Base 2.4.1 + _lws_plat_file_seek_cur@Base 2.4.1 + _lws_plat_file_write@Base 2.4.1 + _lws_plat_service_forced_tsi@Base 4.1.0 + _lws_plat_service_tsi@Base 2.4.1 + humanize_schema_si@Base 3.2.0 + humanize_schema_si_bytes@Base 3.2.0 + humanize_schema_us@Base 3.2.0 + lejp_change_callback@Base 3.2.0 + lejp_check_path_match@Base 3.2.0 + lejp_construct@Base 3.2.0 + lejp_destruct@Base 3.2.0 + lejp_error_to_string@Base 3.2.0 + lejp_get_wildcard@Base 3.2.0 + lejp_parse@Base 3.2.0 + lejp_parser_pop@Base 3.2.0 + lejp_parser_push@Base 3.2.0 + lws_SHA1@Base 1.6.0 + lws_add_http_common_headers@Base 3.2.0 + lws_add_http_header_by_name@Base 1.4 + lws_add_http_header_by_token@Base 1.4 + lws_add_http_header_content_length@Base 1.4 + lws_add_http_header_status@Base 1.4 + lws_adjust_protocol_psds@Base 2.4.1 + lws_adopt_descriptor_vhost@Base 2.4.1 + lws_adopt_descriptor_vhost_via_info@Base 4.0.0 + lws_adopt_socket@Base 1.7.0 + lws_adopt_socket_readbuf@Base 2.0.2 + lws_adopt_socket_vhost@Base 2.4.1 + lws_adopt_socket_vhost_readbuf@Base 2.4.1 + lws_b64_decode_state_init@Base 4.0.0 + lws_b64_decode_stateful@Base 4.0.0 + lws_b64_decode_string@Base 1.4 + lws_b64_decode_string_len@Base 3.2.0 + lws_b64_encode_string@Base 1.2 + lws_b64_encode_string_url@Base 3.2.0 + lws_buflist_append_segment@Base 3.2.0 + lws_buflist_describe@Base 4.0.0 + lws_buflist_destroy_all_segments@Base 3.2.0 + lws_buflist_linear_copy@Base 4.0.0 + lws_buflist_next_segment_len@Base 3.2.0 + lws_buflist_total_len@Base 4.0.0 + lws_buflist_use_segment@Base 3.2.0 + lws_callback_all_protocol@Base 1.6.0 + lws_callback_all_protocol_vhost@Base 2.0.2 + lws_callback_all_protocol_vhost_args@Base 2.4.1 + lws_callback_http_dummy@Base 2.4.1 + lws_callback_on_writable@Base 1.6.0 + lws_callback_on_writable_all_protocol@Base 1.6.0 + lws_callback_on_writable_all_protocol_vhost@Base 2.0.2 + lws_callback_vhost_protocols@Base 2.4.1 + lws_callback_vhost_protocols_vhost@Base 3.2.0 + lws_cancel_service@Base 1.6.0 + lws_cancel_service_pt@Base 1.7.0 + lws_canonical_hostname@Base 1.6.0 + lws_chunked_html_process@Base 2.4.1 + lws_clear_child_pending_on_writable@Base 2.4.1 + lws_client_connect_via_info@Base 1.7.0 + lws_client_http_body_pending@Base 2.4.1 + lws_client_http_multipart@Base 4.0.0 + lws_client_reset@Base 1.7.0 + lws_close_free_wsi@Base 4.1.0 + lws_close_reason@Base 1.7.0 + lws_cmdline_option@Base 3.2.0 + lws_cmdline_option_handle_builtin@Base 4.0.0 + lws_context_deprecate@Base 2.4.1 + lws_context_destroy2@Base 4.1.0 + lws_context_destroy@Base 1.6.0 + lws_context_init_extensions@Base 4.0.19 + lws_context_is_deprecated@Base 2.4.1 + lws_context_user@Base 1.6.0 + lws_create_adopt_udp@Base 3.2.0 + lws_create_context@Base 1.6.0 + lws_create_vhost@Base 2.0.2 + lws_daemonize@Base 1.2 + lws_destroy_event_pipe@Base 4.1.0 + lws_dir@Base 3.2.0 + lws_dir_glob_cb@Base 4.1.0 + lws_dir_rm_rf_cb@Base 4.1.0 + lws_dll2_add_before@Base 3.2.0 + lws_dll2_add_head@Base 3.2.0 + lws_dll2_add_sorted@Base 3.2.0 + lws_dll2_add_tail@Base 3.2.0 + lws_dll2_clear@Base 3.2.0 + lws_dll2_foreach_safe@Base 3.2.0 + lws_dll2_owner_clear@Base 3.2.0 + lws_dll2_remove@Base 3.2.0 + lws_explicit_bzero@Base 3.2.0 + lws_ext_parse_options@Base 4.0.19 + lws_extension_callback_pm_deflate@Base 4.0.19 + lws_filename_purify_inplace@Base 3.2.0 + lws_finalize_http_header@Base 1.4 + lws_finalize_startup@Base 2.0.2 + lws_finalize_write_http_header@Base 3.2.0 + lws_frame_is_binary@Base 1.2 + lws_get_child@Base 2.0.2 + lws_get_child_pending_on_writable@Base 2.4.1 + lws_get_close_length@Base 2.4.1 + lws_get_close_payload@Base 2.4.1 + lws_get_context@Base 1.6.0 + lws_get_count_threads@Base 1.7.0 + lws_get_effective_uid_gid@Base 3.2.0 + lws_get_fops@Base 1.6.0 + lws_get_library_version@Base 1.2 + lws_get_mimetype@Base 2.4.1 + lws_get_network_wsi@Base 2.4.1 + lws_get_opaque_parent_data@Base 2.4.1 + lws_get_opaque_user_data@Base 3.2.0 + lws_get_parent@Base 2.0.2 + lws_get_peer_addresses@Base 1.6.0 + lws_get_peer_simple@Base 2.4.1 + lws_get_peer_simple_fd@Base 4.0.0 + lws_get_peer_write_allowance@Base 1.4 + lws_get_protocol@Base 1.6.0 + lws_get_random@Base 1.6.0 + lws_get_reserved_bits@Base 1.6.0 + lws_get_socket_fd@Base 1.6.0 + lws_get_ssl@Base 2.4.1 + lws_get_tsi@Base 4.0.0 + lws_get_udp@Base 3.2.0 + lws_get_urlarg_by_name@Base 2.4.1 + lws_get_vhost@Base 2.4.1 + lws_get_vhost_by_name@Base 3.2.0 + lws_get_vhost_iface@Base 3.2.0 + lws_get_vhost_listen_port@Base 3.2.0 + lws_get_vhost_name@Base 3.2.0 + lws_get_vhost_port@Base 3.2.0 + lws_get_vhost_user@Base 3.2.0 + lws_h2_client_stream_long_poll_rxonly@Base 4.0.0 + lws_h2_get_peer_txcredit_estimate@Base 4.0.0 + lws_h2_update_peer_txcredit@Base 4.0.0 + lws_handle_POLLOUT_event@Base 2.4.1 + lws_hdr_copy@Base 1.2 + lws_hdr_copy_fragment@Base 1.6.0 + lws_hdr_custom_copy@Base 3.2.0 + lws_hdr_custom_length@Base 3.2.0 + lws_hdr_fragment_length@Base 1.7.0 + lws_hdr_total_length@Base 1.2 + lws_hex_random@Base 4.1.0 + lws_hex_to_byte_array@Base 3.2.0 + lws_http_basic_auth_gen@Base 4.0.0 + lws_http_client_http_response@Base 2.4.1 + lws_http_client_read@Base 2.0.2 + lws_http_compression_apply@Base 3.2.0 + lws_http_cookie_get@Base 4.1.0 + lws_http_get_uri_and_method@Base 3.2.0 + lws_http_headers_detach@Base 3.2.0 + lws_http_is_redirected_to_get@Base 4.0.0 + lws_http_mark_sse@Base 3.2.0 + lws_http_redirect@Base 2.0.2 + lws_http_transaction_completed@Base 1.4 + lws_humanize@Base 3.2.0 + lws_init_vhost_client_ssl@Base 2.4.1 + lws_interface_to_sa@Base 1.7.0 + lws_is_cgi@Base 2.0.2 + lws_is_final_fragment@Base 1.6.0 + lws_is_first_fragment@Base 2.4.1 + lws_is_ssl@Base 1.4 + lws_json_purify@Base 2.4.1 + lws_json_purify_len@Base 4.0.0 + lws_json_simple_find@Base 4.1.0 + lws_json_simple_strcmp@Base 4.1.0 + lws_list_ptr_insert@Base 3.2.0 + lws_now_secs@Base 2.4.1 + lws_now_usecs@Base 3.2.0 + lws_nstrstr@Base 4.1.0 + lws_open@Base 3.2.0 + lws_parse_numeric_address@Base 4.0.0 + lws_parse_uri@Base 1.7.0 + lws_partial_buffered@Base 1.4 + lws_plat_read_file@Base 3.2.0 + lws_plat_recommended_rsa_bits@Base 3.2.0 + lws_plat_write_cert@Base 3.2.0 + lws_plat_write_file@Base 3.2.0 + lws_plugins_destroy@Base 4.1.0 + lws_plugins_init@Base 4.1.0 + lws_protocol_get@Base 2.0.2 + lws_protocol_init@Base 2.4.1 + lws_protocol_vh_priv_get@Base 2.0.2 + lws_protocol_vh_priv_zalloc@Base 2.0.2 + lws_pvo_get_str@Base 3.2.0 + lws_pvo_search@Base 3.2.0 + lws_raw_transaction_completed@Base 3.2.0 + lws_realloc@Base 4.1.0 + lws_remaining_packet_payload@Base 1.6.0 + lws_retry_get_delay_ms@Base 3.2.0 + lws_retry_sul_schedule@Base 4.0.0 + lws_retry_sul_schedule_retry_wsi@Base 4.0.0 + lws_return_http_status@Base 1.6.0 + lws_ring_bump_head@Base 2.4.1 + lws_ring_consume@Base 2.4.1 + lws_ring_create@Base 2.4.1 + lws_ring_destroy@Base 2.4.1 + lws_ring_dump@Base 3.2.0 + lws_ring_get_count_free_elements@Base 2.4.1 + lws_ring_get_count_waiting_elements@Base 2.4.1 + lws_ring_get_element@Base 2.4.1 + lws_ring_get_oldest_tail@Base 2.4.1 + lws_ring_insert@Base 2.4.1 + lws_ring_next_linear_insert_range@Base 2.4.1 + lws_ring_update_oldest_tail@Base 2.4.1 + lws_rx_flow_allow_all_protocol@Base 1.6.0 + lws_rx_flow_control@Base 1.6.0 + lws_sa46_compare_ads@Base 4.0.0 + lws_sa46_parse_numeric_address@Base 4.0.0 + lws_sa46_write_numeric_address@Base 4.0.0 + lws_send_pipe_choked@Base 1.2 + lws_ser_ru16be@Base 4.0.0 + lws_ser_ru32be@Base 4.0.0 + lws_ser_ru64be@Base 4.0.0 + lws_ser_wu16be@Base 4.0.0 + lws_ser_wu32be@Base 4.0.0 + lws_ser_wu64be@Base 4.0.0 + lws_serve_http_file@Base 1.6.0 + lws_serve_http_file_fragment@Base 1.6.0 + lws_service@Base 1.6.0 + lws_service_adjust_timeout@Base 2.4.1 + lws_service_do_ripe_rxflow@Base 4.1.0 + lws_service_fd@Base 1.6.0 + lws_service_fd_tsi@Base 1.7.0 + lws_service_tsi@Base 1.7.0 + lws_set_allocator@Base 1.4 + lws_set_extension_option@Base 2.0.2 + lws_set_fops@Base 2.4.1 + lws_set_log_level@Base 1.2 + lws_set_opaque_parent_data@Base 2.4.1 + lws_set_opaque_user_data@Base 3.2.0 + lws_set_proxy@Base 1.6.0 + lws_set_timeout@Base 1.6.0 + lws_set_timer_usecs@Base 3.2.0 + lws_set_wsi_user@Base 2.4.1 + lws_smd_msg_alloc@Base 4.1.0 + lws_smd_msg_free@Base 4.1.0 + lws_smd_msg_printf@Base 4.1.0 + lws_smd_msg_send@Base 4.1.0 + lws_smd_register@Base 4.1.0 + lws_smd_unregister@Base 4.1.0 + lws_snprintf@Base 2.0.3 + lws_spa_create@Base 2.4.1 + lws_spa_create_via_info@Base 3.2.0 + lws_spa_destroy@Base 2.4.1 + lws_spa_finalize@Base 2.4.1 + lws_spa_get_length@Base 2.4.1 + lws_spa_get_string@Base 2.4.1 + lws_spa_process@Base 2.4.1 + lws_sql_purify@Base 2.4.1 + lws_ssl_remove_wsi_from_buffered_list@Base 1.4 + lws_state_reg_deregister@Base 4.0.0 + lws_state_reg_notifier@Base 4.0.0 + lws_state_reg_notifier_list@Base 4.0.0 + lws_state_transition@Base 4.0.0 + lws_state_transition_steps@Base 4.0.0 + lws_strexp_expand@Base 4.0.0 + lws_strexp_init@Base 4.0.0 + lws_strexp_reset_out@Base 4.0.0 + lws_strncpy@Base 3.2.0 + lws_sul2_schedule@Base 4.1.0 + lws_sul_cancel@Base 4.1.0 + lws_sul_earliest_wakeable_event@Base 4.1.0 + lws_sul_schedule@Base 3.2.0 + lws_sul_schedule_wakesuspend@Base 4.1.0 + lws_system_blob_destroy@Base 4.0.0 + lws_system_blob_direct_set@Base 4.0.0 + lws_system_blob_get@Base 4.0.0 + lws_system_blob_get_single_ptr@Base 4.0.0 + lws_system_blob_get_size@Base 4.0.0 + lws_system_blob_heap_append@Base 4.0.0 + lws_system_blob_heap_empty@Base 4.0.0 + lws_system_context_from_system_mgr@Base 4.0.0 + lws_system_cpd_set@Base 4.1.0 + lws_system_cpd_start@Base 4.1.0 + lws_system_cpd_state_get@Base 4.1.0 + lws_system_get_blob@Base 4.0.0 + lws_system_get_ops@Base 4.0.0 + lws_system_get_state_manager@Base 4.0.0 + lws_timingsafe_bcmp@Base 3.2.0 + lws_tls_cert_updated@Base 3.2.0 + lws_tls_client_vhost_extra_cert_mem@Base 4.0.0 + lws_tls_peer_cert_info@Base 3.2.0 + lws_tls_vhost_cert_info@Base 3.2.0 + lws_token_to_string@Base 1.4 + lws_tokenize@Base 3.2.0 + lws_tokenize_cstr@Base 3.2.0 + lws_tokenize_init@Base 3.2.0 + lws_urldecode@Base 2.4.1 + lws_urlencode@Base 2.0.2 + lws_validity_confirmed@Base 4.0.0 + lws_vbi_decode@Base 4.0.0 + lws_vbi_encode@Base 4.0.0 + lws_vfs_file_open@Base 2.4.1 + lws_vfs_file_seek_end@Base 2.4.1 + lws_vfs_file_seek_set@Base 2.4.1 + lws_vfs_get_length@Base 2.4.1 + lws_vfs_get_mod_time@Base 2.4.1 + lws_vfs_tell@Base 2.4.1 + lws_vhost_destroy1@Base 4.1.0 + lws_vhost_destroy@Base 2.4.1 + lws_vhost_name_to_protocol@Base 2.4.1 + lws_vhost_user@Base 2.4.1 + lws_write@Base 1.6.0 + lws_write_numeric_address@Base 4.0.0 + lws_wsi_tsi@Base 4.1.3 + lws_wsi_tx_credit@Base 4.0.0 + lws_wsi_user@Base 1.6.0 + lws_x509_create@Base 3.2.0 + lws_x509_destroy@Base 3.2.0 + lws_x509_info@Base 3.2.0 + lws_x509_parse_from_pem@Base 3.2.0 + lws_x509_verify@Base 3.2.0 + lwsac_align@Base 3.2.0 + lwsac_cached_file@Base 3.2.0 + lwsac_detach@Base 3.2.0 + lwsac_extend@Base 4.0.0 + lwsac_free@Base 3.2.0 + lwsac_get_next@Base 3.2.0 + lwsac_get_tail_pos@Base 3.2.0 + lwsac_info@Base 3.2.0 + lwsac_reference@Base 3.2.0 + lwsac_scan_extant@Base 4.0.0 + lwsac_sizeof@Base 3.2.0 + lwsac_total_alloc@Base 3.2.0 + lwsac_total_overhead@Base 4.0.0 + lwsac_unreference@Base 3.2.0 + lwsac_use@Base 3.2.0 + lwsac_use_backfill@Base 4.0.0 + lwsac_use_cached_file_detach@Base 3.2.0 + lwsac_use_cached_file_end@Base 3.2.0 + lwsac_use_cached_file_start@Base 3.2.0 + lwsac_use_zero@Base 3.2.0 + lwsl_emit_stderr@Base 1.3 + lwsl_emit_stderr_notimestamp@Base 3.2.0 + lwsl_emit_syslog@Base 1.2 + lwsl_hexdump@Base 1.2 + lwsl_hexdump_level@Base 2.4.1 + lwsl_timestamp@Base 2.0.2 + lwsl_visible@Base 2.4.1 + lwsws_get_config_globals@Base 3.2.0 + lwsws_get_config_vhosts@Base 3.2.0 + wsi_from_fd@Base 4.1.0 diff -Nru libwebsockets-4.0.20/debian/libwebsockets-dev.install libwebsockets-4.1.6/debian/libwebsockets-dev.install --- libwebsockets-4.0.20/debian/libwebsockets-dev.install 2019-10-13 14:23:13.000000000 +0000 +++ libwebsockets-4.1.6/debian/libwebsockets-dev.install 2020-09-07 23:12:45.000000000 +0000 @@ -1,5 +1,5 @@ usr/include/* usr/lib/*/lib*.a -usr/lib/*/lib*.so +usr/lib/*/libwebsockets.so usr/lib/*/pkgconfig/* usr/lib/*/cmake/* diff -Nru libwebsockets-4.0.20/debian/libwebsockets-evlib-ev.install libwebsockets-4.1.6/debian/libwebsockets-evlib-ev.install --- libwebsockets-4.0.20/debian/libwebsockets-evlib-ev.install 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/debian/libwebsockets-evlib-ev.install 2020-09-07 23:12:45.000000000 +0000 @@ -0,0 +1 @@ +usr/lib/*/libwebsockets-evlib_ev.so diff -Nru libwebsockets-4.0.20/debian/libwebsockets-evlib-ev.lintian-overrides libwebsockets-4.1.6/debian/libwebsockets-evlib-ev.lintian-overrides --- libwebsockets-4.0.20/debian/libwebsockets-evlib-ev.lintian-overrides 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/debian/libwebsockets-evlib-ev.lintian-overrides 2020-09-07 23:12:45.000000000 +0000 @@ -0,0 +1,2 @@ +# it's a plugin depending on ABI versioned library +shared-library-lacks-version usr/lib/x86_64-linux-gnu/libwebsockets-evlib_ev.so libwebsockets-evlib_ev.so diff -Nru libwebsockets-4.0.20/debian/libwebsockets-evlib-ev.triggers libwebsockets-4.1.6/debian/libwebsockets-evlib-ev.triggers --- libwebsockets-4.0.20/debian/libwebsockets-evlib-ev.triggers 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/debian/libwebsockets-evlib-ev.triggers 2020-09-07 23:12:45.000000000 +0000 @@ -0,0 +1,2 @@ +# it's a plugin +activate-noawait ldconfig diff -Nru libwebsockets-4.0.20/debian/libwebsockets-evlib-glib.install libwebsockets-4.1.6/debian/libwebsockets-evlib-glib.install --- libwebsockets-4.0.20/debian/libwebsockets-evlib-glib.install 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/debian/libwebsockets-evlib-glib.install 2020-09-07 23:12:45.000000000 +0000 @@ -0,0 +1 @@ +usr/lib/*/libwebsockets-evlib_glib.so diff -Nru libwebsockets-4.0.20/debian/libwebsockets-evlib-glib.lintian-overrides libwebsockets-4.1.6/debian/libwebsockets-evlib-glib.lintian-overrides --- libwebsockets-4.0.20/debian/libwebsockets-evlib-glib.lintian-overrides 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/debian/libwebsockets-evlib-glib.lintian-overrides 2020-09-07 23:12:45.000000000 +0000 @@ -0,0 +1,2 @@ +# it's a plugin depending on ABI versioned library +shared-library-lacks-version usr/lib/x86_64-linux-gnu/libwebsockets-evlib_glib.so libwebsockets-evlib_glib.so diff -Nru libwebsockets-4.0.20/debian/libwebsockets-evlib-glib.triggers libwebsockets-4.1.6/debian/libwebsockets-evlib-glib.triggers --- libwebsockets-4.0.20/debian/libwebsockets-evlib-glib.triggers 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/debian/libwebsockets-evlib-glib.triggers 2020-09-07 23:12:45.000000000 +0000 @@ -0,0 +1,2 @@ +# it's a plugin +activate-noawait ldconfig diff -Nru libwebsockets-4.0.20/debian/libwebsockets-evlib-uv.install libwebsockets-4.1.6/debian/libwebsockets-evlib-uv.install --- libwebsockets-4.0.20/debian/libwebsockets-evlib-uv.install 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/debian/libwebsockets-evlib-uv.install 2020-09-07 23:12:45.000000000 +0000 @@ -0,0 +1 @@ +usr/lib/*/libwebsockets-evlib_uv.so diff -Nru libwebsockets-4.0.20/debian/libwebsockets-evlib-uv.lintian-overrides libwebsockets-4.1.6/debian/libwebsockets-evlib-uv.lintian-overrides --- libwebsockets-4.0.20/debian/libwebsockets-evlib-uv.lintian-overrides 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/debian/libwebsockets-evlib-uv.lintian-overrides 2020-09-07 23:12:45.000000000 +0000 @@ -0,0 +1,2 @@ +# it's a plugin depending on ABI versioned library +shared-library-lacks-version usr/lib/x86_64-linux-gnu/libwebsockets-evlib_uv.so libwebsockets-evlib_uv.so diff -Nru libwebsockets-4.0.20/debian/libwebsockets-evlib-uv.triggers libwebsockets-4.1.6/debian/libwebsockets-evlib-uv.triggers --- libwebsockets-4.0.20/debian/libwebsockets-evlib-uv.triggers 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/debian/libwebsockets-evlib-uv.triggers 2020-09-07 23:12:45.000000000 +0000 @@ -0,0 +1,2 @@ +# it's a plugin +activate-noawait ldconfig diff -Nru libwebsockets-4.0.20/debian/missing-sources/plugins/generic-sessions/assets/lwsgs.js libwebsockets-4.1.6/debian/missing-sources/plugins/generic-sessions/assets/lwsgs.js --- libwebsockets-4.0.20/debian/missing-sources/plugins/generic-sessions/assets/lwsgs.js 2018-03-02 18:39:44.000000000 +0000 +++ libwebsockets-4.1.6/debian/missing-sources/plugins/generic-sessions/assets/lwsgs.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,280 +0,0 @@ -/* - * JavaScript MD5 - * https://github.com/blueimp/JavaScript-MD5 - * - * Copyright 2011, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - * - * Based on - * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message - * Digest Algorithm, as defined in RFC 1321. - * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009 - * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet - * Distributed under the BSD License - * See http://pajhome.org.uk/crypt/md5 for more info. - */ - -/* global define */ - -;(function ($) { - 'use strict' - - /* - * Add integers, wrapping at 2^32. This uses 16-bit operations internally - * to work around bugs in some JS interpreters. - */ - function safeAdd (x, y) { - var lsw = (x & 0xffff) + (y & 0xffff) - var msw = (x >> 16) + (y >> 16) + (lsw >> 16) - return (msw << 16) | (lsw & 0xffff) - } - - /* - * Bitwise rotate a 32-bit number to the left. - */ - function bitRotateLeft (num, cnt) { - return (num << cnt) | (num >>> (32 - cnt)) - } - - /* - * These functions implement the four basic operations the algorithm uses. - */ - function md5cmn (q, a, b, x, s, t) { - return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b) - } - function md5ff (a, b, c, d, x, s, t) { - return md5cmn((b & c) | (~b & d), a, b, x, s, t) - } - function md5gg (a, b, c, d, x, s, t) { - return md5cmn((b & d) | (c & ~d), a, b, x, s, t) - } - function md5hh (a, b, c, d, x, s, t) { - return md5cmn(b ^ c ^ d, a, b, x, s, t) - } - function md5ii (a, b, c, d, x, s, t) { - return md5cmn(c ^ (b | ~d), a, b, x, s, t) - } - - /* - * Calculate the MD5 of an array of little-endian words, and a bit length. - */ - function binlMD5 (x, len) { - /* append padding */ - x[len >> 5] |= 0x80 << (len % 32) - x[((len + 64) >>> 9 << 4) + 14] = len - - var i - var olda - var oldb - var oldc - var oldd - var a = 1732584193 - var b = -271733879 - var c = -1732584194 - var d = 271733878 - - for (i = 0; i < x.length; i += 16) { - olda = a - oldb = b - oldc = c - oldd = d - - a = md5ff(a, b, c, d, x[i], 7, -680876936) - d = md5ff(d, a, b, c, x[i + 1], 12, -389564586) - c = md5ff(c, d, a, b, x[i + 2], 17, 606105819) - b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330) - a = md5ff(a, b, c, d, x[i + 4], 7, -176418897) - d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426) - c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341) - b = md5ff(b, c, d, a, x[i + 7], 22, -45705983) - a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416) - d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417) - c = md5ff(c, d, a, b, x[i + 10], 17, -42063) - b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162) - a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682) - d = md5ff(d, a, b, c, x[i + 13], 12, -40341101) - c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290) - b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329) - - a = md5gg(a, b, c, d, x[i + 1], 5, -165796510) - d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632) - c = md5gg(c, d, a, b, x[i + 11], 14, 643717713) - b = md5gg(b, c, d, a, x[i], 20, -373897302) - a = md5gg(a, b, c, d, x[i + 5], 5, -701558691) - d = md5gg(d, a, b, c, x[i + 10], 9, 38016083) - c = md5gg(c, d, a, b, x[i + 15], 14, -660478335) - b = md5gg(b, c, d, a, x[i + 4], 20, -405537848) - a = md5gg(a, b, c, d, x[i + 9], 5, 568446438) - d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690) - c = md5gg(c, d, a, b, x[i + 3], 14, -187363961) - b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501) - a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467) - d = md5gg(d, a, b, c, x[i + 2], 9, -51403784) - c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473) - b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734) - - a = md5hh(a, b, c, d, x[i + 5], 4, -378558) - d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463) - c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562) - b = md5hh(b, c, d, a, x[i + 14], 23, -35309556) - a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060) - d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353) - c = md5hh(c, d, a, b, x[i + 7], 16, -155497632) - b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640) - a = md5hh(a, b, c, d, x[i + 13], 4, 681279174) - d = md5hh(d, a, b, c, x[i], 11, -358537222) - c = md5hh(c, d, a, b, x[i + 3], 16, -722521979) - b = md5hh(b, c, d, a, x[i + 6], 23, 76029189) - a = md5hh(a, b, c, d, x[i + 9], 4, -640364487) - d = md5hh(d, a, b, c, x[i + 12], 11, -421815835) - c = md5hh(c, d, a, b, x[i + 15], 16, 530742520) - b = md5hh(b, c, d, a, x[i + 2], 23, -995338651) - - a = md5ii(a, b, c, d, x[i], 6, -198630844) - d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415) - c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905) - b = md5ii(b, c, d, a, x[i + 5], 21, -57434055) - a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571) - d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606) - c = md5ii(c, d, a, b, x[i + 10], 15, -1051523) - b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799) - a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359) - d = md5ii(d, a, b, c, x[i + 15], 10, -30611744) - c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380) - b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649) - a = md5ii(a, b, c, d, x[i + 4], 6, -145523070) - d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379) - c = md5ii(c, d, a, b, x[i + 2], 15, 718787259) - b = md5ii(b, c, d, a, x[i + 9], 21, -343485551) - - a = safeAdd(a, olda) - b = safeAdd(b, oldb) - c = safeAdd(c, oldc) - d = safeAdd(d, oldd) - } - return [a, b, c, d] - } - - /* - * Convert an array of little-endian words to a string - */ - function binl2rstr (input) { - var i - var output = '' - var length32 = input.length * 32 - for (i = 0; i < length32; i += 8) { - output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xff) - } - return output - } - - /* - * Convert a raw string to an array of little-endian words - * Characters >255 have their high-byte silently ignored. - */ - function rstr2binl (input) { - var i - var output = [] - output[(input.length >> 2) - 1] = undefined - for (i = 0; i < output.length; i += 1) { - output[i] = 0 - } - var length8 = input.length * 8 - for (i = 0; i < length8; i += 8) { - output[i >> 5] |= (input.charCodeAt(i / 8) & 0xff) << (i % 32) - } - return output - } - - /* - * Calculate the MD5 of a raw string - */ - function rstrMD5 (s) { - return binl2rstr(binlMD5(rstr2binl(s), s.length * 8)) - } - - /* - * Calculate the HMAC-MD5, of a key and some data (raw strings) - */ - function rstrHMACMD5 (key, data) { - var i - var bkey = rstr2binl(key) - var ipad = [] - var opad = [] - var hash - ipad[15] = opad[15] = undefined - if (bkey.length > 16) { - bkey = binlMD5(bkey, key.length * 8) - } - for (i = 0; i < 16; i += 1) { - ipad[i] = bkey[i] ^ 0x36363636 - opad[i] = bkey[i] ^ 0x5c5c5c5c - } - hash = binlMD5(ipad.concat(rstr2binl(data)), 512 + data.length * 8) - return binl2rstr(binlMD5(opad.concat(hash), 512 + 128)) - } - - /* - * Convert a raw string to a hex string - */ - function rstr2hex (input) { - var hexTab = '0123456789abcdef' - var output = '' - var x - var i - for (i = 0; i < input.length; i += 1) { - x = input.charCodeAt(i) - output += hexTab.charAt((x >>> 4) & 0x0f) + hexTab.charAt(x & 0x0f) - } - return output - } - - /* - * Encode a string as utf-8 - */ - function str2rstrUTF8 (input) { - return unescape(encodeURIComponent(input)) - } - - /* - * Take string arguments and return either raw or hex encoded strings - */ - function rawMD5 (s) { - return rstrMD5(str2rstrUTF8(s)) - } - function hexMD5 (s) { - return rstr2hex(rawMD5(s)) - } - function rawHMACMD5 (k, d) { - return rstrHMACMD5(str2rstrUTF8(k), str2rstrUTF8(d)) - } - function hexHMACMD5 (k, d) { - return rstr2hex(rawHMACMD5(k, d)) - } - - function md5 (string, key, raw) { - if (!key) { - if (!raw) { - return hexMD5(string) - } - return rawMD5(string) - } - if (!raw) { - return hexHMACMD5(key, string) - } - return rawHMACMD5(key, string) - } - - if (typeof define === 'function' && define.amd) { - define(function () { - return md5 - }) - } else if (typeof module === 'object' && module.exports) { - module.exports = md5 - } else { - $.md5 = md5 - } -})(this) diff -Nru libwebsockets-4.0.20/debian/missing-sources/plugins/generic-sessions/assets/md5.js libwebsockets-4.1.6/debian/missing-sources/plugins/generic-sessions/assets/md5.js --- libwebsockets-4.0.20/debian/missing-sources/plugins/generic-sessions/assets/md5.js 2018-03-02 18:39:44.000000000 +0000 +++ libwebsockets-4.1.6/debian/missing-sources/plugins/generic-sessions/assets/md5.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,280 +0,0 @@ -/* - * JavaScript MD5 - * https://github.com/blueimp/JavaScript-MD5 - * - * Copyright 2011, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - * - * Based on - * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message - * Digest Algorithm, as defined in RFC 1321. - * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009 - * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet - * Distributed under the BSD License - * See http://pajhome.org.uk/crypt/md5 for more info. - */ - -/* global define */ - -;(function ($) { - 'use strict' - - /* - * Add integers, wrapping at 2^32. This uses 16-bit operations internally - * to work around bugs in some JS interpreters. - */ - function safeAdd (x, y) { - var lsw = (x & 0xffff) + (y & 0xffff) - var msw = (x >> 16) + (y >> 16) + (lsw >> 16) - return (msw << 16) | (lsw & 0xffff) - } - - /* - * Bitwise rotate a 32-bit number to the left. - */ - function bitRotateLeft (num, cnt) { - return (num << cnt) | (num >>> (32 - cnt)) - } - - /* - * These functions implement the four basic operations the algorithm uses. - */ - function md5cmn (q, a, b, x, s, t) { - return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b) - } - function md5ff (a, b, c, d, x, s, t) { - return md5cmn((b & c) | (~b & d), a, b, x, s, t) - } - function md5gg (a, b, c, d, x, s, t) { - return md5cmn((b & d) | (c & ~d), a, b, x, s, t) - } - function md5hh (a, b, c, d, x, s, t) { - return md5cmn(b ^ c ^ d, a, b, x, s, t) - } - function md5ii (a, b, c, d, x, s, t) { - return md5cmn(c ^ (b | ~d), a, b, x, s, t) - } - - /* - * Calculate the MD5 of an array of little-endian words, and a bit length. - */ - function binlMD5 (x, len) { - /* append padding */ - x[len >> 5] |= 0x80 << (len % 32) - x[((len + 64) >>> 9 << 4) + 14] = len - - var i - var olda - var oldb - var oldc - var oldd - var a = 1732584193 - var b = -271733879 - var c = -1732584194 - var d = 271733878 - - for (i = 0; i < x.length; i += 16) { - olda = a - oldb = b - oldc = c - oldd = d - - a = md5ff(a, b, c, d, x[i], 7, -680876936) - d = md5ff(d, a, b, c, x[i + 1], 12, -389564586) - c = md5ff(c, d, a, b, x[i + 2], 17, 606105819) - b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330) - a = md5ff(a, b, c, d, x[i + 4], 7, -176418897) - d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426) - c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341) - b = md5ff(b, c, d, a, x[i + 7], 22, -45705983) - a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416) - d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417) - c = md5ff(c, d, a, b, x[i + 10], 17, -42063) - b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162) - a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682) - d = md5ff(d, a, b, c, x[i + 13], 12, -40341101) - c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290) - b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329) - - a = md5gg(a, b, c, d, x[i + 1], 5, -165796510) - d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632) - c = md5gg(c, d, a, b, x[i + 11], 14, 643717713) - b = md5gg(b, c, d, a, x[i], 20, -373897302) - a = md5gg(a, b, c, d, x[i + 5], 5, -701558691) - d = md5gg(d, a, b, c, x[i + 10], 9, 38016083) - c = md5gg(c, d, a, b, x[i + 15], 14, -660478335) - b = md5gg(b, c, d, a, x[i + 4], 20, -405537848) - a = md5gg(a, b, c, d, x[i + 9], 5, 568446438) - d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690) - c = md5gg(c, d, a, b, x[i + 3], 14, -187363961) - b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501) - a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467) - d = md5gg(d, a, b, c, x[i + 2], 9, -51403784) - c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473) - b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734) - - a = md5hh(a, b, c, d, x[i + 5], 4, -378558) - d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463) - c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562) - b = md5hh(b, c, d, a, x[i + 14], 23, -35309556) - a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060) - d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353) - c = md5hh(c, d, a, b, x[i + 7], 16, -155497632) - b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640) - a = md5hh(a, b, c, d, x[i + 13], 4, 681279174) - d = md5hh(d, a, b, c, x[i], 11, -358537222) - c = md5hh(c, d, a, b, x[i + 3], 16, -722521979) - b = md5hh(b, c, d, a, x[i + 6], 23, 76029189) - a = md5hh(a, b, c, d, x[i + 9], 4, -640364487) - d = md5hh(d, a, b, c, x[i + 12], 11, -421815835) - c = md5hh(c, d, a, b, x[i + 15], 16, 530742520) - b = md5hh(b, c, d, a, x[i + 2], 23, -995338651) - - a = md5ii(a, b, c, d, x[i], 6, -198630844) - d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415) - c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905) - b = md5ii(b, c, d, a, x[i + 5], 21, -57434055) - a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571) - d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606) - c = md5ii(c, d, a, b, x[i + 10], 15, -1051523) - b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799) - a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359) - d = md5ii(d, a, b, c, x[i + 15], 10, -30611744) - c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380) - b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649) - a = md5ii(a, b, c, d, x[i + 4], 6, -145523070) - d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379) - c = md5ii(c, d, a, b, x[i + 2], 15, 718787259) - b = md5ii(b, c, d, a, x[i + 9], 21, -343485551) - - a = safeAdd(a, olda) - b = safeAdd(b, oldb) - c = safeAdd(c, oldc) - d = safeAdd(d, oldd) - } - return [a, b, c, d] - } - - /* - * Convert an array of little-endian words to a string - */ - function binl2rstr (input) { - var i - var output = '' - var length32 = input.length * 32 - for (i = 0; i < length32; i += 8) { - output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xff) - } - return output - } - - /* - * Convert a raw string to an array of little-endian words - * Characters >255 have their high-byte silently ignored. - */ - function rstr2binl (input) { - var i - var output = [] - output[(input.length >> 2) - 1] = undefined - for (i = 0; i < output.length; i += 1) { - output[i] = 0 - } - var length8 = input.length * 8 - for (i = 0; i < length8; i += 8) { - output[i >> 5] |= (input.charCodeAt(i / 8) & 0xff) << (i % 32) - } - return output - } - - /* - * Calculate the MD5 of a raw string - */ - function rstrMD5 (s) { - return binl2rstr(binlMD5(rstr2binl(s), s.length * 8)) - } - - /* - * Calculate the HMAC-MD5, of a key and some data (raw strings) - */ - function rstrHMACMD5 (key, data) { - var i - var bkey = rstr2binl(key) - var ipad = [] - var opad = [] - var hash - ipad[15] = opad[15] = undefined - if (bkey.length > 16) { - bkey = binlMD5(bkey, key.length * 8) - } - for (i = 0; i < 16; i += 1) { - ipad[i] = bkey[i] ^ 0x36363636 - opad[i] = bkey[i] ^ 0x5c5c5c5c - } - hash = binlMD5(ipad.concat(rstr2binl(data)), 512 + data.length * 8) - return binl2rstr(binlMD5(opad.concat(hash), 512 + 128)) - } - - /* - * Convert a raw string to a hex string - */ - function rstr2hex (input) { - var hexTab = '0123456789abcdef' - var output = '' - var x - var i - for (i = 0; i < input.length; i += 1) { - x = input.charCodeAt(i) - output += hexTab.charAt((x >>> 4) & 0x0f) + hexTab.charAt(x & 0x0f) - } - return output - } - - /* - * Encode a string as utf-8 - */ - function str2rstrUTF8 (input) { - return unescape(encodeURIComponent(input)) - } - - /* - * Take string arguments and return either raw or hex encoded strings - */ - function rawMD5 (s) { - return rstrMD5(str2rstrUTF8(s)) - } - function hexMD5 (s) { - return rstr2hex(rawMD5(s)) - } - function rawHMACMD5 (k, d) { - return rstrHMACMD5(str2rstrUTF8(k), str2rstrUTF8(d)) - } - function hexHMACMD5 (k, d) { - return rstr2hex(rawHMACMD5(k, d)) - } - - function md5 (string, key, raw) { - if (!key) { - if (!raw) { - return hexMD5(string) - } - return rawMD5(string) - } - if (!raw) { - return hexHMACMD5(key, string) - } - return rawHMACMD5(key, string) - } - - if (typeof define === 'function' && define.amd) { - define(function () { - return md5 - }) - } else if (typeof module === 'object' && module.exports) { - module.exports = md5 - } else { - $.md5 = md5 - } -})(this) diff -Nru libwebsockets-4.0.20/debian/patches/add-missing-headers.patch libwebsockets-4.1.6/debian/patches/add-missing-headers.patch --- libwebsockets-4.0.20/debian/patches/add-missing-headers.patch 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/debian/patches/add-missing-headers.patch 2020-09-07 23:12:45.000000000 +0000 @@ -0,0 +1,47 @@ +Description: + TODO: Put a short summary on the line above and replace this paragraph + with a longer explanation of this change. Complete the meta-information + with other relevant fields (see below for details). To make it easier, the + information below has been extracted from the changelog. Adjust it or drop + it. + . + libwebsockets (4.1.0-1) unstable; urgency=medium + . + * New upstream release. + * Library transition from libwebsockets16 to libwebsockets17 . + * Update library symbols for this release. +Author: Laszlo Boszormenyi (GCS) + +--- +The information above should follow the Patch Tagging Guidelines, please +checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here +are templates for supplementary fields that you might want to add: + +Origin: , +Bug: +Bug-Debian: https://bugs.debian.org/ +Bug-Ubuntu: https://launchpad.net/bugs/ +Forwarded: +Reviewed-By: +Last-Update: 2020-09-08 + +--- libwebsockets-4.1.0.orig/plugins/protocol_lws_raw_test.c ++++ libwebsockets-4.1.0/plugins/protocol_lws_raw_test.c +@@ -73,6 +73,7 @@ + + #include + #include ++#include + + struct per_vhost_data__raw_test { + struct lws_context *context; +--- libwebsockets-4.1.0.orig/plugins/protocol_lws_sshd_demo.c ++++ libwebsockets-4.1.0/plugins/protocol_lws_sshd_demo.c +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + + #define TEST_SERVER_KEY_PATH "/etc/lws-test-sshd-server-key" + diff -Nru libwebsockets-4.0.20/debian/patches/f9d1f25abe896b9fa1de780e4a5cb41116926a29.patch libwebsockets-4.1.6/debian/patches/f9d1f25abe896b9fa1de780e4a5cb41116926a29.patch --- libwebsockets-4.0.20/debian/patches/f9d1f25abe896b9fa1de780e4a5cb41116926a29.patch 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/debian/patches/f9d1f25abe896b9fa1de780e4a5cb41116926a29.patch 2023-07-20 15:27:19.000000000 +0000 @@ -0,0 +1,30 @@ +From f9d1f25abe896b9fa1de780e4a5cb41116926a29 Mon Sep 17 00:00:00 2001 +From: Andy Green +Date: Wed, 14 Jun 2023 07:14:23 +0100 +Subject: [PATCH] openssl-server: enum vs int disagreement + +https://github.com/warmcat/libwebsockets/issues/2907 +--- + lib/tls/openssl/openssl-server.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/lib/tls/openssl/openssl-server.c b/lib/tls/openssl/openssl-server.c +index f2e77324f..1fc819293 100644 +--- a/lib/tls/openssl/openssl-server.c ++++ b/lib/tls/openssl/openssl-server.c +@@ -607,13 +607,13 @@ lws_tls_server_new_nonblocking(struct lw + return 0; + } + +-int ++enum lws_ssl_capable_status + lws_tls_server_abort_connection(struct lws *wsi) + { + SSL_shutdown(wsi->tls.ssl); + SSL_free(wsi->tls.ssl); + +- return 0; ++ return LWS_SSL_CAPABLE_DONE; + } + + enum lws_ssl_capable_status diff -Nru libwebsockets-4.0.20/debian/patches/series libwebsockets-4.1.6/debian/patches/series --- libwebsockets-4.0.20/debian/patches/series 2019-10-13 14:23:13.000000000 +0000 +++ libwebsockets-4.1.6/debian/patches/series 2023-07-20 15:27:19.000000000 +0000 @@ -1,2 +1,4 @@ #echo-actually-exit.patch #echo-off-by-one.patch +#add-missing-headers.patch +f9d1f25abe896b9fa1de780e4a5cb41116926a29.patch diff -Nru libwebsockets-4.0.20/debian/rules libwebsockets-4.1.6/debian/rules --- libwebsockets-4.0.20/debian/rules 2021-12-01 17:39:49.000000000 +0000 +++ libwebsockets-4.1.6/debian/rules 2022-08-06 05:42:00.000000000 +0000 @@ -10,9 +10,7 @@ DEB_BUILD_MAINT_OPTIONS= hardening=+all future=+lfs export DEB_BUILD_MAINT_OPTIONS -# TODO: remove -Wno-error=format-truncation and -Wno-error=format-overflow on -# next upstream release -DEB_CFLAGS_MAINT_APPEND= -Wno-error=deprecated-declarations -fno-strict-aliasing -Wno-error=format-truncation -Wno-error=format-overflow +DEB_CFLAGS_MAINT_APPEND= -Wno-error=deprecated-declarations -fno-strict-aliasing export DEB_CFLAGS_MAINT_APPEND arch?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) @@ -25,8 +23,8 @@ -DLIB_SUFFIX=/${arch} -DLWS_WITHOUT_DAEMONIZE=OFF \ -DLWS_WITH_LIBEV=ON -DLWS_WITH_LIBUV=ON \ -DLWS_UNIX_SOCK=ON -DLWS_IPV6=ON \ - -DLWS_WITH_ZLIB=ON -DLWS_WITH_EXTERNAL_POLL=ON \ - -DLWS_WITHOUT_EXTENSIONS=OFF + -DLWS_WITH_ZLIB=ON -DLWS_WITHOUT_EXTENSIONS=OFF \ + -DLWS_WITH_GLIB=ON override_dh_install-arch: $(RM) $(CURDIR)/debian/tmp/usr/lib/${arch}/pkgconfig/libwebsockets_static.pc diff -Nru libwebsockets-4.0.20/debian/source/lintian-overrides libwebsockets-4.1.6/debian/source/lintian-overrides --- libwebsockets-4.0.20/debian/source/lintian-overrides 2019-10-13 14:23:13.000000000 +0000 +++ libwebsockets-4.1.6/debian/source/lintian-overrides 2022-08-06 05:42:00.000000000 +0000 @@ -1,5 +1,3 @@ # long lines or unused, uninstalled file -source-is-missing test-apps/test.js line length is 1767 characters (>512) -source-is-missing minimal-examples/http-server/minimal-http-server-eventlib-demos/mount-origin/test.js line length is 1767 characters (>512) -source-is-missing minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/lwsgs.js line length is 3836 characters (>512) -source-is-missing minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/md5.min.js +source-is-missing [minimal-examples/http-server/minimal-http-server-eventlib-demos/mount-origin/test.js] +source-is-missing [test-apps/test.js] diff -Nru libwebsockets-4.0.20/debian/tests/t/01-build.t libwebsockets-4.1.6/debian/tests/t/01-build.t --- libwebsockets-4.0.20/debian/tests/t/01-build.t 2018-03-02 18:39:44.000000000 +0000 +++ libwebsockets-4.1.6/debian/tests/t/01-build.t 2022-08-07 08:43:01.000000000 +0000 @@ -38,7 +38,7 @@ my ($out, $err) = get_program_output [$pc, '--modversion', '--', $mod]; my @lines = split /\r*\n/, $out; is @lines, 1, "'$pc --modversion $mod' output a single line"; - like $lines[0], qr/^ (?: \d+ ) (?: \. \d+ )* $/x, + like $lines[0], qr/^ (?: \d+ ) (?: \. \d+-? )* $/x, "'$pc --modversion $mod' output a version-number-like string"; $lws_version = $lines[0]; @@ -74,6 +74,6 @@ my ($out, $err) = get_program_output [$bin]; my @lines = split /\r*\n/, $out; is @lines, 1, 'The test program output a single line'; - like $lines[0], qr/^ \Q$lws_version\E \b /x, + like $lines[0], qr/^ \Q$lws_version\E /x, 'The test program output the correct library version'; }; Binary files /tmp/tmpmec97nsd/m0nuW2sR0N/libwebsockets-4.0.20/doc-assets/lws-overview.png and /tmp/tmpmec97nsd/q8JCI83EXS/libwebsockets-4.1.6/doc-assets/lws-overview.png differ Binary files /tmp/tmpmec97nsd/m0nuW2sR0N/libwebsockets-4.0.20/doc-assets/ss-operation-modes.png and /tmp/tmpmec97nsd/q8JCI83EXS/libwebsockets-4.1.6/doc-assets/ss-operation-modes.png differ Binary files /tmp/tmpmec97nsd/m0nuW2sR0N/libwebsockets-4.0.20/doc-assets/ss-state-flow.png and /tmp/tmpmec97nsd/q8JCI83EXS/libwebsockets-4.1.6/doc-assets/ss-state-flow.png differ Binary files /tmp/tmpmec97nsd/m0nuW2sR0N/libwebsockets-4.0.20/doc-assets/ss-state-flow-server.png and /tmp/tmpmec97nsd/q8JCI83EXS/libwebsockets-4.1.6/doc-assets/ss-state-flow-server.png differ diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-async-dns.h libwebsockets-4.1.6/include/libwebsockets/lws-async-dns.h --- libwebsockets-4.0.20/include/libwebsockets/lws-async-dns.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-async-dns.h 2020-12-01 17:40:26.000000000 +0000 @@ -40,6 +40,8 @@ LADNS_RET_CONTINUING } lws_async_dns_retcode_t; +struct addrinfo; + typedef struct lws * (*lws_async_dns_cb_t)(struct lws *wsi, const char *ads, const struct addrinfo *result, int n, void *opaque); diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-bb-i2c.h libwebsockets-4.1.6/include/libwebsockets/lws-bb-i2c.h --- libwebsockets-4.0.20/include/libwebsockets/lws-bb-i2c.h 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-bb-i2c.h 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,66 @@ +/* + * I2C - bitbanged generic gpio implementation + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + * This is like an abstract class for gpio, a real implementation provides + * functions for the ops that use the underlying OS gpio arrangements. + */ + +typedef struct lws_bb_i2c { + lws_i2c_ops_t bb_ops; /* init to lws_bb_i2c_ops */ + + /* implementation-specific members */ + + _lws_plat_gpio_t scl; + _lws_plat_gpio_t sda; + + const lws_gpio_ops_t *gpio; + void (*delay)(void); +} lws_bb_i2c_t; + +#define lws_bb_i2c_ops \ + { \ + .init = lws_bb_i2c_init, \ + .start = lws_bb_i2c_start, \ + .stop = lws_bb_i2c_stop, \ + .write = lws_bb_i2c_write, \ + .read = lws_bb_i2c_read, \ + .set_ack = lws_bb_i2c_set_ack, \ + } + +int +lws_bb_i2c_init(const lws_i2c_ops_t *octx); + +int +lws_bb_i2c_start(const lws_i2c_ops_t *octx); + +void +lws_bb_i2c_stop(const lws_i2c_ops_t *octx); + +int +lws_bb_i2c_write(const lws_i2c_ops_t *octx, uint8_t data); + +int +lws_bb_i2c_read(const lws_i2c_ops_t *octx); + +void +lws_bb_i2c_set_ack(const lws_i2c_ops_t *octx, int ack); diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-bb-spi.h libwebsockets-4.1.6/include/libwebsockets/lws-bb-spi.h --- libwebsockets-4.0.20/include/libwebsockets/lws-bb-spi.h 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-bb-spi.h 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,62 @@ +/* + * I2C - bitbanged generic gpio implementation + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + * This is like an abstract class for gpio, a real implementation provides + * functions for the ops that use the underlying OS gpio arrangements. + */ + +#define LWSBBSPI_FLAG_USE_NCMD3 (1 << 7) +#define LWSBBSPI_FLAG_USE_NCMD2 (1 << 6) +#define LWSBBSPI_FLAG_USE_NCMD1 (1 << 5) +#define LWSBBSPI_FLAG_USE_NCMD0 (1 << 4) +#define LWSBBSPI_FLAG_USE_NCS3 (1 << 3) +#define LWSBBSPI_FLAG_USE_NCS2 (1 << 2) +#define LWSBBSPI_FLAG_USE_NCS1 (1 << 1) +#define LWSBBSPI_FLAG_USE_NCS0 (1 << 0) + +#define LWS_SPI_BB_MAX_CH 4 + +typedef struct lws_bb_spi { + lws_spi_ops_t bb_ops; /* init to lws_bb_spi_ops */ + + /* implementation-specific members */ + const lws_gpio_ops_t *gpio; + + _lws_plat_gpio_t clk; + _lws_plat_gpio_t ncs[LWS_SPI_BB_MAX_CH]; + _lws_plat_gpio_t ncmd[LWS_SPI_BB_MAX_CH]; + _lws_plat_gpio_t mosi; + _lws_plat_gpio_t miso; + + uint8_t flags; +} lws_bb_spi_t; + +#define lws_bb_spi_ops \ + .init = lws_bb_spi_init, \ + .queue = lws_bb_spi_queue + +int +lws_bb_spi_init(const lws_spi_ops_t *octx); + +int +lws_bb_spi_queue(const lws_spi_ops_t *octx, const lws_spi_desc_t *desc); diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-button.h libwebsockets-4.1.6/include/libwebsockets/lws-button.h --- libwebsockets-4.0.20/include/libwebsockets/lws-button.h 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-button.h 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,120 @@ +/* + * Generic button ops + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + * Leverages the lws generic gpio pieces to bind gpio buttons to smd events + */ + +#if !defined(__LWS_BUTTON_H__) +#define __LWS_BUTTON_H__ + +typedef uint16_t lws_button_idx_t; + +/* actual minimum may be 1 x RTOS tick depending on platform */ +#define LWS_BUTTON_MON_TIMER_MS 5 + +typedef void (*lws_button_cb_t)(void *opaque, lws_button_idx_t idx, int state); + +/* These are specified in ms but the granularity is LWS_BUTTON_MON_TIMER_MS, + * which may have been rounded up to an RTOS tick depending on platform */ + +enum { + LWSBTNRGMFLAG_CLASSIFY_DOUBLECLICK = (1 << 0) +}; + +typedef struct lws_button_regime { + uint16_t ms_min_down; + uint16_t ms_min_down_longpress; + uint16_t ms_up_settle; + uint16_t ms_doubleclick_grace; + uint16_t ms_repeat_down; + uint8_t flags; + /**< when double-click classification is enabled, clicks are delayed + * by ms_min_down + ms_doubleclick_grace to wait and see if it will + * become a double-click. Set LWSBTNRGMFLAG_CLASSIFY_DOUBLECLICK to + * enable it or leave that bit at 0 to get faster single-click + * classification. + */ +} lws_button_regime_t; + +/* + * This is the const part of the button controller, describing the static + * bindings to gpio, and lws_smd event name information + */ + +typedef struct lws_button_map { + _lws_plat_gpio_t gpio; + const char *smd_interaction_name; + const lws_button_regime_t *regime; + /**< a default regime is applied if this is left NULL */ +} lws_button_map_t; + +typedef struct lws_button_controller { + const char *smd_bc_name; + const lws_gpio_ops_t *gpio_ops; + const lws_button_map_t *button_map; + lws_button_idx_t active_state_bitmap; + uint8_t count_buttons; +} lws_button_controller_t; + +struct lws_button_state; /* opaque */ + +/** + * lws_button_controller_create() - instantiate a button controller + * + * \param ctx: the lws_context + * \param controller: the static controller definition + * + * Instantiates a button controller from a static definition of the buttons + * and their smd names, and active levels, and binds it to a gpio implementation + */ + +LWS_VISIBLE LWS_EXTERN struct lws_button_state * +lws_button_controller_create(struct lws_context *ctx, + const lws_button_controller_t *controller); + +/** + * lws_button_controller_destroy() - destroys a button controller + * + * \param bcs: button controller state previously created + * + * Disables all buttons and then destroys and frees a previously created + * button controller. + */ + +LWS_VISIBLE LWS_EXTERN void +lws_button_controller_destroy(struct lws_button_state *bcs); + + +LWS_VISIBLE LWS_EXTERN lws_button_idx_t +lws_button_get_bit(struct lws_button_state *bcs, const char *name); + +/* + * lws_button_enable() - enable and disable buttons + */ + +LWS_VISIBLE LWS_EXTERN void +lws_button_enable(struct lws_button_state *bcs, + lws_button_idx_t _reset, lws_button_idx_t _set); + +#endif + diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-callbacks.h libwebsockets-4.1.6/include/libwebsockets/lws-callbacks.h --- libwebsockets-4.0.20/include/libwebsockets/lws-callbacks.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-callbacks.h 2020-12-01 17:40:26.000000000 +0000 @@ -81,6 +81,17 @@ }; /* + * With LWS_CALLBACK_FILTER_NETWORK_CONNECTION callback, user_data pointer + * points to one of these + */ + +struct lws_filter_network_conn_args { + struct sockaddr_storage cli_addr; + socklen_t clilen; + lws_sockfd_type accept_fd; +}; + +/* * NOTE: These public enums are part of the abi. If you want to add one, * add it at where specified so existing users are unaffected. */ @@ -390,6 +401,9 @@ * lws know by calling lws_client_http_body_pending(wsi, 0) */ + LWS_CALLBACK_CLIENT_HTTP_REDIRECT = 104, + /**< we're handling a 3xx redirect... return nonzero to hang up */ + LWS_CALLBACK_CLIENT_HTTP_BIND_PROTOCOL = 85, LWS_CALLBACK_CLIENT_HTTP_DROP_PROTOCOL = 76, @@ -578,9 +592,17 @@ /**< called when a client connects to * the server at network level; the connection is accepted but then * passed to this callback to decide whether to hang up immediately - * or not, based on the client IP. in contains the connection - * socket's descriptor. Since the client connection information is - * not available yet, wsi still pointing to the main server socket. + * or not, based on the client IP. + * + * user_data in the callback points to a + * struct lws_filter_network_conn_args that is prepared with the + * sockfd, and the peer's address information. + * + * in contains the connection socket's descriptor. + * + * Since the client connection information is not available yet, + * wsi still pointing to the main server socket. + * * Return non-zero to terminate the connection before sending or * receiving anything. Because this happens immediately after the * network connection from the client, there's no websocket protocol diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-client.h libwebsockets-4.1.6/include/libwebsockets/lws-client.h --- libwebsockets-4.0.20/include/libwebsockets/lws-client.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-client.h 2020-12-01 17:40:26.000000000 +0000 @@ -58,6 +58,20 @@ * HTTP/2: always possible... uses parallel streams */ LCCSCF_MUXABLE_STREAM = (1 << 17), + LCCSCF_H2_PRIOR_KNOWLEDGE = (1 << 18), + LCCSCF_WAKE_SUSPEND__VALIDITY = (1 << 19), + /* our validity checks are important enough to wake from suspend */ + LCCSCF_PRIORITIZE_READS = (1 << 20), + /**< + * Normally lws balances reads and writes on all connections, so both + * are possible even on busy connections, and we go around the event + * loop more often to facilitate that, even if there is pending data. + * + * This flag indicates that you want to handle any pending reads on this + * connection without yielding the service loop for anything else. This + * means you may block other connection processing in favour of incoming + * data processing on this one if it receives back to back incoming rx. + */ }; /** struct lws_client_connect_info - parameters to connect with when using @@ -163,6 +177,12 @@ void *mqtt_cp; #endif + uint16_t keep_warm_secs; + /**< 0 means 5s. If the client connection to the endpoint becomes idle, + * defer closing it for this many seconds in case another outgoing + * connection to the same endpoint turns up. + */ + /* Add new things just above here ---^ * This is part of the ABI, don't needlessly break compatibility * diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-context-vhost.h libwebsockets-4.1.6/include/libwebsockets/lws-context-vhost.h --- libwebsockets-4.0.20/include/libwebsockets/lws-context-vhost.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-context-vhost.h 2020-12-01 17:40:26.000000000 +0000 @@ -221,6 +221,15 @@ #define LWS_SERVER_OPTION_GLIB (1ll << 33) /**< (CTX) Use glib event loop */ +#define LWS_SERVER_OPTION_H2_PRIOR_KNOWLEDGE (1ll << 34) + /**< (VH) Tell the vhost to treat plain text http connections as + * H2 with prior knowledge (no upgrade request involved) + */ + +#define LWS_SERVER_OPTION_NO_LWS_SYSTEM_STATES (1ll << 35) + /**< (CTX) Disable lws_system state, eg, because we are a secure streams + * proxy client that is not trying to track system state by itself. */ + /****** add new things just above ---^ ******/ @@ -232,6 +241,10 @@ typedef int (*lws_context_ready_cb_t)(struct lws_context *context); +typedef int (*lws_peer_limits_notify_t)(struct lws_context *ctx, + lws_sockfd_type sockfd, + lws_sockaddr46 *sa46); + /** struct lws_context_creation_info - parameters to create context and /or vhost with * * This is also used to create vhosts.... if LWS_SERVER_OPTION_EXPLICIT_VHOSTS @@ -242,15 +255,7 @@ * at the same time as the context, they are expected to be created afterwards. */ struct lws_context_creation_info { - int port; - /**< VHOST: Port to listen on. Use CONTEXT_PORT_NO_LISTEN to suppress - * listening for a client. Use CONTEXT_PORT_NO_LISTEN_SERVER if you are - * writing a server but you are using \ref sock-adopt instead of the - * built-in listener. - * - * You can also set port to 0, in which case the kernel will pick - * a random port that is not already in use. You can find out what - * port the vhost is listening on using lws_get_vhost_listen_port() */ +#if defined(LWS_WITH_NETWORK) const char *iface; /**< VHOST: NULL to bind the listen socket to all interfaces, or the * interface name, eg, "eth2" @@ -264,12 +269,94 @@ * entry that has a NULL callback pointer. SEE ALSO .pprotocols below, * which gives an alternative way to provide an array of pointers to * protocol structs. */ +#if defined(LWS_ROLE_WS) const struct lws_extension *extensions; /**< VHOST: NULL or array of lws_extension structs listing the * extensions this context supports. */ +#endif +#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) const struct lws_token_limits *token_limits; /**< CONTEXT: NULL or struct lws_token_limits pointer which is * initialized with a token length limit for each possible WSI_TOKEN_ */ + const char *http_proxy_address; + /**< VHOST: If non-NULL, attempts to proxy via the given address. + * If proxy auth is required, use format + * "username:password\@server:port" */ + const struct lws_protocol_vhost_options *headers; + /**< VHOST: pointer to optional linked list of per-vhost + * canned headers that are added to server responses */ + + const struct lws_protocol_vhost_options *reject_service_keywords; + /**< CONTEXT: Optional list of keywords and rejection codes + text. + * + * The keywords are checked for existing in the user agent string. + * + * Eg, "badrobot" "404 Not Found" + */ + const struct lws_protocol_vhost_options *pvo; + /**< VHOST: pointer to optional linked list of per-vhost + * options made accessible to protocols */ + const char *log_filepath; + /**< VHOST: filepath to append logs to... this is opened before + * any dropping of initial privileges */ + const struct lws_http_mount *mounts; + /**< VHOST: optional linked list of mounts for this vhost */ + const char *server_string; + /**< CONTEXT: string used in HTTP headers to identify server + * software, if NULL, "libwebsockets". */ + + const char *error_document_404; + /**< VHOST: If non-NULL, when asked to serve a non-existent file, + * lws attempts to server this url path instead. Eg, + * "/404.html" */ + int port; + /**< VHOST: Port to listen on. Use CONTEXT_PORT_NO_LISTEN to suppress + * listening for a client. Use CONTEXT_PORT_NO_LISTEN_SERVER if you are + * writing a server but you are using \ref sock-adopt instead of the + * built-in listener. + * + * You can also set port to 0, in which case the kernel will pick + * a random port that is not already in use. You can find out what + * port the vhost is listening on using lws_get_vhost_listen_port() */ + + unsigned int http_proxy_port; + /**< VHOST: If http_proxy_address was non-NULL, uses this port */ + unsigned int max_http_header_data2; + /**< CONTEXT: if max_http_header_data is 0 and this + * is nonzero, this will be used in place of the default. It's + * like this for compatibility with the original short version, + * this is unsigned int length. */ + unsigned int max_http_header_pool2; + /**< CONTEXT: if max_http_header_pool is 0 and this + * is nonzero, this will be used in place of the default. It's + * like this for compatibility with the original short version: + * this is unsigned int length. */ + + int keepalive_timeout; + /**< VHOST: (default = 0 = 5s, 31s for http/2) seconds to allow remote + * client to hold on to an idle HTTP/1.1 connection. Timeout lifetime + * applied to idle h2 network connections */ + uint32_t http2_settings[7]; + /**< VHOST: if http2_settings[0] is nonzero, the values given in + * http2_settings[1]..[6] are used instead of the lws + * platform default values. + * Just leave all at 0 if you don't care. + */ + + unsigned short max_http_header_data; + /**< CONTEXT: The max amount of header payload that can be handled + * in an http request (unrecognized header payload is dropped) */ + unsigned short max_http_header_pool; + /**< CONTEXT: The max number of connections with http headers that + * can be processed simultaneously (the corresponding memory is + * allocated and deallocated dynamically as needed). If the pool is + * fully busy new incoming connections must wait for accept until one + * becomes free. 0 = allow as many ah as number of availble fds for + * the process */ + +#endif + +#if defined(LWS_WITH_TLS) const char *ssl_private_key_password; /**< VHOST: NULL or the passphrase needed for the private key. (For * backwards compatibility, this can also be used to pass the client @@ -320,12 +407,159 @@ * SEE .tls1_3_plus_cipher_list and .client_tls_1_3_plus_cipher_list * for the equivalent for tls1.3. */ - const char *http_proxy_address; - /**< VHOST: If non-NULL, attempts to proxy via the given address. - * If proxy auth is required, use format - * "username:password\@server:port" */ - unsigned int http_proxy_port; - /**< VHOST: If http_proxy_address was non-NULL, uses this port */ + const char *ecdh_curve; + /**< VHOST: if NULL, defaults to initializing server with + * "prime256v1" */ + const char *tls1_3_plus_cipher_list; + /**< VHOST: List of valid ciphers to use for incoming server connections + * ON TLS1.3 AND ABOVE (eg, "TLS_CHACHA20_POLY1305_SHA256" on this vhost + * or you can leave it as NULL to get "DEFAULT". + * SEE .client_tls_1_3_plus_cipher_list to do the same on the vhost + * client SSL_CTX. + */ + + const void *server_ssl_cert_mem; + /**< VHOST: Alternative for \p ssl_cert_filepath that allows setting + * from memory instead of from a file. At most one of + * \p ssl_cert_filepath or \p server_ssl_cert_mem should be non-NULL. */ + const void *server_ssl_private_key_mem; + /**< VHOST: Alternative for \p ssl_private_key_filepath allowing + * init from a private key in memory instead of a file. At most one + * of \p ssl_private_key_filepath or \p server_ssl_private_key_mem + * should be non-NULL. */ + const void *server_ssl_ca_mem; + /**< VHOST: Alternative for \p ssl_ca_filepath allowing + * init from a CA cert in memory instead of a file. At most one + * of \p ssl_ca_filepath or \p server_ssl_ca_mem should be non-NULL. */ + + long ssl_options_set; + /**< VHOST: Any bits set here will be set as server SSL options */ + long ssl_options_clear; + /**< VHOST: Any bits set here will be cleared as server SSL options */ + int simultaneous_ssl_restriction; + /**< CONTEXT: 0 (no limit) or limit of simultaneous SSL sessions + * possible.*/ + int ssl_info_event_mask; + /**< VHOST: mask of ssl events to be reported on LWS_CALLBACK_SSL_INFO + * callback for connections on this vhost. The mask values are of + * the form SSL_CB_ALERT, defined in openssl/ssl.h. The default of + * 0 means no info events will be reported. + */ + unsigned int server_ssl_cert_mem_len; + /**< VHOST: Server SSL context init: length of server_ssl_cert_mem in + * bytes */ + unsigned int server_ssl_private_key_mem_len; + /**< VHOST: length of \p server_ssl_private_key_mem in memory */ + unsigned int server_ssl_ca_mem_len; + /**< VHOST: length of \p server_ssl_ca_mem in memory */ + + const char *alpn; + /**< CONTEXT: If non-NULL, default list of advertised alpn, comma- + * separated + * + * VHOST: If non-NULL, per-vhost list of advertised alpn, comma- + * separated + */ + + +#if defined(LWS_WITH_CLIENT) + const char *client_ssl_private_key_password; + /**< VHOST: Client SSL context init: NULL or the passphrase needed + * for the private key */ + const char *client_ssl_cert_filepath; + /**< VHOST: Client SSL context init: The certificate the client + * should present to the peer on connection */ + const void *client_ssl_cert_mem; + /**< VHOST: Client SSL context init: client certificate memory buffer or + * NULL... use this to load client cert from memory instead of file */ + unsigned int client_ssl_cert_mem_len; + /**< VHOST: Client SSL context init: length of client_ssl_cert_mem in + * bytes */ + const char *client_ssl_private_key_filepath; + /**< VHOST: Client SSL context init: filepath to client private key + * if this is set to NULL but client_ssl_cert_filepath is set, you + * can handle the LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS + * callback of protocols[0] to allow setting of the private key directly + * via tls library calls */ + const void *client_ssl_key_mem; + /**< VHOST: Client SSL context init: client key memory buffer or + * NULL... use this to load client key from memory instead of file */ + const char *client_ssl_ca_filepath; + /**< VHOST: Client SSL context init: CA certificate filepath or NULL */ + const void *client_ssl_ca_mem; + /**< VHOST: Client SSL context init: CA certificate memory buffer or + * NULL... use this to load CA cert from memory instead of file */ + + const char *client_ssl_cipher_list; + /**< VHOST: Client SSL context init: List of valid ciphers to use (eg, + * "RC4-MD5:RC4-SHA:AES128-SHA:AES256-SHA:HIGH:!DSS:!aNULL" + * or you can leave it as NULL to get "DEFAULT" */ + const char *client_tls_1_3_plus_cipher_list; + /**< VHOST: List of valid ciphers to use for outgoing client connections + * ON TLS1.3 AND ABOVE on this vhost (eg, + * "TLS_CHACHA20_POLY1305_SHA256") or you can leave it as NULL to get + * "DEFAULT". + */ + + long ssl_client_options_set; + /**< VHOST: Any bits set here will be set as CLIENT SSL options */ + long ssl_client_options_clear; + /**< VHOST: Any bits set here will be cleared as CLIENT SSL options */ + + + unsigned int client_ssl_ca_mem_len; + /**< VHOST: Client SSL context init: length of client_ssl_ca_mem in + * bytes */ + unsigned int client_ssl_key_mem_len; + /**< VHOST: Client SSL context init: length of client_ssl_key_mem in + * bytes */ + +#endif + +#if !defined(LWS_WITH_MBEDTLS) + SSL_CTX *provided_client_ssl_ctx; + /**< CONTEXT: If non-null, swap out libwebsockets ssl + * implementation for the one provided by provided_ssl_ctx. + * Libwebsockets no longer is responsible for freeing the context + * if this option is selected. */ +#endif +#endif + + int ka_time; + /**< CONTEXT: 0 for no TCP keepalive, otherwise apply this keepalive + * timeout to all libwebsocket sockets, client or server */ + int ka_probes; + /**< CONTEXT: if ka_time was nonzero, after the timeout expires how many + * times to try to get a response from the peer before giving up + * and killing the connection */ + int ka_interval; + /**< CONTEXT: if ka_time was nonzero, how long to wait before each ka_probes + * attempt */ + unsigned int timeout_secs; + /**< VHOST: various processes involving network roundtrips in the + * library are protected from hanging forever by timeouts. If + * nonzero, this member lets you set the timeout used in seconds. + * Otherwise a default timeout is used. */ + unsigned int connect_timeout_secs; + /**< VHOST: client connections have this long to find a working server + * from the DNS results, or the whole connection times out. If zero, + * a default timeout is used */ + int bind_iface; + /**< VHOST: nonzero to strictly bind sockets to the interface name in + * .iface (eg, "eth2"), using SO_BIND_TO_DEVICE. + * + * Requires SO_BINDTODEVICE support from your OS and CAP_NET_RAW + * capability. + * + * Notice that common things like access network interface IP from + * your local machine use your lo / loopback interface and will be + * disallowed by this. + */ + unsigned int timeout_secs_ah_idle; + /**< VHOST: seconds to allow a client to hold an ah without using it. + * 0 defaults to 10s. */ +#endif /* WITH_NETWORK */ + int gid; /**< CONTEXT: group id to change to after setting listen socket, * or -1. See also .username below. */ @@ -343,37 +577,6 @@ * if you care about giving the context and vhost different user pointer * values. */ - int ka_time; - /**< CONTEXT: 0 for no TCP keepalive, otherwise apply this keepalive - * timeout to all libwebsocket sockets, client or server */ - int ka_probes; - /**< CONTEXT: if ka_time was nonzero, after the timeout expires how many - * times to try to get a response from the peer before giving up - * and killing the connection */ - int ka_interval; - /**< CONTEXT: if ka_time was nonzero, how long to wait before each ka_probes - * attempt */ -#if defined(LWS_WITH_TLS) && !defined(LWS_WITH_MBEDTLS) - SSL_CTX *provided_client_ssl_ctx; - /**< CONTEXT: If non-null, swap out libwebsockets ssl - * implementation for the one provided by provided_ssl_ctx. - * Libwebsockets no longer is responsible for freeing the context - * if this option is selected. */ -#else /* maintain structure layout either way */ - void *provided_client_ssl_ctx; /**< dummy if ssl disabled */ -#endif - - unsigned short max_http_header_data; - /**< CONTEXT: The max amount of header payload that can be handled - * in an http request (unrecognized header payload is dropped) */ - unsigned short max_http_header_pool; - /**< CONTEXT: The max number of connections with http headers that - * can be processed simultaneously (the corresponding memory is - * allocated and deallocated dynamically as needed). If the pool is - * fully busy new incoming connections must wait for accept until one - * becomes free. 0 = allow as many ah as number of availble fds for - * the process */ - unsigned int count_threads; /**< CONTEXT: how many contexts to create in an array, 0 = 1 */ unsigned int fd_limit_per_thread; @@ -392,74 +595,15 @@ * cancel pipe, so you may need to allow for some extras for normal * operation. */ - unsigned int timeout_secs; - /**< VHOST: various processes involving network roundtrips in the - * library are protected from hanging forever by timeouts. If - * nonzero, this member lets you set the timeout used in seconds. - * Otherwise a default timeout is used. */ - const char *ecdh_curve; - /**< VHOST: if NULL, defaults to initializing server with - * "prime256v1" */ const char *vhost_name; /**< VHOST: name of vhost, must match external DNS name used to * access the site, like "warmcat.com" as it's used to match * Host: header and / or SNI name for SSL. */ +#if defined(LWS_WITH_PLUGINS) const char * const *plugin_dirs; /**< CONTEXT: NULL, or NULL-terminated array of directories to * scan for lws protocol plugins at context creation time */ - const struct lws_protocol_vhost_options *pvo; - /**< VHOST: pointer to optional linked list of per-vhost - * options made accessible to protocols */ - int keepalive_timeout; - /**< VHOST: (default = 0 = 5s, 31s for http/2) seconds to allow remote - * client to hold on to an idle HTTP/1.1 connection. Timeout lifetime - * applied to idle h2 network connections */ - const char *log_filepath; - /**< VHOST: filepath to append logs to... this is opened before - * any dropping of initial privileges */ - const struct lws_http_mount *mounts; - /**< VHOST: optional linked list of mounts for this vhost */ - const char *server_string; - /**< CONTEXT: string used in HTTP headers to identify server - * software, if NULL, "libwebsockets". */ - unsigned int pt_serv_buf_size; - /**< CONTEXT: 0 = default of 4096. This buffer is used by - * various service related features including file serving, it - * defines the max chunk of file that can be sent at once. - * At the risk of lws having to buffer failed large sends, it - * can be increased to, eg, 128KiB to improve throughput. */ - unsigned int max_http_header_data2; - /**< CONTEXT: if max_http_header_data is 0 and this - * is nonzero, this will be used in place of the default. It's - * like this for compatibility with the original short version, - * this is unsigned int length. */ - long ssl_options_set; - /**< VHOST: Any bits set here will be set as server SSL options */ - long ssl_options_clear; - /**< VHOST: Any bits set here will be cleared as server SSL options */ - unsigned short ws_ping_pong_interval; - /**< CONTEXT: 0 for none, else interval in seconds between sending - * PINGs on idle websocket connections. When the PING is sent, - * the PONG must come within the normal timeout_secs timeout period - * or the connection will be dropped. - * Any RX or TX traffic on the connection restarts the interval timer, - * so a connection which always sends or receives something at intervals - * less than the interval given here will never send PINGs / expect - * PONGs. Conversely as soon as the ws connection is established, an - * idle connection will do the PING / PONG roundtrip as soon as - * ws_ping_pong_interval seconds has passed without traffic - */ - const struct lws_protocol_vhost_options *headers; - /**< VHOST: pointer to optional linked list of per-vhost - * canned headers that are added to server responses */ - - const struct lws_protocol_vhost_options *reject_service_keywords; - /**< CONTEXT: Optional list of keywords and rejection codes + text. - * - * The keywords are checked for existing in the user agent string. - * - * Eg, "badrobot" "404 Not Found" - */ +#endif void *external_baggage_free_on_destroy; /**< CONTEXT: NULL, or pointer to something externally malloc'd, that * should be freed when the context is destroyed. This allows you to @@ -468,38 +612,14 @@ * succeeded to create. */ - const char *client_ssl_private_key_password; - /**< VHOST: Client SSL context init: NULL or the passphrase needed - * for the private key */ - const char *client_ssl_cert_filepath; - /**< VHOST: Client SSL context init: The certificate the client - * should present to the peer on connection */ - const void *client_ssl_cert_mem; - /**< VHOST: Client SSL context init: client certificate memory buffer or - * NULL... use this to load client cert from memory instead of file */ - unsigned int client_ssl_cert_mem_len; - /**< VHOST: Client SSL context init: length of client_ssl_cert_mem in - * bytes */ - const char *client_ssl_private_key_filepath; - /**< VHOST: Client SSL context init: filepath to client private key - * if this is set to NULL but client_ssl_cert_filepath is set, you - * can handle the LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS - * callback of protocols[0] to allow setting of the private key directly - * via tls library calls */ - const char *client_ssl_ca_filepath; - /**< VHOST: Client SSL context init: CA certificate filepath or NULL */ - const void *client_ssl_ca_mem; - /**< VHOST: Client SSL context init: CA certificate memory buffer or - * NULL... use this to load CA cert from memory instead of file */ - unsigned int client_ssl_ca_mem_len; - /**< VHOST: Client SSL context init: length of client_ssl_ca_mem in - * bytes */ - - const char *client_ssl_cipher_list; - /**< VHOST: Client SSL context init: List of valid ciphers to use (eg, - * "RC4-MD5:RC4-SHA:AES128-SHA:AES256-SHA:HIGH:!DSS:!aNULL" - * or you can leave it as NULL to get "DEFAULT" */ + unsigned int pt_serv_buf_size; + /**< CONTEXT: 0 = default of 4096. This buffer is used by + * various service related features including file serving, it + * defines the max chunk of file that can be sent at once. + * At the risk of lws having to buffer failed large sends, it + * can be increased to, eg, 128KiB to improve throughput. */ +#if defined(LWS_WITH_FILE_OPS) const struct lws_plat_file_ops *fops; /**< CONTEXT: NULL, or pointer to an array of fops structs, terminated * by a sentinel with NULL .open. @@ -507,9 +627,9 @@ * If NULL, lws provides just the platform file operations struct for * backwards compatibility. */ - int simultaneous_ssl_restriction; - /**< CONTEXT: 0 (no limit) or limit of simultaneous SSL sessions - * possible.*/ +#endif + +#if defined(LWS_WITH_SOCKS5) const char *socks_proxy_address; /**< VHOST: If non-NULL, attempts to proxy via the given address. * If proxy auth is required, use format @@ -518,6 +638,8 @@ /**< VHOST: If socks_proxy_address was non-NULL, uses this port * if nonzero, otherwise requires "server:port" in .socks_proxy_address */ +#endif + #if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP) cap_value_t caps[4]; /**< CONTEXT: array holding Linux capabilities you want to @@ -530,58 +652,6 @@ /**< CONTEXT: count of Linux capabilities in .caps[]. 0 means * no capabilities will be inherited from root (the default) */ #endif - int bind_iface; - /**< VHOST: nonzero to strictly bind sockets to the interface name in - * .iface (eg, "eth2"), using SO_BIND_TO_DEVICE. - * - * Requires SO_BINDTODEVICE support from your OS and CAP_NET_RAW - * capability. - * - * Notice that common things like access network interface IP from - * your local machine use your lo / loopback interface and will be - * disallowed by this. - */ - int ssl_info_event_mask; - /**< VHOST: mask of ssl events to be reported on LWS_CALLBACK_SSL_INFO - * callback for connections on this vhost. The mask values are of - * the form SSL_CB_ALERT, defined in openssl/ssl.h. The default of - * 0 means no info events will be reported. - */ - unsigned int timeout_secs_ah_idle; - /**< VHOST: seconds to allow a client to hold an ah without using it. - * 0 defaults to 10s. */ - unsigned short ip_limit_ah; - /**< CONTEXT: max number of ah a single IP may use simultaneously - * 0 is no limit. This is a soft limit: if the limit is - * reached, connections from that IP will wait in the ah - * waiting list and not be able to acquire an ah until - * a connection belonging to the IP relinquishes one it - * already has. - */ - unsigned short ip_limit_wsi; - /**< CONTEXT: max number of wsi a single IP may use simultaneously. - * 0 is no limit. This is a hard limit, connections from - * the same IP will simply be dropped once it acquires the - * amount of simultaneous wsi / accepted connections - * given here. - */ - uint32_t http2_settings[7]; - /**< VHOST: if http2_settings[0] is nonzero, the values given in - * http2_settings[1]..[6] are used instead of the lws - * platform default values. - * Just leave all at 0 if you don't care. - */ - const char *error_document_404; - /**< VHOST: If non-NULL, when asked to serve a non-existent file, - * lws attempts to server this url path instead. Eg, - * "/404.html" */ - const char *alpn; - /**< CONTEXT: If non-NULL, default list of advertised alpn, comma- - * separated - * - * VHOST: If non-NULL, per-vhost list of advertised alpn, comma- - * separated - */ void **foreign_loops; /**< CONTEXT: This is ignored if the context is not being started with * an event loop, ie, .options has a flag like @@ -617,30 +687,6 @@ /**< VHOST: opaque pointer lws ignores but passes to the finalize * callback. If you don't care, leave it NULL. */ - unsigned int max_http_header_pool2; - /**< CONTEXT: if max_http_header_pool is 0 and this - * is nonzero, this will be used in place of the default. It's - * like this for compatibility with the original short version: - * this is unsigned int length. */ - - long ssl_client_options_set; - /**< VHOST: Any bits set here will be set as CLIENT SSL options */ - long ssl_client_options_clear; - /**< VHOST: Any bits set here will be cleared as CLIENT SSL options */ - - const char *tls1_3_plus_cipher_list; - /**< VHOST: List of valid ciphers to use for incoming server connections - * ON TLS1.3 AND ABOVE (eg, "TLS_CHACHA20_POLY1305_SHA256" on this vhost - * or you can leave it as NULL to get "DEFAULT". - * SEE .client_tls_1_3_plus_cipher_list to do the same on the vhost - * client SSL_CTX. - */ - const char *client_tls_1_3_plus_cipher_list; - /**< VHOST: List of valid ciphers to use for outgoing client connections - * ON TLS1.3 AND ABOVE on this vhost (eg, - * "TLS_CHACHA20_POLY1305_SHA256") or you can leave it as NULL to get - * "DEFAULT". - */ const char *listen_accept_role; /**< VHOST: NULL for default, or force accepted incoming connections to * bind to this role. Uses the role names from their ops struct, eg, @@ -661,26 +707,6 @@ * the type of the user data to be known so its size can be given. */ - const void *server_ssl_cert_mem; - /**< VHOST: Alternative for \p ssl_cert_filepath that allows setting - * from memory instead of from a file. At most one of - * \p ssl_cert_filepath or \p server_ssl_cert_mem should be non-NULL. */ - unsigned int server_ssl_cert_mem_len; - /**< VHOST: Server SSL context init: length of server_ssl_cert_mem in - * bytes */ - const void *server_ssl_private_key_mem; - /**< VHOST: Alternative for \p ssl_private_key_filepath allowing - * init from a private key in memory instead of a file. At most one - * of \p ssl_private_key_filepath or \p server_ssl_private_key_mem - * should be non-NULL. */ - unsigned int server_ssl_private_key_mem_len; - /**< VHOST: length of \p server_ssl_private_key_mem in memory */ - const void *server_ssl_ca_mem; - /**< VHOST: Alternative for \p ssl_ca_filepath allowing - * init from a CA cert in memory instead of a file. At most one - * of \p ssl_ca_filepath or \p server_ssl_ca_mem should be non-NULL. */ - unsigned int server_ssl_ca_mem_len; - /**< VHOST: length of \p server_ssl_ca_mem in memory */ const char *username; /**< CONTEXT: string username for post-init * permissions. Like .uid but takes a string username. */ const char *groupname; /**< CONTEXT: string groupname for post-init @@ -692,29 +718,32 @@ const lws_system_ops_t *system_ops; /**< CONTEXT: hook up lws_system_ apis to system-specific * implementations */ +#if defined(LWS_WITH_DETAILED_LATENCY) det_lat_buf_cb_t detailed_latency_cb; /**< CONTEXT: NULL, or callback to receive detailed latency information * collected for each read and write */ const char *detailed_latency_filepath; /**< CONTEXT: NULL, or filepath to put latency data into */ +#endif const lws_retry_bo_t *retry_and_idle_policy; /**< VHOST: optional retry and idle policy to apply to this vhost. * Currently only the idle parts are applied to the connections. */ +#if defined(LWS_WITH_SYS_STATE) lws_state_notify_link_t * const *register_notifier_list; /**< CONTEXT: NULL, or pointer to an array of notifiers that should * be registered during context creation, so they can see state change * events from very early on. The array should end with a NULL. */ - uint8_t udp_loss_sim_tx_pc; - /**< CONTEXT: percentage of udp writes we could have performed - * to instead not do, in order to simulate and test udp retry flow */ - uint8_t udp_loss_sim_rx_pc; - /**< CONTEXT: percentage of udp reads we actually received - * to make disappear, in order to simulate and test udp retry flow */ +#endif #if defined(LWS_WITH_SECURE_STREAMS) +#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) + const struct lws_ss_policy *pss_policies; /**< CONTEXT: point to first + * in a linked-list of streamtype policies prepared by user code */ +#else const char *pss_policies_json; /**< CONTEXT: point to a string * containing a JSON description of the secure streams policies. Set * to NULL if not using Secure Streams. */ +#endif const struct lws_ss_plugin **pss_plugins; /**< CONTEXT: point to an array * of pointers to plugin structs here, terminated with a NULL ptr. * Set to NULL if not using Secure Streams. */ @@ -732,6 +761,56 @@ * ss_proxy_bind and the given port */ #endif + int rlimit_nofile; + /**< 0 = inherit the initial ulimit for files / sockets from the startup + * environment. Nonzero = try to set the limit for this process. + */ +#if defined(LWS_WITH_PEER_LIMITS) + lws_peer_limits_notify_t pl_notify_cb; + /**< CONTEXT: NULL, or a callback to receive notifications each time a + * connection is being dropped because of peer limits. + * + * The callback provides the context, and an lws_sockaddr46 with the + * peer address and port. + */ + unsigned short ip_limit_ah; + /**< CONTEXT: max number of ah a single IP may use simultaneously + * 0 is no limit. This is a soft limit: if the limit is + * reached, connections from that IP will wait in the ah + * waiting list and not be able to acquire an ah until + * a connection belonging to the IP relinquishes one it + * already has. + */ + unsigned short ip_limit_wsi; + /**< CONTEXT: max number of wsi a single IP may use simultaneously. + * 0 is no limit. This is a hard limit, connections from + * the same IP will simply be dropped once it acquires the + * amount of simultaneous wsi / accepted connections + * given here. + */ + +#endif /* PEER_LIMITS */ +#if defined(LWS_WITH_UDP) + uint8_t udp_loss_sim_tx_pc; + /**< CONTEXT: percentage of udp writes we could have performed + * to instead not do, in order to simulate and test udp retry flow */ + uint8_t udp_loss_sim_rx_pc; + /**< CONTEXT: percentage of udp reads we actually received + * to make disappear, in order to simulate and test udp retry flow */ +#endif + +#if defined(LWS_WITH_SYS_SMD) + lws_smd_notification_cb_t early_smd_cb; + /**< CONTEXT: NULL, or an smd notification callback that will be registered + * immediately after the smd in the context is initialized. This ensures + * you can get all notifications without having to intercept the event loop + * creation, eg, when using an event library. Other callbacks can be + * registered later manually without problems. + */ + void *early_smd_opaque; + lws_smd_class_t early_smd_class_filter; +#endif + /* Add new things just above here ---^ * This is part of the ABI, don't needlessly break compatibility * diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-display.h libwebsockets-4.1.6/include/libwebsockets/lws-display.h --- libwebsockets-4.0.20/include/libwebsockets/lws-display.h 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-display.h 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,158 @@ +/* + * lws abstract display + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + */ + +#if !defined(__LWS_DISPLAY_H__) +#define __LWS_DISPLAY_H__ + +#include + +typedef uint16_t lws_display_scalar; + +/* + * This is embedded in the actual display implementation object at the top, + * so a pointer to this can be cast to a pointer to the implementation object + * by any code that is specific to how it was implemented. + * + * Notice for the backlight / display intensity we contain pwm_ops... these can + * be some other pwm_ops like existing gpio pwm ops, or handled in a customized + * way like set oled contrast. Either way, the pwm level is arrived at via a + * full set of lws_led_sequences capable of generic lws transitions + */ + +typedef struct lws_display { + int (*init)(const struct lws_display *disp); + const lws_pwm_ops_t *bl_pwm_ops; + int (*contrast)(const struct lws_display *disp, uint8_t contrast); + int (*blit)(const struct lws_display *disp, const uint8_t *src, + lws_display_scalar x, lws_display_scalar y, + lws_display_scalar w, lws_display_scalar h); + int (*power)(const struct lws_display *disp, int state); + + const lws_led_sequence_def_t *bl_active; + const lws_led_sequence_def_t *bl_dim; + const lws_led_sequence_def_t *bl_transition; + + void *variant; + + int bl_index; + + lws_display_scalar w; + /**< display surface width in pixels */ + lws_display_scalar h; + /**< display surface height in pixels */ + + uint8_t latency_wake_ms; + /**< ms required after wake from sleep before display usable again... + * delay bringing up the backlight for this amount of time on wake. + * This is managed via a sul on the event loop, not blocking. */ +} lws_display_t; + +/* + * This contains dynamic data related to display state + */ + +enum lws_display_controller_state { + LWSDISPS_OFF, + LWSDISPS_AUTODIMMED, /* is in pre- blanking static dim mode */ + LWSDISPS_BECOMING_ACTIVE, /* waiting for wake latency before active */ + LWSDISPS_ACTIVE, /* is active */ + LWSDISPS_GOING_OFF /* dimming then off */ +}; + +typedef struct lws_display_state { + + lws_sorted_usec_list_t sul_autodim; + const lws_display_t *disp; + struct lws_context *ctx; + + int autodim_ms; + int off_ms; + + struct lws_led_state *bl_lcs; + + lws_led_state_chs_t chs; + /* set of sequencer transition channels */ + + enum lws_display_controller_state state; + +} lws_display_state_t; + +/** + * lws_display_state_init() - initialize display states + * + * \param lds: the display state object + * \param ctx: the lws context + * \param autodim_ms: ms since last active report to dim display (<0 = never) + * \param off_ms: ms since dim to turn display off (<0 = never) + * \param bl_lcs: the led controller instance that has the backlight + * \param disp: generic display object we belong to + * + * This initializes a display's state, and sets up the optional screen auto-dim + * and blanking on inactive, and gradual brightness change timer. + * + * - auto-dim then off: set autodim to some ms and off_ms to some ms + * - auto-dim only: set autodim to some ms and off_ms to -1 + * - off-only: set autodim to some ms and off_ms to 0 + * - neither: set both autodim and off_ms to -1 + */ +LWS_VISIBLE LWS_EXTERN void +lws_display_state_init(lws_display_state_t *lds, struct lws_context *ctx, + int autodim_ms, int off_ms, struct lws_led_state *bl_lcs, + const lws_display_t *disp); + +/** + * lws_display_state_set_brightness() - gradually change the brightness + * + * \param lds: the display state we are changing + * \param target: the target brightness to transition to + * + * Adjusts the brightness gradually twoards the target at 20Hz + */ +LWS_VISIBLE LWS_EXTERN void +lws_display_state_set_brightness(lws_display_state_t *lds, + const lws_led_sequence_def_t *pwmseq); + +/* + * lws_display_state_active() - inform the system the display is active + * + * \param lds: the display state we are marking as active + * + * Resets the auto-dim and auto-off timers and makes sure the display is on and + * at the active brightness level + */ +LWS_VISIBLE LWS_EXTERN void +lws_display_state_active(lws_display_state_t *lds); + +/* + * lws_display_state_off() - turns off the related display + * + * \param lds: the display state we are turning off + * + * Turns the display to least power mode or completely off if possible. + * Disables the timers related to dimming and blanking. + */ +LWS_VISIBLE LWS_EXTERN void +lws_display_state_off(lws_display_state_t *lds); + +#endif diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-dll2.h libwebsockets-4.1.6/include/libwebsockets/lws-dll2.h --- libwebsockets-4.0.20/include/libwebsockets/lws-dll2.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-dll2.h 2020-12-01 17:40:26.000000000 +0000 @@ -173,64 +173,6 @@ * doubly linked-list */ -#if defined (LWS_WITH_DEPRECATED_LWS_DLL) - -/* - * This is going away in v4.1. You can set the cmake option above to keep it - * around temporarily. Migrate your stuff to the more capable and robust - * lws_dll2 below - */ - -struct lws_dll { - struct lws_dll *prev; - struct lws_dll *next; -}; - -/* - * these all point to the composed list objects... you have to use the - * lws_container_of() helper to recover the start of the containing struct - */ - -#define lws_dll_add_front lws_dll_add_head - -LWS_VISIBLE LWS_EXTERN void -lws_dll_add_head(struct lws_dll *d, struct lws_dll *phead); - -LWS_VISIBLE LWS_EXTERN void -lws_dll_add_tail(struct lws_dll *d, struct lws_dll *phead); - -LWS_VISIBLE LWS_EXTERN void -lws_dll_insert(struct lws_dll *d, struct lws_dll *target, - struct lws_dll *phead, int before); - -static LWS_INLINE struct lws_dll * -lws_dll_get_head(struct lws_dll *phead) { return phead->next; } - -static LWS_INLINE struct lws_dll * -lws_dll_get_tail(struct lws_dll *phead) { return phead->prev; } - -/* - * caution, this doesn't track the tail in the head struct. Use - * lws_dll_remove_track_tail() instead of this if you want tail tracking. Using - * this means you can't use lws_dll_add_tail() amd - */ -LWS_VISIBLE LWS_EXTERN void -lws_dll_remove(struct lws_dll *d) LWS_WARN_DEPRECATED; - -LWS_VISIBLE LWS_EXTERN void -lws_dll_remove_track_tail(struct lws_dll *d, struct lws_dll *phead); - -/* another way to do lws_start_foreach_dll_safe() on a list via a cb */ - -LWS_VISIBLE LWS_EXTERN int -lws_dll_foreach_safe(struct lws_dll *phead, void *user, - int (*cb)(struct lws_dll *d, void *user)); - -#define lws_dll_is_detached(___dll, __head) \ - (!(___dll)->prev && !(___dll)->next && (__head)->prev != (___dll)) - -#endif - /* * lws_dll2_owner / lws_dll2 : more capable version of lws_dll. Differences: * @@ -303,6 +245,21 @@ lws_dll2_add_sorted(lws_dll2_t *d, lws_dll2_owner_t *own, int (*compare)(const lws_dll2_t *d, const lws_dll2_t *i)); +LWS_VISIBLE LWS_EXTERN void * +_lws_dll2_search_sz_pl(lws_dll2_owner_t *own, const char *name, size_t namelen, + size_t dll2_ofs, size_t ptr_ofs); + +/* + * Searches objects in an owner list linearly and returns one with a given + * member C-string matching a supplied length-provided string if it exists, else + * NULL. + */ + +#define lws_dll2_search_sz_pl(own, name, namelen, type, membd2list, membptr) \ + ((type *)_lws_dll2_search_sz_pl(own, name, namelen, \ + offsetof(type, membd2list), \ + offsetof(type, membptr))) + #if defined(_DEBUG) void lws_dll2_describe(struct lws_dll2_owner *owner, const char *desc); diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-esp32.h libwebsockets-4.1.6/include/libwebsockets/lws-esp32.h --- libwebsockets-4.0.20/include/libwebsockets/lws-esp32.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-esp32.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,153 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * 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. - * - * This is only included from libwebsockets.h if LWS_WITH_ESP32 - */ - -/* ESP32 helper declarations */ - -#include -#include - -#define LWS_PLUGIN_STATIC -#define LWS_MAGIC_REBOOT_TYPE_ADS 0x50001ffc -#define LWS_MAGIC_REBOOT_TYPE_REQ_FACTORY 0xb00bcafe -#define LWS_MAGIC_REBOOT_TYPE_FORCED_FACTORY 0xfaceb00b -#define LWS_MAGIC_REBOOT_TYPE_FORCED_FACTORY_BUTTON 0xf0cedfac -#define LWS_MAGIC_REBOOT_TYPE_REQ_FACTORY_ERASE_OTA 0xfac0eeee - -/* user code provides these */ - -extern void -lws_esp32_identify_physical_device(void); - -/* lws-plat-esp32 provides these */ - -typedef void (*lws_cb_scan_done)(uint16_t count, wifi_ap_record_t *recs, void *arg); - -enum genled_state { - LWSESP32_GENLED__INIT, - LWSESP32_GENLED__LOST_NETWORK, - LWSESP32_GENLED__NO_NETWORK, - LWSESP32_GENLED__CONN_AP, - LWSESP32_GENLED__GOT_IP, - LWSESP32_GENLED__OK, -}; - -struct lws_group_member { - struct lws_group_member *next; - uint64_t last_seen; - char model[16]; - char role[16]; - char host[32]; - char mac[20]; - int width, height; - struct ip4_addr addr; - struct ip6_addr addrv6; - uint8_t flags; -}; - -#define LWS_SYSTEM_GROUP_MEMBER_ADD 1 -#define LWS_SYSTEM_GROUP_MEMBER_CHANGE 2 -#define LWS_SYSTEM_GROUP_MEMBER_REMOVE 3 - -#define LWS_GROUP_FLAG_SELF 1 - -struct lws_esp32 { - char sta_ip[16]; - char sta_mask[16]; - char sta_gw[16]; - char serial[16]; - char opts[16]; - char model[16]; - char group[16]; - char role[16]; - char ssid[4][64]; - char password[4][64]; - char active_ssid[64]; - char access_pw[16]; - char hostname[32]; - char mac[20]; - char le_dns[64]; - char le_email[64]; - char region; - char inet; - char conn_ap; - - enum genled_state genled; - uint64_t genled_t; - - lws_cb_scan_done scan_consumer; - void *scan_consumer_arg; - struct lws_group_member *first; - int extant_group_members; - - char acme; - char upload; - - volatile char button_is_down; -}; - -struct lws_esp32_image { - uint32_t romfs; - uint32_t romfs_len; - uint32_t json; - uint32_t json_len; -}; - -extern struct lws_esp32 lws_esp32; -struct lws_vhost; - -extern esp_err_t -lws_esp32_event_passthru(void *ctx, system_event_t *event); -extern void -lws_esp32_wlan_config(void); -extern void -lws_esp32_wlan_start_ap(void); -extern void -lws_esp32_wlan_start_station(void); -struct lws_context_creation_info; -extern void -lws_esp32_set_creation_defaults(struct lws_context_creation_info *info); -extern struct lws_context * -lws_esp32_init(struct lws_context_creation_info *, struct lws_vhost **pvh); -extern int -lws_esp32_wlan_nvs_get(int retry); -extern esp_err_t -lws_nvs_set_str(nvs_handle handle, const char* key, const char* value); -extern void -lws_esp32_restart_guided(uint32_t type); -extern const esp_partition_t * -lws_esp_ota_get_boot_partition(void); -extern int -lws_esp32_get_image_info(const esp_partition_t *part, struct lws_esp32_image *i, char *json, int json_len); -extern int -lws_esp32_leds_network_indication(void); - -extern uint32_t lws_esp32_get_reboot_type(void); -extern uint16_t lws_esp32_sine_interp(int n); - -/* required in external code by esp32 plat (may just return if no leds) */ -extern void lws_esp32_leds_timer_cb(TimerHandle_t th); - -#endif /* LWS_AMAZON_RTOS */ diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-eventlib-exports.h libwebsockets-4.1.6/include/libwebsockets/lws-eventlib-exports.h --- libwebsockets-4.0.20/include/libwebsockets/lws-eventlib-exports.h 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-eventlib-exports.h 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,86 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2020 Andy Green + * + * 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. + * + * These are exports needed by event lib plugins. + * + * You should consider these opaque for normal user code. + */ + +LWS_VISIBLE LWS_EXTERN void * +lws_realloc(void *ptr, size_t size, const char *reason); + +LWS_VISIBLE LWS_EXTERN void +lws_vhost_destroy1(struct lws_vhost *vh); + +LWS_VISIBLE LWS_EXTERN void +lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, + const char *caller); + +struct lws_context_per_thread; +LWS_VISIBLE LWS_EXTERN void +lws_service_do_ripe_rxflow(struct lws_context_per_thread *pt); + +#if !defined(wsi_from_fd) && !defined(WIN32) && !defined(_WIN32) +struct lws_context; +LWS_VISIBLE LWS_EXTERN struct lws * +wsi_from_fd(const struct lws_context *context, int fd); +#endif + +LWS_VISIBLE LWS_EXTERN int +_lws_plat_service_forced_tsi(struct lws_context *context, int tsi); + +LWS_VISIBLE LWS_EXTERN void +lws_context_destroy2(struct lws_context *context); + +LWS_VISIBLE LWS_EXTERN void +lws_destroy_event_pipe(struct lws *wsi); + +LWS_VISIBLE LWS_EXTERN void +__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 diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-freertos.h libwebsockets-4.1.6/include/libwebsockets/lws-freertos.h --- libwebsockets-4.0.20/include/libwebsockets/lws-freertos.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-freertos.h 2020-12-01 17:40:26.000000000 +0000 @@ -65,11 +65,21 @@ #include "esp_wifi.h" #include "esp_system.h" #include "esp_event.h" -#include "esp_event_loop.h" +//#include "esp_event_loop.h" #include "nvs.h" #include "driver/gpio.h" #include "esp_spi_flash.h" #include "freertos/timers.h" + +#if defined(LWS_ESP_PLATFORM) +#include "lwip/sockets.h" +#include "lwip/netdb.h" +#if defined(LWS_WITH_DRIVERS) +#include "libwebsockets/lws-gpio.h" +extern const lws_gpio_ops_t lws_gpio_plat; +#endif +#endif + #endif /* LWS_AMAZON_RTOS */ #if !defined(CONFIG_FREERTOS_HZ) diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-genhash.h libwebsockets-4.1.6/include/libwebsockets/lws-genhash.h --- libwebsockets-4.0.20/include/libwebsockets/lws-genhash.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-genhash.h 2020-12-01 17:40:26.000000000 +0000 @@ -74,12 +74,19 @@ mbedtls_md_context_t ctx; #else const EVP_MD *evp_type; + +#if defined(LWS_HAVE_EVP_PKEY_new_raw_private_key) + EVP_MD_CTX *ctx; + EVP_PKEY *key; +#else #if defined(LWS_HAVE_HMAC_CTX_new) HMAC_CTX *ctx; #else HMAC_CTX ctx; #endif #endif + +#endif }; /** lws_genhash_size() - get hash size in bytes diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-gpio.h libwebsockets-4.1.6/include/libwebsockets/lws-gpio.h --- libwebsockets-4.0.20/include/libwebsockets/lws-gpio.h 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-gpio.h 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,60 @@ +/* + * Generic GPIO ops + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + * This is like an abstract class for gpio, a real implementation provides + * functions for the ops that use the underlying OS gpio arrangements. + */ + +#if !defined(__LWS_GPIO_H__) +#define __LWS_GPIO_H__ + +typedef int _lws_plat_gpio_t; + +typedef enum { + LWSGGPIO_IRQ_NONE, + LWSGGPIO_IRQ_RISING, + LWSGGPIO_IRQ_FALLING, + LWSGGPIO_IRQ_CHANGE, + LWSGGPIO_IRQ_LOW, + LWSGGPIO_IRQ_HIGH +} lws_gpio_irq_t; + +enum { + LWSGGPIO_FL_READ = (1 << 0), + LWSGGPIO_FL_WRITE = (1 << 1), + LWSGGPIO_FL_PULLUP = (1 << 2), + LWSGGPIO_FL_PULLDOWN = (1 << 3), + LWSGGPIO_FL_START_LOW = (1 << 4), +}; + +typedef void (*lws_gpio_irq_cb_t)(void *arg); + +typedef struct lws_gpio_ops { + void (*mode)(_lws_plat_gpio_t gpio, int flags); + int (*read)(_lws_plat_gpio_t gpio); + void (*set)(_lws_plat_gpio_t gpio, int val); + int (*irq_mode)(_lws_plat_gpio_t gpio, lws_gpio_irq_t irq, + lws_gpio_irq_cb_t cb, void *arg); +} lws_gpio_ops_t; + +#endif diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-http.h libwebsockets-4.1.6/include/libwebsockets/lws-http.h --- libwebsockets-4.0.20/include/libwebsockets/lws-http.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-http.h 2020-12-01 17:40:26.000000000 +0000 @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2020 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -215,18 +215,18 @@ enum lws_token_indexes { WSI_TOKEN_GET_URI, /* 0 */ WSI_TOKEN_POST_URI, -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_OPTIONS_URI, #endif WSI_TOKEN_HOST, WSI_TOKEN_CONNECTION, WSI_TOKEN_UPGRADE, /* 5 */ WSI_TOKEN_ORIGIN, -#if defined(LWS_ROLE_WS) +#if defined(LWS_ROLE_WS) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_DRAFT, #endif WSI_TOKEN_CHALLENGE, -#if defined(LWS_ROLE_WS) +#if defined(LWS_ROLE_WS) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_EXTENSIONS, WSI_TOKEN_KEY1, /* 10 */ WSI_TOKEN_KEY2, @@ -235,11 +235,11 @@ WSI_TOKEN_NONCE, #endif WSI_TOKEN_HTTP, -#if defined(LWS_ROLE_H2) +#if defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_HTTP2_SETTINGS, /* 16 */ #endif WSI_TOKEN_HTTP_ACCEPT, -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_HTTP_AC_REQUEST_HEADERS, #endif WSI_TOKEN_HTTP_IF_MODIFIED_SINCE, @@ -254,15 +254,15 @@ WSI_TOKEN_HTTP_CONTENT_TYPE, WSI_TOKEN_HTTP_DATE, WSI_TOKEN_HTTP_RANGE, -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_HTTP_REFERER, #endif -#if defined(LWS_ROLE_WS) +#if defined(LWS_ROLE_WS) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_KEY, WSI_TOKEN_VERSION, WSI_TOKEN_SWORIGIN, #endif -#if defined(LWS_ROLE_H2) +#if defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_HTTP_COLON_AUTHORITY, WSI_TOKEN_HTTP_COLON_METHOD, WSI_TOKEN_HTTP_COLON_PATH, @@ -270,11 +270,11 @@ WSI_TOKEN_HTTP_COLON_STATUS, #endif -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_HTTP_ACCEPT_CHARSET, #endif WSI_TOKEN_HTTP_ACCEPT_RANGES, -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_HTTP_ACCESS_CONTROL_ALLOW_ORIGIN, #endif WSI_TOKEN_HTTP_AGE, @@ -294,7 +294,7 @@ WSI_TOKEN_HTTP_LAST_MODIFIED, WSI_TOKEN_HTTP_LINK, WSI_TOKEN_HTTP_LOCATION, -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_HTTP_MAX_FORWARDS, WSI_TOKEN_HTTP_PROXY_AUTHENTICATE, WSI_TOKEN_HTTP_PROXY_AUTHORIZATION, @@ -303,24 +303,24 @@ WSI_TOKEN_HTTP_RETRY_AFTER, WSI_TOKEN_HTTP_SERVER, WSI_TOKEN_HTTP_SET_COOKIE, -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_HTTP_STRICT_TRANSPORT_SECURITY, #endif WSI_TOKEN_HTTP_TRANSFER_ENCODING, -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_HTTP_USER_AGENT, WSI_TOKEN_HTTP_VARY, WSI_TOKEN_HTTP_VIA, WSI_TOKEN_HTTP_WWW_AUTHENTICATE, #endif -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_PATCH_URI, WSI_TOKEN_PUT_URI, WSI_TOKEN_DELETE_URI, #endif WSI_TOKEN_HTTP_URI_ARGS, -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_PROXY, WSI_TOKEN_HTTP_X_REAL_IP, #endif @@ -328,11 +328,11 @@ WSI_TOKEN_X_FORWARDED_FOR, WSI_TOKEN_CONNECT, WSI_TOKEN_HEAD_URI, -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_TE, WSI_TOKEN_REPLAY_NONCE, /* ACME */ #endif -#if defined(LWS_ROLE_H2) +#if defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_COLON_PROTOCOL, #endif WSI_TOKEN_X_AUTH_TOKEN, @@ -356,7 +356,7 @@ /* parser state additions, no storage associated */ WSI_TOKEN_NAME_PART, -#if defined(LWS_WITH_CUSTOM_HEADERS) +#if defined(LWS_WITH_CUSTOM_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_UNKNOWN_VALUE_PART, #endif WSI_TOKEN_SKIPPING, @@ -851,6 +851,36 @@ lws_http_is_redirected_to_get(struct lws *wsi); /** + * lws_http_cookie_get() - return copy of named cookie if present + * + * \param wsi: the wsi to check + * \param name: name of the cookie + * \param buf: buffer to store the cookie contents into + * \param max_len: on entry, maximum length of buf... on exit, used len of buf + * + * If no cookie header, or no cookie of the requested name, or the value is + * larger than can fit in buf, returns nonzero. + * + * If the cookie is found, copies its value into buf with a terminating NUL, + * sets *max_len to the used length, and returns 0. + * + * This handles the parsing of the possibly multi-cookie header string and + * terminating the requested cookie at the next ; if present. + */ +LWS_VISIBLE LWS_EXTERN int +lws_http_cookie_get(struct lws *wsi, const char *name, char *buf, size_t *max); + +/** + * lws_http_client_http_error() - determine if the response code indicates an error + * + * \param code: the response code to test + * + * Returns nonzero if the code indicates an error, else zero if reflects a + * non-error condition + */ +#define lws_http_client_http_resp_is_error(code) (!(code < 400)) + +/** * lws_h2_update_peer_txcredit() - manually update stream peer tx credit * * \param wsi: the h2 child stream whose peer credit to change diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-i2c.h libwebsockets-4.1.6/include/libwebsockets/lws-i2c.h --- libwebsockets-4.0.20/include/libwebsockets/lws-i2c.h 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-i2c.h 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,54 @@ +/* + * Generic I2C ops + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + * This is like an abstract class for i2c, a real implementation provides + * functions for the ops that use the underlying OS arrangements. + */ + +#if !defined(__LWS_I2C_H__) +#define __LWS_I2C_H__ + +#include +#include + +typedef struct lws_i2c_ops { + int (*init)(const struct lws_i2c_ops *ctx); + int (*start)(const struct lws_i2c_ops *ctx); + void (*stop)(const struct lws_i2c_ops *ctx); + int (*write)(const struct lws_i2c_ops *ctx, uint8_t data); + int (*read)(const struct lws_i2c_ops *ctx); + void (*set_ack)(const struct lws_i2c_ops *octx, int ack); +} lws_i2c_ops_t; + +/* + * These are implemented by calling the ops above, and so are generic + */ + +LWS_VISIBLE LWS_EXTERN int +lws_i2c_command(const lws_i2c_ops_t *ctx, uint8_t ads7, uint8_t c); + +LWS_VISIBLE LWS_EXTERN int +lws_i2c_command_list(const lws_i2c_ops_t *ctx, uint8_t ads7, const uint8_t *buf, + size_t len); + +#endif diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-ili9341-spi.h libwebsockets-4.1.6/include/libwebsockets/lws-ili9341-spi.h --- libwebsockets-4.0.20/include/libwebsockets/lws-ili9341-spi.h 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-ili9341-spi.h 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,54 @@ +/* + * lws abstract display implementation for ili9341 on spi + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + */ + +#if !defined(__LWS_DISPLAY_ILI9341_SPI_H__) +#define __LWS_DISPLAY_ILI9341_SPI_H__ + + +typedef struct lws_display_ili9341 { + + lws_display_t disp; /* use lws_display_ili9341_ops to set */ + const lws_spi_ops_t *spi; /* spi ops */ + + const lws_gpio_ops_t *gpio; /* NULL or gpio ops */ + _lws_plat_gpio_t reset_gpio; /* if gpio ops, nReset gpio # */ + + uint8_t spi_index; /* cs index starting from 0 */ + +} lws_display_ili9341_t; + +int +lws_display_ili9341_spi_init(const struct lws_display *disp); +int +lws_display_ili9341_spi_blit(const struct lws_display *disp, const uint8_t *src, + lws_display_scalar x, lws_display_scalar y, + lws_display_scalar w, lws_display_scalar h); +int +lws_display_ili9341_spi_power(const struct lws_display *disp, int state); + +#define lws_display_ili9341_ops \ + .init = lws_display_ili9341_spi_init, \ + .blit = lws_display_ili9341_spi_blit, \ + .power = lws_display_ili9341_spi_power +#endif diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-jws.h libwebsockets-4.1.6/include/libwebsockets/lws-jws.h --- libwebsockets-4.0.20/include/libwebsockets/lws-jws.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-jws.h 2020-12-01 17:40:26.000000000 +0000 @@ -398,8 +398,162 @@ * Returns either -1 if problems, or the number of bytes written to \p out. * If the section is not the first one, '.' is prepended. */ - LWS_VISIBLE LWS_EXTERN int lws_jws_encode_section(const char *in, size_t in_len, int first, char **p, char *end); + +/** + * lws_jwt_signed_validate() - check a compact JWT against a key and alg + * + * \param ctx: the lws_context + * \param jwk: the key for checking the signature + * \param alg_list: the expected alg name, like "ES512" + * \param com: the compact JWT + * \param len: the length of com + * \param temp: a temp scratchpad + * \param tl: available length of temp scratchpad + * \param out: the output buffer to hold the validated plaintext + * \param out_len: on entry, max length of out; on exit, used length of out + * + * Returns nonzero if the JWT cannot be validated or the plaintext can't fit the + * provided output buffer, or 0 if it is validated as being signed by the + * provided jwk. + * + * If validated, the plaintext in the JWT is copied into out and out_len set to + * the used length. + * + * temp can be discarded or reused after the call returned, it's used to hold + * transformations of the B64 JWS in the JWT. + */ +LWS_VISIBLE LWS_EXTERN 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); + +/** + * lws_jwt_sign_compact() - generate a compact JWT using a key and alg + * + * \param ctx: the lws_context + * \param jwk: the signing key + * \param alg: the signing alg name, like "ES512" + * \param out: the output buffer to hold the signed JWT in compact form + * \param out_len: on entry, the length of out; on exit, the used amount of out + * \param temp: a temp scratchpad + * \param tl: available length of temp scratchpad + * \param format: a printf style format specification + * \param ...: zero or more args for the format specification + * + * Creates a JWT in a single step, from the format string and args through to + * outputting a well-formed compact JWT representation in out. + * + * Returns 0 if all is well and *out_len is the amount of data in out, else + * nonzero if failed. Temp must be large enough to hold various intermediate + * representations. + */ +LWS_VISIBLE LWS_EXTERN 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, ...) LWS_FORMAT(8); + +/** + * lws_jwt_token_sanity() - check a validated jwt payload for sanity + * + * \param in: the JWT payload + * \param in_len: the length of the JWT payload + * \param iss: the expected issuer of the token + * \param aud: the expected audience of the token + * \param csrf_in: NULL, or the csrf token that came in on a URL + * \param sub: a buffer to hold the subject name in the JWT (eg, account name) + * \param sub_len: the max length of the sub buffer + * \param secs_left: set to the number of seconds of valid auth left if valid + * + * This performs some generic sanity tests on validated JWT payload... + * + * - the issuer is as expected + * - the audience is us + * - current time is OK for nbf ("not before") in the token + * - current time is OK for exp ("expiry") in the token + * - if csrf_in is not NULL, that the JWK has a csrf and it matches it + * - if sub is not NULL, that the JWK provides a subject (and copies it to sub) + * + * If the tests pass, *secs_left is set to the number of remaining seconds the + * auth is valid. + * + * Returns 0 if no inconsistency, else nonzero. + */ +LWS_VISIBLE LWS_EXTERN int +lws_jwt_token_sanity(const char *in, size_t in_len, + const char *iss, const char *aud, const char *csrf_in, + char *sub, size_t sub_len, unsigned long *exp_unix_time); + +#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) + +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 */ +}; + +/** + * lws_jwt_sign_token_set_cookie() - creates sets a JWT in a wsi cookie + * + * \param wsi: the wsi to create the cookie header on + * \param i: structure describing what should be in the JWT + * \param p: wsi headers area + * \param end: end of wsi headers area + * + * Creates a JWT specified \p i, and attaches it to the outgoing headers on + * wsi. Returns 0 if successful. + * + * Best-practice security restrictions are applied to the cookie set action, + * including forcing httponly, and __Host- prefix. As required by __Host-, the + * cookie Path is set to /. __Host- is applied by the function, the cookie_name + * should just be "xyz" for "__Host-xyz". + * + * \p extra_json should just be the bare JSON, a { } is provided around it by + * the function if it's non-NULL. For example, "\"authorization\": 1". + * + * It's recommended the secs parameter is kept as small as consistent with one + * user session on the site if possible, eg, 10 minutes or 20 minutes. At the + * server, it can determine how much time is left in the auth and inform the + * client; if the JWT validity expires, the page should reload so the UI always + * reflects what's possible to do with the authorization state correctly. If + * the JWT expires, the user can log back in using credentials usually stored in + * the browser and auto-filled-in, so this is not very inconvenient. + * + * This is a helper on top of the other JOSE and JWT apis that somewhat crosses + * over between JWT and HTTP, since it knows about cookies. So it is only built + * if both LWS_WITH_JOSE and one of the http-related roles enabled. + */ +LWS_VISIBLE LWS_EXTERN 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); +LWS_VISIBLE LWS_EXTERN int +lws_jwt_get_http_cookie_validate_jwt(struct lws *wsi, + struct lws_jwt_sign_set_cookie *i, + char *out, size_t *out_len); +#endif + ///@} diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-led.h libwebsockets-4.1.6/include/libwebsockets/lws-led.h --- libwebsockets-4.0.20/include/libwebsockets/lws-led.h 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-led.h 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,146 @@ +/* + * Generic LED controller ops + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + * This is like an abstract class for leds, a real implementation provides + * functions for the ops that use the underlying, eg, OS gpio arrangements. + */ + +/* only b15 significant for GPIO */ +typedef uint16_t lws_led_intensity_t; +typedef uint16_t lws_led_seq_phase_t; + +/* the normalized max intensity */ +#define LWS_LED_MAX_INTENSITY (0xffff) + +/* the normalized 360 degree phase count for intensity functions */ +#define LWS_LED_FUNC_PHASE 65536 +/* used when the sequence doesn't stop by itself and goes around forever */ +#define LWS_SEQ_LEDPHASE_TOTAL_ENDLESS (-1) + +#define LWS_LED_SEQUENCER_UPDATE_INTERVAL_MS 33 + +struct lws_led_state; /* opaque */ +struct lws_pwm_ops; /* forward ref */ + +typedef lws_led_intensity_t (*lws_led_lookup_t)(lws_led_seq_phase_t ph); + +typedef struct lws_led_sequence_def_t { + lws_led_lookup_t func; + lws_led_seq_phase_t ledphase_offset; + int ledphase_total; /* 65536= one cycle */ + uint16_t ms; + uint8_t flags; +} lws_led_sequence_def_t; + +enum { + LLSI_CURR, + LLSI_NEXT, + LLSI_TRANS +}; + +typedef struct lws_led_state_ch +{ + const lws_led_sequence_def_t *seq; /* NULL = inactive */ + lws_led_seq_phase_t ph; + lws_led_seq_phase_t step; + int phase_budget; + lws_led_intensity_t last; + /**< at the end of the sequence we decouple the sequencer, but leave + * the last computed sample behind for further transitions to base off + */ +} lws_led_state_ch_t; + +typedef struct lws_led_state_chs +{ + lws_led_state_ch_t seqs[3]; +} lws_led_state_chs_t; + +/* this should always be first in the subclassed implementation types */ + +typedef struct lws_led_ops { + void (*intensity)(const struct lws_led_ops *lo, const char *name, + lws_led_intensity_t inten); + /**< for BOOL led control like GPIO, only inten b15 is significant */ + struct lws_led_state * (*create)(const struct lws_led_ops *led_ops); + void (*destroy)(struct lws_led_state *); +} lws_led_ops_t; + +typedef struct lws_led_gpio_map { + const char *name; + _lws_plat_gpio_t gpio; + lws_led_lookup_t intensity_correction; + /**< May be NULL. If GPIO-based LED, ignored. If pwm_ops provided, + * NULL means use default CIE 100% correction function. If non-NULL, + * use the pointed-to correction function. This is useful to provide + * LED-specific intensity correction / scaling so different types of + * LED can "look the same". */ + const struct lws_pwm_ops *pwm_ops; + /**< if NULL, gpio controls the led directly. If set to a pwm_ops, + * the led control is outsourced to the pwm controller. */ + uint8_t active_level; +} lws_led_gpio_map_t; + +typedef struct lws_led_gpio_controller { + const lws_led_ops_t led_ops; + + const lws_gpio_ops_t *gpio_ops; + const lws_led_gpio_map_t *led_map; + uint8_t count_leds; +} lws_led_gpio_controller_t; + +/* ops */ + +LWS_VISIBLE LWS_EXTERN struct lws_led_state * +lws_led_gpio_create(const lws_led_ops_t *led_ops); + +LWS_VISIBLE LWS_EXTERN void +lws_led_gpio_destroy(struct lws_led_state *lcs); + +/** + * lws_led_gpio_intensity() - set the static intensity of an led + * + * \param lo: the base class of the led controller + * \param index: which led in the controller set + * \param inten: 16-bit unsigned intensity + * + * For LEDs controlled by a BOOL like GPIO, only inten b15 is significant. + * For PWM type LED control, as many bits as the hardware can support from b15 + * down are significant. + */ +LWS_VISIBLE LWS_EXTERN void +lws_led_gpio_intensity(const struct lws_led_ops *lo, const char *name, + lws_led_intensity_t inten); + +LWS_VISIBLE LWS_EXTERN int +lws_led_transition(struct lws_led_state *lcs, const char *name, + const lws_led_sequence_def_t *next, + const lws_led_sequence_def_t *trans); + + +#define lws_led_gpio_ops \ + { \ + .create = lws_led_gpio_create, \ + .destroy = lws_led_gpio_destroy, \ + .intensity = lws_led_gpio_intensity, \ + } + diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-lejp.h libwebsockets-4.1.6/include/libwebsockets/lws-lejp.h --- libwebsockets-4.0.20/include/libwebsockets/lws-lejp.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-lejp.h 2020-12-01 17:40:26.000000000 +0000 @@ -153,11 +153,12 @@ * * LEJPCB_VAL_STR_START: We are starting to parse a string, no data yet * - * LEJPCB_VAL_STR_CHUNK: We parsed LEJP_STRING_CHUNK -1 bytes of string data in - * ctx->buf, which is as much as we can buffer, so we are - * spilling it. If all your strings are less than - * LEJP_STRING_CHUNK - 1 bytes, you will never see this - * callback. + * LEJPCB_VAL_STR_CHUNK: We filled the string buffer in the ctx, but it's not + * the end of the string. We produce this to spill the + * intermediate buffer to the user code, so we can handle + * huge JSON strings using only the small buffer in the + * ctx. If the whole JSON string fits in the ctx buffer, + * you won't get these callbacks. * * LEJPCB_VAL_STR_END: String parsing has completed, the last chunk of the * string is in ctx->buf. @@ -255,6 +256,7 @@ uint8_t path_match_len; uint8_t wildcount; uint8_t pst_sp; /* parsing stack head */ + uint8_t outer_array; }; LWS_VISIBLE LWS_EXTERN void diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-misc.h libwebsockets-4.1.6/include/libwebsockets/lws-misc.h --- libwebsockets-4.0.20/include/libwebsockets/lws-misc.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-misc.h 2020-12-01 17:40:26.000000000 +0000 @@ -181,6 +181,68 @@ (size_t)(size1 + 1) : (size_t)(destsize)) /** + * lws_nstrstr(): like strstr for length-based strings without terminating NUL + * + * \param buf: the string to search + * \param len: the length of the string to search + * \param name: the substring to search for + * \param nl: the length of name + * + * Returns NULL if \p name is not present in \p buf. Otherwise returns the + * address of the first instance of \p name in \p buf. + * + * Neither buf nor name need to be NUL-terminated. + */ +LWS_VISIBLE LWS_EXTERN const char * +lws_nstrstr(const char *buf, size_t len, const char *name, size_t nl); + +/** + * lws_json_simple_find(): dumb JSON string parser + * + * \param buf: the JSON to search + * \param len: the length of the JSON to search + * \param name: the name field to search the JSON for, eg, "\"myname\":" + * \param alen: set to the length of the argument part if non-NULL return + * + * Either returns NULL if \p name is not present in buf, or returns a pointer + * to the argument body of the first instance of \p name, and sets *alen to the + * length of the argument body. + * + * This can cheaply handle fishing out, eg, myarg from {"myname": "myarg"} by + * searching for "\"myname\":". It will return a pointer to myarg and set *alen + * to 5. It equally handles args like "myname": true, or "myname":false, and + * null or numbers are all returned as delimited strings. + * + * Anything more complicated like the value is a subobject or array, you should + * parse it using a full parser like lejp. This is suitable is the JSON is + * and will remain short and simple, and contains well-known names amongst other + * extensible JSON members. + */ +LWS_VISIBLE LWS_EXTERN const char * +lws_json_simple_find(const char *buf, size_t len, const char *name, size_t *alen); + +/** + * lws_json_simple_strcmp(): dumb JSON string comparison + * + * \param buf: the JSON to search + * \param len: the length of the JSON to search + * \param name: the name field to search the JSON for, eg, "\"myname\":" + * \param comp: return a strcmp of this and the discovered argument + * + * Helper that combines lws_json_simple_find() with strcmp() if it was found. + * If the \p name was not found, returns -1. Otherwise returns a strcmp() + * between what was found and \p comp, ie, return 0 if they match or something + * else if they don't. + * + * If the JSON is relatively simple and you want to target constrained + * devices, this can be a good choice. If the JSON may be complex, you + * should use a full JSON parser. + */ +LWS_VISIBLE LWS_EXTERN int +lws_json_simple_strcmp(const char *buf, size_t len, const char *name, const char *comp); + + +/** * lws_hex_to_byte_array(): convert hex string like 0123456789ab into byte data * * \param h: incoming NUL-terminated hex string @@ -199,6 +261,26 @@ LWS_VISIBLE LWS_EXTERN int lws_hex_to_byte_array(const char *h, uint8_t *dest, int max); + +/** + * lws_hex_random(): generate len - 1 or - 2 characters of random ascii hex + * + * \param context: the lws_context used to get the random + * \param dest: destination for hex ascii chars + * \param len: the number of bytes the buffer dest points to can hold + * + * This creates random ascii-hex strings up to a given length, with a + * terminating NUL. Hex characters are produced in pairs, if the length of + * the destination buffer is even, after accounting for the NUL there will be + * an unused byte at the end after the NUL. So lengths should be odd to get + * length - 1 characters exactly followed by the NUL. + * + * There will not be any characters produced that are not 0-9, a-f, so it's + * safe to go straight into, eg, JSON. + */ +LWS_VISIBLE LWS_EXTERN int +lws_hex_random(struct lws_context *context, char *dest, size_t len); + /* * lws_timingsafe_bcmp(): constant time memcmp * @@ -254,6 +336,15 @@ 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 * \param wsi: lws connection * \param user: user data @@ -577,6 +668,53 @@ */ LWS_VISIBLE LWS_EXTERN int lws_dir(const char *dirpath, void *user, lws_dir_callback_function cb); + +/** + * lws_dir_rm_rf_cb() - callback for lws_dir that performs recursive rm -rf + * + * \param dirpath: directory we are at in lws_dir + * \param user: ignored + * \param lde: lws_dir info on the file or directory we are at + * + * This is a readymade rm -rf callback for use with lws_dir. It recursively + * removes everything below the starting dir and then the starting dir itself. + * Works on linux, OSX and Windows at least. + */ +LWS_VISIBLE LWS_EXTERN int +lws_dir_rm_rf_cb(const char *dirpath, void *user, struct lws_dir_entry *lde); + +/* + * We pass every file in the base dir through a filter, and call back on the + * ones that match. Directories are ignored. + * + * The original path filter string may look like, eg, "sai-*.deb" or "*.txt" + */ + +typedef int (*lws_dir_glob_cb_t)(void *data, const char *path); + +typedef struct lws_dir_glob { + const char *filter; + lws_dir_glob_cb_t cb; + void *user; +} lws_dir_glob_t; + +/** + * lws_dir_glob_cb() - callback for lws_dir that performs filename globbing + * + * \param dirpath: directory we are at in lws_dir + * \param user: pointer to your prepared lws_dir_glob_cb_t + * \param lde: lws_dir info on the file or directory we are at + * + * \p user is prepared with an `lws_dir_glob_t` containing a callback for paths + * that pass the filtering, a user pointer to pass to that callback, and a + * glob string like "*.txt". It may not contain directories, the lws_dir musr + * be started at the correct dir. + * + * Only the base path passed to lws_dir is scanned, it does not look in subdirs. + */ +LWS_VISIBLE LWS_EXTERN int +lws_dir_glob_cb(const char *dirpath, void *user, struct lws_dir_entry *lde); + #endif /** @@ -663,9 +801,9 @@ uint64_t factor; } lws_humanize_unit_t; -LWS_VISIBLE LWS_EXTERN const lws_humanize_unit_t humanize_schema_si[7]; -LWS_VISIBLE LWS_EXTERN const lws_humanize_unit_t humanize_schema_si_bytes[7]; -LWS_VISIBLE LWS_EXTERN const lws_humanize_unit_t humanize_schema_us[8]; +LWS_VISIBLE extern const lws_humanize_unit_t humanize_schema_si[7]; +LWS_VISIBLE extern const lws_humanize_unit_t humanize_schema_si_bytes[7]; +LWS_VISIBLE extern const lws_humanize_unit_t humanize_schema_us[8]; /** * lws_humanize() - Convert possibly large number to human-readable uints @@ -723,6 +861,13 @@ /* opaque internal struct */ struct lws_spawn_piped; +#if defined(WIN32) +struct _lws_siginfo_t { + int retcode; +}; +typedef struct _lws_siginfo_t siginfo_t; +#endif + typedef void (*lsp_cb_t)(void *opaque, lws_usec_t *accounting, siginfo_t *si, int we_killed_him); @@ -808,6 +953,7 @@ * lws_spawn_stdwsi_closed() - inform the spawn one of its stdxxx pipes closed * * \p lsp: the spawn object + * \p wsi: the wsi that is closing * * When you notice one of the spawn stdxxx pipes closed, inform the spawn * instance using this api. When it sees all three have closed, it will @@ -817,7 +963,7 @@ * has closed. */ LWS_VISIBLE LWS_EXTERN void -lws_spawn_stdwsi_closed(struct lws_spawn_piped *lsp); +lws_spawn_stdwsi_closed(struct lws_spawn_piped *lsp, struct lws *wsi); /** * lws_spawn_get_stdfd() - return std channel index for stdwsi diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-netdev.h libwebsockets-4.1.6/include/libwebsockets/lws-netdev.h --- libwebsockets-4.0.20/include/libwebsockets/lws-netdev.h 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-netdev.h 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,283 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2020 Andy Green + * + * 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. + */ + +#define LWS_WIFI_MAX_SCAN_TRACK 16 +#define LWS_ETH_ALEN 6 + +typedef uint8_t lws_wifi_ch_t; +typedef int8_t lws_wifi_rssi_t; +struct lws_netdev_instance; + +typedef enum { + LWSNDTYP_UNKNOWN, + LWSNDTYP_WIFI, + LWSNDTYP_ETH, +} lws_netdev_type_t; + +/* + * Base class for netdev configuration + */ + +typedef struct lws_netdev_config { + void *plat_config; +} lws_netdev_config_t; + +/* + * Const Logical generic network interface ops + */ + +typedef struct lws_netdev_ops { + struct lws_netdev_instance * (*create)(struct lws_context *ctx, + const struct lws_netdev_ops *ops, + const char *name, void *platinfo); + int (*configure)(struct lws_netdev_instance *nd, + lws_netdev_config_t *config); + int (*up)(struct lws_netdev_instance *nd); + int (*down)(struct lws_netdev_instance *nd); + int (*event)(struct lws_netdev_instance *nd, lws_usec_t timestamp, + void *buf, size_t len); + /**< these are SMD events coming from lws event loop thread context */ + void (*destroy)(struct lws_netdev_instance **pnd); + int (*connect)(struct lws_netdev_instance *wnd, const char *ssid, + const char *passphrase, uint8_t *bssid); + void (*scan)(struct lws_netdev_instance *nd); +} lws_netdev_ops_t; + +/* + * Network devices on this platform + * + * We also hold a list of all known network credentials (when they are needed + * because there is a network interface without anything to connect to) and + * the lws_settings instance they are stored in + */ + +typedef struct lws_netdevs { + lws_dll2_owner_t owner; + /**< list of netdevs / lws_netdev_instance_t -based objects */ + + lws_dll2_owner_t owner_creds; + /**< list of known credentials */ + struct lwsac *ac_creds; + /**< lwsac holding retreived credentials settings, or NULL */ + lws_settings_instance_t *si; + + lws_sockaddr46 sa46_dns_resolver; + + uint8_t refcount_creds; + /**< when there are multiple netdevs, must refcount creds in mem */ +} lws_netdevs_t; + +/* + * Base class for an allocated instantiated derived object using lws_netdev_ops, + * ie, a specific ethernet device + */ + +typedef struct lws_netdev_instance { + const char *name; + const lws_netdev_ops_t *ops; + void *platinfo; + lws_dll2_t list; + uint8_t mac[LWS_ETH_ALEN]; + uint8_t type; /* lws_netdev_type_t */ +} lws_netdev_instance_t; + +enum { + LNDIW_ALG_OPEN, + LNDIW_ALG_WPA2, + + LNDIW_MODE_STA = (1 << 0), + LNDIW_MODE_AP = (1 << 1), + LNDIW_UP = (1 << 7), + + LNDIW_ACQ_IPv4 = (1 << 0), + LNDIW_ACQ_IPv6 = (1 << 1), +}; + +/* + * Group AP / Station State + */ + +typedef enum { + LWSNDVWIFI_STATE_INITIAL, + /* + * We should gratuitously try whatever last worked for us, then + * if that fails, worry about the rest of the logic + */ + LWSNDVWIFI_STATE_SCAN, + /* + * Unconnected, scanning: AP known in one of the config slots -> + * configure it, start timeout + LWSNDVWIFI_STATE_STAT, if no AP + * already up in same group with lower MAC, after a random + * period start up our AP (LWSNDVWIFI_STATE_AP) + */ + LWSNDVWIFI_STATE_AP, + /* Trying to be the group AP... periodically do a scan + * LWSNDVWIFI_STATE_AP_SCAN, faster and then slower + */ + LWSNDVWIFI_STATE_AP_SCAN, + /* + * doing a scan while trying to be the group AP... if we see a + * lower MAC being the AP for the same group AP, abandon being + * an AP and join that AP as a station + */ + LWSNDVWIFI_STATE_STAT_GRP_AP, + /* + * We have decided to join another group member who is being the + * AP, as its MAC is lower than ours. This is a stable state, + * but we still do periodic scans + * LWSNDVWIFI_STATE_STAT_GRP_AP_SCAN and will always prefer an + * AP configured in a slot. + */ + LWSNDVWIFI_STATE_STAT_GRP_AP_SCAN, + /* + * We have joined a group member who is doing the AP job... we + * want to check every now and then if a configured AP has + * appeared that we should better use instead. Otherwise stay + * in LWSNDVWIFI_STATE_STAT_GRP_AP + */ + LWSNDVWIFI_STATE_STAT, + /* + * trying to connect to another non-group AP. If we don't get an + * IP within a timeout and retries, blacklist it and go back + */ + LWSNDVWIFI_STATE_STAT_HAPPY, +} lws_netdev_wifi_state_t; + +/* + * Generic WIFI credentials + */ + +typedef struct lws_wifi_creds { + lws_dll2_t list; + + uint8_t bssid[LWS_ETH_ALEN]; + char passphrase[64]; + char ssid[33]; + uint8_t alg; +} lws_wifi_creds_t; + +/* + * Generic WIFI Network Device Instance + */ + +typedef struct lws_netdev_instance_wifi { + lws_netdev_instance_t inst; + lws_dll2_owner_t scan; /* sorted scan results */ + lws_sorted_usec_list_t sul_scan; + + lws_wifi_creds_t *ap_cred; + const char *ap_ip; + + const char *sta_ads; + + char current_attempt_ssid[33]; + uint8_t current_attempt_bssid[LWS_ETH_ALEN]; + + uint8_t flags; + uint8_t state; /* lws_netdev_wifi_state_t */ +} lws_netdev_instance_wifi_t; + +/* + * Logical scan results sorted list item + */ + +typedef struct lws_wifi_sta { + lws_dll2_t list; + + uint32_t last_seen; /* unix time */ + uint32_t last_tried; /* unix time */ + + uint8_t bssid[LWS_ETH_ALEN]; + char *ssid; /* points to overallocation */ + uint8_t ssid_len; + lws_wifi_ch_t ch; + lws_wifi_rssi_t rssi[8]; + int16_t rssi_avg; + uint8_t authmode; + + uint8_t rssi_count; + uint8_t rssi_next; + + /* ssid overallocated afterwards */ +} lws_wifi_sta_t; + +#define rssi_averaged(_x) (_x->rssi_count ? \ + ((int)_x->rssi_avg / (int)_x->rssi_count) : \ + -200) + +LWS_VISIBLE LWS_EXTERN lws_netdevs_t * +lws_netdevs_from_ctx(struct lws_context *ctx); + +LWS_VISIBLE LWS_EXTERN int +lws_netdev_credentials_settings_set(lws_netdevs_t *nds); + +LWS_VISIBLE LWS_EXTERN int +lws_netdev_credentials_settings_get(lws_netdevs_t *nds); + +LWS_VISIBLE LWS_EXTERN struct lws_netdev_instance * +lws_netdev_wifi_create_plat(struct lws_context *ctx, + const lws_netdev_ops_t *ops, const char *name, + void *platinfo); +LWS_VISIBLE LWS_EXTERN int +lws_netdev_wifi_configure_plat(struct lws_netdev_instance *nd, + lws_netdev_config_t *config); +LWS_VISIBLE LWS_EXTERN int +lws_netdev_wifi_event_plat(struct lws_netdev_instance *nd, lws_usec_t timestamp, + void *buf, size_t len); +LWS_VISIBLE LWS_EXTERN int +lws_netdev_wifi_up_plat(struct lws_netdev_instance *nd); +LWS_VISIBLE LWS_EXTERN int +lws_netdev_wifi_down_plat(struct lws_netdev_instance *nd); +LWS_VISIBLE LWS_EXTERN void +lws_netdev_wifi_destroy_plat(struct lws_netdev_instance **pnd); +LWS_VISIBLE LWS_EXTERN void +lws_netdev_wifi_scan_plat(lws_netdev_instance_t *nd); + +LWS_VISIBLE LWS_EXTERN int +lws_netdev_wifi_connect_plat(lws_netdev_instance_t *wnd, const char *ssid, + const char *passphrase, uint8_t *bssid); + +LWS_VISIBLE LWS_EXTERN lws_netdev_instance_t * +lws_netdev_find(lws_netdevs_t *netdevs, const char *ifname); + +#define lws_netdev_wifi_plat_ops \ + .create = lws_netdev_wifi_create_plat, \ + .configure = lws_netdev_wifi_configure_plat, \ + .event = lws_netdev_wifi_event_plat, \ + .up = lws_netdev_wifi_up_plat, \ + .down = lws_netdev_wifi_down_plat, \ + .connect = lws_netdev_wifi_connect_plat, \ + .scan = lws_netdev_wifi_scan_plat, \ + .destroy = lws_netdev_wifi_destroy_plat + +/* + * This is for plat / OS level init that is necessary to be able to use + * networking or wifi at all, without mentioning any specific device + */ + +LWS_VISIBLE LWS_EXTERN int +lws_netdev_plat_init(void); + +LWS_VISIBLE LWS_EXTERN int +lws_netdev_plat_wifi_init(void); diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-network-helper.h libwebsockets-4.1.6/include/libwebsockets/lws-network-helper.h --- libwebsockets-4.0.20/include/libwebsockets/lws-network-helper.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-network-helper.h 2020-12-01 17:40:26.000000000 +0000 @@ -29,6 +29,10 @@ */ ///@{ +#if defined(LWS_ESP_PLATFORM) +#include +#endif + typedef union { #if defined(LWS_WITH_IPV6) struct sockaddr_in6 sa6; diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-plugin-generic-sessions.h libwebsockets-4.1.6/include/libwebsockets/lws-plugin-generic-sessions.h --- libwebsockets-4.0.20/include/libwebsockets/lws-plugin-generic-sessions.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-plugin-generic-sessions.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,75 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * 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. - */ - -/*! \defgroup generic-sessions plugin: generic-sessions - * \ingroup Protocols-and-Plugins - * - * ##Plugin Generic-sessions related - * - * generic-sessions plugin provides a reusable, generic session and login / - * register / forgot password framework including email verification. - */ -///@{ - -#define LWSGS_EMAIL_CONTENT_SIZE 16384 -/**< Maximum size of email we might send */ - -/* SHA-1 binary and hexified versions */ -/** typedef struct lwsgw_hash_bin */ -typedef struct { unsigned char bin[32]; /**< binary representation of hash */} lwsgw_hash_bin; -/** typedef struct lwsgw_hash */ -typedef struct { char id[65]; /**< ascii hex representation of hash */ } lwsgw_hash; - -/** enum lwsgs_auth_bits */ -enum lwsgs_auth_bits { - LWSGS_AUTH_LOGGED_IN = 1, /**< user is logged in as somebody */ - LWSGS_AUTH_ADMIN = 2, /**< logged in as the admin user */ - LWSGS_AUTH_VERIFIED = 4, /**< user has verified his email */ - LWSGS_AUTH_FORGOT_FLOW = 8, /**< just completed "forgot password" */ -}; - -/** struct lws_session_info - information about user session status */ -struct lws_session_info { - char username[32]; /**< username logged in as, or empty string */ - char email[100]; /**< email address associated with login, or empty string */ - char ip[72]; /**< ip address session was started from */ - unsigned int mask; /**< access rights mask associated with session - * see enum lwsgs_auth_bits */ - char session[42]; /**< session id string, usable as opaque uid when not logged in */ -}; - -/** enum lws_gs_event */ -enum lws_gs_event { - LWSGSE_CREATED, /**< a new user was created */ - LWSGSE_DELETED /**< an existing user was deleted */ -}; - -/** struct lws_gs_event_args */ -struct lws_gs_event_args { - enum lws_gs_event event; /**< which event happened */ - const char *username; /**< which username the event happened to */ - const char *email; /**< the email address of that user */ -}; - -///@} diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-protocols-plugins.h libwebsockets-4.1.6/include/libwebsockets/lws-protocols-plugins.h --- libwebsockets-4.0.20/include/libwebsockets/lws-protocols-plugins.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-protocols-plugins.h 2020-12-01 17:40:26.000000000 +0000 @@ -68,7 +68,7 @@ * to the selected protocol. For example if this protocol was * called "myprotocol-v2", you might set id to 2, and the user * code that acts differently according to the version can do so by - * switch (wsi->protocol->id), user code might use some bits as + * switch (wsi->a.protocol->id), user code might use some bits as * capability flags based on selected protocol version, etc. */ void *user; /**< ignored by lws, but user code can pass a pointer here it can later access from the protocol callback */ @@ -194,36 +194,116 @@ LWS_VISIBLE LWS_EXTERN int lws_protocol_init(struct lws_context *context); -#ifdef LWS_WITH_PLUGINS +#define LWS_PLUGIN_API_MAGIC 190 -/* PLUGINS implies LIBUV */ +/* + * Abstract plugin header for any kind of plugin class, always at top of + * actual class plugin export type. + * + * The export type object must be exported with the same name as the plugin + * file, eg, libmyplugin.so must export a const one of these as the symbol + * "myplugin". + * + * That is the only expected export from the plugin. + */ + +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 */ -#define LWS_PLUGIN_API_MAGIC 180 + /* plugin-class specific superclass data follows */ +} lws_plugin_header_t; + +/* + * "lws_protocol_plugin" class export, for lws_protocol implementations done + * as plugins + */ +typedef struct lws_plugin_protocol { + lws_plugin_header_t hdr; -/** struct lws_plugin_capability - how a plugin introduces itself to lws */ -struct lws_plugin_capability { - unsigned int api_magic; /**< caller fills this in, plugin fills rest */ const struct lws_protocols *protocols; /**< array of supported protocols provided by plugin */ - int count_protocols; /**< how many protocols */ const struct lws_extension *extensions; /**< array of extensions provided by plugin */ + int count_protocols; /**< how many protocols */ int count_extensions; /**< how many extensions */ -}; +} lws_plugin_protocol_t; + -typedef int (*lws_plugin_init_func)(struct lws_context *, - struct lws_plugin_capability *); -typedef int (*lws_plugin_destroy_func)(struct lws_context *); +/* + * This is the dynamic, runtime created part of the plugin instantiation. + * These are kept in a linked-list and destroyed with the context. + */ -/** struct lws_plugin */ struct lws_plugin { struct lws_plugin *list; /**< linked list */ + + const lws_plugin_header_t *hdr; + + union { +#if defined(LWS_WITH_LIBUV) && defined(UV_ERRNO_MAP) #if (UV_VERSION_MAJOR > 0) - uv_lib_t lib; /**< shared library pointer */ + uv_lib_t lib; /**< shared library pointer */ +#endif #endif - void *l; /**< so we can compile on ancient libuv */ - char name[64]; /**< name of the plugin */ - struct lws_plugin_capability caps; /**< plugin capabilities */ + void *l; /**< */ + } u; }; -#endif +/* + * Event lib library plugin type (when LWS_WITH_EVLIB_PLUGINS) + * Public so new event libs can equally be supported outside lws itself + */ + +typedef struct lws_plugin_evlib { + lws_plugin_header_t hdr; + const struct lws_event_loop_ops *ops; +} lws_plugin_evlib_t; + +typedef int (*each_plugin_cb_t)(struct lws_plugin *p, void *user); + +/** + * lws_plugins_init() - dynamically load plugins of matching class from dirs + * + * \param pplugin: pointer to linked-list for this kind of plugin + * \param d: array of directory paths to look in + * \param _class: class string that plugin must declare + * \param filter: NULL, or a string that must appear after the third char of the plugin filename + * \param each: NULL, or each_plugin_cb_t callback for each instantiated plugin + * \param each_user: pointer passed to each callback + * + * Allows you to instantiate a class of plugins to a specified linked-list. + * The each callback allows you to init each inistantiated callback and pass a + * pointer each_user to it. + * + * To take down the plugins, pass a pointer to the linked-list head to + * lws_plugins_destroy. + * + * This is used for lws protocol plugins but you can define your own plugin + * class name like "mypluginclass", declare it in your plugin headers, and load + * your own plugins to your own list using this api the same way. + */ +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_plugins_destroy() - dynamically unload list of plugins + * + * \param pplugin: pointer to linked-list for this kind of plugin + * \param each: NULL, or each_plugin_cb_t callback for each instantiated plugin + * \param each_user: pointer passed to each callback + * + * Allows you to destroy a class of plugins from a specified linked-list + * created by a call to lws_plugins_init(). + * + * The each callback allows you to deinit each inistantiated callback and pass a + * pointer each_user to it, just before its footprint is destroyed. + */ +LWS_VISIBLE LWS_EXTERN int +lws_plugins_destroy(struct lws_plugin **pplugin, each_plugin_cb_t each, + void *each_user); ///@} diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-pwm.h libwebsockets-4.1.6/include/libwebsockets/lws-pwm.h --- libwebsockets-4.0.20/include/libwebsockets/lws-pwm.h 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-pwm.h 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,67 @@ +/* + * Generic PWM controller ops + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + */ + +typedef struct lws_pwm_map { + _lws_plat_gpio_t gpio; + uint8_t index; + uint8_t active_level; +} lws_pwm_map_t; + +typedef struct lws_pwm_ops { + int (*init)(const struct lws_pwm_ops *lo); + void (*intensity)(const struct lws_pwm_ops *lo, _lws_plat_gpio_t gpio, + lws_led_intensity_t inten); + const lws_pwm_map_t *pwm_map; + uint8_t count_pwm_map; +} lws_pwm_ops_t; + +LWS_VISIBLE LWS_EXTERN int +lws_pwm_plat_init(const struct lws_pwm_ops *lo); + +LWS_VISIBLE LWS_EXTERN void +lws_pwm_plat_intensity(const struct lws_pwm_ops *lo, _lws_plat_gpio_t gpio, + lws_led_intensity_t inten); + +#define lws_pwm_plat_ops \ + .init = lws_pwm_plat_init, \ + .intensity = lws_pwm_plat_intensity + +/* + * May be useful for making your own transitions or sequences + */ + +LWS_VISIBLE LWS_EXTERN lws_led_intensity_t +lws_led_func_linear(lws_led_seq_phase_t n); +LWS_VISIBLE LWS_EXTERN lws_led_intensity_t +lws_led_func_sine(lws_led_seq_phase_t n); + +/* canned sequences that can work out of the box */ + +extern const lws_led_sequence_def_t lws_pwmseq_sine_endless_slow, + lws_pwmseq_sine_endless_fast, + lws_pwmseq_linear_wipe, + lws_pwmseq_sine_up, lws_pwmseq_sine_down, + lws_pwmseq_static_on, + lws_pwmseq_static_half, + lws_pwmseq_static_off; diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-secure-streams-client.h libwebsockets-4.1.6/include/libwebsockets/lws-secure-streams-client.h --- libwebsockets-4.0.20/include/libwebsockets/lws-secure-streams-client.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-secure-streams-client.h 2020-12-01 17:40:26.000000000 +0000 @@ -41,18 +41,23 @@ */ #if defined(LWS_SS_USE_SSPC) -#define lws_ss_handle lws_sspc_handle -#define lws_ss_create lws_sspc_create -#define lws_ss_destroy lws_sspc_destroy -#define lws_ss_request_tx lws_sspc_request_tx -#define lws_ss_client_connect lws_sspc_client_connect -#define lws_ss_get_sequencer lws_sspc_get_sequencer -#define lws_ss_proxy_create lws_sspc_proxy_create -#define lws_ss_get_context lws_sspc_get_context -#define lws_ss_rideshare lws_sspc_rideshare -#define lws_ss_set_metadata lws_sspc_set_metadata -#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_handle lws_sspc_handle +#define lws_ss_create lws_sspc_create +#define lws_ss_destroy lws_sspc_destroy +#define lws_ss_request_tx lws_sspc_request_tx +#define lws_ss_request_tx_len lws_sspc_request_tx_len +#define lws_ss_client_connect lws_sspc_client_connect +#define lws_ss_get_sequencer lws_sspc_get_sequencer +#define lws_ss_proxy_create lws_sspc_proxy_create +#define lws_ss_get_context lws_sspc_get_context +#define lws_ss_rideshare lws_sspc_rideshare +#define lws_ss_set_metadata lws_sspc_set_metadata +#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_start_timeout lws_sspc_start_timeout +#define lws_ss_cancel_timeout lws_sspc_cancel_timeout +#define lws_ss_to_user_object lws_sspc_to_user_object +#define lws_ss_change_handlers lws_sspc_change_handlers #endif @@ -60,8 +65,8 @@ LWS_VISIBLE LWS_EXTERN int lws_sspc_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, - void *opaque_user_data, struct lws_sspc_handle **ppss, - struct lws_sequencer *seq_owner, const char **ppayload_fmt); + void *opaque_user_data, struct lws_sspc_handle **ppss, + struct lws_sequencer *seq_owner, const char **ppayload_fmt); /** * lws_sspc_destroy() - Destroy secure stream @@ -82,10 +87,30 @@ * write on this stream, the *tx callback will occur with an empty buffer for * the stream owner to fill in. */ -LWS_VISIBLE LWS_EXTERN void +LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t lws_sspc_request_tx(struct lws_sspc_handle *pss); /** + * lws_sspc_request_tx_len() - Schedule stream for tx with length hint + * + * \param h: pointer to handle representing stream that wants to transmit + * \param len: the length of the write in bytes + * + * Schedules a write on the stream represented by \p pss. When it's possible to + * write on this stream, the *tx callback will occur with an empty buffer for + * the stream owner to fill in. + * + * This api variant should be used when it's possible the payload will go out + * over h1 with x-web-form-urlencoded or similar Content-Type. + * + * The serialized, sspc type api actually serializes and forwards the length + * hint to its upstream proxy, where it's available for use to produce the + * internet-capable protocol framing. + */ +LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t +lws_sspc_request_tx_len(struct lws_sspc_handle *h, unsigned long len); + +/** * lws_sspc_client_connect() - Attempt the client connect * * \param h: secure streams handle @@ -163,10 +188,31 @@ */ LWS_VISIBLE LWS_EXTERN int lws_sspc_set_metadata(struct lws_sspc_handle *h, const char *name, - void *value, size_t len); + const void *value, size_t len); LWS_VISIBLE LWS_EXTERN int lws_sspc_add_peer_tx_credit(struct lws_sspc_handle *h, int32_t add); LWS_VISIBLE LWS_EXTERN int lws_sspc_get_est_peer_tx_credit(struct lws_sspc_handle *h); + +LWS_VISIBLE LWS_EXTERN void +lws_sspc_start_timeout(struct lws_sspc_handle *h, unsigned int timeout_ms); + +LWS_VISIBLE LWS_EXTERN void +lws_sspc_cancel_timeout(struct lws_sspc_handle *h); + +LWS_VISIBLE LWS_EXTERN void * +lws_sspc_to_user_object(struct lws_sspc_handle *h); + +LWS_VISIBLE LWS_EXTERN void +lws_sspc_change_handlers(struct lws_sspc_handle *h, + lws_ss_state_return_t (*rx)(void *userobj, const uint8_t *buf, + size_t len, int flags), + lws_ss_state_return_t (*tx)(void *userobj, lws_ss_tx_ordinal_t ord, + uint8_t *buf, size_t *len, int *flags), + lws_ss_state_return_t (*state)(void *userobj, void *h_src + /* ss handle type */, + lws_ss_constate_t state, + lws_ss_tx_ordinal_t ack)); + diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-secure-streams.h libwebsockets-4.1.6/include/libwebsockets/lws-secure-streams.h --- libwebsockets-4.0.20/include/libwebsockets/lws-secure-streams.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-secure-streams.h 2020-12-01 17:40:26.000000000 +0000 @@ -73,7 +73,7 @@ * - 3: 4-byte MSB-first flags * - 7: 4-byte MSB-first us between client requested write and wrote to proxy * - 11: 8-byte MSB-first us resolution unix time client wrote to proxy - * - 17: payload + * - 19: payload * * - Proxied secure stream destroy * @@ -84,10 +84,28 @@ * * - 0: LWSSS_SER_TXPRE_METADATA * - 1: 2-byte MSB-first rest-of-frame length - * - 2: 1-byte metadata name length - * - 3: metadata name + * - 3: 1-byte metadata name length + * - 4: metadata name * - ...: metadata value (for rest of packet) * + * - TX credit management - sent when using tx credit apis, cf METADATA + * + * - 0: LWSSS_SER_TXPRE_TXCR_UPDATE + * - 1: 2-byte MSB-first rest-of-frame length 00, 04 + * - 3: 4-byte additional tx credit adjust value + * + * - Stream timeout management - forwarded when user applying or cancelling t.o. + * + * - 0: LWSSS_SER_TXPRE_TIMEOUT_UPDATE + * - 1: 2-byte MSB-first rest-of-frame length 00, 04 + * - 3: 4-byte MSB-first unsigned 32-bit timeout, 0 = use policy, -1 = cancel + * + * - Passing up payload length hint + * + * - 0: LWSSS_SER_TXPRE_PAYLOAD_LENGTH_HINT + * - 1: 2-byte MSB-first rest-of-frame length 00, 04 + * - 3: 4-byte MSB-first unsigned 32-bit payload length hint + * * Proxy to client * * - Proxied connection setup result @@ -117,9 +135,9 @@ * - Proxied state * * - 0: LWSSS_SER_RXPRE_CONNSTATE - * - 1: 00, 05 - * - 3: 1 byte state index - * - 7: 4-byte MSB-first ordinal + * - 1: 00, 05 if state < 256, else 00, 08 + * - 3: 1 byte state index if state < 256, else 4-byte MSB-first state index + * - 4 or 7: 4-byte MSB-first ordinal * * * Proxied tx may be read by the proxy but rejected due to lack of buffer space @@ -165,6 +183,10 @@ LWSSSCS_QOS_NACK_REMOTE, LWSSSCS_QOS_ACK_LOCAL, /* local proxy accepted our tx */ LWSSSCS_QOS_NACK_LOCAL, /* local proxy refused our tx */ + LWSSSCS_TIMEOUT, /* optional timeout timer fired */ + + LWSSSCS_SERVER_TXN, + LWSSSCS_SERVER_UPGRADE, /* the server protocol upgraded */ LWSSSCS_SINK_JOIN, /* sinks get this when a new source * stream joins the sink */ @@ -215,23 +237,39 @@ LWSSS_SER_TXPRE_TX_PAYLOAD, LWSSS_SER_TXPRE_METADATA, LWSSS_SER_TXPRE_TXCR_UPDATE, + LWSSS_SER_TXPRE_TIMEOUT_UPDATE, + LWSSS_SER_TXPRE_PAYLOAD_LENGTH_HINT, LWSSS_SER_TXPRE_TLSNEG_ENCLAVE_SIGNED, }; typedef enum { - LPCS_WAIT_INITIAL_TX = 1, /* after connect, must send streamtype */ - LPCS_REPORTING_FAIL, /* stream creation failed, wait to to tell */ - LPCS_REPORTING_OK, /* stream creation succeeded, wait to to tell */ - LPCS_OPERATIONAL, /* ready for payloads */ - LPCS_DESTROYED, - - LPCS_SENDING_INITIAL_TX = 1, /* after connect, must send streamtype */ - LPCS_WAITING_CREATE_RESULT, /* wait to hear if proxy ss create OK */ - LPCS_LOCAL_CONNECTED, /* we are in touch with the proxy */ - LPCS_ONWARD_CONNECT, /* request onward ss connection */ + LPCSPROX_WAIT_INITIAL_TX = 1, /* after connect, must send streamtype */ + LPCSPROX_REPORTING_FAIL, /* stream creation failed, wait to to tell */ + LPCSPROX_REPORTING_OK, /* stream creation succeeded, wait to to tell */ + LPCSPROX_OPERATIONAL, /* ready for payloads */ + LPCSPROX_DESTROYED, + + LPCSCLI_SENDING_INITIAL_TX, /* after connect, must send streamtype */ + LPCSCLI_WAITING_CREATE_RESULT, /* wait to hear if proxy ss create OK */ + LPCSCLI_LOCAL_CONNECTED, /* we are in touch with the proxy */ + LPCSCLI_ONWARD_CONNECT, /* request onward ss connection */ + LPCSCLI_OPERATIONAL, /* ready for payloads */ } lws_ss_conn_states_t; +/* + * Returns from state() callback can tell the caller what the user code + * wants to do + */ + +typedef enum lws_ss_state_return { + LWSSSSRET_TX_DONT_SEND = 1, /* (*tx) only */ + + LWSSSSRET_OK = 0, /* no error */ + LWSSSSRET_DISCONNECT_ME = -1, /* caller should disconnect us */ + LWSSSSRET_DESTROY_ME = -2, /* caller should destroy us */ +} lws_ss_state_return_t; + /** * lws_ss_info_t: information about stream to be created * @@ -240,6 +278,27 @@ * to create the requested stream. */ +enum { + LWSSSINFLAGS_REGISTER_SINK = (1 << 0), + /**< If set, we're not creating a specific stream, but registering + * ourselves as the "sink" for .streamtype. It's analogous to saying + * we want to be the many-to-one "server" for .streamtype; when other + * streams are created with that streamtype, they should be forwarded + * to this stream owner, where they join and part from the sink via + * (*state) LWSSSCS_SINK_JOIN / _PART events, the new client handle + * being provided in the h_src parameter. + */ + LWSSSINFLAGS_PROXIED = (1 << 1), + /**< Set if the stream is being created as a stand-in at the proxy */ + LWSSSINFLAGS_SERVER = (1 << 2), + /**< Set on the server object copy of the ssi / info to indicate that + * stream creation using this ssi is for Accepted connections belonging + * to a server */ + LWSSSINFLAGS_ACCEPTED = (1 << 3), + /**< Set on the accepted object copy of the ssi / info to indicate that + * we are an accepted connection from a server's listening socket */ +}; + typedef struct lws_ss_info { const char *streamtype; /**< type of stream we want to create */ size_t user_alloc; /**< size of user allocation */ @@ -249,31 +308,28 @@ /**< offset of opaque user data ptr in user_alloc type, set to offsetof(mytype, opaque_ud_member) */ - int (*rx)(void *userobj, const uint8_t *buf, size_t len, - int flags); + lws_ss_state_return_t (*rx)(void *userobj, const uint8_t *buf, + size_t len, int flags); /**< callback with rx payload for this stream */ - int (*tx)(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, - size_t *len, int *flags); + lws_ss_state_return_t (*tx)(void *userobj, lws_ss_tx_ordinal_t ord, + uint8_t *buf, size_t *len, int *flags); /**< callback to send payload on this stream... 0 = send as set in * len and flags, 1 = do not send anything (ie, not even 0 len frame) */ - int (*state)(void *userobj, void *h_src /* ss handle type */, - lws_ss_constate_t state, lws_ss_tx_ordinal_t ack); + lws_ss_state_return_t (*state)(void *userobj, void *h_src /* ss handle type */, + lws_ss_constate_t state, lws_ss_tx_ordinal_t ack); /**< advisory cb about state of stream and QoS status if applicable... * h_src is only used with sinks and LWSSSCS_SINK_JOIN/_PART events. * Return nonzero to indicate you want to destroy the stream. */ int manual_initial_tx_credit; /**< 0 = manage any tx credit automatically, nonzero explicitly sets the * peer stream to have the given amount of tx credit, if the protocol - * can support it. */ - char register_sink; - /**< If set, we're not creating a specific stream, but registering - * ourselves as the "sink" for .streamtype. It's analogous to saying - * we want to be the many-to-one "server" for .streamtype; when other - * streams are created with that streamtype, they should be forwarded - * to this stream owner, where they join and part from the sink via - * (*state) LWSSSCS_SINK_JOIN / _PART events, the new client handle - * being provided in the h_src parameter. - */ + * can support it. + * + * In the special case of _lws_smd streamtype, this is used to indicate + * the connection's rx class mask. + * */ + uint8_t flags; + } lws_ss_info_t; /** @@ -335,8 +391,10 @@ * Schedules a write on the stream represented by \p pss. When it's possible to * write on this stream, the *tx callback will occur with an empty buffer for * the stream owner to fill in. + * + * Returns 0 or LWSSSSRET_SS_HANDLE_DESTROYED */ -LWS_VISIBLE LWS_EXTERN void +LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t lws_ss_request_tx(struct lws_ss_handle *pss); /** @@ -352,10 +410,9 @@ * This api variant should be used when it's possible the payload will go out * over h1 with x-web-form-urlencoded or similar Content-Type. */ -LWS_VISIBLE LWS_EXTERN void +LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t lws_ss_request_tx_len(struct lws_ss_handle *pss, unsigned long len); - /** * lws_ss_client_connect() - Attempt the client connect * @@ -420,6 +477,48 @@ LWS_VISIBLE LWS_EXTERN struct lws_context * lws_ss_get_context(struct lws_ss_handle *h); +#define LWSSS_TIMEOUT_FROM_POLICY 0 + +/** + * lws_ss_start_timeout() - start or restart the timeout on the stream + * + * \param h: secure streams handle + * \param timeout_ms: LWSSS_TIMEOUT_FROM_POLICY for policy value, else use timeout_ms + * + * Starts or restarts the stream's own timeout timer. If the specified time + * passes without lws_ss_cancel_timeout() being called on the stream, then the + * stream state callback receives LWSSSCS_TIMEOUT + * + * The process being protected by the timeout is up to the user code, it may be + * arbitrarily long and cross multiple protocol transactions or involve other + * streams. It's up to the user to decide when to start and when / if to cancel + * the stream timeout. + */ +LWS_VISIBLE LWS_EXTERN void +lws_ss_start_timeout(struct lws_ss_handle *h, unsigned int timeout_ms); + +/** + * lws_ss_cancel_timeout() - remove any timeout on the stream + * + * \param h: secure streams handle + * + * Disable any timeout that was applied to the stream by lws_ss_start_timeout(). + */ +LWS_VISIBLE LWS_EXTERN void +lws_ss_cancel_timeout(struct lws_ss_handle *h); + +/** + * lws_ss_to_user_object() - convenience helper to get user object from handle + * + * \param h: secure streams handle + * + * Returns the user allocation related to the handle. Normally you won't need + * this since it's available in the rx, tx and state callbacks as "userdata" + * already. + */ +LWS_VISIBLE LWS_EXTERN void * +lws_ss_to_user_object(struct lws_ss_handle *h); + /** * lws_ss_rideshare() - find the current streamtype when types rideshare * @@ -463,8 +562,62 @@ */ LWS_VISIBLE LWS_EXTERN int lws_ss_set_metadata(struct lws_ss_handle *h, const char *name, - void *value, size_t len); + const void *value, size_t len); +/* + * lws_ss_server_ack() - indicate how we feel about what the server has sent + * + * \param h: ss handle of accepted connection + * \param nack: 0 means we are OK with it, else some problem + * + * For SERVER secure streams + * + * Depending on the protocol, the server sending us something may be + * transactional, ie, built into it sending something is the idea we will + * respond somehow out-of-band; HTTP is like this with, eg, 200 response code. + * + * Calling this with nack=0 indicates that when we later respond, we want to + * acknowledge the transaction (eg, it means a 200 if http underneath), if + * nonzero that the transaction should act like it failed. + * + * If the underlying protocol doesn't understand transactions (eg, ws) then this + * has no effect either way. + */ +LWS_VISIBLE LWS_EXTERN void +lws_ss_server_ack(struct lws_ss_handle *h, int nack); + +/** + * lws_ss_change_handlers() - helper for dynamically changing stream handlers + * + * \param h: ss handle + * \param rx: the new RX handler + * \param tx: the new TX handler + * \param state: the new state handler + * + * Handlers set to NULL are left unchanged. + * + * This works on any handle, client or server and takes effect immediately. + * + * Depending on circumstances this may be helpful when + * + * a) a server stream undergoes an LWSSSCS_SERVER_UPGRADE (as in http -> ws) and + * the payloads in the new protocol have a different purpose that is best + * handled in their own rx and tx callbacks, and + * + * b) you may want to serve several different, possibly large things based on + * what was requested. Setting a customized handler allows clean encapsulation + * of the different serving strategies. + * + * If the stream is long-lived, like ws, you should set the changed handler back + * to the default when the transaction wanting it is completed. + */ +LWS_VISIBLE LWS_EXTERN void +lws_ss_change_handlers(struct lws_ss_handle *h, + int (*rx)(void *userobj, const uint8_t *buf, size_t len, int flags), + int (*tx)(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, + size_t *len, int *flags), + int (*state)(void *userobj, void *h_src /* ss handle type */, + lws_ss_constate_t state, lws_ss_tx_ordinal_t ack)); /** * lws_ss_add_peer_tx_credit() - allow peer to transmit more to us diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-secure-streams-policy.h libwebsockets-4.1.6/include/libwebsockets/lws-secure-streams-policy.h --- libwebsockets-4.0.20/include/libwebsockets/lws-secure-streams-policy.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-secure-streams-policy.h 2020-12-01 17:40:26.000000000 +0000 @@ -51,6 +51,7 @@ * has the LWSSSPOLF_NAILED_UP flag. */ +#if defined(LWS_WITH_SSPLUGINS) typedef struct lws_ss_plugin { struct lws_ss_plugin *next; const char *name; /**< auth plugin name */ @@ -74,13 +75,14 @@ add http headers) this callback will give it the opportunity to do so */ } lws_ss_plugin_t; - +#endif typedef struct lws_ss_x509 { struct lws_ss_x509 *next; const char *vhost_name; /**< vhost name using cert ctx */ const uint8_t *ca_der; /**< DER x.509 cert */ size_t ca_der_len; /**< length of DER cert */ + uint8_t keep:1; /**< ie, if used in server tls */ } lws_ss_x509_t; enum { @@ -116,13 +118,23 @@ /**< set up lws_system client cert */ LWSSSPOLF_LOCAL_SINK = (1 << 13), /**< expected to bind to a local sink only */ + LWSSSPOLF_WAKE_SUSPEND__VALIDITY = (1 << 14), + /**< this stream's idle validity checks are critical enough we + * should arrange to wake from suspend to perform them + */ + LWSSSPOLF_SERVER = (1 << 15), + /**< we listen on a socket as a server */ + LWSSSPOLF_ALLOW_REDIRECTS = (1 << 16), + /**< follow redirects */ + LWSSSPOLF_HTTP_MULTIPART_IN = (1 << 17), + /**< handle inbound multipart mime at SS level */ }; typedef struct lws_ss_trust_store { struct lws_ss_trust_store *next; const char *name; - lws_ss_x509_t *ssx509[8]; + const lws_ss_x509_t *ssx509[6]; int count; } lws_ss_trust_store_t; @@ -130,6 +142,8 @@ LWSSSP_H1, LWSSSP_H2, LWSSSP_WS, + LWSSSP_MQTT, + LWSSSP_RAW, LWSSS_HBI_AUTH = 0, @@ -179,6 +193,8 @@ union { +#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) || defined(LWS_ROLE_WS) + /* details for http-related protocols... */ struct { @@ -206,8 +222,15 @@ /* false = TEXT, true = BINARY */ } ws; } u; + + uint16_t resp_expect; + uint8_t fail_redirect:1; } http; +#endif + +#if defined(LWS_ROLE_MQTT) + struct { const char *topic; /* stream sends on this topic */ const char *subscribe; /* stream subscribes to this topic */ @@ -223,18 +246,39 @@ } mqtt; +#endif + /* details for non-http related protocols... */ } u; +#if defined(LWS_WITH_SSPLUGINS) const struct lws_ss_plugin *plugins[2]; /**< NULL or auth plugin */ const void *plugins_info[2]; /**< plugin-specific data */ +#endif - const lws_ss_trust_store_t *trust_store; /**< CA certs needed for conn - validation, only set between policy parsing and vhost creation */ + /* + * We're either a client connection policy that wants a trust store, + * or we're a server policy that wants a mem cert and key... Hold + * these mutually-exclusive things in a union. + */ + + union { + const lws_ss_trust_store_t *store; + /**< CA certs needed for conn validation, only set between + * policy parsing and vhost creation */ + struct { + const lws_ss_x509_t *cert; + /**< the server's signed cert with the pubkey */ + const lws_ss_x509_t *key; + /**< the server's matching private key */ + } server; + } trust; const lws_retry_bo_t *retry_bo; /**< retry policy to use */ + uint32_t timeout_ms; /**< default message response + * timeout in ms */ uint32_t flags; /**< stream attribute flags */ uint16_t port; /**< endpoint port */ @@ -244,3 +288,30 @@ uint8_t client_cert; /**< which client cert to apply 0 = none, 1+ = cc 0+ */ } lws_ss_policy_t; + +#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) + +/* + * These only exist / have meaning if there's a dynamic JSON policy enabled + */ + +LWS_VISIBLE LWS_EXTERN int +lws_ss_policy_parse_begin(struct lws_context *context, int overlay); + +LWS_VISIBLE LWS_EXTERN int +lws_ss_policy_parse_abandon(struct lws_context *context); + +LWS_VISIBLE LWS_EXTERN int +lws_ss_policy_parse(struct lws_context *context, const uint8_t *buf, size_t len); + +LWS_VISIBLE LWS_EXTERN int +lws_ss_policy_overlay(struct lws_context *context, const char *overlay); + +/* + * You almost certainly don't want this, it returns the first policy object + * in a linked-list of objects created by lws_ss_policy_parse above + */ +LWS_VISIBLE LWS_EXTERN const lws_ss_policy_t * +lws_ss_policy_get(struct lws_context *context); + +#endif diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-sequencer.h libwebsockets-4.1.6/include/libwebsockets/lws-sequencer.h --- libwebsockets-4.0.20/include/libwebsockets/lws-sequencer.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-sequencer.h 2020-12-01 17:40:26.000000000 +0000 @@ -87,6 +87,8 @@ lws_seq_event_cb cb; /* seq callback */ const char *name; /* seq name */ const lws_retry_bo_t *retry; /* retry policy */ + uint8_t wakesuspend:1; /* important enough to + * wake system */ } lws_seq_info_t; /** diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-service.h libwebsockets-4.1.6/include/libwebsockets/lws-service.h --- libwebsockets-4.0.20/include/libwebsockets/lws-service.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-service.h 2020-12-01 17:40:26.000000000 +0000 @@ -167,7 +167,8 @@ * APIs specific to libuv event loop itegration */ ///@{ -#ifdef LWS_WITH_LIBUV +#if defined(LWS_WITH_LIBUV) && defined(UV_ERRNO_MAP) + /* * Any direct libuv allocations in lws protocol handlers must participate in the * lws reference counting scheme. Two apis are provided: diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-settings.h libwebsockets-4.1.6/include/libwebsockets/lws-settings.h --- libwebsockets-4.0.20/include/libwebsockets/lws-settings.h 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-settings.h 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,112 @@ +/* + * Generic Settings storage + * + * Copyright (C) 2020 Andy Green + * + * 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. + * + * + * This is like an abstract class for non-volatile storage, whether in a file- + * system or flash-backed blocks, etc. Named blobs of variable size are stored + * in nonvolatile media of some sort. Typically, these are JSON objects under + * a naming scheme like, eg, "network". + * + * There's a platform-specific storage identifier opaque_plat provided when the + * storage object is instantiated, this describes eg the storage device or + * partition in instantiation-specific terms. + * + * Blobs have a further "filename" associated with them. + */ + +#define LSOOPEN_FLAG_WRITEABLE (1 << 0) + +struct lws_settings_ops; + +typedef struct { + void *handle_plat; + const struct lws_settings_ops *so; + uint8_t refcount; + void *opaque_plat; +} lws_settings_instance_t; + +typedef struct lws_settings_ops { + int (*get)(lws_settings_instance_t *si, const char *name, + uint8_t *dest, size_t *max_actual); + /**< if dest is NULL, max_actual is set to the actual length without + * copying anything out */ + int (*set)(lws_settings_instance_t *si, const char *name, + const uint8_t *src, size_t len); +} lws_settings_ops_t; + +/** + * lws_settings_plat_get() - read a named blob from a settings instance + * + * \param si: the settings instance + * \param name: the name of the setting blob in the instance + * \param dest: NULL, or the buffer to copy the setting blob info + * \param max_actual: point to size of dest, or zero; actual blob size on exit + * + * If the named blob doesn't exist in the si, or can't read, returns nonzero. + * Otherwise, returns 0 and sets *max_actual to the true blob size. If dest is + * non-NULL, as much of the blob as will fit in the amount specified by + * *max_actual on entry is copied to dest. + */ +LWS_VISIBLE LWS_EXTERN int +lws_settings_plat_get(lws_settings_instance_t *si, const char *name, + uint8_t *dest, size_t *max_actual); + +/** + * lws_settings_plat_get() - read a named blob from a settings instance + * + * \param si: the settings instance + * \param name: the name of the setting blob in the instance + * \param src: blob to copy to settings instance + * \param len: length of blob to copy + * + * Creates or replaces a settings blob of the given name made up of the \p len + * bytes of data from \p src. + */ +LWS_VISIBLE LWS_EXTERN int +lws_settings_plat_set(lws_settings_instance_t *si, const char *name, + const uint8_t *src, size_t len); + +/** + * lws_settings_plat_printf() - read a named blob from a settings instance + * + * \param si: the settings instance + * \param name: the name of the setting blob in the instance + * \param format: printf-style format string + * + * Creates or replaces a settings blob of the given name from the printf-style + * format string and arguments provided. There's no specific limit to the size, + * the size is computed and then a temp heap buffer used. + */ +LWS_VISIBLE LWS_EXTERN int +lws_settings_plat_printf(lws_settings_instance_t *si, const char *name, + const char *format, ...) LWS_FORMAT(3); + +#define lws_settings_ops_plat \ + .get = lws_settings_plat_get, \ + .set = lws_settings_plat_set, + +LWS_VISIBLE LWS_EXTERN lws_settings_instance_t * +lws_settings_init(const lws_settings_ops_t *so, void *opaque_plat); + +LWS_VISIBLE LWS_EXTERN void +lws_settings_deinit(lws_settings_instance_t **si); diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-smd.h libwebsockets-4.1.6/include/libwebsockets/lws-smd.h --- libwebsockets-4.0.20/include/libwebsockets/lws-smd.h 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-smd.h 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,175 @@ +/* + * lws System Message Distribution + * + * Copyright (C) 2010 - 2020 Andy Green + * + * 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. + */ + +#define LWS_SMD_MAX_PAYLOAD 384 +#define LWS_SMD_CLASS_BITFIELD_BYTES 4 + +#define LWS_SMD_STREAMTYPENAME "_lws_smd" +#define LWS_SMD_SS_RX_HEADER_LEN 16 + +typedef uint32_t lws_smd_class_t; + +struct lws_smd_msg; /* opaque */ +struct lws_smd_peer; /* opaque */ + +/* + * Well-known device classes + */ + +enum { + LWSSMDCL_INTERACTION = (1 << 0), + /**< + * Any kind of event indicating a user was interacting with the device, + * eg, press a button, touched the screen, lifted the device etc + */ + LWSSMDCL_SYSTEM_STATE = (1 << 1), + /**< + * The lws_system state changed, eg, to OPERATIONAL + */ + LWSSMDCL_NETWORK = (1 << 2), + /**< + * Something happened on the network, eg, link-up or DHCP, or captive + * portal state update + */ +}; + +/** + * lws_smd_msg_alloc() - allocate a message of length len + * + * \param ctx: the lws_context + * \param _class: the smd message class, recipients filter on this + * \param len: the required payload length + * + * This helper returns an opaque lws_smd_msg pointer and sets *buf to a buffer + * associated with it of length \p len. + * + * In this way the lws_msg_smd type remains completely opaque and the allocated + * area can be prepared by the caller directly, without copying. + * + * On failure, it returns NULL... it may fail for OOM but it may also fail if + * you request to allocate for a message class that the system has no + * participant who is listening for that class of event currently... the event + * generation action at the caller should be bypassed without error then. + * + * This is useful if you have a message you know the length of. For text-based + * messages like JSON, lws_smd_msg_printf() is more convenient. + */ +LWS_VISIBLE LWS_EXTERN void * /* payload */ +lws_smd_msg_alloc(struct lws_context *ctx, lws_smd_class_t _class, size_t len); + +/** + * lws_smd_msg_free() - abandon a previously allocated message before sending + * + * \param payload: pointer the previously-allocated message payload + * + * Destroys a previously-allocated opaque message object and the requested + * buffer space, in the case that between allocating it and sending it, some + * condition was met that means it can no longer be sent, eg, an error + * generating the content. Otherwise there is no need to destroy allocated + * message objects with this, lws will take care of it. + */ +LWS_VISIBLE LWS_EXTERN void +lws_smd_msg_free(void **payload); + +/** + * lws_smd_msg_send() - queue a previously allocated message + * + * \param ctx: the lws_context + * \param msg: the prepared message + * + * Queues an allocated, prepared message for delivery to smd clients + * + * This is threadsafe to call from a non-service thread. + */ +LWS_VISIBLE LWS_EXTERN int +lws_smd_msg_send(struct lws_context *ctx, void *payload); + +/** + * lws_smd_msg_printf() - queue a previously allocated message + * + * \param ctx: the lws_context + * \param _class: the message class + * \param format: the format string to prepare the payload with + * \param ...: arguments for the format string, if any + * + * For string-based messages, eg, JSON, allows formatted creating of the payload + * size discovery, allocation and message send all in one step. + * + * Unlike lws_smd_msg_alloc() you do not need to know the length beforehand as + * this computes it and calls lws_smd_msg_alloc() with the correct length. + * + * To be clear this also calls through to lws_smd_msg_send(), it really does + * everything in one step. If there are no registered participants that want + * messages of \p _class, this function returns immediately without doing any + * allocation or anything else. + * + * This is threadsafe to call from a non-service thread. + */ +LWS_VISIBLE LWS_EXTERN int +lws_smd_msg_printf(struct lws_context *ctx, lws_smd_class_t _class, + const char *format, ...) LWS_FORMAT(3); + +typedef int (*lws_smd_notification_cb_t)(void *opaque, lws_smd_class_t _class, + lws_usec_t timestamp, void *buf, + size_t len); + +#define LWSSMDREG_FLAG_PROXIED_SS (1 << 0) +/**< It's actually a proxied SS connection registering, opaque is the ss h */ + +/* + * lws_smd_register() - register to receive smd messages + * + * \param ctx: the lws_context + * \param opaque: an opaque pointer handed to the callback + * \param flags: typically 0 + * \param _class_filter: bitmap of message classes we care about + * \param cb: the callback to receive messages + * + * Queues an allocated, prepared message for delivery to smd clients. + * + * Returns NULL on failure, or an opaque handle which may be given to + * lws_smd_unregister() to stop participating in the shared message queue. + * + * This is threadsafe to call from a non-service thread. + */ + +LWS_VISIBLE LWS_EXTERN struct lws_smd_peer * +lws_smd_register(struct lws_context *ctx, void *opaque, int flags, + lws_smd_class_t _class_filter, lws_smd_notification_cb_t cb); + +/* + * lws_smd_unregister() - unregister receiving smd messages + * + * \param pr: the handle returned from the registration + * + * Destroys the registration of the callback for messages and ability to send + * messages. + * + * It's not necessary to call this if the registration wants to survive for as + * long as the lws_context... lws_context_destroy will also clean up any + * registrations still active by then. + */ + +LWS_VISIBLE LWS_EXTERN void +lws_smd_unregister(struct lws_smd_peer *pr); diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-spi.h libwebsockets-4.1.6/include/libwebsockets/lws-spi.h --- libwebsockets-4.0.20/include/libwebsockets/lws-spi.h 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-spi.h 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,73 @@ +/* + * Generic I2C ops + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + * This is like an abstract class for spi, a real implementation provides + * functions for the ops that use the underlying OS arrangements. + * + * It uses descriptor / queuing semantics but eg the GPIO BB implementantion is + * synchronous. + */ + +#if !defined(__LWS_SPI_H__) +#define __LWS_SPI_H__ + +#include +#include + +typedef int (*lws_spi_cb_t)(void *opaque); + +enum { + LWSSPIMODE_CPOL = (1 << 0), + LWSSPIMODE_CPHA = (1 << 1), + + LWS_SPI_BUSMODE_CLK_IDLE_LOW_SAMP_RISING = 0, + LWS_SPI_BUSMODE_CLK_IDLE_HIGH_SAMP_RISING = LWSSPIMODE_CPOL, + LWS_SPI_BUSMODE_CLK_IDLE_LOW_SAMP_FALLING = LWSSPIMODE_CPHA, + LWS_SPI_BUSMODE_CLK_IDLE_HIGH_SAMP_FALLING = LWSSPIMODE_CPHA | + LWSSPIMODE_CPOL, + + LWS_SPI_TXN_HALF_DUPLEX_DISCRETE = 0, + /**< separate MISO and MOSI, but only either MISO or MOSI has data at + * one time... i2c style in SPI */ +}; + +typedef struct lws_spi_desc { + const uint8_t *src; + const uint8_t *data; + uint8_t *dest; + void *opaque; + lws_spi_cb_t completion_cb; + uint16_t count_cmd; + uint16_t count_write; + uint16_t count_read; + uint8_t txn_type; + uint8_t channel; +} lws_spi_desc_t; + +typedef struct lws_spi_ops { + int (*init)(const struct lws_spi_ops *ctx); + int (*queue)(const struct lws_spi_ops *ctx, const lws_spi_desc_t *desc); + uint8_t bus_mode; +} lws_spi_ops_t; + +#endif diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-ssd1306-i2c.h libwebsockets-4.1.6/include/libwebsockets/lws-ssd1306-i2c.h --- libwebsockets-4.0.20/include/libwebsockets/lws-ssd1306-i2c.h 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-ssd1306-i2c.h 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,64 @@ +/* + * lws abstract display implementation for ssd1306 on i2c + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + */ + +#if !defined(__LWS_DISPLAY_SSD1306_I2C_H__) +#define __LWS_DISPLAY_SSD1306_I2C_H__ + +/* + * D/C# pin on SSD1306 sets the I2C slave ads + * from these two options (7-bit address) + */ + +#define SSD1306_I2C7_ADS1 0x3c +#define SSD1306_I2C7_ADS2 0x3d + +typedef struct lws_display_ssd1306 { + + lws_display_t disp; /* use lws_display_ssd1306_ops to set ops */ + const lws_i2c_ops_t *i2c; /* i2c ops */ + + const lws_gpio_ops_t *gpio; /* NULL or gpio ops */ + _lws_plat_gpio_t reset_gpio; /* if gpio ops, nReset gpio # */ + + uint8_t i2c7_address; /* one of SSD1306_I2C7_ADS... */ + +} lws_display_ssd1306_t; + +int +lws_display_ssd1306_i2c_init(const struct lws_display *disp); +int +lws_display_ssd1306_i2c_contrast(const struct lws_display *disp, uint8_t b); +int +lws_display_ssd1306_i2c_blit(const struct lws_display *disp, const uint8_t *src, + lws_display_scalar x, lws_display_scalar y, + lws_display_scalar w, lws_display_scalar h); +int +lws_display_ssd1306_i2c_power(const struct lws_display *disp, int state); + +#define lws_display_ssd1306_ops \ + .init = lws_display_ssd1306_i2c_init, \ + .contrast = lws_display_ssd1306_i2c_contrast, \ + .blit = lws_display_ssd1306_i2c_blit, \ + .power = lws_display_ssd1306_i2c_power +#endif diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-state.h libwebsockets-4.1.6/include/libwebsockets/lws-state.h --- libwebsockets-4.0.20/include/libwebsockets/lws-state.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-state.h 2020-12-01 17:40:26.000000000 +0000 @@ -25,6 +25,8 @@ struct lws_state_notify_link; struct lws_state_manager; +#if defined(LWS_WITH_SYS_STATE) + typedef int (*lws_state_notify_t)(struct lws_state_manager *mgr, struct lws_state_notify_link *link, int current, int target); @@ -37,10 +39,14 @@ typedef struct lws_state_manager { lws_dll2_owner_t notify_list; + struct lws_context *context; void *parent; +#if defined(LWS_WITH_SYS_SMD) + lws_smd_class_t smd_class; +#endif /**< optional opaque pointer to owning object... useful to make such * a pointer available to a notification callback. Ignored by lws */ - const char **state_names; /* may be NULL */ + const char **state_names; const char *name; int state; } lws_state_manager_t; @@ -107,3 +113,7 @@ */ LWS_EXTERN LWS_VISIBLE int lws_state_transition(lws_state_manager_t *mgr, int target); + +#else + +#endif diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-struct.h libwebsockets-4.1.6/include/libwebsockets/lws-struct.h --- libwebsockets-4.0.20/include/libwebsockets/lws-struct.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-struct.h 2020-12-01 17:40:26.000000000 +0000 @@ -35,6 +35,7 @@ LSMT_LIST, LSMT_CHILD_PTR, LSMT_SCHEMA, + LSMT_BLOB_PTR, } lws_struct_map_type_eum; @@ -189,6 +190,23 @@ LSMT_SCHEMA \ } +/* + * This is just used to create the table schema, it is not part of serialization + * and deserialization. Blobs should be accessed separately. + */ + +#define LSM_BLOB_PTR(type, blobptr_name, qname) \ + { \ + qname, /* JSON item, or sqlite3 column name */ \ + NULL, \ + NULL, \ + offsetof(type, blobptr_name), /* member that points to blob */ \ + sizeof (((type *)0)->blobptr_name), /* size of blob pointer */ \ + 0, /* member holding blob len */ \ + 0, /* size of blob length member */ \ + LSMT_BLOB_PTR \ + } + typedef struct lws_struct_serialize_st { const struct lws_dll2 *dllpos; const lws_struct_map_t *map; @@ -201,7 +219,8 @@ } lws_struct_serialize_st_t; enum { - LSSERJ_FLAG_PRETTY = 1 + LSSERJ_FLAG_PRETTY = (1 << 0), + LSSERJ_FLAG_OMIT_SCHEMA = (1 << 1) }; typedef struct lws_struct_serialize { @@ -242,7 +261,7 @@ lws_struct_json_serialize(lws_struct_serialize_t *js, uint8_t *buf, size_t len, size_t *written); -#if defined(LWS_WITH_STRUCT_SQLITE3) +typedef struct sqlite3 sqlite3; LWS_VISIBLE LWS_EXTERN int lws_struct_sq3_serialize(sqlite3 *pdb, const lws_struct_map_t *schema, @@ -258,9 +277,8 @@ LWS_VISIBLE LWS_EXTERN int lws_struct_sq3_open(struct lws_context *context, const char *sqlite3_path, - sqlite3 **pdb); + char create_if_missing, sqlite3 **pdb); LWS_VISIBLE LWS_EXTERN int lws_struct_sq3_close(sqlite3 **pdb); -#endif diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-system.h libwebsockets-4.1.6/include/libwebsockets/lws-system.h --- libwebsockets-4.0.20/include/libwebsockets/lws-system.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-system.h 2020-12-01 17:40:26.000000000 +0000 @@ -98,9 +98,24 @@ * can operate normally */ LWS_SYSTATE_IFACE_COLDPLUG, /* existing net ifaces iterated */ LWS_SYSTATE_DHCP, /* at least one net iface configured */ + LWS_SYSTATE_CPD_PRE_TIME, /* Captive portal detect without valid + * time, good for non-https tests... if + * you care about it, implement and + * call lws_system_ops_t + * .captive_portal_detect_request() + * and move the state forward according + * to the result. */ LWS_SYSTATE_TIME_VALID, /* ntpclient ran, or hw time valid... * tls cannot work until we reach here */ + LWS_SYSTATE_CPD_POST_TIME, /* Captive portal detect after time was + * time, good for https tests... if + * you care about it, implement and + * call lws_system_ops_t + * .captive_portal_detect_request() + * and move the state forward according + * to the result. */ + LWS_SYSTATE_POLICY_VALID, /* user code knows how to operate... */ LWS_SYSTATE_REGISTERED, /* device has an identity... */ LWS_SYSTATE_AUTH1, /* identity used for main auth token */ @@ -114,6 +129,16 @@ * LWS_SYSTATE_POLICY_VALID */ } lws_system_states_t; +/* Captive Portal Detect -related */ + +typedef enum { + LWS_CPD_UNKNOWN = 0, /* test didn't happen ince last DHCP acq yet */ + LWS_CPD_INTERNET_OK, /* no captive portal: our CPD test passed OK, + * we can go out on the internet */ + LWS_CPD_CAPTIVE_PORTAL, /* we inferred we're behind a captive portal */ + LWS_CPD_NO_INTERNET, /* we couldn't touch anything */ +} lws_cpd_result_t; + typedef void (*lws_attach_cb_t)(struct lws_context *context, int tsi, void *opaque); struct lws_attach_item; @@ -138,8 +163,20 @@ * __lws_system_attach() is provided to do the actual work inside the * system-specific locking. */ + 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 + */ + + uint32_t wake_latency_us; + /**< time taken for this device to wake from suspend, in us + */ } lws_system_ops_t; +#if defined(LWS_WITH_SYS_STATE) + /** * lws_system_get_state_manager() - return the state mgr object for system state * @@ -151,7 +188,7 @@ LWS_EXTERN LWS_VISIBLE lws_state_manager_t * lws_system_get_state_manager(struct lws_context *context); - +#endif /* wrappers handle NULL members or no ops struct set at all cleanly */ @@ -168,6 +205,8 @@ LWS_EXTERN LWS_VISIBLE const lws_system_ops_t * lws_system_get_ops(struct lws_context *context); +#if defined(LWS_WITH_SYS_STATE) + /** * lws_system_context_from_system_mgr() - return context from system state mgr * @@ -179,6 +218,7 @@ LWS_EXTERN LWS_VISIBLE struct lws_context * lws_system_context_from_system_mgr(lws_state_manager_t *mgr); +#endif /** * __lws_system_attach() - get and set items on context attach list @@ -231,7 +271,7 @@ * Register a network interface as being managed by DHCP. lws will proceed to * try to acquire an IP. Requires LWS_WITH_SYS_DHCP_CLIENT at cmake. */ -int +LWS_EXTERN LWS_VISIBLE int lws_dhcpc_request(struct lws_context *c, const char *i, int af, dhcpc_cb_t cb, void *opaque); @@ -243,7 +283,7 @@ * * Remove handling of the network interface from dhcp. */ -int +LWS_EXTERN LWS_VISIBLE int lws_dhcpc_remove(struct lws_context *context, const char *iface); /** @@ -255,5 +295,42 @@ * Returns 1 if any network interface managed by dhcpc has reached the BOUND * state (has acquired an IP, gateway and DNS server), otherwise 0. */ -int +LWS_EXTERN LWS_VISIBLE int lws_dhcpc_status(struct lws_context *context, lws_sockaddr46 *sa46); + +/** + * lws_system_cpd_start() - helper to initiate captive portal detection + * + * \param context: the lws_context + * + * Resets the context's captive portal state to LWS_CPD_UNKNOWN and calls the + * lws_system_ops_t captive_portal_detect_request() implementation to begin + * testing the captive portal state. + */ +LWS_EXTERN LWS_VISIBLE int +lws_system_cpd_start(struct lws_context *context); + + +/** + * lws_system_cpd_set() - 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 + * + * 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 void +lws_system_cpd_set(struct lws_context *context, lws_cpd_result_t result); + + +/** + * lws_system_cpd_state_get() - returns the last tested captive portal state + * + * \param context: the lws_context + * + * Returns one of the LWS_CPD_ constants indicating the system's understanding + * of the current captive portal situation. + */ +LWS_EXTERN LWS_VISIBLE lws_cpd_result_t +lws_system_cpd_state_get(struct lws_context *context); diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-threadpool.h libwebsockets-4.1.6/include/libwebsockets/lws-threadpool.h --- libwebsockets-4.0.20/include/libwebsockets/lws-threadpool.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-threadpool.h 2020-12-01 17:40:26.000000000 +0000 @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2020 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -71,7 +71,11 @@ }; struct lws_threadpool_task_args { - struct lws *wsi; /**< user must set to wsi task is bound to */ +#if defined(LWS_WITH_SECURE_STREAMS) + struct lws_ss_handle *ss; /**< either wsi or ss must be set */ +#endif + struct lws *wsi; /**< either wsi or ss must be set */ + void *user; /**< user may set (user-private pointer) */ const char *name; /**< user may set to describe task */ char async_task; /**< set to allow the task to shrug off the loss @@ -173,12 +177,21 @@ * This doesn't free the task. It only shortcuts it to state * LWS_TP_STATUS_STOPPED. lws_threadpool_task_status() must be performed on * the task separately once it is in LWS_TP_STATUS_STOPPED to free the task. + * + * DEPRECATED: You should use lws_threadpool_dequeue_task() with + * lws_threadpool_get_task_wsi() / _ss() if you know there can only be one task + * per connection, or call it via lws_threadpool_foreach_task_wsi() / _ss() to + * get the tasks bound to the connection. */ LWS_VISIBLE LWS_EXTERN int -lws_threadpool_dequeue(struct lws *wsi); +lws_threadpool_dequeue(struct lws *wsi) LWS_WARN_DEPRECATED; + +LWS_VISIBLE LWS_EXTERN int +lws_threadpool_dequeue_task(struct lws_threadpool_task *task); + /** - * lws_threadpool_task_status() - Dequeue or try to stop a running task + * lws_threadpool_task_status() - reap completed tasks * * \param wsi: the wsi to query the current task of * \param task: receives a pointer to the opaque task @@ -193,10 +206,21 @@ * * Its use is to make sure the service thread has seen the state of the task * before deleting it. + * + * DEPRECATED... use lws_threadpool_task_status() instead and get the task + * pointer from lws_threadpool_get_task_wsi() / _ss() if you know there can only + * be one, else call it via lws_threadpool_foreach_task_wsi() / _ss() */ LWS_VISIBLE LWS_EXTERN enum lws_threadpool_task_status lws_threadpool_task_status_wsi(struct lws *wsi, - struct lws_threadpool_task **task, void **user); + struct lws_threadpool_task **task, void **user) + LWS_WARN_DEPRECATED; + +LWS_VISIBLE LWS_EXTERN enum lws_threadpool_task_status +lws_threadpool_task_status(struct lws_threadpool_task *task, void **user); + +LWS_VISIBLE LWS_EXTERN enum lws_threadpool_task_status +lws_threadpool_task_status_noreap(struct lws_threadpool_task *task); /** * lws_threadpool_task_sync() - Indicate to a stalled task it may continue @@ -229,4 +253,28 @@ LWS_VISIBLE LWS_EXTERN void lws_threadpool_dump(struct lws_threadpool *tp); + + + +LWS_VISIBLE LWS_EXTERN struct lws_threadpool_task * +lws_threadpool_get_task_wsi(struct lws *wsi); + +#if defined(LWS_WITH_SECURE_STREAMS) +LWS_VISIBLE LWS_EXTERN struct lws_threadpool_task * +lws_threadpool_get_task_ss(struct lws_ss_handle *ss); +#endif + + +LWS_VISIBLE LWS_EXTERN int +lws_threadpool_foreach_task_wsi(struct lws *wsi, void *user, + int (*cb)(struct lws_threadpool_task *task, + void *user)); + +#if defined(LWS_WITH_SECURE_STREAMS) +LWS_VISIBLE LWS_EXTERN int +lws_threadpool_foreach_task_ss(struct lws_ss_handle *ss, void *user, + int (*cb)(struct lws_threadpool_task *task, void *user)); +#endif + + //@} diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-timeout-timer.h libwebsockets-4.1.6/include/libwebsockets/lws-timeout-timer.h --- libwebsockets-4.0.20/include/libwebsockets/lws-timeout-timer.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-timeout-timer.h 2020-12-01 17:40:26.000000000 +0000 @@ -113,6 +113,10 @@ void lws_set_timeout_us(struct lws *wsi, enum pending_timeout reason, lws_usec_t us); +/* helper for clearer LWS_TO_KILL_ASYNC / LWS_TO_KILL_SYNC usage */ +#define lws_wsi_close(w, to_kill) lws_set_timeout(wsi, 1, to_kill) + + #define LWS_SET_TIMER_USEC_CANCEL ((lws_usec_t)-1ll) #define LWS_USEC_PER_SEC ((lws_usec_t)1000000) @@ -146,6 +150,8 @@ LWS_VISIBLE LWS_EXTERN void lws_set_timer_usecs(struct lws *wsi, lws_usec_t usecs); +#if defined(LWS_WITH_DEPRECATED_THINGS) + /* * lws_timed_callback_vh_protocol() - calls back a protocol on a vhost after * the specified delay in seconds @@ -155,6 +161,8 @@ * \param reason: callback reason * \param secs: how many seconds in the future to do the callback. * + * DEPRECATED since v4.1 + * * Callback the specified protocol with a fake wsi pointing to the specified * vhost and protocol, with the specified reason, at the specified time in the * future. @@ -168,7 +176,8 @@ LWS_VISIBLE LWS_EXTERN int lws_timed_callback_vh_protocol(struct lws_vhost *vh, const struct lws_protocols *prot, - int reason, int secs); + int reason, int secs) +LWS_WARN_DEPRECATED; /* * lws_timed_callback_vh_protocol_us() - calls back a protocol on a vhost after @@ -179,6 +188,8 @@ * \param reason: callback reason * \param us: how many us in the future to do the callback. * + * DEPRECATED since v4.1 + * * Callback the specified protocol with a fake wsi pointing to the specified * vhost and protocol, with the specified reason, at the specified time in the * future. @@ -192,7 +203,10 @@ LWS_VISIBLE LWS_EXTERN int lws_timed_callback_vh_protocol_us(struct lws_vhost *vh, const struct lws_protocols *prot, int reason, - lws_usec_t us); + lws_usec_t us) +LWS_WARN_DEPRECATED; + +#endif struct lws_sorted_usec_list; @@ -200,34 +214,117 @@ typedef struct lws_sorted_usec_list { struct lws_dll2 list; /* simplify the code by keeping this at start */ - sul_cb_t cb; lws_usec_t us; + sul_cb_t cb; + uint32_t latency_us; /* us it may safely be delayed */ } lws_sorted_usec_list_t; +/* + * There are multiple sul owners to allow accounting for, a) events that must + * wake from suspend, and b) events that can be missued due to suspend + */ +#define LWS_COUNT_PT_SUL_OWNERS 2 + +#define LWSSULLI_MISS_IF_SUSPENDED 0 +#define LWSSULLI_WAKE_IF_SUSPENDED 1 /* - * lws_sul_schedule() - schedule a callback + * lws_sul2_schedule() - schedule a callback * * \param context: the lws_context * \param tsi: the thread service index (usually 0) + * \param flags: LWSSULLI_... * \param sul: pointer to the sul element - * \param cb: the scheduled callback - * \param us: the delay before the callback arrives, or - * LWS_SET_TIMER_USEC_CANCEL to cancel it. * * Generic callback-at-a-later time function. The callback happens on the * event loop thread context. * * Although the api has us resultion, the actual resolution depends on the - * platform and is commonly 1ms. + * platform and may be, eg, 1ms. * * This doesn't allocate and doesn't fail. * - * You can call it again with another us value to change the delay. + * If flags contains LWSSULLI_WAKE_IF_SUSPENDED, the scheduled event is placed + * on a sul owner list that, if the system has entered low power suspend mode, + * tries to arrange that the system should wake from platform suspend just + * before the event is due. Scheduled events without this flag will be missed + * in the case the system is in suspend and nothing else happens to have woken + * it. + * + * You can call it again with another us value to change the delay or move the + * event to a different owner (ie, wake or miss on suspend). + */ +LWS_VISIBLE LWS_EXTERN void +lws_sul2_schedule(struct lws_context *context, int tsi, int flags, + lws_sorted_usec_list_t *sul); + +/* + * lws_sul_cancel() - cancel scheduled callback + * + * \param sul: pointer to the sul element + * + * If it's scheduled, remove the sul from its owning sorted list. + * If not scheduled, it's a NOP. + */ +LWS_VISIBLE LWS_EXTERN void +lws_sul_cancel(lws_sorted_usec_list_t *sul); + +/* + * lws_sul_earliest_wakeable_event() - get earliest wake-from-suspend event + * + * \param ctx: the lws context + * \param pearliest: pointer to lws_usec_t to take the result + * + * Either returns 1 if no pending event, or 0 and sets *pearliest to the + * MONOTONIC time of the current earliest next expected event. + */ +LWS_VISIBLE LWS_EXTERN int +lws_sul_earliest_wakeable_event(struct lws_context *ctx, lws_usec_t *pearliest); + +/* + * For backwards compatibility + * + * If us is LWS_SET_TIMER_USEC_CANCEL, the sul is removed from the scheduler. + * New code can use lws_sul_cancel() + */ + +LWS_VISIBLE LWS_EXTERN void +lws_sul_schedule(struct lws_context *ctx, int tsi, lws_sorted_usec_list_t *sul, + sul_cb_t _cb, lws_usec_t _us); +LWS_VISIBLE LWS_EXTERN void +lws_sul_schedule_wakesuspend(struct lws_context *ctx, int tsi, + lws_sorted_usec_list_t *sul, sul_cb_t _cb, + lws_usec_t _us); + +#if defined(LWS_WITH_SUL_DEBUGGING) +/** + * lws_sul_debug_zombies() - assert there are no scheduled sul in a given object + * + * \param ctx: lws_context + * \param po: pointer to the object that is about to be destroyed + * \param len: length of the object that is about to be destroyed + * \param destroy_description: string clue what any failure is related to + * + * This is an optional debugging helper that walks the sul scheduler lists + * confirming that there are no suls scheduled that live inside the object + * footprint described by po and len. When internal objects are about to be + * destroyed, like wsi / user_data or secure stream handles, if + * LWS_WITH_SUL_DEBUGGING is enabled the scheduler is checked for anything + * in the object being destroyed. If something found, an error is printed and + * an assert fired. + * + * Internal sul like timeouts should always be cleaned up correctly, but user + * suls in, eg, wsi user_data area, or in secure stream user allocation, may be + * the cause of difficult to find bugs if valgrind not available and the user + * code left a sul in the scheduler after destroying the object the sul was + * living in. */ LWS_VISIBLE LWS_EXTERN void -lws_sul_schedule(struct lws_context *context, int tsi, - lws_sorted_usec_list_t *sul, sul_cb_t cb, lws_usec_t us); +lws_sul_debug_zombies(struct lws_context *ctx, void *po, size_t len, + const char *destroy_description); +#else +#define lws_sul_debug_zombies(_a, _b, _c, _d) +#endif /* * lws_validity_confirmed() - reset the validity timer for a network connection @@ -257,10 +354,9 @@ */ LWS_VISIBLE LWS_EXTERN int -__lws_sul_insert(lws_dll2_owner_t *own, lws_sorted_usec_list_t *sul, - lws_usec_t us); +__lws_sul_insert(lws_dll2_owner_t *own, lws_sorted_usec_list_t *sul); LWS_VISIBLE LWS_EXTERN lws_usec_t -__lws_sul_service_ripe(lws_dll2_owner_t *own, lws_usec_t usnow); +__lws_sul_service_ripe(lws_dll2_owner_t *own, int own_len, lws_usec_t usnow); ///@} diff -Nru libwebsockets-4.0.20/include/libwebsockets/lws-tokenize.h libwebsockets-4.1.6/include/libwebsockets/lws-tokenize.h --- libwebsockets-4.0.20/include/libwebsockets/lws-tokenize.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets/lws-tokenize.h 2020-12-01 17:40:26.000000000 +0000 @@ -192,10 +192,15 @@ * \p exp: the exp object to init * \p priv: the user's object pointer to pass to callback * \p cb: the callback to expand named objects - * \p out: the start of the output buffer + * \p out: the start of the output buffer, or NULL just to get the length * \p olen: the length of the output buffer in bytes * * Prepares an lws_strexp_t for use and sets the initial output buffer + * + * If \p out is NULL, substitution proceeds normally, but no output is produced, + * only the length is returned. olen should be set to the largest feasible + * overall length. To use this mode, the substitution callback must also check + * for NULL \p out and avoid producing the output. */ LWS_VISIBLE LWS_EXTERN void lws_strexp_init(lws_strexp_t *exp, void *priv, lws_strexp_expand_cb cb, @@ -205,12 +210,17 @@ * lws_strexp_reset_out() - reset the output buffer on an existing strexp * * \p exp: the exp object to init - * \p out: the start of the output buffer + * \p out: the start of the output buffer, or NULL to just get length * \p olen: the length of the output buffer in bytes * * Provides a new output buffer for lws_strexp_expand() to continue to write * into. It can be the same as the old one if it has been copied out or used. * The position of the next write will be reset to the start of the given buf. + * + * If \p out is NULL, substitution proceeds normally, but no output is produced, + * only the length is returned. \p olen should be set to the largest feasible + * overall length. To use this mode, the substitution callback must also check + * for NULL \p out and avoid producing the output. */ LWS_VISIBLE LWS_EXTERN void lws_strexp_reset_out(lws_strexp_t *exp, char *out, size_t olen); diff -Nru libwebsockets-4.0.20/include/libwebsockets.h libwebsockets-4.1.6/include/libwebsockets.h --- libwebsockets-4.0.20/include/libwebsockets.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/include/libwebsockets.h 2020-12-01 17:40:26.000000000 +0000 @@ -147,6 +147,10 @@ #endif #endif +#if defined(__FreeBSD__) +#include +#endif + #if defined(__GNUC__) /* warn_unused_result attribute only supported by GCC 3.4 or later */ @@ -173,22 +177,6 @@ #endif -#if defined(LWS_WITH_LIBEV) -#include -#endif /* LWS_WITH_LIBEV */ -#ifdef LWS_WITH_LIBUV -#include -#ifdef LWS_HAVE_UV_VERSION_H -#include -#endif -#ifdef LWS_HAVE_NEW_UV_VERSION_H -#include -#endif -#endif /* LWS_WITH_LIBUV */ -#if defined(LWS_WITH_LIBEVENT) -#include -#endif /* LWS_WITH_LIBEVENT */ - #ifndef LWS_EXTERN #define LWS_EXTERN extern #endif @@ -202,6 +190,18 @@ #endif #endif +#if defined(LWS_WITH_LIBUV_INTERNAL) +#include + +#ifdef LWS_HAVE_UV_VERSION_H +#include +#endif + +#ifdef LWS_HAVE_NEW_UV_VERSION_H +#include +#endif +#endif + #if defined(LWS_WITH_TLS) #ifdef USE_WOLFSSL @@ -243,9 +243,11 @@ #define MBEDTLS_CONFIG_FILE #endif #endif +#if defined(LWS_WITH_TLS) #include #include #include +#endif #else #include #if !defined(LWS_WITH_MBEDTLS) @@ -343,23 +345,17 @@ lws_sockfd_type fd; /**< file descriptor */ SHORT events; /**< which events to respond to */ SHORT revents; /**< which events happened */ + uint8_t write_blocked; }; #define LWS_POLLHUP (FD_CLOSE) #define LWS_POLLIN (FD_READ | FD_ACCEPT) #define LWS_POLLOUT (FD_WRITE) -#if !defined(pid_t) -#define pid_t int -#endif - #else #if defined(LWS_PLAT_FREERTOS) #include -#if defined(LWS_WITH_ESP32) -#include -#endif #else typedef int lws_sockfd_type; typedef int lws_filefd_type; @@ -535,6 +531,9 @@ #include #include +#if defined(LWS_WITH_SYS_SMD) +#include +#endif #include #include #include @@ -546,8 +545,9 @@ #include #include #include -#include + #include + #if defined(LWS_ROLE_MQTT) #include #endif @@ -609,6 +609,21 @@ #endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #ifdef __cplusplus } #endif diff -Nru libwebsockets-4.0.20/lib/abstract/CMakeLists.txt libwebsockets-4.1.6/lib/abstract/CMakeLists.txt --- libwebsockets-4.0.20/lib/abstract/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/abstract/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,57 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +list(APPEND SOURCES + abstract/abstract.c +) +if (LWS_WITH_SEQUENCER) + list(APPEND SOURCES + abstract/test-sequencer.c) +endif() + +list(APPEND SOURCES + abstract/transports/unit-test.c) + +#if (LWS_WITH_SMTP) +# list(APPEND SOURCES +# abstract/protocols/smtp/smtp.c +# abstract/protocols/smtp/smtp-sequencer.c +# ) +#endif() + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() + diff -Nru libwebsockets-4.0.20/lib/CMakeLists.txt libwebsockets-4.1.6/lib/CMakeLists.txt --- libwebsockets-4.0.20/lib/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,357 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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_directories(.) + +macro(add_subdir_include_dirs arg1) + add_subdirectory(${arg1}) + list(APPEND LWS_LIB_BUILD_INC_PATHS ${_CMAKE_INC_LIST}) +endmacro() + +set(LWS_LIB_INCLUDES "") + +# +# Plat specific build items +# + +if (LWS_PLAT_FREERTOS) + add_subdir_include_dirs(plat/freertos) + if (ESP_PLATFORM) + include_directories($ENV{IDF_PATH}/components/freertos/include + $ENV{IDF_PATH}/components/freertos/xtensa/include + $ENV{IDF_PATH}/components/xtensa/include + $ENV{IDF_PATH}/components/xtensa/esp32/include + $ENV{IDF_PATH}/components/esp_common/include + $ENV{IDF_PATH}/components/esp_timer/include + $ENV{IDF_PATH}/components/soc/include + $ENV{IDF_PATH}/components/soc/src/esp32/include + $ENV{IDF_PATH}/components/lwip/port/esp32/include + $ENV{IDF_PATH}/components/lwip/lwip/src/include + $ENV{IDF_PATH}/components/lwip/port/esp32/include + ${CMAKE_BINARY_DIR}/config + $ENV{IDF_PATH}/components/esp_rom/include + $ENV{IDF_PATH}/components/esp_system/include + $ENV{IDF_PATH}/components/lwip/include/apps/sntp + $ENV{IDF_PATH}/components/soc/soc/esp32/include + $ENV{IDF_PATH}/components/heap/include + $ENV{IDF_PATH}/components/mbedtls/mbedtls/include + $ENV{IDF_PATH}/components/mbedtls/port/include + $ENV{IDF_PATH}/components/esp_wifi/include + $ENV{IDF_PATH}/components/esp_event/include + $ENV{IDF_PATH}/components/esp_netif/include + $ENV{IDF_PATH}/components/esp_eth/include + $ENV{IDF_PATH}/components/driver/include + $ENV{IDF_PATH}/components/soc/soc/include + $ENV{IDF_PATH}/components/tcpip_adapter/include + $ENV{IDF_PATH}/components/lwip/include/apps + $ENV{IDF_PATH}/components/nvs_flash/include + $ENV{IDF_PATH}/components/esp32/include + $ENV{IDF_PATH}/components/spi_flash/include + $ENV{IDF_PATH}/components/mdns/include + $ENV{IDF_PATH}/components/lwip/lwip/src/include/lwip + $ENV{IDF_PATH}/components/lwip/lwip/src/include + $ENV{IDF_PATH}/components/lwip/lwip/src/include/lwip + $ENV{IDF_PATH}/components/newlib/platform_include ) + endif() + +else() + if (LWS_PLAT_OPTEE) + add_subdir_include_dirs(plat/optee) + else() + if (WIN32) + add_subdir_include_dirs(plat/windows) + else() + add_subdir_include_dirs(plat/unix) + endif() + endif() +endif() + +if (LIB_LIST) + set(CMAKE_REQUIRED_LIBRARIES ${LIB_LIST} ${CMAKE_REQUIRED_LIBRARIES}) +endif() + +if (LWS_WITH_ZLIB) + if (LWS_WITH_BUNDLED_ZLIB) + if (WIN32) + # it's trying to delete internal zlib entry + LIST(REMOVE_AT CMAKE_REQUIRED_LIBRARIES 0 ) + endif() + endif() +endif() + + +# ideally we want to use pipe2() + +CHECK_C_SOURCE_COMPILES("#define _GNU_SOURCE\n#include \nint main(void) {int fd[2];\n return pipe2(fd, 0);\n}\n" LWS_HAVE_PIPE2) + +# tcp keepalive needs this on linux to work practically... but it only exists +# after kernel 2.6.37 + +CHECK_C_SOURCE_COMPILES("#include \nint main(void) { return TCP_USER_TIMEOUT; }\n" LWS_HAVE_TCP_USER_TIMEOUT) + +if (LWS_WITH_TLS) + add_subdir_include_dirs(tls) +endif() + +# 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") + +add_subdir_include_dirs(core) +add_subdir_include_dirs(misc) +add_subdir_include_dirs(system) + +if (LWS_WITH_DRIVERS) + add_subdir_include_dirs(drivers) +endif() + +if (LWS_WITH_NETWORK) + add_subdir_include_dirs(core-net) + if (LWS_WITH_ABSTRACT) + add_subdir_include_dirs(abstract) + endif() + add_subdir_include_dirs(roles) +endif() + +if (LWS_WITH_JOSE) + add_subdir_include_dirs(jose) +endif() + +if (LWS_WITH_SECURE_STREAMS) + add_subdir_include_dirs(secure-streams) +endif() + +add_subdir_include_dirs(event-libs) + +if (LWS_WITH_STATIC) + if (LWS_STATIC_PIC) + set(CMAKE_POSITION_INDEPENDENT_CODE ON) + endif() + + add_library(websockets STATIC ${SOURCES})# ${HDR_PUBLIC}) + set_target_properties(websockets PROPERTIES LINKER_LANGUAGE C) + list(APPEND LWS_LIBRARIES websockets) + target_include_directories(websockets PRIVATE ${LWS_LIB_BUILD_INC_PATHS}) + + if (WIN32) + # Windows uses the same .lib ending for static libraries and shared + # library linker files, so rename the static library. + set_target_properties(websockets + PROPERTIES + OUTPUT_NAME websockets_static) + endif() + +endif() + +if (LWS_WITH_SHARED) + if (NOT RESOURCES) + set(RESOURCES "") + endif() + + add_library(websockets_shared SHARED ${SOURCES} ${RESOURCES})# ${HDR_PUBLIC}) + set_target_properties(websockets_shared PROPERTIES LINKER_LANGUAGE C) + list(APPEND LWS_LIBRARIES websockets_shared) + target_include_directories(websockets_shared PRIVATE ${LWS_LIB_BUILD_INC_PATHS}) + + # We want the shared lib to be named "libwebsockets" + # not "libwebsocket_shared". + set_target_properties(websockets_shared + PROPERTIES + OUTPUT_NAME websockets) + + if (WIN32) + # Compile as DLL (export function declarations) + set_property( + TARGET websockets_shared + PROPERTY COMPILE_DEFINITIONS + LWS_DLL + LWS_INTERNAL) + endif() + + if (APPLE) + set_property(TARGET websockets_shared PROPERTY MACOSX_RPATH YES) + endif() + + if (UNIX AND LWS_WITH_PLUGINS_API) + set (CMAKE_POSITION_INDEPENDENT_CODE ON) + if (NOT((${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") OR + (${CMAKE_SYSTEM_NAME} MATCHES "QNX"))) + if (LWS_WITH_SHARED) + target_link_libraries(websockets_shared dl) + endif() + endif() + endif() + +endif() + +# +# expose the library private include dirs to plugins, test apps etc that are +# 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() + + +# Set the so version of the lib. +# Equivalent to LDFLAGS=-version-info x:x:x + +if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR COMPILER_IS_CLANG) + foreach(lib ${LWS_LIBRARIES}) + set_target_properties(${lib} + PROPERTIES + SOVERSION ${SOVERSION}) + endforeach() +endif() + + +# Setup the linking for all libs. +foreach (lib ${LWS_LIBRARIES}) + target_link_libraries(${lib} ${LIB_LIST}) +endforeach() + +# +# These will be available to parent projects including libwebsockets +# using add_subdirectory() +# +set(LIBWEBSOCKETS_LIBRARIES ${LWS_LIBRARIES} CACHE STRING "Libwebsocket libraries") +if (LWS_WITH_STATIC) + set(LIBWEBSOCKETS_LIBRARIES_STATIC websockets CACHE STRING "Libwebsocket static library") +endif() +if (LWS_WITH_SHARED) + set(LIBWEBSOCKETS_LIBRARIES_SHARED websockets_shared CACHE STRING "Libwebsocket shared library") +endif() + +# 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) + + #set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries" PARENT_SCOPE) +set(CPACK_COMPONENT_DEV_DISPLAY_NAME "Development files" PARENT_SCOPE) + + +if (UNIX) + +# figure out pkfcfg required libs here + +set(lws_requires "") +if (LWS_HAVE_LIBCAP) + if (NOT lws_requires STREQUAL "") + set(lws_requires "${lws_requires},libcap") + else() + set(lws_requires "libcap") + endif() +endif() + + +# Generate and install pkgconfig. +# (This is not indented, because the tabs will be part of the output) +file(WRITE "${PROJECT_BINARY_DIR}/libwebsockets.pc" +"prefix=\"${CMAKE_INSTALL_PREFIX}\" +exec_prefix=\${prefix} +libdir=\${exec_prefix}/lib${LIB_SUFFIX} +includedir=\${prefix}/include + +Name: libwebsockets +Description: Websockets server and client library +Version: ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH} + +Libs: -L\${libdir} -lwebsockets +Cflags: -I\${includedir} +" +) +if (NOT ${lws_requires} STREQUAL "") + file(APPEND "${PROJECT_BINARY_DIR}/libwebsockets.pc" "Requires: ${lws_requires}") +endif() + + + install(FILES "${PROJECT_BINARY_DIR}/libwebsockets.pc" + DESTINATION lib${LIB_SUFFIX}/pkgconfig) + +file(WRITE "${PROJECT_BINARY_DIR}/libwebsockets_static.pc" +"prefix=\"${CMAKE_INSTALL_PREFIX}\" +exec_prefix=\${prefix} +libdir=\${exec_prefix}/lib${LIB_SUFFIX} +includedir=\${prefix}/include + +Name: libwebsockets_static +Description: Websockets server and client static library +Version: ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH} + +Libs: -L\${libdir} -lwebsockets_static +Libs.private: +Cflags: -I\${includedir} +" +) + +if (NOT ${lws_requires} STREQUAL "") + file(APPEND "${PROJECT_BINARY_DIR}/libwebsockets_static.pc" "Requires: ${lws_requires}") +endif() + + + install(FILES "${PROJECT_BINARY_DIR}/libwebsockets_static.pc" + DESTINATION lib${LIB_SUFFIX}/pkgconfig) + +endif(UNIX) + + +# Keep explicit parent scope exports at end +# + +export_to_parent_intermediate() +if (DEFINED LWS_PLAT_UNIX) + set(LWS_PLAT_UNIX ${LWS_PLAT_UNIX} PARENT_SCOPE) + if (ILLUMOS) + add_definitions("-D__illumos__") + endif() +endif() +set(LWS_HAVE_MBEDTLS_NET_SOCKETS ${LWS_HAVE_MBEDTLS_NET_SOCKETS} PARENT_SCOPE) +set(TEST_SERVER_SSL_KEY "${TEST_SERVER_SSL_KEY}" PARENT_SCOPE) +set(TEST_SERVER_SSL_CERT "${TEST_SERVER_SSL_CERT}" PARENT_SCOPE) +set(TEST_SERVER_DATA ${TEST_SERVER_DATA} PARENT_SCOPE) +set(LWS_HAVE_PIPE2 ${LWS_HAVE_PIPE2} PARENT_SCOPE) +set(LWS_LIBRARIES ${LWS_LIBRARIES} PARENT_SCOPE) +if (DEFINED WIN32_HELPERS_PATH) + set(WIN32_HELPERS_PATH ${WIN32_HELPERS_PATH} PARENT_SCOPE) +endif() +if (DEFINED HDR_PRIVATE) +set(HDR_PRIVATE ${HDR_PRIVATE} PARENT_SCOPE) +endif() +if (DEFINED ZLIB_FOUND) + set(ZLIB_FOUND ${ZLIB_FOUND} PARENT_SCOPE) +endif() +if (DEFINED LIB_LIST_AT_END) +set(LIB_LIST_AT_END ${LIB_LIST_AT_END} PARENT_SCOPE) +endif() +set(USE_WOLFSSL ${USE_WOLFSSL} PARENT_SCOPE) +set(LWS_DEPS_LIB_PATHS ${LWS_DEPS_LIB_PATHS} PARENT_SCOPE) + diff -Nru libwebsockets-4.0.20/lib/core/alloc.c libwebsockets-4.1.6/lib/core/alloc.c --- libwebsockets-4.0.20/lib/core/alloc.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/core/alloc.c 2020-12-01 17:40:26.000000000 +0000 @@ -111,7 +111,7 @@ if (size) { #if defined(LWS_PLAT_FREERTOS) - lwsl_notice("%s: size %lu: %s (free heap %d)\n", __func__, + lwsl_debug("%s: size %lu: %s (free heap %d)\n", __func__, #if defined(LWS_AMAZON_RTOS) (unsigned long)size, reason, (unsigned int)xPortGetFreeHeapSize() - (int)size); #else diff -Nru libwebsockets-4.0.20/lib/core/CMakeLists.txt libwebsockets-4.1.6/lib/core/CMakeLists.txt --- libwebsockets-4.0.20/lib/core/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/core/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,41 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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_directories(.) + +list(APPEND SOURCES + core/alloc.c + core/buflist.c + core/context.c + core/lws_dll2.c + core/libwebsockets.c + core/logs.c +) + +if (LWS_WITH_FILE_OPS) + list(APPEND SOURCES core/vfs.c) +endif() + +exports_to_parent_scope() + diff -Nru libwebsockets-4.0.20/lib/core/context.c libwebsockets-4.1.6/lib/core/context.c --- libwebsockets-4.0.20/lib/core/context.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/core/context.c 2020-12-01 17:40:26.000000000 +0000 @@ -28,7 +28,12 @@ #define LWS_BUILD_HASH "unknown-build-hash" #endif -static const char *library_version = LWS_LIBRARY_VERSION " " LWS_BUILD_HASH; +static const char *library_version = LWS_LIBRARY_VERSION; + +#if defined(LWS_HAVE_SYS_RESOURCE_H) +/* for setrlimit */ +#include +#endif #if defined(LWS_WITH_NETWORK) /* in ms */ @@ -57,7 +62,8 @@ lws_stats_log_dump(pt->context); - __lws_sul_insert(&pt->pt_sul_owner, &pt->sul_stats, 10 * LWS_US_PER_SEC); + __lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], + &pt->sul_stats, 10 * LWS_US_PER_SEC); } #endif #if defined(LWS_WITH_PEER_LIMITS) @@ -69,20 +75,24 @@ lws_peer_cull_peer_wait_list(pt->context); - __lws_sul_insert(&pt->pt_sul_owner, &pt->sul_peer_limits, 10 * LWS_US_PER_SEC); + __lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], + &pt->sul_peer_limits, 10 * LWS_US_PER_SEC); } #endif #if defined(LWS_WITH_NETWORK) -#if defined(_DEBUG) +#if defined(LWS_WITH_SYS_STATE) + static const char * system_state_names[] = { "undef", "CONTEXT_CREATED", "INITIALIZED", "IFACE_COLDPLUG", "DHCP", + "CPD_PRE_TIME", "TIME_VALID", + "CPD_POST_TIME", "POLICY_VALID", "REGISTERED", "AUTH1", @@ -90,7 +100,7 @@ "OPERATIONAL", "POLICY_INVALID" }; -#endif + /* * Handle provoking protocol init when we pass through the right system state @@ -103,6 +113,9 @@ { struct lws_context *context = lws_container_of(mgr, struct lws_context, mgr_system); +#if defined(LWS_WITH_SECURE_STREAMS) && defined(LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM) + lws_system_blob_t *ab0, *ab1; +#endif int n; /* @@ -125,20 +138,29 @@ } #endif -#if defined(LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM) +#if defined(LWS_WITH_SYS_NTPCLIENT) + if (target == LWS_SYSTATE_TIME_VALID && + lws_now_secs() < 1594017754) /* 06:42 Mon Jul 6 2020 UTC */ { + lws_ntpc_trigger(context); + + return 1; + } +#endif + +#if defined(LWS_WITH_SECURE_STREAMS) && defined(LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM) /* * Skip this if we are running something without the policy for it * * If root token is empty, skip too. */ + + ab0 = lws_system_get_blob(context, LWS_SYSBLOB_TYPE_AUTH, 0); + ab1 = lws_system_get_blob(context, LWS_SYSBLOB_TYPE_AUTH, 1); + if (target == LWS_SYSTATE_AUTH1 && - context->pss_policies && - !lws_system_blob_get_size(lws_system_get_blob(context, - LWS_SYSBLOB_TYPE_AUTH, - 0)) && - lws_system_blob_get_size(lws_system_get_blob(context, - LWS_SYSBLOB_TYPE_AUTH, - 1))) { + context->pss_policies && ab0 && ab1 && + !lws_system_blob_get_size(ab0) && + lws_system_blob_get_size(ab1)) { lwsl_info("%s: AUTH1 state triggering api.amazon.com auth\n", __func__); /* * Start trying to acquire it if it's not already in progress @@ -150,6 +172,24 @@ #endif #if defined(LWS_WITH_SECURE_STREAMS) +#if defined(LWS_WITH_DRIVERS) + /* + * See if we should do the SS Captive Portal Detection + */ + if (target == LWS_SYSTATE_CPD_PRE_TIME) { + if (lws_system_cpd_state_get(context) == LWS_CPD_INTERNET_OK) + return 0; /* allow it */ + + /* + * Don't allow it to move past here until we get an IP and + * CPD passes, driven by SMD + */ + + return 1; + } +#endif + +#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) /* * Skip this if we are running something without the policy for it */ @@ -163,6 +203,7 @@ return 1; } #endif +#endif /* protocol part */ @@ -173,9 +214,8 @@ return 0; lwsl_info("%s: doing protocol init on POLICY_VALID\n", __func__); - lws_protocol_init(context); - return 0; + return lws_protocol_init(context); } static void @@ -188,12 +228,132 @@ lws_state_transition_steps(&context->mgr_system, LWS_SYSTATE_OPERATIONAL); } +#endif /* WITH_SYS_STATE */ + +#if defined(LWS_WITH_SYS_SMD) +static int +lws_system_smd_cb(void *opaque, lws_smd_class_t _class, lws_usec_t timestamp, + void *buf, size_t len) +{ + struct lws_context *cx = (struct lws_context *)opaque; + + if (_class != LWSSMDCL_NETWORK) + return 0; + + /* something external requested CPD check */ + + if (!lws_json_simple_strcmp(buf, len, "\"trigger\":", "cpdcheck")) + lws_system_cpd_start(cx); + else + /* + * IP acquisition on any interface triggers captive portal + * check on default route + */ + if (!lws_json_simple_strcmp(buf, len, "\"type\":", "ipacq")) + lws_system_cpd_start(cx); + +#if defined(LWS_WITH_SYS_NTPCLIENT) + /* + * Captive portal detect showing internet workable triggers NTP Client + */ + if (!lws_json_simple_strcmp(buf, len, "\"type\":", "cps") && + !lws_json_simple_strcmp(buf, len, "\"result\":", "OK") && + lws_now_secs() < 1594017754) /* 06:42 Mon Jul 6 2020 UTC */ + lws_ntpc_trigger(cx); +#endif + +#if defined(LWS_WITH_SYS_DHCP_CLIENT) + /* + * Any network interface linkup triggers DHCP + */ + if (!lws_json_simple_strcmp(buf, len, "\"type\":", "linkup")) + lws_ntpc_trigger(cx); + +#endif + +#if defined(LWS_WITH_DRIVERS) && defined(LWS_WITH_NETWORK) + lws_netdev_smd_cb(opaque, _class, timestamp, buf, len); +#endif + + return 0; +} +#endif + + + +#endif /* NETWORK */ + +#if !defined(LWS_WITH_NO_LOGS) + +static const char * const opts_str = +#if defined(LWS_WITH_NETWORK) + "NET " +#else + "NoNET " +#endif +#if defined(LWS_WITH_CLIENT) + "CLI " +#endif +#if defined(LWS_WITH_SERVER) + "SRV " +#endif +#if defined(LWS_ROLE_H1) + "H1 " +#endif +#if defined(LWS_ROLE_H2) + "H2 " +#endif +#if defined(LWS_ROLE_WS) + "WS " +#endif +#if defined(LWS_ROLE_MQTT) + "MQTT " +#endif +#if defined(LWS_WITH_SECURE_STREAMS) && !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) + "SS-JSON-POL " +#endif +#if defined(LWS_WITH_SECURE_STREAMS) && defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) + "SS-STATIC-POL " +#endif +#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) + "SSPROX " +#endif +#if defined(LWS_WITH_SYS_ASYNC_DNS) + "ASYNC_DNS " +#endif +#if defined(LWS_WITH_SYS_NTPCLIENT) + "NTPCLIENT " +#endif +#if defined(LWS_WITH_SYS_DHCP_CLIENT) + "DHCP_CLIENT " +#endif +; + +#endif + +#if defined(LWS_WITH_EVLIB_PLUGINS) && defined(LWS_WITH_EVENT_LIBS) +static const struct lws_evlib_map { + uint64_t flag; + const char *name; +} map[] = { + { LWS_SERVER_OPTION_LIBUV, "evlib_uv" }, + { LWS_SERVER_OPTION_LIBEVENT, "evlib_event" }, + { LWS_SERVER_OPTION_GLIB, "evlib_glib" }, + { LWS_SERVER_OPTION_LIBEV, "evlib_ev" }, +}; +static const char * const dlist[] = { + LWS_INSTALL_LIBDIR, + NULL +}; #endif struct lws_context * lws_create_context(const struct lws_context_creation_info *info) { struct lws_context *context = NULL; +#if !defined(LWS_WITH_NO_LOGS) + const char *s = "IPv6-absent"; +#endif #if defined(LWS_WITH_FILE_OPS) struct lws_plat_file_ops *prev; #endif @@ -201,14 +361,28 @@ pid_t pid_daemon = get_daemonize_pid(); #endif #if defined(LWS_WITH_NETWORK) - int n, count_threads = 1; + int count_threads = 1; uint8_t *u; #endif #if defined(__ANDROID__) struct rlimit rt; #endif - size_t s1 = 4096, size = sizeof(struct lws_context); - int lpf = info->fd_limit_per_thread; + size_t +#if defined(LWS_PLAT_FREERTOS) + /* smaller default, can set in info->pt_serv_buf_size */ + s1 = 2048, +#else + s1 = 4096, +#endif + size = sizeof(struct lws_context); + int n, lpf = info->fd_limit_per_thread; + const lws_plugin_evlib_t *plev = NULL; +#if defined(LWS_WITH_EVLIB_PLUGINS) && defined(LWS_WITH_EVENT_LIBS) + struct lws_plugin *evlib_plugin_list = NULL; +#endif +#if defined(LWS_WITH_LIBUV) + char fatal_exit_defer = 0; +#endif if (lpf) { lpf+= 2; @@ -223,30 +397,21 @@ #endif } - lwsl_info("Initial logging level %d\n", log_level); - lwsl_info("Libwebsockets version: %s\n", library_version); + lwsl_notice("LWS: %s, loglevel %d\n", library_version, log_level); -#ifdef LWS_WITH_IPV6 +#if defined(LWS_WITH_IPV6) && !defined(LWS_WITH_NO_LOGS) if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DISABLE_IPV6)) - lwsl_info("IPV6 compiled in and enabled\n"); + s = "IPV6-on"; else - lwsl_info("IPV6 compiled in but disabled\n"); -#else - lwsl_info("IPV6 not compiled in\n"); + s = "IPV6-off"; #endif - lwsl_info(" LWS_DEF_HEADER_LEN : %u\n", LWS_DEF_HEADER_LEN); - lwsl_info(" LWS_MAX_SMP : %u\n", LWS_MAX_SMP); - lwsl_info(" sizeof (*info) : %ld\n", (long)sizeof(*info)); #if defined(LWS_WITH_STATS) lwsl_info(" LWS_WITH_STATS : on\n"); #endif - lwsl_info(" SYSTEM_RANDOM_FILEPATH: '%s'\n", SYSTEM_RANDOM_FILEPATH); -#if defined(LWS_WITH_HTTP2) - lwsl_info(" HTTP2 support : available\n"); -#else - lwsl_info(" HTTP2 support : not configured\n"); -#endif + + lwsl_notice("%s%s\n", opts_str, s); + if (lws_plat_context_early_init()) return NULL; @@ -261,7 +426,112 @@ s1 = info->pt_serv_buf_size; /* pt fakewsi and the pt serv buf allocations ride after the context */ - size += count_threads * (s1 + sizeof(struct lws)); + size += count_threads * s1; +#if !defined(LWS_PLAT_FREERTOS) + size += (count_threads * sizeof(struct lws)); +#endif +#endif /* network */ + +#if defined(LWS_WITH_POLL) + { + extern const lws_plugin_evlib_t evlib_poll; + plev = &evlib_poll; + } +#endif + +#if defined(LWS_WITH_EVLIB_PLUGINS) && defined(LWS_WITH_EVENT_LIBS) + + /* + * New style dynamically loaded event lib support + * + * We have to pick and load the event lib plugin before we allocate + * the context object, so we can overallocate it correctly + */ + + lwsl_info("%s: ev lib path %s\n", __func__, LWS_INSTALL_LIBDIR); + + for (n = 0; n < (int)LWS_ARRAY_SIZE(map); n++) { + if (!lws_check_opt(info->options, map[n].flag)) + continue; + + if (lws_plugins_init(&evlib_plugin_list, + dlist, "lws_evlib_plugin", + map[n].name, NULL, NULL)) { + lwsl_err("%s: failed to load %s\n", __func__, + map[n].name); + goto bail; + } + +#if defined(LWS_WITH_LIBUV) + if (!n) /* libuv */ + fatal_exit_defer = !!info->foreign_loops; +#endif + + if (!evlib_plugin_list) { + lwsl_err("%s: unable to load evlib plugin %s\n", + __func__, map[n].name); + + goto bail; + } + plev = (const lws_plugin_evlib_t *)evlib_plugin_list->hdr; + break; + } +#else +#if defined(LWS_WITH_EVENT_LIBS) + /* + * set the context event loops ops struct + * + * after this, all event_loop actions use the generic ops + */ + + /* + * oldstyle built-in event lib support + * + * We have composed them into the libwebsockets lib itself, we can + * just pick the ops we want and done + */ + +#if defined(LWS_WITH_LIBUV) + if (lws_check_opt(info->options, LWS_SERVER_OPTION_LIBUV)) { + extern const lws_plugin_evlib_t evlib_uv; + plev = &evlib_uv; + fatal_exit_defer = !!info->foreign_loops; + } +#endif + +#if defined(LWS_WITH_LIBEVENT) + if (lws_check_opt(info->options, LWS_SERVER_OPTION_LIBEVENT)) { + extern const lws_plugin_evlib_t evlib_event; + plev = &evlib_event; + } +#endif + +#if defined(LWS_WITH_GLIB) + if (lws_check_opt(info->options, LWS_SERVER_OPTION_GLIB)) { + extern const lws_plugin_evlib_t evlib_glib; + plev = &evlib_glib; + } +#endif + +#if defined(LWS_WITH_LIBEV) + if (lws_check_opt(info->options, LWS_SERVER_OPTION_LIBEV)) { + extern const lws_plugin_evlib_t evlib_ev; + plev = &evlib_ev; + } +#endif + +#endif /* with event libs */ + +#endif /* not with ev plugins */ + + if (!plev) + goto fail_event_libs; + +#if defined(LWS_WITH_NETWORK) + size += (size_t)plev->ops->evlib_size_ctx /* the ctx evlib priv */ + + (count_threads * (size_t)plev->ops->evlib_size_pt) /* the pt evlib priv */; + + lwsl_info("Event loop: %s\n", plev->ops->name); #endif context = lws_zalloc(size, "context"); @@ -270,12 +540,28 @@ return NULL; } +#if defined(LWS_WITH_NETWORK) + context->event_loop_ops = plev->ops; +#endif +#if defined(LWS_WITH_EVENT_LIBS) + /* at the very end */ + context->evlib_ctx = (uint8_t *)context + size - + plev->ops->evlib_size_ctx; +#endif +#if defined(LWS_WITH_EVLIB_PLUGINS) && defined(LWS_WITH_EVENT_LIBS) + context->evlib_plugin_list = evlib_plugin_list; +#endif + +#if !defined(LWS_PLAT_FREERTOS) context->uid = info->uid; context->gid = info->gid; context->username = info->username; context->groupname = info->groupname; +#endif context->system_ops = info->system_ops; context->pt_serv_buf_size = (unsigned int)s1; + +#if defined(LWS_WITH_UDP) context->udp_loss_sim_tx_pc = info->udp_loss_sim_tx_pc; context->udp_loss_sim_rx_pc = info->udp_loss_sim_rx_pc; @@ -283,12 +569,19 @@ lwsl_warn("%s: simulating udp loss tx: %d%%, rx: %d%%\n", __func__, context->udp_loss_sim_tx_pc, context->udp_loss_sim_rx_pc); +#endif + +#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) + /* directly use the user-provided policy object list */ + context->pss_policies = info->pss_policies; +#endif #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) context->ss_proxy_bind = info->ss_proxy_bind; context->ss_proxy_port = info->ss_proxy_port; context->ss_proxy_address = info->ss_proxy_address; - lwsl_notice("%s: using ss proxy bind '%s', port %d, ads '%s'\n", + if (context->ss_proxy_bind && context->ss_proxy_address) + lwsl_notice("%s: using ss proxy bind '%s', port %d, ads '%s'\n", __func__, context->ss_proxy_bind, context->ss_proxy_port, context->ss_proxy_address); #endif @@ -300,22 +593,25 @@ context->detailed_latency_filepath = info->detailed_latency_filepath; context->latencies_fd = -1; #endif -#if defined(LWS_WITHOUT_EXTENSIONS) +#if defined(LWS_ROLE_WS) && defined(LWS_WITHOUT_EXTENSIONS) if (info->extensions) lwsl_warn("%s: LWS_WITHOUT_EXTENSIONS but extensions ptr set\n", __func__); #endif -#endif +#endif /* network */ #if defined(LWS_WITH_SECURE_STREAMS) +#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) context->pss_policies_json = info->pss_policies_json; +#endif +#if defined(LWS_WITH_SSPLUGINS) context->pss_plugins = info->pss_plugins; #endif +#endif /* if he gave us names, set the uid / gid */ if (lws_plat_drop_app_privileges(context, 0)) goto bail; - lwsl_info("context created\n"); #if defined(LWS_WITH_TLS) && defined(LWS_WITH_NETWORK) #if defined(LWS_WITH_MBEDTLS) context->tls_ops = &tls_ops_mbedtls; @@ -380,11 +676,27 @@ #endif context->pcontext_finalize = info->pcontext; +#if defined(LWS_WITH_TLS) && defined(LWS_WITH_NETWORK) context->simultaneous_ssl_restriction = info->simultaneous_ssl_restriction; +#endif context->options = info->options; +#if !defined(LWS_PLAT_FREERTOS) && !defined(LWS_PLAT_OPTEE) && !defined(WIN32) + /* + * If asked, try to set the rlimit / ulimit for process sockets / files. + * We read the effective limit in a moment, so we will find out the + * real limit according to system constraints then. + */ + if (info->rlimit_nofile) { + struct rlimit rl; + + rl.rlim_cur = rl.rlim_max = info->rlimit_nofile; + setrlimit(RLIMIT_NOFILE, &rl); + } +#endif + #ifndef LWS_NO_DAEMONIZE if (pid_daemon) { context->started_with_parent = pid_daemon; @@ -396,20 +708,31 @@ if (n == -1) { lwsl_err("Get RLIMIT_NOFILE failed!\n"); - return NULL; + goto free_context_fail; } context->max_fds = rt.rlim_cur; #else -#if defined(WIN32) || defined(_WIN32) || defined(LWS_AMAZON_RTOS) +#if defined(WIN32) || defined(_WIN32) || defined(LWS_AMAZON_RTOS) || defined(LWS_ESP_PLATFORM) context->max_fds = getdtablesize(); #else - context->max_fds = sysconf(_SC_OPEN_MAX); + { + long l = sysconf(_SC_OPEN_MAX); + + context->max_fds = 2560; + + if (l > 10000000) + lwsl_warn("%s: unreasonable ulimit -n workaround\n", + __func__); + else + if (l != -1l) + context->max_fds = (int)l; + } #endif if (context->max_fds < 0) { lwsl_err("%s: problem getting process max files\n", __func__); - return NULL; + goto free_context_fail; } #endif @@ -427,53 +750,10 @@ } } - context->token_limits = info->token_limits; - #if defined(LWS_WITH_NETWORK) - - /* - * set the context event loops ops struct - * - * after this, all event_loop actions use the generic ops - */ - -#if defined(LWS_WITH_POLL) - context->event_loop_ops = &event_loop_ops_poll; -#endif - - if (lws_check_opt(context->options, LWS_SERVER_OPTION_LIBUV)) -#if defined(LWS_WITH_LIBUV) - context->event_loop_ops = &event_loop_ops_uv; -#else - goto fail_event_libs; -#endif - - if (lws_check_opt(context->options, LWS_SERVER_OPTION_LIBEV)) -#if defined(LWS_WITH_LIBEV) - context->event_loop_ops = &event_loop_ops_ev; -#else - goto fail_event_libs; -#endif - - if (lws_check_opt(context->options, LWS_SERVER_OPTION_LIBEVENT)) -#if defined(LWS_WITH_LIBEVENT) - context->event_loop_ops = &event_loop_ops_event; -#else - goto fail_event_libs; -#endif - - if (lws_check_opt(context->options, LWS_SERVER_OPTION_GLIB)) -#if defined(LWS_WITH_GLIB) - context->event_loop_ops = &event_loop_ops_glib; -#else - goto fail_event_libs; + context->token_limits = info->token_limits; #endif - if (!context->event_loop_ops) - goto fail_event_libs; - - lwsl_info("Using event loop: %s\n", context->event_loop_ops->name); -#endif #if defined(LWS_WITH_TLS) && defined(LWS_WITH_NETWORK) time(&context->tls.last_cert_check_s); @@ -497,18 +777,15 @@ context->tls.alpn_default = context->tls.alpn_discovered; } - lwsl_info("Default ALPN advertisment: %s\n", context->tls.alpn_default); #endif - +#if defined(LWS_WITH_NETWORK) if (info->timeout_secs) context->timeout_secs = info->timeout_secs; else - context->timeout_secs = AWAITING_TIMEOUT; - - context->ws_ping_pong_interval = info->ws_ping_pong_interval; - - lwsl_info(" default timeout (secs): %u\n", context->timeout_secs); +#endif + context->timeout_secs = 5; +#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) if (info->max_http_header_data) context->max_http_header_data = info->max_http_header_data; else @@ -526,7 +803,7 @@ info->max_http_header_pool2; else context->max_http_header_pool = context->max_fds; - +#endif if (info->fd_limit_per_thread) context->fd_limit_per_thread = lpf; @@ -535,6 +812,28 @@ context->fd_limit_per_thread = context->max_fds / context->count_threads; +#if defined(LWS_WITH_SYS_SMD) + lws_mutex_init(context->smd.lock_messages); + lws_mutex_init(context->smd.lock_peers); + + /* lws_system smd participant */ + + if (!lws_smd_register(context, context, 0, LWSSMDCL_NETWORK, + lws_system_smd_cb)) { + lwsl_err("%s: early smd register failed\n", __func__); + } + + /* user smd participant */ + + if (info->early_smd_cb && + !lws_smd_register(context, info->early_smd_opaque, 0, + info->early_smd_class_filter, + info->early_smd_cb)) { + lwsl_err("%s: early smd register failed\n", __func__); + } +#endif + + n = 0; #if defined(LWS_WITH_NETWORK) context->default_retry.retry_ms_table = default_backoff_table; @@ -565,6 +864,7 @@ context->pt[n].context = context; context->pt[n].tid = n; +#if !defined(LWS_PLAT_FREERTOS) /* * We overallocated for a fakewsi (can't compose it in the * pt because size isn't known at that time). point to it @@ -576,6 +876,12 @@ u += sizeof(struct lws); memset(context->pt[n].fake_wsi, 0, sizeof(struct lws)); +#endif + +#if defined(LWS_WITH_EVENT_LIBS) + context->pt[n].evlib_pt = u; + u += plev->ops->evlib_size_pt; +#endif #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) context->pt[n].http.ah_list = NULL; @@ -597,9 +903,6 @@ #endif } - lwsl_info(" Threads: %d each %d fds\n", context->count_threads, - context->fd_limit_per_thread); - if (!info->ka_interval && info->ka_time > 0) { lwsl_err("info->ka_interval can't be 0 if ka_time used\n"); return NULL; @@ -618,19 +921,7 @@ context->ip_limit_ah = info->ip_limit_ah; context->ip_limit_wsi = info->ip_limit_wsi; -#endif - - lwsl_info(" mem: context: %5lu B (%ld ctx + (%ld thr x %d))\n", - (long)sizeof(struct lws_context) + - (context->count_threads * context->pt_serv_buf_size), - (long)sizeof(struct lws_context), - (long)context->count_threads, - context->pt_serv_buf_size); -#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) - lwsl_info(" mem: http hdr size: (%u + %lu), max count %u\n", - context->max_http_header_data, - (long)sizeof(struct allocated_headers), - context->max_http_header_pool); + context->pl_notify_cb = info->pl_notify_cb; #endif /* @@ -644,8 +935,24 @@ lwsl_err("OOM allocating %d fds\n", context->max_fds); goto bail; } - lwsl_info(" mem: pollfd map: %5u B\n", n); #endif + + lwsl_info(" ctx: %5luB (%ld ctx + pt(%ld thr x %d)), " + "pt-fds: %d, fdmap: %d\n", + (long)sizeof(struct lws_context) + + (context->count_threads * context->pt_serv_buf_size), + (long)sizeof(struct lws_context), + (long)context->count_threads, + context->pt_serv_buf_size, + context->fd_limit_per_thread, n); + +#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) + lwsl_info(" http: ah_data: %u, ah: %lu, max count %u\n", + context->max_http_header_data, + (long)sizeof(struct allocated_headers), + context->max_http_header_pool); +#endif + #if defined(LWS_WITH_SERVER) if (info->server_string) { context->server_string = info->server_string; @@ -661,13 +968,19 @@ context->fd_limit_per_thread; #endif + + /* + * Past here, we may have added handles to the event lib + * loop and if libuv, have to take care about how to unpick them... + */ + if (lws_plat_init(context, info)) - goto bail; + goto bail_libuv_aware; #if defined(LWS_WITH_NETWORK) if (context->event_loop_ops->init_context) if (context->event_loop_ops->init_context(context, info)) - goto bail; + goto bail_libuv_aware; if (context->event_loop_ops->init_pt) @@ -678,11 +991,11 @@ lp = info->foreign_loops[n]; if (context->event_loop_ops->init_pt(context, lp, n)) - goto bail; + goto bail_libuv_aware; } if (lws_create_event_pipes(context)) - goto bail; + goto bail_libuv_aware; #endif lws_context_init_ssl_library(info); @@ -698,13 +1011,13 @@ #if defined(LWS_WITH_STATS) context->pt[0].sul_stats.cb = lws_sul_stats_cb; - __lws_sul_insert(&context->pt[0].pt_sul_owner, &context->pt[0].sul_stats, - 10 * LWS_US_PER_SEC); + __lws_sul_insert_us(&context->pt[0].pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], + &context->pt[0].sul_stats, 10 * LWS_US_PER_SEC); #endif #if defined(LWS_WITH_PEER_LIMITS) context->pt[0].sul_peer_limits.cb = lws_sul_peer_limits_cb; - __lws_sul_insert(&context->pt[0].pt_sul_owner, - &context->pt[0].sul_peer_limits, 10 * LWS_US_PER_SEC); + __lws_sul_insert_us(&context->pt[0].pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], + &context->pt[0].sul_peer_limits, 10 * LWS_US_PER_SEC); #endif #if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP) @@ -755,34 +1068,38 @@ if (!vh) { lwsl_err("%s: failed to create system vhost\n", __func__); - goto bail; + goto bail_libuv_aware; } context->vhost_system = vh; if (lws_protocol_init_vhost(vh, NULL)) { lwsl_err("%s: failed to init system vhost\n", __func__); - goto bail; + goto bail_libuv_aware; } #if defined(LWS_WITH_SYS_ASYNC_DNS) if (lws_async_dns_init(context)) - goto bail; + goto bail_libuv_aware; #endif } #endif +#if defined(LWS_WITH_SYS_STATE) /* * init the lws_state mgr for the system state */ -#if defined(_DEBUG) - context->mgr_system.state_names = system_state_names; + + context->mgr_system.state_names = system_state_names; + context->mgr_system.name = "system"; + context->mgr_system.state = LWS_SYSTATE_CONTEXT_CREATED; + context->mgr_system.parent = context; + context->mgr_system.context = context; +#if defined(LWS_WITH_SYS_SMD) + context->mgr_system.smd_class = LWSSMDCL_SYSTEM_STATE; #endif - context->mgr_system.name = "system"; - context->mgr_system.state = LWS_SYSTATE_CONTEXT_CREATED; - context->mgr_system.parent = context; - context->protocols_notify.name = "prot_init"; - context->protocols_notify.notify_cb = lws_state_notify_protocol_init; + context->protocols_notify.name = "prot_init"; + context->protocols_notify.notify_cb = lws_state_notify_protocol_init; lws_state_reg_notifier(&context->mgr_system, &context->protocols_notify); @@ -794,6 +1111,7 @@ lws_state_reg_notifier_list(&context->mgr_system, info->register_notifier_list); +#endif /* * if he's not saying he'll make his own vhosts later then act @@ -811,6 +1129,7 @@ #if defined(LWS_WITH_SECURE_STREAMS) +#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) if (context->pss_policies_json) { /* * You must create your context with the explicit vhosts flag @@ -819,21 +1138,31 @@ assert(lws_check_opt(info->options, LWS_SERVER_OPTION_EXPLICIT_VHOSTS)); - if (lws_ss_policy_parse_begin(context)) - goto bail; + if (lws_ss_policy_parse_begin(context, 0)) + goto bail_libuv_aware; n = lws_ss_policy_parse(context, (uint8_t *)context->pss_policies_json, strlen(context->pss_policies_json)); if (n != LEJP_CONTINUE && n < 0) - goto bail; + goto bail_libuv_aware; if (lws_ss_policy_set(context, "hardcoded")) { lwsl_err("%s: policy set failed\n", __func__); - goto bail; + goto bail_libuv_aware; } } else - lws_create_vhost(context, info); +#else + if (context->pss_policies) { + /* user code set the policy objects directly, no parsing step */ + + if (lws_ss_policy_set(context, "hardcoded")) { + lwsl_err("%s: policy set failed\n", __func__); + goto bail_libuv_aware; + } + } //else +#endif + // lws_create_vhost(context, info); #endif lws_context_init_extensions(info, context); @@ -848,8 +1177,9 @@ */ if (!lws_check_opt(info->options, LWS_SERVER_OPTION_EXPLICIT_VHOSTS)) if (lws_plat_drop_app_privileges(context, 1)) - goto bail; + goto bail_libuv_aware; +#if defined(LWS_WITH_SYS_STATE) /* * We want to move on the syste, state as far as it can go towards * OPERATIONAL now. But we have to return from here first so the user @@ -861,6 +1191,7 @@ lws_sul_schedule(context, 0, &context->sul_system_state, lws_context_creation_completion_cb, 1); +#endif /* expedite post-context init (eg, protocols) */ lws_cancel_service(context); @@ -870,6 +1201,14 @@ #if defined(LWS_WITH_NETWORK) fail_clean_pipes: + +#if defined(LWS_WITH_LIBUV) + if (fatal_exit_defer) { + lws_context_destroy(context); + return context; + } +#endif + for (n = 0; n < context->count_threads; n++) lws_destroy_event_pipe(context->pt[n].pipe_wsi); @@ -885,28 +1224,83 @@ return NULL; -#if defined(LWS_WITH_NETWORK) +bail_libuv_aware: + lws_context_destroy(context); +#if defined(LWS_WITH_LIBUV) + return fatal_exit_defer ? context : NULL; +#else + return NULL; +#endif + fail_event_libs: - lwsl_err("Requested event library support not configured, available:\n"); - { - extern const struct lws_event_loop_ops *available_event_libs[]; - const struct lws_event_loop_ops **elops = available_event_libs; + lwsl_err("Requested event library support not configured\n"); - while (*elops) { - lwsl_err(" - %s\n", (*elops)->name); - elops++; - } - } -#endif +free_context_fail: lws_free(context); return NULL; } +#if defined(LWS_WITH_NETWORK) +int +lws_system_cpd_start(struct lws_context *cx) +{ + cx->captive_portal_detect = LWS_CPD_UNKNOWN; + + /* if there's a platform implementation, use it */ + + if (lws_system_get_ops(cx) && + lws_system_get_ops(cx)->captive_portal_detect_request) + return lws_system_get_ops(cx)->captive_portal_detect_request(cx); + +#if defined(LWS_WITH_SECURE_STREAMS) + /* + * Otherwise try to use SS "captive_portal_detect" if that's enabled + */ + return lws_ss_sys_cpd(cx); +#else + return 0; +#endif +} + +static const char *cname[] = { "Unknown", "OK", "Captive", "No internet" }; + +void +lws_system_cpd_set(struct lws_context *cx, lws_cpd_result_t result) +{ + if (cx->captive_portal_detect != LWS_CPD_UNKNOWN) + return; + + lwsl_notice("%s: setting CPD result %s\n", __func__, cname[result]); + + cx->captive_portal_detect = (uint8_t)result; + +#if defined(LWS_WITH_SYS_STATE) +#if defined(LWS_WITH_SYS_SMD) + lws_smd_msg_printf(cx, LWSSMDCL_NETWORK, + "{\"type\":\"cpd\",\"result\":\"%s\"}", + cname[cx->captive_portal_detect]); +#endif + + /* if nothing is there to intercept anything, go all the way */ + if (cx->mgr_system.state != LWS_SYSTATE_POLICY_INVALID) + lws_state_transition_steps(&cx->mgr_system, + LWS_SYSTATE_OPERATIONAL); +#endif +} + +lws_cpd_result_t +lws_system_cpd_state_get(struct lws_context *cx) +{ + return (lws_cpd_result_t)cx->captive_portal_detect; +} + +#endif + int -lws_context_is_deprecated(struct lws_context *context) +lws_context_is_deprecated(struct lws_context *cx) { - return context->deprecated; + return cx->deprecated; } /* @@ -973,6 +1367,10 @@ #endif } +#if defined(LWS_WITH_SYS_SMD) + _lws_smd_destroy(context); +#endif + #if defined(LWS_WITH_SYS_ASYNC_DNS) lws_async_dns_deinit(&context->async_dns); #endif @@ -994,8 +1392,26 @@ lws_system_blob_destroy( lws_system_get_blob(context, n, 0)); +#if LWS_MAX_SMP > 1 + lws_mutex_refcount_destroy(&context->mr); +#endif + + /* drop any lingering deferred vhost frees */ + + while (context->deferred_free_list) { + struct lws_deferred_free *df = context->deferred_free_list; + + context->deferred_free_list = df->next; + lws_free(df); + }; + +#if defined(LWS_WITH_EVLIB_PLUGINS) && defined(LWS_WITH_EVENT_LIBS) + if (context->evlib_plugin_list) + lws_plugins_destroy(&context->evlib_plugin_list, NULL, NULL); +#endif + lws_free(context); - lwsl_info("%s: ctx %p freed\n", __func__, context); + lwsl_debug("%s: ctx %p freed\n", __func__, context); if (pcontext_finalize) *pcontext_finalize = NULL; @@ -1035,9 +1451,19 @@ #if defined(LWS_WITH_SECURE_STREAMS) lws_dll2_foreach_safe(&pt->ss_owner, NULL, lws_ss_destroy_dll); +#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) + + while (context->server_der_list) { + struct lws_ss_x509 *x = context->server_der_list; + + context->server_der_list = x->next; + lws_free((void *)x->ca_der); + } + if (context->ac_policy) lwsac_free(&context->ac_policy); #endif +#endif #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) lws_dll2_foreach_safe(&pt->ss_client_owner, NULL, lws_sspc_destroy_dll); @@ -1125,14 +1551,14 @@ 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++) if (context->pt[n].inside_service) { lwsl_debug("%p: bailing as inside service\n", __func__); return; } - } +// } #endif lws_context_destroy3(context); @@ -1157,8 +1583,10 @@ } vpt->foreign_pfd_list = NULL; + lws_pt_lock(pt, __func__); if (pt->pipe_wsi) lws_destroy_event_pipe(pt->pipe_wsi); + lws_pt_unlock(pt); pt->pipe_wsi = NULL; while (pt->fds_count) { @@ -1225,7 +1653,9 @@ context->being_destroyed = 1; #if defined(LWS_WITH_NETWORK) +#if defined(LWS_WITH_SYS_STATE) lws_state_transition(&context->mgr_system, LWS_SYSTATE_POLICY_INVALID); +#endif m = context->count_threads; while (m--) { @@ -1314,12 +1744,14 @@ #endif } +#if defined(LWS_WITH_SYS_STATE) struct lws_context * lws_system_context_from_system_mgr(lws_state_manager_t *mgr) { #if defined(LWS_WITH_NETWORK) - return lws_container_of(mgr, struct lws_context, mgr_system); + return mgr->context; #else return NULL; #endif } +#endif diff -Nru libwebsockets-4.0.20/lib/core/libwebsockets.c libwebsockets-4.1.6/lib/core/libwebsockets.c --- libwebsockets-4.0.20/lib/core/libwebsockets.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/core/libwebsockets.c 2020-12-01 17:40:26.000000000 +0000 @@ -27,6 +27,7 @@ #ifdef LWS_HAVE_SYS_TYPES_H #include #endif +#include void lws_ser_wu16be(uint8_t *b, uint16_t u) @@ -152,6 +153,27 @@ return lws_ptr_diff(dest, odest); } +static char *hexch = "0123456789abcdef"; + +int +lws_hex_random(struct lws_context *context, char *dest, size_t len) +{ + size_t n = (len - 1) / 2; + uint8_t b, *r = (uint8_t *)dest + len - n; + + if (lws_get_random(context, r, n) != n) + return 1; + + while (n--) { + b = *r++; + *dest++ = hexch[b >> 4]; + *dest++ = hexch[b & 0xf]; + } + + *dest = '\0'; + + return 0; +} #if !defined(LWS_PLAT_OPTEE) @@ -344,6 +366,114 @@ return d; } +const char * +lws_nstrstr(const char *buf, size_t len, const char *name, size_t nl) +{ + const char *end = buf + len - nl + 1; + size_t n; + + if (nl > len) + /* it cannot be found if the needle is longer than the haystack */ + return NULL; + + while (buf < end) { + if (*buf != name[0]) { + buf++; + continue; + } + + if (nl == 1) + /* single char match, we are done */ + return buf; + + if (buf[nl - 1] == name[nl - 1]) { + /* + * This is looking interesting then... the first + * and last chars match, let's check the insides + */ + n = 1; + while (n < nl && buf[n] == name[n]) + n++; + + if (n == nl) + /* it's a hit */ + return buf; + } + + buf++; + } + + return NULL; +} + +/* + * name wants to be something like "\"myname\":" + */ + +const char * +lws_json_simple_find(const char *buf, size_t len, const char *name, size_t *alen) +{ + size_t nl = strlen(name); + const char *np = lws_nstrstr(buf, len, name, nl), + *end = buf + len, *as; + int qu = 0; + + if (!np) + return NULL; + + np += nl; + + while (np < end && (*np == ' ' || *np == '\t')) + np++; + + if (np >= end) + return NULL; + + /* + * The arg could be lots of things after "name": with JSON, commonly a + * string like "mystring", true, false, null, [...] or {...} ... we want + * to handle common, simple cases cheaply with this; the user can choose + * a full JSON parser like lejp if it's complicated. So if no opening + * quote, return until a terminator like , ] }. If there's an opening + * quote, return until closing quote, handling escaped quotes. + */ + + if (*np == '\"') { + qu = 1; + np++; + } + + as = np; + while (np < end && + (!qu || *np != '\"') && /* end quote is EOT if quoted */ + (qu || (*np != '}' && *np != ']' && *np != ',')) /* delimiters */ + ) { + if (qu && *np == '\\') /* skip next char if quoted escape */ + np++; + np++; + } + + *alen = lws_ptr_diff(np, as); + + return as; +} + +int +lws_json_simple_strcmp(const char *buf, size_t len, const char *name, + const char *comp) +{ + size_t al; + const char *hit = lws_json_simple_find(buf, len, name, &al); + + if (!hit) + return -1; + + if (al != strlen(comp)) + return -1; + + return strncmp(hit, comp, al); +} + static const char *hex = "0123456789ABCDEF"; const char * @@ -413,7 +543,14 @@ continue; } - if (*p == '\"' || *p == '\\' || *p < 0x20) { + if (*p == '\\') { + p++; + *q++ = '\\'; + *q++ = '\\'; + continue; + } + + if (*p == '\"' || *p < 0x20) { *q++ = '\\'; *q++ = 'u'; *q++ = '0'; @@ -469,7 +606,9 @@ } if (*filename == ':' || +#if !defined(WIN32) *filename == '\\' || +#endif *filename == '$' || *filename == '%') *filename = '_'; @@ -567,12 +706,14 @@ return 0; } +#if !defined(LWS_PLAT_FREERTOS) void lws_get_effective_uid_gid(struct lws_context *context, int *uid, int *gid) { *uid = context->uid; *gid = context->gid; } +#endif int lws_snprintf(char *str, size_t size, const char *format, ...) @@ -926,7 +1067,9 @@ break; } - exp->out[exp->pos++] = *in; + if (exp->out) + exp->out[exp->pos] = *in; + exp->pos++; if (exp->olen - exp->pos < 1) { *pused_in = used + 1; *pused_out = exp->pos; @@ -945,8 +1088,11 @@ if (exp->olen - exp->pos < 3) return -1; - exp->out[exp->pos++] = '$'; - exp->out[exp->pos++] = *in; + if (exp->out) { + exp->out[exp->pos++] = '$'; + exp->out[exp->pos++] = *in; + } else + exp->pos += 2; if (*in != '$') exp->state = LWS_EXPS_LITERAL; break; @@ -981,7 +1127,8 @@ in++; } - exp->out[exp->pos] = '\0'; + if (exp->out) + exp->out[exp->pos] = '\0'; *pused_in = used; *pused_out = exp->pos; @@ -1047,6 +1194,12 @@ pthread_mutex_unlock(&mr->lock); } +void +lws_mutex_refcount_assert_held(struct lws_mutex_refcount *mr) +{ + assert(mr->lock_owner == pthread_self() && mr->lock_depth); +} + #endif /* SMP */ @@ -1076,10 +1229,20 @@ static const char * const builtins[] = { "-d", +#if defined(LWS_WITH_UDP) "--udp-tx-loss", - "--udp-rx-loss" + "--udp-rx-loss", +#endif + "--ignore-sigterm" }; +#if !defined(LWS_PLAT_FREERTOS) +static void +lws_sigterm_catch(int sig) +{ +} +#endif + void lws_cmdline_option_handle_builtin(int argc, const char **argv, struct lws_context_creation_info *info) @@ -1098,12 +1261,21 @@ case 0: logs = m; break; +#if defined(LWS_WITH_UDP) case 1: info->udp_loss_sim_tx_pc = m; break; case 2: info->udp_loss_sim_rx_pc = m; break; + case 3: +#else + case 1: +#endif +#if !defined(LWS_PLAT_FREERTOS) + signal(SIGTERM, lws_sigterm_catch); +#endif + break; } } diff -Nru libwebsockets-4.0.20/lib/core/logs.c libwebsockets-4.1.6/lib/core/logs.c --- libwebsockets-4.0.20/lib/core/logs.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/core/logs.c 2020-12-01 17:40:26.000000000 +0000 @@ -162,7 +162,8 @@ #if !(defined(LWS_PLAT_OPTEE) && !defined(LWS_WITH_NETWORK)) void _lws_logv(int filter, const char *format, va_list vl) { -#if LWS_MAX_SMP == 1 +#if LWS_MAX_SMP == 1 && !defined(LWS_WITH_THREADPOOL) + /* this is incompatible with multithreaded logging */ static char buf[256]; #else char buf[1024]; diff -Nru libwebsockets-4.0.20/lib/core/lws_dll2.c libwebsockets-4.1.6/lib/core/lws_dll2.c --- libwebsockets-4.0.20/lib/core/lws_dll2.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/core/lws_dll2.c 2020-12-01 17:40:26.000000000 +0000 @@ -209,6 +209,25 @@ lws_dll2_add_tail(d, own); } +void * +_lws_dll2_search_sz_pl(lws_dll2_owner_t *own, const char *name, size_t namelen, + size_t dll2_ofs, size_t ptr_ofs) +{ + lws_start_foreach_dll(struct lws_dll2 *, p, lws_dll2_get_head(own)) { + uint8_t *ref = ((uint8_t *)p) - dll2_ofs; + /* + * We have to read the const char * at the computed place and + * the string is where that points + */ + const char *str = *((const char **)(ref + ptr_ofs)); + + if (str && !strncmp(str, name, namelen) && !str[namelen]) + return (void *)ref; + } lws_end_foreach_dll(p); + + return NULL; +} + #if defined(_DEBUG) void diff -Nru libwebsockets-4.0.20/lib/core/lws_dll.c libwebsockets-4.1.6/lib/core/lws_dll.c --- libwebsockets-4.0.20/lib/core/lws_dll.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/core/lws_dll.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,248 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * 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" - -#ifdef LWS_HAVE_SYS_TYPES_H -#include -#endif - -void -lws_dll_add_head(struct lws_dll *d, struct lws_dll *phead) -{ - if (!lws_dll_is_detached(d, phead)) { - assert(0); /* only wholly detached things can be added */ - return; - } - - /* our next guy is current first guy, if any */ - if (phead->next != d) - d->next = phead->next; - - /* if there is a next guy, set his prev ptr to our next ptr */ - if (d->next) - d->next->prev = d; - /* there is nobody previous to us, we are the head */ - d->prev = NULL; - - /* set the first guy to be us */ - phead->next = d; - - /* if there was nothing on the list before, we are also now the tail */ - if (!phead->prev) - phead->prev = d; - - assert(d->prev != d); - assert(d->next != d); -} - -void -lws_dll_add_tail(struct lws_dll *d, struct lws_dll *phead) -{ - if (!lws_dll_is_detached(d, phead)) { - assert(0); /* only wholly detached things can be added */ - return; - } - - /* our previous guy is current last guy */ - d->prev = phead->prev; - /* if there is a prev guy, set his next ptr to our prev ptr */ - if (d->prev) - d->prev->next = d; - /* our next ptr is NULL */ - d->next = NULL; - /* set the last guy to be us */ - phead->prev = d; - - /* list head is also us if we're the first */ - if (!phead->next) - phead->next = d; - - assert(d->prev != d); - assert(d->next != d); -} - -void -lws_dll_insert(struct lws_dll *n, struct lws_dll *target, - struct lws_dll *phead, int before) -{ - if (!lws_dll_is_detached(n, phead)) { - assert(0); /* only wholly detached things can be inserted */ - return; - } - if (!target) { - /* - * the case where there's no target identified degenerates to - * a simple add at head or tail - */ - if (before) { - lws_dll_add_head(n, phead); - return; - } - lws_dll_add_tail(n, phead); - return; - } - - /* - * in the case there's a target "cursor", we have to do the work to - * stitch the new guy in appropriately - */ - - if (before) { - /* - * we go before dd - * DDp <-> DD <-> DDn --> DDp <-> us <-> DD <-> DDn - */ - /* we point forward to dd */ - n->next = target; - /* we point back to what dd used to point back to */ - n->prev = target->prev; - /* DDp points forward to us now */ - if (target->prev) - target->prev->next = n; - /* DD points back to us now */ - target->prev = n; - - /* if target was the head, we are now the head */ - if (phead->next == target) - phead->next = n; - - /* since we are before another guy, we cannot become the tail */ - - } else { - /* - * we go after dd - * DDp <-> DD <-> DDn --> DDp <-> DD <-> us <-> DDn - */ - /* we point forward to what dd used to point forward to */ - n->next = target->next; - /* we point back to dd */ - n->prev = target; - /* DDn points back to us */ - if (target->next) - target->next->prev = n; - /* DD points forward to us */ - target->next = n; - - /* if target was the tail, we are now the tail */ - if (phead->prev == target) - phead->prev = n; - - /* since we go after another guy, we cannot become the head */ - } -} - -/* situation is: - * - * HEAD: struct lws_dll * = &entry1 - * - * Entry 1: struct lws_dll .pprev = &HEAD , .next = Entry 2 - * Entry 2: struct lws_dll .pprev = &entry1 , .next = &entry2 - * Entry 3: struct lws_dll .pprev = &entry2 , .next = NULL - * - * Delete Entry1: - * - * - HEAD = &entry2 - * - Entry2: .pprev = &HEAD, .next = &entry3 - * - Entry3: .pprev = &entry2, .next = NULL - * - * Delete Entry2: - * - * - HEAD = &entry1 - * - Entry1: .pprev = &HEAD, .next = &entry3 - * - Entry3: .pprev = &entry1, .next = NULL - * - * Delete Entry3: - * - * - HEAD = &entry1 - * - Entry1: .pprev = &HEAD, .next = &entry2 - * - Entry2: .pprev = &entry1, .next = NULL - * - */ - -void -lws_dll_remove(struct lws_dll *d) -{ - if (!d->prev && !d->next) - return; - - /* - * remove us - * - * USp <-> us <-> USn --> USp <-> USn - */ - - /* if we have a next guy, set his prev to our prev */ - if (d->next) - d->next->prev = d->prev; - - /* set our prev guy to our next guy instead of us */ - if (d->prev) - d->prev->next = d->next; - - /* we're out of the list, we should not point anywhere any more */ - d->prev = NULL; - d->next = NULL; -} - -void -lws_dll_remove_track_tail(struct lws_dll *d, struct lws_dll *phead) -{ - if (lws_dll_is_detached(d, phead)) { - assert(phead->prev != d); - assert(phead->next != d); - return; - } - - /* if we have a next guy, set his prev to our prev */ - if (d->next) - d->next->prev = d->prev; - - /* if we have a previous guy, set his next to our next */ - if (d->prev) - d->prev->next = d->next; - - if (phead->prev == d) - phead->prev = d->prev; - - if (phead->next == d) - phead->next = d->next; - - /* we're out of the list, we should not point anywhere any more */ - d->prev = NULL; - d->next = NULL; -} - - -int -lws_dll_foreach_safe(struct lws_dll *phead, void *user, - int (*cb)(struct lws_dll *d, void *user)) -{ - lws_start_foreach_dll_safe(struct lws_dll *, p, tp, phead->next) { - if (cb(p, user)) - return 1; - } lws_end_foreach_dll_safe(p, tp); - - return 0; -} diff -Nru libwebsockets-4.0.20/lib/core/private-lib-core.h libwebsockets-4.1.6/lib/core/private-lib-core.h --- libwebsockets-4.0.20/lib/core/private-lib-core.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/core/private-lib-core.h 2020-12-01 17:40:26.000000000 +0000 @@ -28,6 +28,7 @@ #include "lws_config.h" #include "lws_config_private.h" + #if defined(LWS_WITH_CGI) && defined(LWS_HAVE_VFORK) && \ !defined(NO_GNU_SOURCE_THIS_TIME) && !defined(_GNU_SOURCE) #define _GNU_SOURCE @@ -46,6 +47,7 @@ #include #include #include +#include #ifdef LWS_HAVE_INTTYPES_H #include @@ -60,8 +62,14 @@ #include #endif -#if LWS_MAX_SMP > 1 +#if LWS_MAX_SMP > 1 || defined(LWS_WITH_SYS_SMD) + /* https://stackoverflow.com/questions/33557506/timespec-redefinition-error */ + #define HAVE_STRUCT_TIMESPEC #include +#else + #if !defined(pid_t) && defined(WIN32) + #define pid_t int + #endif #endif #ifndef LWS_DEF_HEADER_LEN @@ -82,9 +90,6 @@ #ifndef SPEC_LATEST_SUPPORTED #define SPEC_LATEST_SUPPORTED 13 #endif -#ifndef AWAITING_TIMEOUT -#define AWAITING_TIMEOUT 20 -#endif #ifndef CIPHERS_LIST_STRING #define CIPHERS_LIST_STRING "DEFAULT" #endif @@ -106,6 +111,7 @@ #define strerror(x) "" #endif + /* * * ------ private platform defines ------ @@ -134,6 +140,7 @@ #include "libwebsockets.h" + /* * Generic bidi tx credit management */ @@ -148,8 +155,19 @@ uint8_t manual; }; +#ifdef LWS_WITH_IPV6 +#if defined(WIN32) || defined(_WIN32) +#include +#else +#include +#endif +#endif + +#undef X509_NAME +#if defined(LWS_WITH_TLS) #include "private-lib-tls.h" +#endif #if defined(WIN32) || defined(_WIN32) // Visual studio older than 2015 and WIN_CE has only _stricmp @@ -171,7 +189,7 @@ extern "C" { #endif - +#define lws_safe_modulo(_a, _b) ((_b) ? ((_a) % (_b)) : 0) #if defined(__clang__) #define lws_memory_barrier() __sync_synchronize() @@ -194,43 +212,16 @@ struct lws_protocols; struct lws; -#if defined(LWS_WITH_NETWORK) +#if defined(LWS_WITH_NETWORK) /* network */ #include "private-lib-event-libs.h" #if defined(LWS_WITH_SECURE_STREAMS) #include "private-lib-secure-streams.h" #endif -struct lws_io_watcher { -#ifdef LWS_WITH_LIBEV - struct lws_io_watcher_libev ev; -#endif -#ifdef LWS_WITH_LIBUV - struct lws_io_watcher_libuv uv; -#endif -#ifdef LWS_WITH_LIBEVENT - struct lws_io_watcher_libevent event; -#endif -#ifdef LWS_WITH_GLIB - struct lws_io_watcher_glib glib; -#endif - struct lws_context *context; - - uint8_t actual_events; -}; - -struct lws_signal_watcher { -#ifdef LWS_WITH_LIBEV - struct lws_signal_watcher_libev ev; -#endif -#ifdef LWS_WITH_LIBUV - struct lws_signal_watcher_libuv uv; -#endif -#ifdef LWS_WITH_LIBEVENT - struct lws_signal_watcher_libevent event; +#if defined(LWS_WITH_SYS_SMD) +#include "private-lib-system-smd.h" #endif - struct lws_context *context; -}; struct lws_foreign_thread_pollfd { struct lws_foreign_thread_pollfd *next; @@ -238,30 +229,7 @@ int _and; int _or; }; -#endif - -#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_unlock(struct lws_mutex_refcount *mr); -#endif +#endif /* network */ #if defined(LWS_WITH_NETWORK) #include "private-lib-core-net.h" @@ -315,58 +283,72 @@ lws_system_blob_t system_blobs[LWS_SYSBLOB_TYPE_COUNT]; +#if defined(LWS_WITH_SYS_SMD) + lws_smd_t smd; +#endif + #if defined(LWS_WITH_NETWORK) - struct lws_context_per_thread pt[LWS_MAX_SMP]; - lws_retry_bo_t default_retry; - lws_sorted_usec_list_t sul_system_state; + struct lws_context_per_thread pt[LWS_MAX_SMP]; + lws_retry_bo_t default_retry; + lws_sorted_usec_list_t sul_system_state; #if defined(LWS_PLAT_FREERTOS) - struct sockaddr_in frt_pipe_si; + struct sockaddr_in frt_pipe_si; #endif #if defined(LWS_WITH_HTTP2) - struct http2_settings set; + struct http2_settings set; #endif #if defined(LWS_WITH_SERVER_STATUS) - struct lws_conn_stats conn_stats; + struct lws_conn_stats conn_stats; #endif #if LWS_MAX_SMP > 1 - struct lws_mutex_refcount mr; + struct lws_mutex_refcount mr; #endif #if defined(LWS_WITH_NETWORK) -#if defined(LWS_WITH_LIBEV) - struct lws_context_eventlibs_libev ev; -#endif -#if defined(LWS_WITH_LIBUV) - struct lws_context_eventlibs_libuv uv; -#endif -#if defined(LWS_WITH_LIBEVENT) - struct lws_context_eventlibs_libevent event; -#endif -#if defined(LWS_WITH_GLIB) - struct lws_context_eventlibs_glib glib; + +/* + * LWS_WITH_NETWORK =====> + */ + +#if defined(LWS_WITH_EVENT_LIBS) + struct lws_plugin *evlib_plugin_list; + void *evlib_ctx; /* overallocated */ #endif #if defined(LWS_WITH_TLS) - struct lws_context_tls tls; + struct lws_context_tls tls; +#endif +#if defined(LWS_WITH_DRIVERS) + lws_netdevs_t netdevs; #endif #if defined(LWS_WITH_SYS_ASYNC_DNS) - lws_async_dns_t async_dns; + lws_async_dns_t async_dns; #endif +#if defined(LWS_WITH_SYS_NTPCLIENT) + void *ntpclient_priv; +#endif + +#if defined(LWS_WITH_SECURE_STREAMS) + struct lws_ss_handle *hss_fetch_policy; #if defined(LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM) - void *pol_args; struct lws_ss_handle *hss_auth; - struct lws_ss_handle *hss_fetch_policy; lws_sorted_usec_list_t sul_api_amazon_com; lws_sorted_usec_list_t sul_api_amazon_com_kick; #endif +#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) + struct lws_ss_x509 *server_der_list; +#endif +#endif +#if defined(LWS_WITH_SYS_STATE) lws_state_manager_t mgr_system; lws_state_notify_link_t protocols_notify; +#endif #if defined (LWS_WITH_SYS_DHCP_CLIENT) lws_dll2_owner_t dhcpc_owner; /**< list of ifaces with dhcpc */ @@ -374,27 +356,27 @@ /* pointers */ - struct lws_vhost *vhost_list; - struct lws_vhost *no_listener_vhost_list; - struct lws_vhost *vhost_pending_destruction_list; - struct lws_vhost *vhost_system; + struct lws_vhost *vhost_list; + struct lws_vhost *no_listener_vhost_list; + struct lws_vhost *vhost_pending_destruction_list; + struct lws_vhost *vhost_system; #if defined(LWS_WITH_SERVER) - const char *server_string; + const char *server_string; #endif - struct lws_event_loop_ops *event_loop_ops; + const struct lws_event_loop_ops *event_loop_ops; #endif #if defined(LWS_WITH_TLS) - const struct lws_tls_ops *tls_ops; + const struct lws_tls_ops *tls_ops; #endif #if defined(LWS_WITH_DETAILED_LATENCY) - det_lat_buf_cb_t detailed_latency_cb; + det_lat_buf_cb_t detailed_latency_cb; #endif #if defined(LWS_WITH_PLUGINS) - struct lws_plugin *plugin_list; + struct lws_plugin *plugin_list; #endif #ifdef _WIN32 /* different implementation between unix and windows */ @@ -403,6 +385,11 @@ struct lws **lws_lookup; #endif + +/* + * <====== LWS_WITH_NETWORK end + */ + #endif /* NETWORK */ #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) @@ -415,12 +402,14 @@ #endif struct lws_context **pcontext_finalize; +#if !defined(LWS_PLAT_FREERTOS) const char *username, *groupname; +#endif #if defined(LWS_WITH_DETAILED_LATENCY) const char *detailed_latency_filepath; #endif -#if defined(LWS_AMAZON_RTOS) +#if defined(LWS_AMAZON_RTOS) && defined(LWS_WITH_MBEDTLS) mbedtls_entropy_context mec; mbedtls_ctr_drbg_context mcdc; #endif @@ -432,18 +421,24 @@ #endif #if defined(LWS_WITH_PEER_LIMITS) - struct lws_peer **pl_hash_table; - struct lws_peer *peer_wait_list; - time_t next_cull; + struct lws_peer **pl_hash_table; + struct lws_peer *peer_wait_list; + lws_peer_limits_notify_t pl_notify_cb; + time_t next_cull; #endif - const lws_system_ops_t *system_ops; + const lws_system_ops_t *system_ops; #if defined(LWS_WITH_SECURE_STREAMS) - const char *pss_policies_json; - const lws_ss_policy_t *pss_policies; - const lws_ss_plugin_t **pss_plugins; - struct lwsac *ac_policy; +#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) + const char *pss_policies_json; + struct lwsac *ac_policy; + void *pol_args; +#endif + const lws_ss_policy_t *pss_policies; +#if defined(LWS_WITH_SSPLUGINS) + const lws_ss_plugin_t **pss_plugins; +#endif #endif void *external_baggage_free_on_destroy; @@ -453,7 +448,9 @@ const struct lws_protocol_vhost_options *reject_service_keywords; lws_reload_func deprecation_cb; #endif +#if !defined(LWS_PLAT_FREERTOS) void (*eventlib_signal_cb)(void *event_lib_handle, int signum); +#endif #if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP) cap_value_t caps[4]; @@ -472,18 +469,21 @@ #endif int max_fds; - int count_event_loop_static_asset_handles; #if !defined(LWS_NO_DAEMONIZE) pid_t started_with_parent; #endif - int uid, gid; +#if !defined(LWS_PLAT_FREERTOS) + int uid, gid; + int count_event_loop_static_asset_handles; int fd_random; + int count_cgi_spawned; +#endif + #if defined(LWS_WITH_DETAILED_LATENCY) int latencies_fd; #endif int count_wsi_allocated; - int count_cgi_spawned; unsigned int fd_limit_per_thread; unsigned int timeout_secs; unsigned int pt_serv_buf_size; @@ -514,7 +514,6 @@ short plugin_protocol_count; short plugin_extension_count; short server_string_len; - unsigned short ws_ping_pong_interval; unsigned short deprecation_pending_listen_close_count; #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) uint16_t ss_proxy_port; @@ -523,6 +522,8 @@ uint8_t max_fi; uint8_t udp_loss_sim_tx_pc; uint8_t udp_loss_sim_rx_pc; + uint8_t captive_portal_detect; + uint8_t captive_portal_detect_type; #if defined(LWS_WITH_STATS) uint8_t updated; @@ -585,7 +586,7 @@ #define lws_ssl_capable_read lws_ssl_capable_read_no_ssl #define lws_ssl_capable_write lws_ssl_capable_write_no_ssl #define lws_ssl_pending lws_ssl_pending_no_ssl - #define lws_server_socket_service_ssl(_b, _c) (0) + #define lws_server_socket_service_ssl(_b, _c, _d) (0) #define lws_ssl_close(_a) (0) #define lws_ssl_context_destroy(_a) #define lws_ssl_SSL_CTX_destroy(_a) @@ -620,6 +621,7 @@ #define lws_pt_mutex_init(_a) (void)(_a) #define lws_pt_mutex_destroy(_a) (void)(_a) #define lws_pt_lock(_a, b) (void)(_a) +#define lws_pt_assert_lock_held(_a) (void)(_a) #define lws_pt_unlock(_a) (void)(_a) #define lws_context_lock(_a, _b) (void)(_a) #define lws_context_unlock(_a) (void)(_a) @@ -701,12 +703,15 @@ LWS_EXTERN int lws_plat_drop_app_privileges(struct lws_context *context, int actually_drop); -#if defined(LWS_WITH_UNIX_SOCK) +#if defined(LWS_WITH_UNIX_SOCK) && !defined(WIN32) int lws_plat_user_colon_group_to_ids(const char *u_colon_g, uid_t *puid, gid_t *pgid); #endif int +lws_plat_ntpclient_config(struct lws_context *context); + +int lws_plat_ifname_to_hwaddr(int fd, const char *ifname, uint8_t *hwaddr, int len); LWS_EXTERN int @@ -716,6 +721,8 @@ LWS_EXTERN int alloc_file(struct lws_context *context, const char *filename, uint8_t **buf, lws_filepos_t *amount); +void lws_msleep(unsigned int); + void lws_context_destroy2(struct lws_context *context); diff -Nru libwebsockets-4.0.20/lib/core-net/adopt.c libwebsockets-4.1.6/lib/core-net/adopt.c --- libwebsockets-4.0.20/lib/core-net/adopt.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/core-net/adopt.c 2020-12-01 17:40:26.000000000 +0000 @@ -49,6 +49,7 @@ { struct lws *new_wsi; int n = fixed_tsi; + size_t s = sizeof(struct lws); if (n < 0) n = lws_get_idlest_tsi(vhost->context); @@ -58,19 +59,27 @@ return NULL; } - new_wsi = lws_zalloc(sizeof(struct lws), "new server wsi"); +#if defined(LWS_WITH_EVENT_LIBS) + s += vhost->context->event_loop_ops->evlib_size_wsi; +#endif + + new_wsi = lws_zalloc(s, "new server wsi"); if (new_wsi == NULL) { lwsl_err("Out of memory for new connection\n"); return NULL; } +#if defined(LWS_WITH_EVENT_LIBS) + new_wsi->evlib_wsi = (uint8_t *)new_wsi + sizeof(*new_wsi); +#endif + new_wsi->wsistate |= LWSIFR_SERVER; new_wsi->tsi = n; lwsl_debug("new wsi %p joining vhost %s, tsi %d\n", new_wsi, vhost->name, new_wsi->tsi); lws_vhost_bind_wsi(vhost, new_wsi); - new_wsi->context = vhost->context; + new_wsi->a.context = vhost->context; new_wsi->pending_timeout = NO_PENDING_TIMEOUT; new_wsi->rxflow_change_to = LWS_RXFLOW_ALLOW; new_wsi->retry_policy = vhost->retry_policy; @@ -95,7 +104,7 @@ * to the start of the supported list, so it can look * for matching ones during the handshake */ - new_wsi->protocol = vhost->protocols; + new_wsi->a.protocol = vhost->protocols; new_wsi->user_space = NULL; new_wsi->desc.sockfd = LWS_SOCK_INVALID; new_wsi->position_in_fds_table = LWS_NO_FDS_POS; @@ -131,16 +140,22 @@ * we initialize it, it may become "live" concurrently unexpectedly... */ + lws_context_lock(vh->context, __func__); + n = -1; if (parent) n = parent->tsi; new_wsi = lws_create_new_server_wsi(vh, n); - if (!new_wsi) + if (!new_wsi) { + lws_context_unlock(vh->context); return NULL; + } - new_wsi->opaque_user_data = opaque; + new_wsi->a.opaque_user_data = opaque; pt = &context->pt[(int)new_wsi->tsi]; + lws_pt_lock(pt, __func__); + lws_stats_bump(pt, LWSSTATS_C_CONNECTIONS, 1); if (parent) { @@ -150,11 +165,11 @@ } if (vh_prot_name) { - new_wsi->protocol = lws_vhost_name_to_protocol(new_wsi->vhost, + new_wsi->a.protocol = lws_vhost_name_to_protocol(new_wsi->a.vhost, vh_prot_name); - if (!new_wsi->protocol) { + if (!new_wsi->a.protocol) { lwsl_err("Protocol %s not enabled on vhost %s\n", - vh_prot_name, new_wsi->vhost->name); + vh_prot_name, new_wsi->a.vhost->name); goto bail; } if (lws_ensure_user_space(new_wsi)) { @@ -163,18 +178,28 @@ } } + if (!LWS_SSL_ENABLED(new_wsi->a.vhost) || + !(type & LWS_ADOPT_SOCKET)) + type &= ~LWS_ADOPT_ALLOW_SSL; + if (lws_role_call_adoption_bind(new_wsi, type, vh_prot_name)) { lwsl_err("%s: no role for desc type 0x%x\n", __func__, type); goto bail; } + lws_pt_unlock(pt); + /* * 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 * he gets another identity (he may do async dns now...) */ + lws_vhost_lock(new_wsi->a.vhost); lws_dll2_add_head(&new_wsi->vh_awaiting_socket, - &new_wsi->vhost->vh_awaiting_socket_owner); + &new_wsi->a.vhost->vh_awaiting_socket_owner); + lws_vhost_unlock(new_wsi->a.vhost); + + lws_context_unlock(vh->context); return new_wsi; @@ -188,17 +213,115 @@ vh->context->count_wsi_allocated--; lws_vhost_unbind_wsi(new_wsi); + lws_free(new_wsi); + lws_pt_unlock(pt); + lws_context_unlock(vh->context); + return NULL; } +#if defined(LWS_WITH_SERVER) && defined(LWS_WITH_SECURE_STREAMS) + +/* + * If the incoming wsi is bound to a vhost that is a ss server, this creates + * an accepted ss bound to the wsi. + * + * For h1 or raw, we can do the binding here, but for muxed protocols like h2 + * or mqtt we have to do it not on the nwsi but on the stream. And for h2 we + * start off bound to h1 role, since we don't know if we will upgrade to h2 + * until we meet the server. + * + * 1) No tls is assumed to mean no muxed protocol so can do it at adopt. + * + * 2) After alpn if not muxed we can do it. + * + * 3) For muxed, do it at the nwsi migration and on new stream + */ + +int +lws_adopt_ss_server_accept(struct lws *new_wsi) +{ + lws_ss_handle_t *h; + void *pv, **ppv; + + if (!new_wsi->a.vhost->ss_handle) + return 0; + + pv = (char *)&new_wsi->a.vhost->ss_handle[1]; + + /* + * Yes... the vhost is pointing to its secure stream representing the + * server... we want to create an accepted SS and bind it to new_wsi, + * the info/ssi from the server SS (so the SS callbacks defined there), + * the opaque_user_data of the server object and the policy of it. + */ + + ppv = (void **)((char *)pv + + new_wsi->a.vhost->ss_handle->info.opaque_user_data_offset); + + /* + * indicate we are an accepted connection referencing the + * server object + */ + + new_wsi->a.vhost->ss_handle->info.flags |= LWSSSINFLAGS_SERVER; + + if (lws_ss_create(new_wsi->a.context, new_wsi->tsi, + &new_wsi->a.vhost->ss_handle->info, + *ppv, &h, NULL, NULL)) { + lwsl_err("%s: accept ss creation failed\n", __func__); + goto fail1; + } + + /* + * We made a fresh accepted SS conn from the server pieces, + * now bind the wsi... the problem is, this is the nwsi if it's + * h2. + */ + + h->wsi = new_wsi; + new_wsi->a.opaque_user_data = h; + h->info.flags |= LWSSSINFLAGS_ACCEPTED; + new_wsi->for_ss = 1; /* indicate wsi should invalidate any ss link to it on close */ + + // lwsl_notice("%s: opaq %p, role %s\n", __func__, + // new_wsi->a.opaque_user_data, new_wsi->role_ops->name); + + h->policy = new_wsi->a.vhost->ss_handle->policy; + + /* + * Let's give it appropriate state notifications + */ + + if (lws_ss_event_helper(h, LWSSSCS_CREATING)) + goto fail; + if (lws_ss_event_helper(h, LWSSSCS_CONNECTING)) + goto fail; + if (lws_ss_event_helper(h, LWSSSCS_CONNECTED)) + goto fail; + + // lwsl_notice("%s: accepted ss complete, pcol %s\n", __func__, + // new_wsi->a.protocol->name); + + return 0; + +fail: + lws_ss_destroy(&h); +fail1: + return 1; +} + +#endif + + static struct lws * lws_adopt_descriptor_vhost2(struct lws *new_wsi, lws_adoption_type type, lws_sock_file_fd_type fd) { struct lws_context_per_thread *pt = - &new_wsi->context->pt[(int)new_wsi->tsi]; + &new_wsi->a.context->pt[(int)new_wsi->tsi]; int n; /* enforce that every fd is nonblocking */ @@ -221,7 +344,7 @@ new_wsi->desc = fd; - if (!LWS_SSL_ENABLED(new_wsi->vhost) || + if (!LWS_SSL_ENABLED(new_wsi->a.vhost) || !(type & LWS_ADOPT_SOCKET)) type &= ~LWS_ADOPT_ALLOW_SSL; @@ -236,8 +359,8 @@ if (new_wsi->role_ops->adoption_cb[lwsi_role_server(new_wsi)]) n = new_wsi->role_ops->adoption_cb[lwsi_role_server(new_wsi)]; - if (new_wsi->context->event_loop_ops->sock_accept) - if (new_wsi->context->event_loop_ops->sock_accept(new_wsi)) + if (new_wsi->a.context->event_loop_ops->sock_accept) + if (new_wsi->a.context->event_loop_ops->sock_accept(new_wsi)) goto fail; #if LWS_MAX_SMP > 1 @@ -251,7 +374,7 @@ if (!(type & LWS_ADOPT_ALLOW_SSL)) { lws_pt_lock(pt, __func__); - if (__insert_wsi_socket_into_fds(new_wsi->context, new_wsi)) { + if (__insert_wsi_socket_into_fds(new_wsi->a.context, new_wsi)) { lws_pt_unlock(pt); lwsl_err("%s: fail inserting socket\n", __func__); goto fail; @@ -260,7 +383,7 @@ } #if defined(LWS_WITH_SERVER) else - if (lws_server_socket_service_ssl(new_wsi, fd.sockfd)) { + if (lws_server_socket_service_ssl(new_wsi, fd.sockfd, 0)) { #if defined(LWS_WITH_ACCESS_LOG) lwsl_notice("%s: fail ssl negotiation: %s\n", __func__, new_wsi->simple_ip); @@ -271,21 +394,39 @@ } #endif + lws_vhost_lock(new_wsi->a.vhost); /* he has fds visibility now, remove from vhost orphan list */ lws_dll2_remove(&new_wsi->vh_awaiting_socket); + lws_vhost_unlock(new_wsi->a.vhost); /* * by deferring callback to this point, after insertion to fds, * lws_callback_on_writable() can work from the callback */ - if ((new_wsi->protocol->callback)(new_wsi, n, new_wsi->user_space, + if ((new_wsi->a.protocol->callback)(new_wsi, n, new_wsi->user_space, NULL, 0)) goto fail; /* role may need to do something after all adoption completed */ lws_role_call_adoption_bind(new_wsi, type | _LWS_ADOPT_FINISH, - new_wsi->protocol->name); + new_wsi->a.protocol->name); + +#if defined(LWS_WITH_SERVER) && defined(LWS_WITH_SECURE_STREAMS) + /* + * Did we come from an accepted client connection to a ss server? + * + * !!! For mux protocols, this will cause an additional inactive ss + * representing the nwsi. Doing that allows us to support both h1 + * (here) and h2 (at lws_wsi_server_new()) + */ + + lwsl_info("%s: wsi %p, vhost %s ss_handle %p\n", __func__, new_wsi, + new_wsi->a.vhost->name, new_wsi->a.vhost->ss_handle); + + if (lws_adopt_ss_server_accept(new_wsi)) + goto fail; +#endif #if LWS_MAX_SMP > 1 /* its actual pt can service it now */ @@ -338,11 +479,16 @@ if (peer && info->vh->context->ip_limit_wsi && peer->count_wsi >= info->vh->context->ip_limit_wsi) { - lwsl_notice("Peer reached wsi limit %d\n", + lwsl_info("Peer reached wsi limit %d\n", info->vh->context->ip_limit_wsi); lws_stats_bump(&info->vh->context->pt[0], LWSSTATS_C_PEER_LIMIT_WSI_DENIED, 1); + if (info->vh->context->pl_notify_cb) + info->vh->context->pl_notify_cb( + info->vh->context, + info->fd.sockfd, + &peer->sa46); compatible_close(info->fd.sockfd); return NULL; } @@ -404,7 +550,7 @@ if (wsi->position_in_fds_table == LWS_NO_FDS_POS) return wsi; - pt = &wsi->context->pt[(int)wsi->tsi]; + pt = &wsi->a.context->pt[(int)wsi->tsi]; n = lws_buflist_append_segment(&wsi->buflist, (const uint8_t *)readbuf, len); @@ -436,7 +582,7 @@ pfd = &pt->fds[wsi->position_in_fds_table]; pfd->revents |= LWS_POLLIN; lwsl_err("%s: calling service\n", __func__); - if (lws_service_fd_tsi(wsi->context, pfd, wsi->tsi)) + if (lws_service_fd_tsi(wsi->a.context, pfd, wsi->tsi)) /* service closed us */ return NULL; @@ -540,7 +686,7 @@ } if (!wsi->do_bind && !wsi->pf_packet) { - +#if !defined(__APPLE__) if (connect(sock.sockfd, wsi->dns_results_next->ai_addr, (socklen_t)wsi->dns_results_next->ai_addrlen) == -1) { lwsl_err("%s: conn fd %d fam %d %s:%u failed " @@ -553,7 +699,7 @@ compatible_close(sock.sockfd); goto resume; } - +#endif memcpy(&wsi->udp->sa, wsi->dns_results_next->ai_addr, wsi->dns_results_next->ai_addrlen); wsi->udp->salen = (socklen_t)wsi->dns_results_next->ai_addrlen; @@ -616,7 +762,9 @@ h.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ h.ai_socktype = SOCK_DGRAM; h.ai_protocol = IPPROTO_UDP; +#if defined(AI_PASSIVE) h.ai_flags = AI_PASSIVE; +#endif #ifdef AI_ADDRCONFIG h.ai_flags |= AI_ADDRCONFIG; #endif diff -Nru libwebsockets-4.0.20/lib/core-net/close.c libwebsockets-4.1.6/lib/core-net/close.c --- libwebsockets-4.0.20/lib/core-net/close.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/core-net/close.c 2020-12-01 17:40:26.000000000 +0000 @@ -50,7 +50,7 @@ * if we have wsi in our transaction queue, if we are closing we * must go through and close all those first */ - if (wsi->vhost) { + if (wsi->a.vhost) { /* we are no longer an active client connection that can piggyback */ lws_dll2_remove(&wsi->dll_cli_active_conns); @@ -71,21 +71,39 @@ } #endif - if (wsi->vhost) + if (wsi->a.vhost) { + lws_vhost_lock(wsi->a.vhost); lws_dll2_remove(&wsi->vh_awaiting_socket); + lws_vhost_unlock(wsi->a.vhost); + } /* * Protocol user data may be allocated either internally by lws * or by specified the user. We should only free what we allocated. */ - if (wsi->protocol && wsi->protocol->per_session_data_size && - wsi->user_space && !wsi->user_space_externally_allocated) + if (wsi->a.protocol && wsi->a.protocol->per_session_data_size && + wsi->user_space && !wsi->user_space_externally_allocated) { + /* confirm no sul left scheduled in user data itself */ + lws_sul_debug_zombies(wsi->a.context, wsi->user_space, + wsi->a.protocol->per_session_data_size, __func__); lws_free_set_NULL(wsi->user_space); + } + + /* + * Don't let buflist content or state from the wsi's previous life + * carry over to the new life + */ lws_buflist_destroy_all_segments(&wsi->buflist); + lws_dll2_remove(&wsi->dll_buflist); lws_buflist_destroy_all_segments(&wsi->buflist_out); #if defined(LWS_WITH_UDP) - lws_free_set_NULL(wsi->udp); + if (wsi->udp) { + /* confirm no sul left scheduled in wsi->udp itself */ + lws_sul_debug_zombies(wsi->a.context, wsi->udp, + sizeof(*wsi->udp), "close udp wsi"); + lws_free_set_NULL(wsi->udp); + } #endif wsi->retry = 0; @@ -103,13 +121,13 @@ lws_buflist_destroy_all_segments(&wsi->http.buflist_post_body); #endif - if (wsi->vhost && wsi->vhost->lserv_wsi == wsi) - wsi->vhost->lserv_wsi = NULL; + if (wsi->a.vhost && wsi->a.vhost->lserv_wsi == wsi) + wsi->a.vhost->lserv_wsi = NULL; #if defined(LWS_WITH_CLIENT) - if (wsi->vhost) + if (wsi->a.vhost) lws_dll2_remove(&wsi->dll_cli_active_conns); #endif - wsi->context->count_wsi_allocated--; + wsi->a.context->count_wsi_allocated--; __lws_same_vh_protocol_remove(wsi); #if defined(LWS_WITH_CLIENT) @@ -118,7 +136,7 @@ #endif #if defined(LWS_WITH_PEER_LIMITS) - lws_peer_track_wsi_close(wsi->context, wsi->peer); + lws_peer_track_wsi_close(wsi->a.context, wsi->peer); wsi->peer = NULL; #endif @@ -144,15 +162,19 @@ return; __lws_reset_wsi(wsi); + __lws_wsi_remove_from_sul(wsi); - if (wsi->context->event_loop_ops->destroy_wsi) - wsi->context->event_loop_ops->destroy_wsi(wsi); + if (wsi->a.context->event_loop_ops->destroy_wsi) + wsi->a.context->event_loop_ops->destroy_wsi(wsi); lws_vhost_unbind_wsi(wsi); lwsl_debug("%s: %p, remaining wsi %d, tsi fds count %d\n", __func__, wsi, - wsi->context->count_wsi_allocated, - wsi->context->pt[(int)wsi->tsi].fds_count); + wsi->a.context->count_wsi_allocated, + wsi->a.context->pt[(int)wsi->tsi].fds_count); + + /* confirm no sul left scheduled in wsi itself */ + lws_sul_debug_zombies(wsi->a.context, wsi, sizeof(wsi), __func__); lws_free(wsi); } @@ -174,8 +196,8 @@ lwsl_info("%s: detach %p from parent %p\n", __func__, wsi, wsi->parent); - if (wsi->parent->protocol) - wsi->parent->protocol->callback(wsi, + if (wsi->parent->a.protocol) + wsi->parent->a.protocol->callback(wsi, LWS_CALLBACK_CHILD_CLOSING, wsi->parent->user_space, wsi, 0); @@ -201,14 +223,14 @@ return; wsi->already_did_cce = 1; - lws_stats_bump(&wsi->context->pt[(int)wsi->tsi], + lws_stats_bump(&wsi->a.context->pt[(int)wsi->tsi], LWSSTATS_C_CONNS_CLIENT_FAILED, 1); - if (!wsi->protocol) + if (!wsi->a.protocol) return; if (!wsi->client_suppress_CONNECTION_ERROR) - wsi->protocol->callback(wsi, + wsi->a.protocol->callback(wsi, LWS_CALLBACK_CLIENT_CONNECTION_ERROR, wsi->user_space, arg, len); } @@ -251,8 +273,11 @@ lwsl_info("%s: wsi %p: going down with stuff in buflist\n", __func__, wsi); } - context = wsi->context; + context = wsi->a.context; pt = &context->pt[(int)wsi->tsi]; + + lws_pt_assert_lock_held(pt); + lws_stats_bump(pt, LWSSTATS_C_API_CLOSE, 1); #if defined(LWS_WITH_CLIENT) @@ -272,7 +297,7 @@ wsi2 = wsi->child_list; while (wsi2) { wsi1 = wsi2->sibling_list; - wsi2->parent = NULL; +// wsi2->parent = NULL; /* stop it doing shutdown processing */ wsi2->socket_is_permanently_unusable = 1; __lws_close_free_wsi(wsi2, reason, @@ -286,8 +311,8 @@ if (wsi->role_ops == &role_ops_raw_file) { lws_remove_child_from_any_parent(wsi); __remove_wsi_socket_from_fds(wsi); - if (wsi->protocol) - wsi->protocol->callback(wsi, wsi->role_ops->close_cb[0], + if (wsi->a.protocol) + wsi->a.protocol->callback(wsi, wsi->role_ops->close_cb[0], wsi->user_space, NULL, 0); goto async_close; } @@ -303,11 +328,16 @@ /* we are not a network connection, but a handler for CGI io */ if (wsi->parent && wsi->parent->http.cgi) { - if (wsi->parent->child_list == wsi && !wsi->sibling_list) - lws_cgi_remove_and_kill(wsi->parent); + /* + * We need to keep the logical cgi around so we can + * drain it + */ + +// if (wsi->parent->child_list == wsi && !wsi->sibling_list) +// lws_cgi_remove_and_kill(wsi->parent); /* end the binding between us and master */ - if (wsi->parent->http.cgi) + if (wsi->parent->http.cgi && wsi->parent->http.cgi->lsp) wsi->parent->http.cgi->lsp->stdwsi[(int)wsi->lsp_channel] = NULL; } @@ -385,9 +415,9 @@ lwsi_state(wsi) == LRS_H1C_ISSUE_HANDSHAKE) goto just_kill_connection; - if (!wsi->told_user_closed && wsi->user_space && wsi->protocol && + if (!wsi->told_user_closed && wsi->user_space && wsi->a.protocol && wsi->protocol_bind_balance) { - wsi->protocol->callback(wsi, + wsi->a.protocol->callback(wsi, wsi->role_ops->protocol_unbind_cb[ !!lwsi_role_server(wsi)], wsi->user_space, (void *)__func__, 0); @@ -418,6 +448,7 @@ lws_vfs_file_close(&wsi->http.fop_fd); #endif + lws_sul_cancel(&wsi->sul_connect_timeout); #if defined(LWS_WITH_SYS_ASYNC_DNS) lws_async_dns_cancel(wsi); #endif @@ -427,8 +458,13 @@ lws_buflist_destroy_all_segments(&wsi->http.buflist_post_body); #endif #if defined(LWS_WITH_UDP) - if (wsi->udp) + if (wsi->udp) { + /* confirm no sul left scheduled in wsi->udp itself */ + lws_sul_debug_zombies(wsi->a.context, wsi->udp, + sizeof(*wsi->udp), "close udp wsi"); + lws_free_set_NULL(wsi->udp); + } #endif if (wsi->role_ops->close_kill_connection) @@ -437,24 +473,53 @@ n = 0; if (!wsi->told_user_closed && wsi->user_space && - wsi->protocol_bind_balance && wsi->protocol) { + wsi->protocol_bind_balance && wsi->a.protocol) { lwsl_debug("%s: %p: DROP_PROTOCOL %s\n", __func__, wsi, - wsi->protocol ? wsi->protocol->name: "NULL"); - if (wsi->protocol) - wsi->protocol->callback(wsi, + wsi->a.protocol ? wsi->a.protocol->name: "NULL"); + if (wsi->a.protocol) + 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; } +#if defined(LWS_WITH_SECURE_STREAMS) && defined(LWS_WITH_SERVER) + if (wsi->for_ss) { + /* + * We were adopted for a particular ss, but, eg, we may not + * have succeeded with the connection... we are closing which is + * good, but we have to invalidate any pointer the related ss + * handle may be holding on us + */ + lws_ss_handle_t *h = (lws_ss_handle_t *)wsi->a.opaque_user_data; + + if (h) { + h->wsi = NULL; + wsi->a.opaque_user_data = NULL; + } + } +#endif + #if defined(LWS_WITH_CLIENT) - if ((lwsi_state(wsi) == LRS_WAITING_SERVER_REPLY || + if (( +#if defined(LWS_ROLE_WS) + /* + * If our goal is a ws upgrade, effectively we did not reach + * ESTABLISHED if we did not get the upgrade server reply + */ + (lwsi_state(wsi) == LRS_WAITING_SERVER_REPLY && + wsi->role_ops == &role_ops_ws) || +#endif lwsi_state(wsi) == LRS_WAITING_DNS || lwsi_state(wsi) == LRS_WAITING_CONNECT) && - !wsi->already_did_cce && wsi->protocol) { + !wsi->already_did_cce && wsi->a.protocol) { static const char _reason[] = "closed before established"; + lwsl_debug("%s: closing in unestablished state 0x%x\n", + __func__, lwsi_state(wsi)); + wsi->socket_is_permanently_unusable = 1; + lws_inform_client_conn_fail(wsi, (void *)_reason, sizeof(_reason)); } @@ -546,10 +611,7 @@ // lwsl_notice("%s: wsi %p, fd %d\n", __func__, wsi, wsi->desc.sockfd); /* checking return redundant since we anyway close */ - if (wsi->desc.sockfd != LWS_SOCK_INVALID) - __remove_wsi_socket_from_fds(wsi); - else - __lws_same_vh_protocol_remove(wsi); + __remove_wsi_socket_from_fds(wsi); lwsi_set_state(wsi, LRS_DEAD_SOCKET); lws_buflist_destroy_all_segments(&wsi->buflist); @@ -587,7 +649,14 @@ */ ccb = 1; - pro = wsi->protocol; + pro = wsi->a.protocol; + + if (wsi->already_did_cce) + /* + * If we handled this by CLIENT_CONNECTION_ERROR, it's + * mutually exclusive with CLOSE + */ + ccb = 0; #if defined(LWS_WITH_CLIENT) if (!ccb && (lwsi_state_PRE_CLOSE(wsi) & LWSIFS_NOT_EST) && @@ -597,8 +666,8 @@ #endif if (ccb) { - if (!wsi->protocol && wsi->vhost && wsi->vhost->protocols) - pro = &wsi->vhost->protocols[0]; + if (!wsi->a.protocol && wsi->a.vhost && wsi->a.vhost->protocols) + pro = &wsi->a.vhost->protocols[0]; if (pro) pro->callback(wsi, @@ -613,8 +682,8 @@ lws_remove_child_from_any_parent(wsi); wsi->socket_is_permanently_unusable = 1; - if (wsi->context->event_loop_ops->wsi_logical_close) - if (wsi->context->event_loop_ops->wsi_logical_close(wsi)) + if (wsi->a.context->event_loop_ops->wsi_logical_close) + if (wsi->a.context->event_loop_ops->wsi_logical_close(wsi)) return; __lws_close_free_wsi_final(wsi); @@ -632,21 +701,34 @@ if (n) lwsl_debug("closing: close ret %d\n", LWS_ERRNO); + __remove_wsi_socket_from_fds(wsi); + if (lws_socket_is_valid(wsi->desc.sockfd)) + delete_from_fd(wsi->a.context, wsi->desc.sockfd); + +#if !defined(LWS_PLAT_FREERTOS) && !defined(WIN32) && !defined(LWS_PLAT_OPTEE) + delete_from_fdwsi(wsi->a.context, wsi); +#endif + + sanity_assert_no_sockfd_traces(wsi->a.context, wsi->desc.sockfd); + wsi->desc.sockfd = LWS_SOCK_INVALID; } /* outermost destroy notification for wsi (user_space still intact) */ - if (wsi->vhost) - wsi->vhost->protocols[0].callback(wsi, LWS_CALLBACK_WSI_DESTROY, + if (wsi->a.vhost) + wsi->a.vhost->protocols[0].callback(wsi, LWS_CALLBACK_WSI_DESTROY, wsi->user_space, NULL, 0); #ifdef LWS_WITH_CGI if (wsi->http.cgi) { lws_spawn_piped_destroy(&wsi->http.cgi->lsp); + lws_sul_cancel(&wsi->http.cgi->sul_grace); lws_free_set_NULL(wsi->http.cgi); } #endif + __lws_wsi_remove_from_sul(wsi); + sanity_assert_no_wsi_traces(wsi->a.context, wsi); __lws_free_wsi(wsi); } @@ -654,7 +736,7 @@ void lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, const char *caller) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; lws_pt_lock(pt, __func__); __lws_close_free_wsi(wsi, reason, caller); diff -Nru libwebsockets-4.0.20/lib/core-net/CMakeLists.txt libwebsockets-4.1.6/lib/core-net/CMakeLists.txt --- libwebsockets-4.0.20/lib/core-net/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/core-net/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,85 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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_directories(.) + +list(APPEND SOURCES + core-net/dummy-callback.c + core-net/output.c + core-net/close.c + core-net/network.c + core-net/vhost.c + core-net/pollfd.c + core-net/service.c + core-net/sorted-usec-list.c + core-net/wsi.c + core-net/wsi-timeout.c + core-net/adopt.c + roles/pipe/ops-pipe.c +) + +if (LWS_WITH_SYS_STATE) + list(APPEND SOURCES + core-net/state.c + ) +endif() + +if (LWS_WITH_DETAILED_LATENCY) + list(APPEND SOURCES + core-net/detailed-latency.c) +endif() + +if (LWS_WITH_LWS_DSH) + list(APPEND SOURCES + core-net/lws-dsh.c) +endif() + +if (LWS_WITH_SEQUENCER) + list(APPEND SOURCES + core-net/sequencer.c) +endif() + +if (NOT LWS_WITHOUT_CLIENT) + list(APPEND SOURCES + core-net/connect.c + core-net/client.c) +endif() + +if (NOT LWS_WITHOUT_SERVER) + list(APPEND SOURCES + core-net/server.c) +endif() + +if (LWS_WITH_SOCKS5 AND NOT LWS_WITHOUT_CLIENT) + list(APPEND SOURCES + core-net/socks5-client.c) +endif() + +if (LWS_WITH_NETWORK AND LWS_WITH_STATS) + list(APPEND SOURCES + core-net/stats.c + ) +endif() + +exports_to_parent_scope() diff -Nru libwebsockets-4.0.20/lib/core-net/connect.c libwebsockets-4.1.6/lib/core-net/connect.c --- libwebsockets-4.0.20/lib/core-net/connect.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/core-net/connect.c 2020-12-01 17:40:26.000000000 +0000 @@ -31,6 +31,7 @@ const char *local = i->protocol; struct lws *wsi, *safe = NULL; const struct lws_protocols *p; + size_t s = sizeof(struct lws); const char *cisin[CIS_COUNT]; int tid = 0, n, m; size_t size; @@ -54,17 +55,30 @@ /* PHASE 1: create a bare wsi */ - wsi = lws_zalloc(sizeof(struct lws), "client wsi"); +#if defined(LWS_WITH_EVENT_LIBS) + s += i->context->event_loop_ops->evlib_size_wsi; +#endif + + wsi = lws_zalloc(s, "client wsi"); if (wsi == NULL) goto bail; +#if defined(LWS_WITH_EVENT_LIBS) + wsi->evlib_wsi = (uint8_t *)wsi + sizeof(*wsi); +#endif + /* * Until we exit, we can report connection failure directly to the * caller without needing to call through to protocol CONNECTION_ERROR. */ wsi->client_suppress_CONNECTION_ERROR = 1; - wsi->context = i->context; + if (i->keep_warm_secs) + wsi->keep_warm_secs = i->keep_warm_secs; + else + wsi->keep_warm_secs = 5; + + wsi->a.context = i->context; wsi->desc.sockfd = LWS_SOCK_INVALID; wsi->seq = i->seq; wsi->flags = i->ssl_connection; @@ -78,23 +92,31 @@ wsi->detlat.earliest_write_req_pre_write = lws_now_usecs(); #endif - wsi->vhost = NULL; + if (i->ssl_connection & LCCSCF_WAKE_SUSPEND__VALIDITY) + wsi->conn_validity_wakesuspend = 1; + + wsi->a.vhost = NULL; if (!i->vhost) { struct lws_vhost *v = i->context->vhost_list; - if (v && !strcmp(v->name, "system")) + + if (!v) { /* coverity */ + lwsl_err("%s: no vhost\n", __func__); + goto bail; + } + if (!strcmp(v->name, "system")) v = v->vhost_next; lws_vhost_bind_wsi(v, wsi); } else lws_vhost_bind_wsi(i->vhost, wsi); - if (!wsi->vhost) { + if (!wsi->a.vhost) { lwsl_err("%s: No vhost in the context\n", __func__); goto bail; } #if LWS_MAX_SMP > 1 - tid = wsi->vhost->protocols[0].callback(wsi, LWS_CALLBACK_GET_THREAD_ID, + tid = wsi->a.vhost->protocols[0].callback(wsi, LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0); #endif @@ -156,7 +178,7 @@ wsi->txc.manual_initial_tx_credit = (int32_t)i->manual_initial_tx_credit; #endif - wsi->protocol = &wsi->vhost->protocols[0]; + wsi->a.protocol = &wsi->a.vhost->protocols[0]; wsi->client_pipeline = !!(i->ssl_connection & LCCSCF_PIPELINE); wsi->client_no_follow_redirect = !!(i->ssl_connection & LCCSCF_HTTP_NO_FOLLOW_REDIRECT); @@ -172,16 +194,16 @@ } if (local) { - lwsl_info("%s: protocol binding to %s\n", __func__, local); - p = lws_vhost_name_to_protocol(wsi->vhost, 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); if (p) lws_bind_protocol(wsi, p, __func__); else - lwsl_err("%s: unknown protocol %s\n", __func__, local); + lwsl_info("%s: unknown protocol %s\n", __func__, local); lwsl_info("%s: wsi %p: %s %s entry\n", __func__, wsi, wsi->role_ops->name, - wsi->protocol ? wsi->protocol->name : "none"); + wsi->a.protocol ? wsi->a.protocol->name : "none"); } /* @@ -241,7 +263,7 @@ /* all the pointers default to NULL, but no need to zero the args */ memset(wsi->stash, 0, sizeof(*wsi->stash)); - wsi->opaque_user_data = wsi->stash->opaque_user_data = + wsi->a.opaque_user_data = wsi->stash->opaque_user_data = i->opaque_user_data; pc = (char *)&wsi->stash[1]; @@ -305,9 +327,9 @@ !strcmp(i->local_protocol_name, "raw-proxy"))) { lwsl_debug("%s: wsi %p: adoption cb %d to %s %s\n", __func__, wsi, wsi->role_ops->adoption_cb[0], - wsi->role_ops->name, wsi->protocol->name); + wsi->role_ops->name, wsi->a.protocol->name); - wsi->protocol->callback(wsi, wsi->role_ops->adoption_cb[0], + wsi->a.protocol->callback(wsi, wsi->role_ops->adoption_cb[0], wsi->user_space, NULL, 0); } @@ -351,6 +373,7 @@ } #endif + /* fallthru */ wsi = lws_http_client_connect_via_info2(wsi); @@ -381,8 +404,10 @@ bail2: #endif +#if defined(LWS_WITH_TLS) if (i->ssl_connection & LCCSCF_USE_SSL) lws_tls_restrict_return(i->context); +#endif if (i->pwsi) *i->pwsi = NULL; diff -Nru libwebsockets-4.0.20/lib/core-net/dummy-callback.c libwebsockets-4.1.6/lib/core-net/dummy-callback.c --- libwebsockets-4.0.20/lib/core-net/dummy-callback.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/core-net/dummy-callback.c 2020-12-01 17:40:26.000000000 +0000 @@ -24,6 +24,9 @@ #include "private-lib-core.h" +/* max individual proxied header payload size */ +#define MAXHDRVAL 1024 + #if defined(LWS_WITH_HTTP_PROXY) static int proxy_header(struct lws *wsi, struct lws *par, unsigned char *temp, @@ -33,16 +36,23 @@ if (n < 1) { lwsl_debug("%s: no index %d:\n", __func__, index); + return 0; } - if (lws_hdr_copy(par, (char *)temp, temp_len, index) < 0) + if (lws_hdr_copy(par, (char *)temp, temp_len, index) < 0) { + lwsl_notice("%s: unable to copy par hdr idx %d (len %d)\n", + __func__, index, n); return -1; + } lwsl_debug("%s: index %d: %s\n", __func__, index, (char *)temp); - if (lws_add_http_header_by_token(wsi, index, temp, n, p, end)) + if (lws_add_http_header_by_token(wsi, index, temp, n, p, end)) { + lwsl_notice("%s: unable to append par hdr idx %d (len %d)\n", + __func__, index, n); return -1; + } return 0; } @@ -112,7 +122,8 @@ if (!wsi->h1_ws_proxied || !wsi->parent) break; - lws_process_ws_upgrade2(wsi->parent); + if (lws_process_ws_upgrade2(wsi->parent)) + return -1; #if defined(LWS_WITH_HTTP2) if (wsi->parent->mux_substream) @@ -125,7 +136,7 @@ case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: case LWS_CALLBACK_CLIENT_CLOSED: - lwsl_user("%s: client closed: parent %p\n", __func__, wsi->parent); + lwsl_info("%s: client closed: parent %p\n", __func__, wsi->parent); if (wsi->parent) lws_set_timeout(wsi->parent, 1, LWS_TO_KILL_ASYNC); break; @@ -133,7 +144,7 @@ case LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER: { unsigned char **p = (unsigned char **)in, *end = (*p) + len, - tmp[128]; + tmp[MAXHDRVAL]; proxy_header(wsi, wsi->parent, tmp, sizeof(tmp), WSI_TOKEN_HTTP_ACCEPT_LANGUAGE, p, end); @@ -193,7 +204,7 @@ return 1; case LWS_CALLBACK_CLOSED: - lwsl_user("%s: closed\n", __func__); + lwsl_info("%s: closed\n", __func__); return -1; case LWS_CALLBACK_RECEIVE: @@ -250,6 +261,7 @@ #endif + int lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) @@ -282,7 +294,7 @@ case LWS_CALLBACK_HTTP_BODY_COMPLETION: #if defined(LWS_WITH_HTTP_PROXY) if (wsi->child_list) { - lwsl_user("%s: LWS_CALLBACK_HTTP_BODY_COMPLETION: %d\n", __func__, (int)len); + lwsl_info("%s: LWS_CALLBACK_HTTP_BODY_COMPLETION: %d\n", __func__, (int)len); break; } #endif @@ -296,7 +308,7 @@ #if defined(LWS_WITH_HTTP_PROXY) case LWS_CALLBACK_HTTP_BODY: if (wsi->child_list) { - lwsl_user("%s: LWS_CALLBACK_HTTP_BODY: stashing %d\n", __func__, (int)len); + lwsl_info("%s: LWS_CALLBACK_HTTP_BODY: stashing %d\n", __func__, (int)len); if (lws_buflist_append_segment(&wsi->http.buflist_post_body, in, len) < 0) return -1; lws_callback_on_writable(wsi->child_list); @@ -314,7 +326,7 @@ lwsl_debug("AUX_BF__CGI forcing close\n"); return -1; } - if (!n && wsi->http.cgi && + if (!n && wsi->http.cgi && wsi->http.cgi->lsp && wsi->http.cgi->lsp->stdwsi[LWS_STDOUT]) lws_rx_flow_control( wsi->http.cgi->lsp->stdwsi[LWS_STDOUT], 1); @@ -325,12 +337,16 @@ else wsi->reason_bf &= ~LWS_CB_REASON_AUX_BF__CGI; - if (wsi->http.cgi && wsi->http.cgi->cgi_transaction_over) + if (wsi->http.cgi && wsi->http.cgi->cgi_transaction_over) { + lwsl_info("%s: txn over\n", __func__); return -1; + } + break; } - if (wsi->reason_bf & LWS_CB_REASON_AUX_BF__CGI_CHUNK_END) { + if ((wsi->http.cgi && wsi->http.cgi->cgi_transaction_over) || + (wsi->reason_bf & LWS_CB_REASON_AUX_BF__CGI_CHUNK_END)) { if (!wsi->mux_substream) { memcpy(buf + LWS_PRE, "0\x0d\x0a\x0d\x0a", 5); lwsl_debug("writing chunk term and exiting\n"); @@ -482,7 +498,7 @@ return 0; start = p = (unsigned char *)buf + LWS_PRE; - end = p + sizeof(buf) - LWS_PRE - 256; + end = p + sizeof(buf) - LWS_PRE - MAXHDRVAL; if (lws_add_http_header_status(lws_get_parent(wsi), lws_http_client_http_response(wsi), &p, end)) @@ -492,21 +508,21 @@ * copy these headers from the client connection to the parent */ - proxy_header(parent, wsi, end, 256, + proxy_header(parent, wsi, end, MAXHDRVAL, WSI_TOKEN_HTTP_CONTENT_LENGTH, &p, end); - proxy_header(parent, wsi, end, 256, + proxy_header(parent, wsi, end, MAXHDRVAL, WSI_TOKEN_HTTP_CONTENT_TYPE, &p, end); - proxy_header(parent, wsi, end, 256, + proxy_header(parent, wsi, end, MAXHDRVAL, WSI_TOKEN_HTTP_ETAG, &p, end); - proxy_header(parent, wsi, end, 256, + proxy_header(parent, wsi, end, MAXHDRVAL, WSI_TOKEN_HTTP_ACCEPT_LANGUAGE, &p, end); - proxy_header(parent, wsi, end, 256, + proxy_header(parent, wsi, end, MAXHDRVAL, WSI_TOKEN_HTTP_CONTENT_ENCODING, &p, end); - proxy_header(parent, wsi, end, 256, + proxy_header(parent, wsi, end, MAXHDRVAL, WSI_TOKEN_HTTP_CACHE_CONTROL, &p, end); - proxy_header(parent, wsi, end, 256, + proxy_header(parent, wsi, end, MAXHDRVAL, WSI_TOKEN_HTTP_SET_COOKIE, &p, end); - proxy_header(parent, wsi, end, 256, + proxy_header(parent, wsi, end, MAXHDRVAL, WSI_TOKEN_HTTP_LOCATION, &p, end); if (!parent->mux_substream) @@ -637,8 +653,9 @@ /* TBD stdin rx flow control */ break; case LWS_STDOUT: - /* quench POLLIN on STDOUT until MASTER got writeable */ - lws_rx_flow_control(args->stdwsi[LWS_STDOUT], 0); + if (args->stdwsi[LWS_STDOUT]) + /* quench POLLIN on STDOUT until MASTER got writeable */ + lws_rx_flow_control(args->stdwsi[LWS_STDOUT], 0); wsi->reason_bf |= LWS_CB_REASON_AUX_BF__CGI; /* when writing to MASTER would not block */ lws_callback_on_writable(wsi); @@ -773,33 +790,38 @@ lwsl_notice("LWS_CALLBACK_CGI_STDIN_DATA: " "sent %d only %d went", n, args->len); + lwsl_info("%s: proxied %d bytes\n", __func__, n); + if (wsi->http.cgi->post_in_expected && args->stdwsi[LWS_STDIN] && args->stdwsi[LWS_STDIN]->desc.filefd > 0) { wsi->http.cgi->post_in_expected -= n; + if (!wsi->http.cgi->post_in_expected) { struct lws *siwsi = args->stdwsi[LWS_STDIN]; - lwsl_debug("%s: expected POST in end: " - "closing stdin wsi %p, fd %d\n", - __func__, siwsi, siwsi->desc.sockfd); - - __remove_wsi_socket_from_fds(siwsi); - lwsi_set_state(siwsi, LRS_DEAD_SOCKET); - siwsi->socket_is_permanently_unusable = 1; -// lws_remove_child_from_any_parent(siwsi); - if (wsi->context->event_loop_ops-> - close_handle_manually) { - - wsi->context->event_loop_ops-> - close_handle_manually(siwsi); - siwsi->told_event_loop_closed = 1; - } else { - compatible_close(siwsi->desc.sockfd); - __lws_free_wsi(siwsi); - } - wsi->http.cgi->lsp->pipe_fds[LWS_STDIN][1] = -1; - -// args->stdwsi[LWS_STDIN] = NULL; + /* + * The situation here is that we finished + * proxying the incoming body from the net to + * the STDIN stdwsi... and we want to close it + * so it can understand we are done (necessary + * if no content-length)... + */ + + lwsl_info("%s: expected POST in end: " + "closing stdin wsi %p, fd %d\n", + __func__, siwsi, + siwsi->desc.sockfd); + + /* + * We don't want the child / parent relationship + * to be handled in close, since we want the + * rest of the cgi and children to stay up + */ + + lws_remove_child_from_any_parent(siwsi); + lws_wsi_close(siwsi, LWS_TO_KILL_ASYNC); + wsi->http.cgi->lsp->stdwsi[LWS_STDIN] = NULL; + lws_spawn_stdwsi_closed(wsi->http.cgi->lsp, siwsi); } } diff -Nru libwebsockets-4.0.20/lib/core-net/network.c libwebsockets-4.1.6/lib/core-net/network.c --- libwebsockets-4.0.20/lib/core-net/network.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/core-net/network.c 2020-12-01 17:40:26.000000000 +0000 @@ -23,6 +23,7 @@ */ #include "private-lib-core.h" +#include #if !defined(LWS_PLAT_FREERTOS) && !defined(LWS_PLAT_OPTEE) static int @@ -152,7 +153,7 @@ name[0] = '\0'; #ifdef LWS_WITH_IPV6 - if (LWS_IPV6_ENABLED(wsi->vhost)) { + if (LWS_IPV6_ENABLED(wsi->a.vhost)) { len = sizeof(sin6); p = &sin6; } else @@ -167,7 +168,7 @@ goto bail; } - lws_get_addresses(wsi->vhost, p, name, name_len, rip, rip_len); + lws_get_addresses(wsi->a.vhost, p, name, name_len, rip, rip_len); bail: #endif @@ -224,14 +225,14 @@ iface); return LWS_ITOSA_NOT_EXIST; } - n = sizeof(uint16_t) + strlen(iface); + n = (int)(sizeof(uint16_t) + strlen(iface)); strcpy(serv_unix.sun_path, iface); if (serv_unix.sun_path[0] == '@') serv_unix.sun_path[0] = '\0'; else unlink(serv_unix.sun_path); - //lwsl_hexdump_notice(v, n); + // lwsl_hexdump_notice(v, n); } else #endif @@ -314,7 +315,7 @@ return LWS_ITOSA_NOT_EXIST; } -#if defined(LWS_WITH_UNIX_SOCK) +#if defined(LWS_WITH_UNIX_SOCK) && !defined(WIN32) if (!port && LWS_UNIX_SOCK_ENABLED(vhost)) { uid_t uid = vhost->context->uid; gid_t gid = vhost->context->gid; @@ -327,21 +328,21 @@ return LWS_ITOSA_NOT_EXIST; } } - if (uid && gid) { - if (chown(serv_unix.sun_path, uid, gid)) { + if (iface && iface[0] != '@' && uid && gid) { + if (chown(iface, uid, gid)) { lwsl_err("%s: failed to set %s perms %u:%u\n", - __func__, serv_unix.sun_path, + __func__, iface, (unsigned int)uid, (unsigned int)gid); return LWS_ITOSA_NOT_EXIST; } lwsl_notice("%s: vh %s unix skt %s perms %u:%u\n", - __func__, vhost->name, serv_unix.sun_path, + __func__, vhost->name, iface, (unsigned int)uid, (unsigned int)gid); - if (chmod(serv_unix.sun_path, 0660)) { + if (chmod(iface, 0660)) { lwsl_err("%s: failed to set %s to 0600 mode\n", - __func__, serv_unix.sun_path); + __func__, iface); return LWS_ITOSA_NOT_EXIST; } @@ -429,20 +430,45 @@ lws_retry_sul_schedule_retry_wsi(struct lws *wsi, lws_sorted_usec_list_t *sul, sul_cb_t cb, uint16_t *ctry) { - return lws_retry_sul_schedule(wsi->context, wsi->tsi, sul, + return lws_retry_sul_schedule(wsi->a.context, wsi->tsi, sul, wsi->retry_policy, cb, ctry); } #if defined(LWS_WITH_IPV6) unsigned long -lws_get_addr_scope(const char *ipaddr) +lws_get_addr_scope(const char *ifname_or_ipaddr) { - unsigned long scope = 0; - -#ifndef WIN32 - struct ifaddrs *addrs, *addr; + unsigned long scope; char ip[NI_MAXHOST]; unsigned int i; +#if !defined(WIN32) + struct ifaddrs *addrs, *addr; +#else + PIP_ADAPTER_ADDRESSES adapter, addrs = NULL; + PIP_ADAPTER_UNICAST_ADDRESS addr; + struct sockaddr_in6 *sockaddr; + ULONG size = 0; + int found = 0; + DWORD ret; +#endif + + /* + * First see if we can look the string up as a network interface name... + * windows vista+ also has this + */ + + scope = if_nametoindex(ifname_or_ipaddr); + if (scope > 0) + /* we found it from the interface name lookup */ + return scope; + + /* + * if not, try to look it up as an IP -> interface -> interface index + */ + + scope = 0; + +#if !defined(WIN32) getifaddrs(&addrs); for (addr = addrs; addr; addr = addr->ifa_next) { @@ -450,6 +476,7 @@ addr->ifa_addr->sa_family != AF_INET6) continue; + ip[0] = '\0'; getnameinfo(addr->ifa_addr, sizeof(struct sockaddr_in6), ip, sizeof(ip), @@ -462,21 +489,13 @@ break; } - if (!strcmp(ip, ipaddr)) { + if (!strcmp(ip, ifname_or_ipaddr)) { scope = if_nametoindex(addr->ifa_name); break; } } freeifaddrs(addrs); #else - PIP_ADAPTER_ADDRESSES adapter, addrs = NULL; - PIP_ADAPTER_UNICAST_ADDRESS addr; - ULONG size = 0; - DWORD ret; - struct sockaddr_in6 *sockaddr; - char ip[NI_MAXHOST]; - unsigned int i; - int found = 0; for (i = 0; i < 5; i++) { @@ -515,7 +534,7 @@ &sockaddr->sin6_addr, ip, sizeof(ip)); - if (!strcmp(ip, ipaddr)) { + if (!strcmp(ip, ifname_or_ipaddr)) { scope = sockaddr->sin6_scope_id; found = 1; break; @@ -832,8 +851,10 @@ return sa46a->sa4.sin_addr.s_addr != sa46b->sa4.sin_addr.s_addr; } +#if defined(LWS_WITH_SYS_STATE) lws_state_manager_t * lws_system_get_state_manager(struct lws_context *context) { return &context->mgr_system; } +#endif diff -Nru libwebsockets-4.0.20/lib/core-net/output.c libwebsockets-4.1.6/lib/core-net/output.c --- libwebsockets-4.0.20/lib/core-net/output.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/core-net/output.c 2020-12-01 17:40:26.000000000 +0000 @@ -31,12 +31,19 @@ lws_issue_raw(struct lws *wsi, unsigned char *buf, size_t len) { struct lws_context *context = lws_get_context(wsi); - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; size_t real_len = len; unsigned int n, m; - // lwsl_notice("%s: len %d\n", __func__, (int)len); - // lwsl_hexdump_level(LLL_NOTICE, buf, len); + /* + * If you're looking to dump data being sent down the tls tunnel, see + * lws_ssl_capable_write() in lib/tls/mbedtls/mbedtls-ssl.c or + * lib/tls/openssl/openssl-ssl.c. + * + * There's also a corresponding lws_ssl_capable_read() in those files + * where you can enable a dump of decrypted data as soon as it was + * read. + */ /* * Detect if we got called twice without going through the @@ -47,8 +54,8 @@ lwsl_hexdump_level(LLL_INFO, buf, len); lwsl_info("** %p: vh: %s, prot: %s, role %s: " "Inefficient back-to-back write of %lu detected...\n", - wsi, wsi->vhost ? wsi->vhost->name : "no vhost", - wsi->protocol->name, wsi->role_ops->name, + wsi, wsi->a.vhost ? wsi->a.vhost->name : "no vhost", + wsi->a.protocol->name, wsi->role_ops->name, (unsigned long)len); } @@ -65,8 +72,8 @@ if (buf && lws_has_buffered_out(wsi)) { lwsl_info("** %p: vh: %s, prot: %s, incr buflist_out by %lu\n", - wsi, wsi->vhost ? wsi->vhost->name : "no vhost", - wsi->protocol->name, (unsigned long)len); + wsi, wsi->a.vhost ? wsi->a.vhost->name : "no vhost", + wsi->a.protocol->name, (unsigned long)len); /* * already buflist ahead of this, add it on the tail of the @@ -97,10 +104,10 @@ lwsl_err("%s: invalid sock %p\n", __func__, wsi); /* limit sending */ - if (wsi->protocol->tx_packet_size) - n = (int)wsi->protocol->tx_packet_size; + if (wsi->a.protocol->tx_packet_size) + n = (int)wsi->a.protocol->tx_packet_size; else { - n = (int)wsi->protocol->rx_buffer_size; + n = (int)wsi->a.protocol->rx_buffer_size; if (!n) n = context->pt_serv_buf_size; } @@ -228,7 +235,7 @@ lws_write(struct lws *wsi, unsigned char *buf, size_t len, enum lws_write_protocol wp) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; #if defined(LWS_WITH_DETAILED_LATENCY) lws_usec_t us; #endif @@ -248,8 +255,8 @@ wsi->http.access_log.sent += len; #endif #if defined(LWS_WITH_SERVER_STATUS) - if (wsi->vhost) - wsi->vhost->conn_stats.tx += len; + if (wsi->a.vhost) + wsi->a.vhost->conn_stats.tx += len; #endif #if defined(LWS_WITH_DETAILED_LATENCY) us = lws_now_usecs(); @@ -264,7 +271,7 @@ return m; #if defined(LWS_WITH_DETAILED_LATENCY) - if (wsi->context->detailed_latency_cb) { + if (wsi->a.context->detailed_latency_cb) { wsi->detlat.req_size = len; wsi->detlat.acc_size = m; wsi->detlat.type = LDLT_WRITE; @@ -274,7 +281,7 @@ else wsi->detlat.latencies[LAT_DUR_PROXY_PROXY_REQ_TO_WRITE] = 0; wsi->detlat.latencies[LAT_DUR_USERCB] = lws_now_usecs() - us; - lws_det_lat_cb(wsi->context, &wsi->detlat); + lws_det_lat_cb(wsi->a.context, &wsi->detlat); } #endif @@ -285,7 +292,7 @@ int lws_ssl_capable_read_no_ssl(struct lws *wsi, unsigned char *buf, int len) { - struct lws_context *context = wsi->context; + struct lws_context *context = wsi->a.context; struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; int n = 0; @@ -314,8 +321,8 @@ return LWS_SSL_CAPABLE_ERROR; #if defined(LWS_WITH_SERVER_STATUS) - if (wsi->vhost) - wsi->vhost->conn_stats.rx += n; + if (wsi->a.vhost) + wsi->a.vhost->conn_stats.rx += n; #endif lws_stats_bump(pt, LWSSTATS_B_READ, n); @@ -341,15 +348,15 @@ #if defined(LWS_WITH_UDP) if (lws_wsi_is_udp(wsi)) { - if (wsi->context->udp_loss_sim_tx_pc) { + if (wsi->a.context->udp_loss_sim_tx_pc) { uint16_t u16; /* * We should randomly drop some of these */ - if (lws_get_random(wsi->context, &u16, 2) == 2 && + if (lws_get_random(wsi->a.context, &u16, 2) == 2 && ((u16 * 100) / 0xffff) <= - wsi->context->udp_loss_sim_tx_pc) { + wsi->a.context->udp_loss_sim_tx_pc) { lwsl_warn("%s: dropping udp tx\n", __func__); /* pretend it was sent */ n = len; diff -Nru libwebsockets-4.0.20/lib/core-net/pollfd.c libwebsockets-4.1.6/lib/core-net/pollfd.c --- libwebsockets-4.0.20/lib/core-net/pollfd.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/core-net/pollfd.c 2020-12-01 17:40:26.000000000 +0000 @@ -27,8 +27,7 @@ int _lws_change_pollfd(struct lws *wsi, int _and, int _or, struct lws_pollargs *pa) { -#if !defined(LWS_WITH_LIBUV) && !defined(LWS_WITH_LIBEV) && \ - !defined(LWS_WITH_LIBEVENT) && !defined(LWS_WITH_GLIB) +#if !defined(LWS_WITH_EVENT_LIBS) volatile struct lws_context_per_thread *vpt; #endif struct lws_context_per_thread *pt; @@ -67,13 +66,12 @@ return 0; } - context = wsi->context; + context = wsi->a.context; pt = &context->pt[(int)wsi->tsi]; assert(wsi->position_in_fds_table < (int)pt->fds_count); -#if !defined(LWS_WITH_LIBUV) && !defined(LWS_WITH_LIBEV) && \ - !defined(LWS_WITH_LIBEVENT) && !defined(LWS_WITH_GLIB) +#if !defined(LWS_WITH_EVENT_LIBS) /* * This only applies when we use the default poll() event loop. * @@ -157,8 +155,8 @@ #if defined(LWS_WITH_EXTERNAL_POLL) - if (wsi->vhost && - wsi->vhost->protocols[0].callback(wsi, + if (wsi->a.vhost && + wsi->a.vhost->protocols[0].callback(wsi, LWS_CALLBACK_CHANGE_MODE_POLL_FD, wsi->user_space, (void *)pa, 0)) { ret = -1; @@ -200,8 +198,8 @@ goto bail; } sampled_tid = pt->service_tid; - if (sampled_tid && wsi->vhost) { - tid = wsi->vhost->protocols[0].callback(wsi, + if (sampled_tid && wsi->a.vhost) { + tid = wsi->a.vhost->protocols[0].callback(wsi, LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0); if (tid == -1) { ret = -1; @@ -273,6 +271,8 @@ // __dump_fds(pt, "pre insert"); + lws_pt_assert_lock_held(pt); + lwsl_debug("%s: %p: tsi=%d, sock=%d, pos-in-fds=%d\n", __func__, wsi, wsi->tsi, wsi->desc.sockfd, pt->fds_count); @@ -283,7 +283,7 @@ } #if !defined(_WIN32) - if (!wsi->context->max_fds_unrelated_to_ulimit && + if (!wsi->a.context->max_fds_unrelated_to_ulimit && wsi->desc.sockfd - lws_plat_socket_offset() >= context->max_fds) { lwsl_err("Socket fd %d is too high (%d) offset %d\n", wsi->desc.sockfd, context->max_fds, @@ -293,13 +293,13 @@ #endif assert(wsi); - assert(wsi->event_pipe || wsi->vhost); + assert(wsi->event_pipe || wsi->a.vhost); assert(lws_socket_is_valid(wsi->desc.sockfd)); #if defined(LWS_WITH_EXTERNAL_POLL) - if (wsi->vhost && - wsi->vhost->protocols[0].callback(wsi, LWS_CALLBACK_LOCK_POLL, + if (wsi->a.vhost && + wsi->a.vhost->protocols[0].callback(wsi, LWS_CALLBACK_LOCK_POLL, wsi->user_space, (void *) &pa, 1)) return -1; #endif @@ -320,8 +320,8 @@ #if defined(LWS_WITH_EXTERNAL_POLL) /* external POLL support via protocol 0 */ - if (wsi->vhost && - wsi->vhost->protocols[0].callback(wsi, LWS_CALLBACK_ADD_POLL_FD, + if (wsi->a.vhost && + wsi->a.vhost->protocols[0].callback(wsi, LWS_CALLBACK_ADD_POLL_FD, wsi->user_space, (void *) &pa, 0)) ret = -1; #endif @@ -332,8 +332,8 @@ #endif #if defined(LWS_WITH_EXTERNAL_POLL) - if (wsi->vhost && - wsi->vhost->protocols[0].callback(wsi, LWS_CALLBACK_UNLOCK_POLL, + if (wsi->a.vhost && + wsi->a.vhost->protocols[0].callback(wsi, LWS_CALLBACK_UNLOCK_POLL, wsi->user_space, (void *)&pa, 1)) ret = -1; #endif @@ -346,7 +346,7 @@ int __remove_wsi_socket_from_fds(struct lws *wsi) { - struct lws_context *context = wsi->context; + struct lws_context *context = wsi->a.context; #if defined(LWS_WITH_EXTERNAL_POLL) struct lws_pollargs pa = { wsi->desc.sockfd, 0, 0 }; #endif @@ -354,10 +354,12 @@ struct lws *end_wsi; int v, m, ret = 0; + lws_pt_assert_lock_held(pt); + // __dump_fds(pt, "pre remove"); #if !defined(_WIN32) - if (!wsi->context->max_fds_unrelated_to_ulimit && + if (!wsi->a.context->max_fds_unrelated_to_ulimit && wsi->desc.sockfd - lws_plat_socket_offset() > context->max_fds) { lwsl_err("fd %d too high (%d)\n", wsi->desc.sockfd, context->max_fds); @@ -366,20 +368,19 @@ } #endif #if defined(LWS_WITH_EXTERNAL_POLL) - if (wsi->vhost && wsi->vhost->protocols && - wsi->vhost->protocols[0].callback(wsi, LWS_CALLBACK_LOCK_POLL, + if (wsi->a.vhost && wsi->a.vhost->protocols && + wsi->a.vhost->protocols[0].callback(wsi, LWS_CALLBACK_LOCK_POLL, wsi->user_space, (void *)&pa, 1)) return -1; #endif - lws_same_vh_protocol_remove(wsi); + __lws_same_vh_protocol_remove(wsi); /* the guy who is to be deleted's slot index in pt->fds */ m = wsi->position_in_fds_table; /* these are the only valid possibilities for position_in_fds_table */ - assert(m == LWS_NO_FDS_POS || (m >= 0 && - (unsigned int)m < pt->fds_count)); + assert(m == LWS_NO_FDS_POS || (m >= 0 && (unsigned int)m < pt->fds_count)); if (context->event_loop_ops->io) context->event_loop_ops->io(wsi, @@ -418,7 +419,7 @@ lwsl_err("no wsi for fd %d pos %d, " "pt->fds_count=%d\n", (int)pt->fds[m].fd, m, pt->fds_count); - assert(0); + // assert(0); } else end_wsi->position_in_fds_table = m; } @@ -429,8 +430,8 @@ #if defined(LWS_WITH_EXTERNAL_POLL) /* remove also from external POLL support via protocol 0 */ - if (lws_socket_is_valid(wsi->desc.sockfd) && wsi->vhost && - wsi->vhost->protocols[0].callback(wsi, LWS_CALLBACK_DEL_POLL_FD, + if (lws_socket_is_valid(wsi->desc.sockfd) && wsi->a.vhost && + wsi->a.vhost->protocols[0].callback(wsi, LWS_CALLBACK_DEL_POLL_FD, wsi->user_space, (void *) &pa, 0)) ret = -1; #endif @@ -443,8 +444,8 @@ #endif #if defined(LWS_WITH_EXTERNAL_POLL) - if (wsi->vhost && - wsi->vhost->protocols[0].callback(wsi, LWS_CALLBACK_UNLOCK_POLL, + if (wsi->a.vhost && + wsi->a.vhost->protocols[0].callback(wsi, LWS_CALLBACK_UNLOCK_POLL, wsi->user_space, (void *) &pa, 1)) ret = -1; #endif @@ -461,7 +462,7 @@ struct lws_pollargs pa; int ret = 0; - if (!wsi || (!wsi->protocol && !wsi->event_pipe) || + if (!wsi || (!wsi->a.protocol && !wsi->event_pipe) || wsi->position_in_fds_table == LWS_NO_FDS_POS) return 0; @@ -470,8 +471,8 @@ return 1; #if defined(LWS_WITH_EXTERNAL_POLL) - if (wsi->vhost && - wsi->vhost->protocols[0].callback(wsi, LWS_CALLBACK_LOCK_POLL, + if (wsi->a.vhost && + wsi->a.vhost->protocols[0].callback(wsi, LWS_CALLBACK_LOCK_POLL, wsi->user_space, (void *) &pa, 0)) return -1; #endif @@ -479,8 +480,8 @@ ret = _lws_change_pollfd(wsi, _and, _or, &pa); #if defined(LWS_WITH_EXTERNAL_POLL) - if (wsi->vhost && - wsi->vhost->protocols[0].callback(wsi, LWS_CALLBACK_UNLOCK_POLL, + if (wsi->a.vhost && + wsi->a.vhost->protocols[0].callback(wsi, LWS_CALLBACK_UNLOCK_POLL, wsi->user_space, (void *) &pa, 0)) ret = -1; #endif @@ -494,7 +495,7 @@ struct lws_context_per_thread *pt; int ret = 0; - pt = &wsi->context->pt[(int)wsi->tsi]; + pt = &wsi->a.context->pt[(int)wsi->tsi]; lws_pt_lock(pt, __func__); ret = __lws_change_pollfd(wsi, _and, _or); @@ -515,7 +516,7 @@ if (wsi->socket_is_permanently_unusable) return 0; - pt = &wsi->context->pt[(int)wsi->tsi]; + pt = &wsi->a.context->pt[(int)wsi->tsi]; #if defined(LWS_WITH_DETAILED_LATENCY) if (!wsi->detlat.earliest_write_req) @@ -565,35 +566,35 @@ void lws_same_vh_protocol_insert(struct lws *wsi, int n) { - lws_vhost_lock(wsi->vhost); + lws_vhost_lock(wsi->a.vhost); lws_dll2_remove(&wsi->same_vh_protocol); lws_dll2_add_head(&wsi->same_vh_protocol, - &wsi->vhost->same_vh_protocol_owner[n]); + &wsi->a.vhost->same_vh_protocol_owner[n]); wsi->bound_vhost_index = n; - lws_vhost_unlock(wsi->vhost); + lws_vhost_unlock(wsi->a.vhost); } void __lws_same_vh_protocol_remove(struct lws *wsi) { - if (wsi->vhost && wsi->vhost->same_vh_protocol_owner) + if (wsi->a.vhost && wsi->a.vhost->same_vh_protocol_owner) lws_dll2_remove(&wsi->same_vh_protocol); } void lws_same_vh_protocol_remove(struct lws *wsi) { - if (!wsi->vhost) + if (!wsi->a.vhost) return; - lws_vhost_lock(wsi->vhost); + lws_vhost_lock(wsi->a.vhost); __lws_same_vh_protocol_remove(wsi); - lws_vhost_unlock(wsi->vhost); + lws_vhost_unlock(wsi->a.vhost); } @@ -619,7 +620,7 @@ lws_dll2_get_head(&vhost->same_vh_protocol_owner[n])) { wsi = lws_container_of(d, struct lws, same_vh_protocol); - assert(wsi->protocol == protocol); + assert(wsi->a.protocol == protocol); lws_callback_on_writable(wsi); } lws_end_foreach_dll_safe(d, d1); diff -Nru libwebsockets-4.0.20/lib/core-net/private-lib-core-net.h libwebsockets-4.1.6/lib/core-net/private-lib-core-net.h --- libwebsockets-4.0.20/lib/core-net/private-lib-core-net.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/core-net/private-lib-core-net.h 2020-12-01 17:40:26.000000000 +0000 @@ -48,14 +48,6 @@ #include "private-lib-roles.h" -#ifdef LWS_WITH_IPV6 -#if defined(WIN32) || defined(_WIN32) -#include -#else -#include -#endif -#endif - #ifdef __cplusplus extern "C" { #endif @@ -77,6 +69,10 @@ LWS_SSL_CAPABLE_MORE_SERVICE = -4, /* general retry */ }; +#define __lws_sul_insert_us(owner, sul, _us) \ + (sul)->us = lws_now_usecs() + _us; \ + __lws_sul_insert(owner, sul) + /* * @@ -178,6 +174,7 @@ PMDR_HAS_PENDING, PMDR_EMPTY_NONFINAL, PMDR_EMPTY_FINAL, + PMDR_NOTHING_WE_SHOULD_DO, PMDR_FAILED = -1 }; @@ -187,10 +184,11 @@ struct lws_peer *next; struct lws_peer *peer_wait_list; + lws_sockaddr46 sa46; + time_t time_created; time_t time_closed_all; - uint8_t addr[32]; uint32_t hash; uint32_t count_wsi; uint32_t total_wsi; @@ -198,8 +196,6 @@ #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) struct lws_peer_role_http http; #endif - - uint8_t af; }; #endif @@ -268,12 +264,11 @@ #define LWS_H2_FRAME_HEADER_LENGTH 9 -int -__lws_sul_insert(lws_dll2_owner_t *own, lws_sorted_usec_list_t *sul, - lws_usec_t us); lws_usec_t -__lws_sul_service_ripe(lws_dll2_owner_t *own, lws_usec_t usnow); +__lws_sul_service_ripe(lws_dll2_owner_t *own, int num_own, lws_usec_t usnow); + +#if defined(LWS_WITH_DEPRECATED_THINGS) struct lws_timed_vh_protocol { struct lws_timed_vh_protocol *next; @@ -284,6 +279,8 @@ int tsi_req; }; +#endif + /* * lws_dsh */ @@ -368,7 +365,7 @@ lws_dll2_owner_t ss_client_owner; #endif - struct lws_dll2_owner pt_sul_owner; + struct lws_dll2_owner pt_sul_owner[LWS_COUNT_PT_SUL_OWNERS]; #if defined (LWS_WITH_SEQUENCER) lws_sorted_usec_list_t sul_seq_heartbeat; @@ -394,11 +391,13 @@ lws_sorted_usec_list_t sul_peer_limits; #endif +#if !defined(LWS_PLAT_FREERTOS) + struct lws *fake_wsi; /* used for callbacks where there's no wsi */ +#endif + #if defined(LWS_WITH_TLS) struct lws_pt_tls tls; #endif - struct lws *fake_wsi; /* used for callbacks where there's no wsi */ - struct lws_context *context; /* @@ -411,7 +410,7 @@ struct lws_pollfd *fds; volatile struct lws_foreign_thread_pollfd * volatile foreign_pfd_list; #ifdef _WIN32 - WSAEVENT events; + WSAEVENT events[WSA_MAXIMUM_WAIT_EVENTS]; CRITICAL_SECTION interrupt_lock; #endif lws_sockfd_type dummy_pipe_fds[2]; @@ -430,22 +429,8 @@ #endif /* --- event library based members --- */ -#if defined(LWS_WITH_LIBEV) - struct lws_pt_eventlibs_libev ev; -#endif -#if defined(LWS_WITH_LIBUV) - struct lws_pt_eventlibs_libuv uv; -#endif -#if defined(LWS_WITH_LIBEVENT) - struct lws_pt_eventlibs_libevent event; -#endif -#if defined(LWS_WITH_GLIB) - struct lws_pt_eventlibs_glib glib; -#endif - -#if defined(LWS_WITH_LIBEV) || defined(LWS_WITH_LIBUV) || \ - defined(LWS_WITH_LIBEVENT) || defined(LWS_WITH_GLIB) - struct lws_signal_watcher w_sigint; +#if defined(LWS_WITH_EVENT_LIBS) + void *evlib_pt; /* overallocated */ #endif #if defined(LWS_WITH_DETAILED_LATENCY) @@ -477,9 +462,6 @@ unsigned char event_loop_destroy_processing_done:1; unsigned char destroy_self:1; unsigned char is_destroyed:1; -#ifdef _WIN32 - unsigned char interrupt_requested:1; -#endif }; #if defined(LWS_WITH_SERVER_STATUS) @@ -532,8 +514,8 @@ char socks_user[96]; char socks_password[96]; #endif -#if defined(LWS_WITH_LIBEV) - struct lws_io_watcher w_accept; +#if defined(LWS_WITH_EVENT_LIBS) + void *evlib_vh; /* overallocated */ #endif #if defined(LWS_WITH_SERVER_STATUS) struct lws_conn_stats conn_stats; @@ -546,6 +528,10 @@ const lws_retry_bo_t *retry_policy; +#if defined(LWS_WITH_SERVER) && defined(LWS_WITH_SECURE_STREAMS) + lws_ss_handle_t *ss_handle; /* ss handle for the server obj */ +#endif + struct lws *lserv_wsi; const char *name; const char *iface; @@ -573,7 +559,9 @@ struct lws_vhost_tls tls; #endif +#if defined(LWS_WITH_DEPRECATED_THINGS) struct lws_timed_vh_protocol *timed_vh_protocol_list; +#endif void *user; int listen_port; @@ -590,6 +578,7 @@ int ka_interval; int keepalive_timeout; int timeout_secs_ah_idle; + int connect_timeout_secs; int count_bound_wsi; @@ -597,6 +586,12 @@ int log_fd; #endif +#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) + int8_t ss_refcount; + /**< refcount of number of ss connections with streamtypes using this + * trust store */ +#endif + uint8_t allocated_vhost_protocols:1; uint8_t created_vhost_protocols:1; uint8_t being_destroyed:1; @@ -639,7 +634,50 @@ * struct lws */ +/* + * These pieces are very commonly used (via accessors) in user protocol handlers + * and have to be valid, even in the case no real wsi is available for the cb. + * + * We put all this category of pointers in there and compose it at the top of + * struct lws, so a dummy wsi providing these only needs to be this big, while + * still being castable for being a struct wsi * + */ + +struct lws_a { + struct lws_context *context; + struct lws_vhost *vhost; + const struct lws_protocols *protocol; + void *opaque_user_data; +}; + +/* + * For RTOS-class platforms, their code is relatively new, post-minimal examples + * and tend to not have legacy user protocol handler baggage touching unexpected + * things in fakewsi unconditionally... we can use an lws_a on the stack and + * don't need to define the rest of the wsi content, just cast it, this saves + * a wsi footprint in heap (typ 800 bytes nowadays even on RTOS). + * + * For other platforms that have been around for years and have thousands of + * different user protocol handler implementations, it's likely some of them + * will be touching the struct lws content unconditionally in the handler even + * when we are calling back with a non wsi-specific reason, and may react badly + * to it being garbage. So continue to implement those as a full, zero-ed down + * prepared fakewsi on heap at context creation time. + */ + +#if defined(LWS_PLAT_FREERTOS) +#define lws_fakewsi_def_plwsa(pt) struct lws_a lwsa, *plwsa = &lwsa +#else +#define lws_fakewsi_def_plwsa(pt) struct lws_a *plwsa = &(pt)->fake_wsi->a +#endif +/* since we reuse the pt version, also correct to zero down the lws_a part */ +#define lws_fakewsi_prep_plwsa_ctx(_c) \ + memset(plwsa, 0, sizeof(*plwsa)); plwsa->context = _c + struct lws { + + struct lws_a a; + /* structs */ #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) @@ -665,12 +703,8 @@ /* lifetime members */ -#if defined(LWS_WITH_LIBEV) || defined(LWS_WITH_LIBUV) || \ - defined(LWS_WITH_LIBEVENT) || defined(LWS_WITH_GLIB) - struct lws_io_watcher w_read; -#endif -#if defined(LWS_WITH_LIBEV) || defined(LWS_WITH_LIBEVENT) - struct lws_io_watcher w_write; +#if defined(LWS_WITH_EVENT_LIBS) + void *evlib_wsi; /* overallocated */ #endif #if defined(LWS_WITH_DETAILED_LATENCY) @@ -680,6 +714,7 @@ lws_sorted_usec_list_t sul_timeout; lws_sorted_usec_list_t sul_hrtimer; lws_sorted_usec_list_t sul_validity; + lws_sorted_usec_list_t sul_connect_timeout; struct lws_dll2 dll_buflist; /* guys with pending rxflow */ struct lws_dll2 same_vh_protocol; @@ -699,18 +734,15 @@ #endif /* pointers */ - struct lws_context *context; - struct lws_vhost *vhost; struct lws *parent; /* points to parent, if any */ struct lws *child_list; /* points to first child */ struct lws *sibling_list; /* subsequent children at same level */ const struct lws_role_ops *role_ops; - const struct lws_protocols *protocol; struct lws_sequencer *seq; /* associated sequencer if any */ const lws_retry_bo_t *retry_policy; #if defined(LWS_WITH_THREADPOOL) - struct lws_threadpool_task *tp_task; + lws_dll2_owner_t tp_task_owner; /* struct lws_threadpool_task */ #endif #if defined(LWS_WITH_PEER_LIMITS) @@ -728,7 +760,6 @@ #endif void *user_space; void *opaque_parent_data; - void *opaque_user_data; struct lws_buflist *buflist; /* input-side buflist */ struct lws_buflist *buflist_out; /* output-side buflist */ @@ -796,13 +827,17 @@ unsigned int h1_ws_proxied:1; unsigned int proxied_ws_parent:1; unsigned int do_bind:1; - unsigned int oom4:1; unsigned int validity_hup:1; unsigned int skip_fallback:1; + unsigned int file_desc:1; + unsigned int conn_validity_wakesuspend:1; unsigned int could_have_pending:1; /* detect back-to-back writes */ unsigned int outer_will_close:1; unsigned int shadow:1; /* we do not control fd lifecycle at all */ +#if defined(LWS_WITH_SECURE_STREAMS) + unsigned int for_ss:1; +#endif #ifdef LWS_WITH_ACCESS_LOG unsigned int access_log_pending:1; @@ -833,6 +868,9 @@ uint16_t ocport, c_port; uint16_t retry; +#if defined(LWS_WITH_CLIENT) + uint16_t keep_warm_secs; +#endif /* chars */ @@ -885,9 +923,11 @@ struct lws_dll2 dll; lws_sorted_usec_list_t sul; + lws_sorted_usec_list_t sul_reap; + struct lws_context *context; struct lws *stdwsi[3]; - int pipe_fds[3][2]; + lws_filefd_type pipe_fds[3][2]; int count_log_lines; lws_usec_t created; /* set by lws_spawn_piped() */ @@ -895,9 +935,15 @@ lws_usec_t accounting[4]; +#if defined(WIN32) + HANDLE child_pid; + lws_sorted_usec_list_t sul_poll; +#else pid_t child_pid; siginfo_t si; +#endif + int reap_retry_budget; uint8_t pipes_alive:2; uint8_t we_killed_him_timeout:1; @@ -954,6 +1000,7 @@ #define lws_pt_lock(pt, reason) lws_mutex_refcount_lock(&pt->mr, reason) #define lws_pt_unlock(pt) lws_mutex_refcount_unlock(&pt->mr) +#define lws_pt_assert_lock_held(pt) lws_mutex_refcount_assert_held(&pt->mr) static LWS_INLINE void lws_pt_stats_lock(struct lws_context_per_thread *pt) @@ -1095,11 +1142,15 @@ int lws_libuv_check_watcher_active(struct lws *wsi); -LWS_VISIBLE LWS_EXTERN int -lws_plat_plugins_init(struct lws_context * context, const char * const *d); +#if defined(LWS_WITH_EVLIB_PLUGINS) || defined(LWS_WITH_PLUGINS) +const lws_plugin_header_t * +lws_plat_dlopen(struct lws_plugin **pplugin, const char *libpath, + const char *sofilename, const char *_class, + each_plugin_cb_t each, void *each_user); -LWS_VISIBLE LWS_EXTERN int -lws_plat_plugins_destroy(struct lws_context * context); +int +lws_plat_destroy_dl(struct lws_plugin *p); +#endif struct lws * lws_adopt_socket_vhost(struct lws_vhost *vh, lws_sockfd_type accept_fd); @@ -1152,8 +1203,10 @@ lws_sum_stats(const struct lws_context *ctx, struct lws_conn_stats *cs); #endif +#if defined(LWS_WITH_DEPRECATED_THINGS) int __lws_timed_callback_remove(struct lws_vhost *vh, struct lws_timed_vh_protocol *p); +#endif int LWS_WARN_UNUSED_RESULT __insert_wsi_socket_into_fds(struct lws_context *context, struct lws *wsi); @@ -1260,6 +1313,10 @@ lws_plat_change_pollfd(struct lws_context *context, struct lws *wsi, struct lws_pollfd *pfd); +#if defined(LWS_WITH_SERVER) && defined(LWS_WITH_SECURE_STREAMS) +int +lws_adopt_ss_server_accept(struct lws *new_wsi); +#endif int lws_plat_pipe_create(struct lws *wsi); @@ -1384,13 +1441,29 @@ int lws_protocol_init_vhost(struct lws_vhost *vh, int *any); int -_lws_generic_transaction_completed_active_conn(struct lws **wsi); +_lws_generic_transaction_completed_active_conn(struct lws **wsi, char take_vh_lock); #define ACTIVE_CONNS_SOLO 0 #define ACTIVE_CONNS_MUXED 1 #define ACTIVE_CONNS_QUEUED 2 #define ACTIVE_CONNS_FAILED 3 +#if defined(_DEBUG) && !defined(LWS_PLAT_FREERTOS) && !defined(WIN32) && !defined(LWS_PLAT_OPTEE) + +int +sanity_assert_no_wsi_traces(const struct lws_context *context, struct lws *wsi); +int +sanity_assert_no_sockfd_traces(const struct lws_context *context, + lws_sockfd_type sfd); +#else +static inline int sanity_assert_no_wsi_traces(const struct lws_context *context, struct lws *wsi) { (void)context; (void)wsi; return 0; } +static inline int sanity_assert_no_sockfd_traces(const struct lws_context *context, lws_sockfd_type sfd) { (void)context; (void)sfd; return 0; } +#endif + + +void +delete_from_fdwsi(const struct lws_context *context, struct lws *wsi); + int lws_vhost_active_conns(struct lws *wsi, struct lws **nwsi, const char *adsin); @@ -1411,6 +1484,65 @@ int lws_socks5c_greet(struct lws *wsi, const char **pcce); +int +lws_plat_mbedtls_net_send(void *ctx, const uint8_t *buf, size_t len); + +int +lws_plat_mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len); + +lws_usec_t +lws_sul_nonmonotonic_adjust(struct lws_context *ctx, int64_t step_us); + +void +lws_netdev_instance_remove_destroy(struct lws_netdev_instance *ni); + +#if defined(LWS_WITH_SYS_SMD) +int +lws_netdev_smd_cb(void *opaque, lws_smd_class_t _class, lws_usec_t timestamp, + void *buf, size_t len); +#endif + +void +lws_netdev_instance_create(lws_netdev_instance_t *ni, struct lws_context *ctx, + const lws_netdev_ops_t *ops, const char *name, + void *platinfo); + +int +lws_netdev_wifi_rssi_sort_compare(const lws_dll2_t *d, const lws_dll2_t *i); +void +lws_netdev_wifi_scan_empty(lws_netdev_instance_wifi_t *wnd); + +lws_wifi_sta_t * +lws_netdev_wifi_scan_find(lws_netdev_instance_wifi_t *wnd, const char *ssid, + const uint8_t *bssid); + +int +lws_netdev_wifi_scan_select(lws_netdev_instance_wifi_t *wnd); + +lws_wifi_creds_t * +lws_netdev_credentials_find(lws_netdevs_t *netdevs, const char *ssid, + const uint8_t *bssid); + +int +lws_netdev_wifi_redo_last(lws_netdev_instance_wifi_t *wnd); + +void +lws_ntpc_trigger(struct lws_context *ctx); + +void +lws_netdev_wifi_scan(lws_sorted_usec_list_t *sul); + +#define lws_netdevs_from_ndi(ni) \ + lws_container_of((ni)->list.owner, lws_netdevs_t, owner) + +#define lws_context_from_netdevs(nd) \ + lws_container_of(nd, struct lws_context, netdevs) + +/* get the owner of the ni, then compute the context the owner is embedded in */ +#define netdev_instance_to_ctx(ni) \ + lws_container_of(lws_netdevs_from_ndi(ni), \ + struct lws_context, netdevs) + enum { LW5CHS_RET_RET0, LW5CHS_RET_BAIL3, diff -Nru libwebsockets-4.0.20/lib/core-net/sequencer.c libwebsockets-4.1.6/lib/core-net/sequencer.c --- libwebsockets-4.0.20/lib/core-net/sequencer.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/core-net/sequencer.c 2020-12-01 17:40:26.000000000 +0000 @@ -53,7 +53,8 @@ lws_usec_t time_created; lws_usec_t timeout; /* 0 or time we timeout */ - char going_down; + uint8_t going_down:1; + uint8_t wakesuspend:1; } lws_seq_t; #define QUEUE_SANITY_LIMIT 10 @@ -77,8 +78,8 @@ /* schedule the next one */ - __lws_sul_insert(&pt->pt_sul_owner, &pt->sul_seq_heartbeat, - LWS_US_PER_SEC); + __lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], + &pt->sul_seq_heartbeat, LWS_US_PER_SEC); } int @@ -87,8 +88,8 @@ pt->sul_seq_heartbeat.cb = lws_sul_seq_heartbeat_cb; /* schedule the first heartbeat */ - __lws_sul_insert(&pt->pt_sul_owner, &pt->sul_seq_heartbeat, - LWS_US_PER_SEC); + __lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], + &pt->sul_seq_heartbeat, LWS_US_PER_SEC); return 0; } @@ -106,6 +107,7 @@ seq->pt = pt; seq->name = i->name; seq->retry = i->retry; + seq->wakesuspend = i->wakesuspend; *i->puser = (void *)&seq[1]; @@ -242,7 +244,8 @@ lws_dll2_add_tail(&seqe->seq_event_list, &seq->seq_event_owner); seq->sul_pending.cb = lws_seq_sul_pending_cb; - __lws_sul_insert(&seq->pt->pt_sul_owner, &seq->sul_pending, 1); + __lws_sul_insert_us(&seq->pt->pt_sul_owner[seq->wakesuspend], + &seq->sul_pending, 1); lws_pt_unlock(seq->pt); /* } pt ------------------------------------- */ @@ -300,8 +303,10 @@ { seq->sul_timeout.cb = lws_seq_sul_timeout_cb; /* list is always at the very top of the sul */ - return __lws_sul_insert(&seq->pt->pt_sul_owner, + __lws_sul_insert_us(&seq->pt->pt_sul_owner[seq->wakesuspend], (lws_sorted_usec_list_t *)&seq->sul_timeout.list, us); + + return 0; } lws_seq_t * diff -Nru libwebsockets-4.0.20/lib/core-net/server.c libwebsockets-4.1.6/lib/core-net/server.c --- libwebsockets-4.0.20/lib/core-net/server.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/core-net/server.c 2020-12-01 17:40:26.000000000 +0000 @@ -175,9 +175,9 @@ struct lws_cgi * const *pcgi; #endif -#ifdef LWS_WITH_LIBUV - uv_uptime(&d); -#endif +//#ifdef LWS_WITH_LIBUV && +// uv_uptime(&d); +//#endif buf += lws_snprintf(buf, end - buf, "{ " "\"version\":\"%s\",\n" diff -Nru libwebsockets-4.0.20/lib/core-net/service.c libwebsockets-4.1.6/lib/core-net/service.c --- libwebsockets-4.0.20/lib/core-net/service.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/core-net/service.c 2020-12-01 17:40:26.000000000 +0000 @@ -27,7 +27,7 @@ int lws_callback_as_writeable(struct lws *wsi) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; int n, m; lws_stats_bump(pt, LWSSTATS_C_WRITEABLE_CB, 1); @@ -42,7 +42,7 @@ } #endif #if defined(LWS_WITH_DETAILED_LATENCY) - if (wsi->context->detailed_latency_cb && lwsi_state_est(wsi)) { + if (wsi->a.context->detailed_latency_cb && lwsi_state_est(wsi)) { lws_usec_t us = lws_now_usecs(); wsi->detlat.earliest_write_req_pre_write = @@ -53,7 +53,7 @@ } #endif n = wsi->role_ops->writeable_cb[lwsi_role_server(wsi)]; - m = user_callback_handle_rxflow(wsi->protocol->callback, + m = user_callback_handle_rxflow(wsi->a.protocol->callback, wsi, (enum lws_callback_reasons) n, wsi->user_space, NULL, 0); @@ -245,7 +245,7 @@ int lws_rxflow_cache(struct lws *wsi, unsigned char *buf, int n, int len) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; uint8_t *buffered; size_t blen; int ret = LWSRXFC_CACHED, m; @@ -299,8 +299,25 @@ if (!context) return 1; +#if defined(LWS_WITH_SYS_SMD) + if (!tsi && lws_smd_message_pending(context)) { + lws_smd_msg_distribute(context); + if (lws_smd_message_pending(context)) + return 0; + } +#endif + pt = &context->pt[tsi]; +#if defined(LWS_WITH_EXTERNAL_POLL) + { + lws_usec_t u = __lws_sul_service_ripe(pt->pt_sul_owner, + LWS_COUNT_PT_SUL_OWNERS, lws_now_usecs()); + if (u < timeout_ms * 1000) + timeout_ms = u / 1000; + } +#endif + /* * Figure out if we really want to wait in poll()... we only need to * wait if really nothing already to do and we have to wait for @@ -363,8 +380,8 @@ if (!ebuf->token) ebuf->token = pt->serv_buf + LWS_PRE; if (!ebuf->len || - (unsigned int)ebuf->len > wsi->context->pt_serv_buf_size - LWS_PRE) - ebuf->len = wsi->context->pt_serv_buf_size - LWS_PRE; + (unsigned int)ebuf->len > wsi->a.context->pt_serv_buf_size - LWS_PRE) + ebuf->len = wsi->a.context->pt_serv_buf_size - LWS_PRE; e = ebuf->len; ep = ebuf->token; @@ -387,7 +404,7 @@ ebuf->token = ep; ebuf->len = n = lws_ssl_capable_read(wsi, ep, e); - lwsl_info("%s: wsi %p: %s: ssl_capable_read %d\n", __func__, + lwsl_debug("%s: wsi %p: %s: ssl_capable_read %d\n", __func__, wsi, hint, ebuf->len); if (!bns && /* only acknowledge error when we handled buflist content */ @@ -442,7 +459,7 @@ lws_buflist_aware_finished_consuming(struct lws *wsi, struct lws_tokens *ebuf, int used, int buffered, const char *hint) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; int m; //lwsl_debug("%s %s consuming buffered %d used %zu / %zu\n", __func__, hint, @@ -587,18 +604,17 @@ if (wsi->position_in_fds_table >= 0) { - pt->fds[wsi->position_in_fds_table].revents |= - pt->fds[wsi->position_in_fds_table].events & LWS_POLLIN; - if (pt->fds[wsi->position_in_fds_table].revents & LWS_POLLIN) { - forced = 1; - /* - * he's going to get serviced now, take him off the - * list of guys with buffered SSL. If he still has some - * at the end of the service, he'll get put back on the - * list then. - */ - __lws_ssl_remove_wsi_from_buffered_list(wsi); - } + pt->fds[wsi->position_in_fds_table].revents |= + pt->fds[wsi->position_in_fds_table].events & + LWS_POLLIN; + if (pt->fds[wsi->position_in_fds_table].revents & + LWS_POLLIN) + /* + * We're not going to remove the wsi from the + * pending tls list. The processing will have + * to do it if he exhausts the pending tls. + */ + forced = 1; } } lws_end_foreach_dll_safe(p, p1); @@ -707,6 +723,8 @@ case LWS_HPI_RET_HANDLED: break; case LWS_HPI_RET_PLEASE_CLOSE_ME: + //lwsl_notice("%s: %s pollin says please close me\n", __func__, + // wsi->role_ops->name); close_and_handled: lwsl_debug("%p: Close and handled\n", wsi); lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, @@ -717,7 +735,7 @@ * it waits for libuv service to complete the first async * close */ - if (context->event_loop_ops == &event_loop_ops_uv) + if (!strcmp(context->event_loop_ops->name, "libuv")) lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "close_and_handled uv repeat test"); #endif diff -Nru libwebsockets-4.0.20/lib/core-net/socks5-client.c libwebsockets-4.1.6/lib/core-net/socks5-client.c --- libwebsockets-4.0.20/lib/core-net/socks5-client.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/core-net/socks5-client.c 2020-12-01 17:40:26.000000000 +0000 @@ -99,7 +99,7 @@ lws_socks5c_generate_msg(struct lws *wsi, enum socks_msg_type type, ssize_t *msg_len) { - struct lws_context *context = wsi->context; + struct lws_context *context = wsi->a.context; struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; uint8_t *p = pt->serv_buf, *end = &p[context->pt_serv_buf_size]; ssize_t n, passwd_len; @@ -121,8 +121,8 @@ break; case SOCKS_MSG_USERNAME_PASSWORD: - n = strlen(wsi->vhost->socks_user); - passwd_len = strlen(wsi->vhost->socks_password); + n = strlen(wsi->a.vhost->socks_user); + passwd_len = strlen(wsi->a.vhost->socks_password); if (n > 254 || passwd_len > 254) return 1; @@ -136,14 +136,14 @@ /* length of the user name */ *p++ = n; /* user name */ - memcpy(p, wsi->vhost->socks_user, n); + memcpy(p, wsi->a.vhost->socks_user, n); p += n; /* length of the password */ *p++ = passwd_len; /* password */ - memcpy(p, wsi->vhost->socks_password, passwd_len); + memcpy(p, wsi->a.vhost->socks_password, passwd_len); p += passwd_len; break; @@ -219,12 +219,12 @@ int lws_socks5c_greet(struct lws *wsi, const char **pcce) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; ssize_t plen; int n; /* socks proxy */ - if (!wsi->vhost->socks_proxy_port) + if (!wsi->a.vhost->socks_proxy_port) return 0; if (lws_socks5c_generate_msg(wsi, SOCKS_MSG_GREETING, &plen)) { @@ -241,7 +241,7 @@ } lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SOCKS_GREETING_REPLY, - wsi->context->timeout_secs); + wsi->a.context->timeout_secs); lwsi_set_state(wsi, LRS_WAITING_SOCKS_GREETING_REPLY); @@ -252,7 +252,7 @@ lws_socks5c_handle_state(struct lws *wsi, struct lws_pollfd *pollfd, const char **pcce) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; int conn_mode = 0, pending_timeout = 0; ssize_t len; int n; @@ -267,7 +267,7 @@ } n = recv(wsi->desc.sockfd, pt->serv_buf, - wsi->context->pt_serv_buf_size, 0); + wsi->a.context->pt_serv_buf_size, 0); if (n < 0) { if (LWS_ERRNO == LWS_EAGAIN) { lwsl_debug("SOCKS read EAGAIN, retrying\n"); @@ -339,7 +339,7 @@ } lws_set_timeout(wsi, pending_timeout, - wsi->context->timeout_secs); + wsi->a.context->timeout_secs); lwsi_set_state(wsi, conn_mode); break; @@ -359,13 +359,13 @@ #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) if (lwsi_role_http(wsi) && lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS, - wsi->vhost->socks_proxy_address)) { + wsi->a.vhost->socks_proxy_address)) { *pcce = "socks connect fail"; return LW5CHS_RET_BAIL3; } #endif - wsi->c_port = wsi->vhost->socks_proxy_port; + wsi->c_port = wsi->a.vhost->socks_proxy_port; /* clear his proxy connection timeout */ lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0); diff -Nru libwebsockets-4.0.20/lib/core-net/sorted-usec-list.c libwebsockets-4.1.6/lib/core-net/sorted-usec-list.c --- libwebsockets-4.0.20/lib/core-net/sorted-usec-list.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/core-net/sorted-usec-list.c 2020-12-01 17:40:26.000000000 +0000 @@ -43,69 +43,59 @@ return 0; } +/* + * notice owner was chosen already, and sul->us was already computed + */ + int -__lws_sul_insert(lws_dll2_owner_t *own, lws_sorted_usec_list_t *sul, - lws_usec_t us) +__lws_sul_insert(lws_dll2_owner_t *own, lws_sorted_usec_list_t *sul) { - lws_usec_t now = lws_now_usecs(); lws_dll2_remove(&sul->list); - if (us == LWS_SET_TIMER_USEC_CANCEL) { - /* we are clearing the timeout */ - sul->us = 0; - - return 0; - } - - sul->us = now + us; assert(sul->cb); /* * we sort the pt's list of sequencers with pending timeouts, so it's - * cheap to check it every second + * cheap to check it every poll wait */ lws_dll2_add_sorted(&sul->list, own, sul_compare); -#if 0 // defined(_DEBUG) - { - lws_usec_t worst = 0; - int n = 1; - - lwsl_info("%s: own %p: count %d\n", __func__, own, own->count); - - lws_start_foreach_dll_safe(struct lws_dll2 *, p, tp, - lws_dll2_get_head(own)) { - lws_sorted_usec_list_t *sul = (lws_sorted_usec_list_t *)p; - lwsl_info("%s: %d: %llu (+%lld)\n", __func__, n++, - (unsigned long long)sul->us, - (long long)(sul->us - now)); - if (sul->us < worst) { - lwsl_err("%s: wrongly sorted sul entry!\n", - __func__); - assert(0); - } - worst = sul->us; - } lws_end_foreach_dll_safe(p, tp); - } -#endif - return 0; } void -lws_sul_schedule(struct lws_context *context, int tsi, - lws_sorted_usec_list_t *sul, sul_cb_t cb, lws_usec_t us) +lws_sul_cancel(lws_sorted_usec_list_t *sul) +{ + lws_dll2_remove(&sul->list); + + /* we are clearing the timeout and leaving ourselves detached */ + sul->us = 0; +} + +void +lws_sul2_schedule(struct lws_context *context, int tsi, int flags, + lws_sorted_usec_list_t *sul) { struct lws_context_per_thread *pt = &context->pt[tsi]; - sul->cb = cb; + lws_pt_assert_lock_held(pt); - __lws_sul_insert(&pt->pt_sul_owner, sul, us); + __lws_sul_insert( + &pt->pt_sul_owner[!!(flags & LWSSULLI_WAKE_IF_SUSPENDED)], sul); } +/* + * own points to the first in an array of length own_len + * + * While any sul list owner has a "ripe", ie, ready to handle sul we do them + * strictly in order of sul time. When nobody has a ripe sul we return 0, if + * actually nobody has any sul, or the interval between usnow and the next + * earliest scheduled event on any list. + */ + lws_usec_t -__lws_sul_service_ripe(lws_dll2_owner_t *own, lws_usec_t usnow) +__lws_sul_service_ripe(lws_dll2_owner_t *own, int own_len, lws_usec_t usnow) { struct lws_context_per_thread *pt = (struct lws_context_per_thread *) lws_container_of(own, struct lws_context_per_thread, @@ -114,36 +104,269 @@ if (pt->attach_owner.count) lws_system_do_attach(pt); - while (lws_dll2_get_head(own)) { + lws_pt_assert_lock_held(pt); - /* .list is always first member in lws_sorted_usec_list_t */ - lws_sorted_usec_list_t *sul = (lws_sorted_usec_list_t *) - lws_dll2_get_head(own); + /* must be at least 1 */ + assert(own_len > 0); - assert(sul->us); /* shouldn't be on the list otherwise */ + /* + * Of the own_len sul owning lists, the earliest next sul could be on + * any of them. We have to find it and handle each in turn until no + * ripe sul left on any owning list, and we can exit. + * + * This ensures the ripe sul are handled strictly in the right order no + * matter which owning list they are on. + */ - if (sul->us > usnow) - return sul->us - usnow; + do { + lws_sorted_usec_list_t *hit = NULL; + lws_usec_t lowest = 0; + int n = 0; + + for (n = 0; n < own_len; n++) { + lws_sorted_usec_list_t *sul; + if (!own[n].count) + continue; + sul = (lws_sorted_usec_list_t *) + lws_dll2_get_head(&own[n]); + + if (!hit || sul->us <= lowest) { + hit = sul; + lowest = sul->us; + } + } + + if (!hit) + return 0; + + if (lowest > usnow) + return lowest - usnow; + + /* his moment has come... remove him from his owning list */ + + lws_dll2_remove(&hit->list); + hit->us = 0; - /* his moment has come... remove him from timeout list */ - lws_dll2_remove(&sul->list); - sul->us = 0; pt->inside_lws_service = 1; - sul->cb(sul); + hit->cb(hit); pt->inside_lws_service = 0; + } while (1); + + /* unreachable */ + + return 0; +} + +/* + * Normally we use the OS monotonic time, which does not step when the + * gettimeofday() time is adjusted after, eg, ntpclient. But on some OSes, + * high resolution monotonic time doesn't exist; sul time is computed from and + * compared against gettimeofday() time and breaks when that steps. + * + * For those cases, this allows us to retrospectively adjust existing suls on + * all owning lists by the step amount, at the same time we adjust the + * nonmonotonic clock. Then nothing breaks so long as we do this when the + * gettimeofday() clock is stepped. + * + * Linux and so on offer Posix MONOTONIC, which lws uses. FreeRTOS doesn't + * have a high-resolution monotonic clock and has to use gettimeofday(), which + * requires this adjustment when it is stepped. + */ + +lws_usec_t +lws_sul_nonmonotonic_adjust(struct lws_context *ctx, int64_t step_us) +{ + struct lws_context_per_thread *pt = &ctx->pt[0]; + int n, m; + + /* + * for each pt + */ + + for (m = 0; m < ctx->count_threads; m++) { + /* - * The callback may have done any mixture of delete - * and add sul entries... eg, close a wsi may pull out - * multiple entries making iterating it statefully - * unsafe. Always restart at the current head of list. + * For each owning list... */ + + lws_pt_lock(pt, __func__); + + for (n = 0; n < LWS_COUNT_PT_SUL_OWNERS; n++) { + + if (!pt->pt_sul_owner[n].count) + continue; + + /* ... and for every existing sul on a list... */ + + lws_start_foreach_dll(struct lws_dll2 *, p, + lws_dll2_get_head( + &pt->pt_sul_owner[n])) { + lws_sorted_usec_list_t *sul = lws_container_of( + p, lws_sorted_usec_list_t, list); + + /* + * ... retrospectively step its ripe time by the + * step we will adjust the gettimeofday() clock + * with + */ + + sul->us += step_us; + + } lws_end_foreach_dll(p); + } + + lws_pt_unlock(pt); + + pt++; } - /* - * Nothing left to take care of in the list (cannot return 0 otherwise - * because we will service anything equal to usnow rather than return) - */ + return 0; +} + +/* + * Earliest wakeable event on any pt + */ + +int +lws_sul_earliest_wakeable_event(struct lws_context *ctx, lws_usec_t *pearliest) +{ + struct lws_context_per_thread *pt; + int n = 0, hit = -1; + lws_usec_t lowest = 0; + + for (n = 0; n < ctx->count_threads; n++) { + pt = &ctx->pt[n]; + + lws_pt_lock(pt, __func__); + + if (pt->pt_sul_owner[LWSSULLI_WAKE_IF_SUSPENDED].count) { + lws_sorted_usec_list_t *sul = (lws_sorted_usec_list_t *) + lws_dll2_get_head(&pt->pt_sul_owner[ + LWSSULLI_WAKE_IF_SUSPENDED]); + + if (hit == -1 || sul->us < lowest) { + hit = n; + lowest = sul->us; + } + } + + lws_pt_unlock(pt); + } + + + if (hit == -1) + /* there is no pending event */ + return 1; + + *pearliest = lowest; return 0; } + +void +lws_sul_schedule(struct lws_context *ctx, int tsi, lws_sorted_usec_list_t *sul, + sul_cb_t _cb, lws_usec_t _us) +{ + struct lws_context_per_thread *_pt = &ctx->pt[tsi]; + + lws_pt_lock(_pt, __func__); + + if (_us == (lws_usec_t)LWS_SET_TIMER_USEC_CANCEL) + lws_sul_cancel(sul); + else { + sul->cb = _cb; + sul->us = lws_now_usecs() + _us; + lws_sul2_schedule(ctx, tsi, LWSSULLI_MISS_IF_SUSPENDED, sul); + } + + lws_pt_unlock(_pt); +} + +void +lws_sul_schedule_wakesuspend(struct lws_context *ctx, int tsi, + lws_sorted_usec_list_t *sul, sul_cb_t _cb, + lws_usec_t _us) +{ + struct lws_context_per_thread *_pt = &ctx->pt[tsi]; + + lws_pt_lock(_pt, __func__); + + if (_us == (lws_usec_t)LWS_SET_TIMER_USEC_CANCEL) + lws_sul_cancel(sul); + else { + sul->cb = _cb; + sul->us = lws_now_usecs() + _us; + lws_sul2_schedule(ctx, tsi, LWSSULLI_WAKE_IF_SUSPENDED, sul); + } + + lws_pt_unlock(_pt); +} + +#if defined(LWS_WITH_SUL_DEBUGGING) + +/* + * Sanity checker for any sul left scheduled when its containing object is + * freed... code scheduling suls must take care to cancel them when destroying + * their object. This optional debugging helper checks that when an object is + * being destroyed, there is no live sul scheduled from inside the object. + */ + +void +lws_sul_debug_zombies(struct lws_context *ctx, void *po, size_t len, + const char *destroy_description) +{ + struct lws_context_per_thread *pt; + int n, m; + + for (n = 0; n < ctx->count_threads; n++) { + pt = &ctx->pt[n]; + + lws_pt_lock(pt, __func__); + + for (m = 0; m < LWS_COUNT_PT_SUL_OWNERS; m++) { + + lws_start_foreach_dll(struct lws_dll2 *, p, + lws_dll2_get_head(&pt->pt_sul_owner[m])) { + lws_sorted_usec_list_t *sul = + lws_container_of(p, + lws_sorted_usec_list_t, list); + + /* + * Is the sul resident inside the object that is + * indicated as being deleted? + */ + + if ((void *)sul >= po && + (size_t)lws_ptr_diff(sul, po) < len) { + lwsl_err("%s: ERROR: Zombie Sul " + "(on list %d) %s, cb %p\n", + __func__, m, + destroy_description, sul->cb); + /* + * This assert fires if you have left + * a sul scheduled to fire later, but + * are about to destroy the object the + * sul lives in. You must take care to + * do lws_sul_cancel(&sul) on any suls + * that may be scheduled before + * destroying the object the sul lives + * 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); + } + + } lws_end_foreach_dll(p); + } + + lws_pt_unlock(pt); + } +} + +#endif diff -Nru libwebsockets-4.0.20/lib/core-net/state.c libwebsockets-4.1.6/lib/core-net/state.c --- libwebsockets-4.0.20/lib/core-net/state.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/core-net/state.c 2020-12-01 17:40:26.000000000 +0000 @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2020 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -109,6 +109,13 @@ /* Indicate success by calling the notifers again with both args same */ _report(mgr, target, target); +#if defined(LWS_WITH_SYS_SMD) + if (mgr->smd_class) + (void)lws_smd_msg_printf(mgr->context, + mgr->smd_class, "{\"state\":\"%s\"}", + mgr->state_names[target]); +#endif + return 0; } @@ -121,6 +128,9 @@ char temp8[8]; #endif + if (mgr->state > target) + return 0; + while (!n && mgr->state != target) n = _lws_state_transition(mgr, mgr->state + 1); diff -Nru libwebsockets-4.0.20/lib/core-net/vhost.c libwebsockets-4.1.6/lib/core-net/vhost.c --- libwebsockets-4.0.20/lib/core-net/vhost.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/core-net/vhost.c 2020-12-01 17:40:26.000000000 +0000 @@ -46,22 +46,6 @@ NULL }; -const struct lws_event_loop_ops *available_event_libs[] = { -#if defined(LWS_WITH_POLL) - &event_loop_ops_poll, -#endif -#if defined(LWS_WITH_LIBUV) - &event_loop_ops_uv, -#endif -#if defined(LWS_WITH_LIBEVENT) - &event_loop_ops_event, -#endif -#if defined(LWS_WITH_LIBEV) - &event_loop_ops_ev, -#endif - NULL -}; - #if defined(LWS_WITH_ABSTRACT) const struct lws_protocols *available_abstract_protocols[] = { #if defined(LWS_ROLE_RAW) @@ -85,6 +69,7 @@ #if defined(LWS_ROLE_MQTT) &protocol_secstream_mqtt, #endif + &protocol_secstream_raw, NULL }; #endif @@ -125,7 +110,9 @@ if (!alpn) return 0; +#if !defined(LWS_ESP_PLATFORM) lwsl_info("%s: '%s'\n", __func__, alpn); +#endif LWS_FOR_EVERY_AVAILABLE_ROLE_START(ar) if (ar->alpn && !strcmp(ar->alpn, alpn) && ar->alpn_negotiated) @@ -144,18 +131,18 @@ * if the vhost is told to bind accepted sockets to a given role, * then look it up by name and try to bind to the specific role. */ - if (lws_check_opt(wsi->vhost->options, + if (lws_check_opt(wsi->a.vhost->options, LWS_SERVER_OPTION_ADOPT_APPLY_LISTEN_ACCEPT_CONFIG) && - wsi->vhost->listen_accept_role) { + wsi->a.vhost->listen_accept_role) { const struct lws_role_ops *role = - lws_role_by_name(wsi->vhost->listen_accept_role); + lws_role_by_name(wsi->a.vhost->listen_accept_role); if (!prot) - prot = wsi->vhost->listen_accept_protocol; + prot = wsi->a.vhost->listen_accept_protocol; if (!role) lwsl_err("%s: can't find role '%s'\n", __func__, - wsi->vhost->listen_accept_role); + wsi->a.vhost->listen_accept_role); if (role && role->adoption_bind) { n = role->adoption_bind(wsi, type, prot); @@ -174,7 +161,7 @@ lwsl_warn("%s: adoption bind to role '%s', " "protocol '%s', type 0x%x, failed\n", __func__, - wsi->vhost->listen_accept_role, prot, type); + wsi->a.vhost->listen_accept_role, prot, type); } /* @@ -310,16 +297,17 @@ lws_protocol_init_vhost(struct lws_vhost *vh, int *any) { const struct lws_protocol_vhost_options *pvo, *pvo1; - struct lws *wsi = vh->context->pt[0].fake_wsi; + lws_fakewsi_def_plwsa(&vh->context->pt[0]); int n; - wsi->context = vh->context; - wsi->vhost = vh; + lws_fakewsi_prep_plwsa_ctx(vh->context); + + plwsa->vhost = vh; /* initialize supported protocols on this vhost */ for (n = 0; n < vh->count_protocols; n++) { - wsi->protocol = &vh->protocols[n]; + plwsa->protocol = &vh->protocols[n]; if (!vh->protocols[n].name) continue; pvo = lws_vhost_protocol_options(vh, vh->protocols[n].name); @@ -369,10 +357,10 @@ * inform all the protocols that they are doing their * one-time initialization if they want to. * - * NOTE the wsi is all zeros except for the context, vh - * + protocol ptrs so lws_get_context(wsi) etc can work + * NOTE the fakewsi is garbage, except the key pointers that are + * prepared in case the protocol handler wants to touch them */ - if (vh->protocols[n].callback(wsi, + if (vh->protocols[n].callback((struct lws *)plwsa, LWS_CALLBACK_PROTOCOL_INIT, NULL, (void *)pvo, 0)) { if (vh->protocol_vh_privs[n]) { @@ -429,8 +417,9 @@ context->protocol_init_done = 1; #if defined(LWS_WITH_SERVER) - if (any) + if (any) { lws_tls_check_all_cert_lifetimes(context); + } #endif return 0; @@ -466,8 +455,7 @@ lws_create_vhost(struct lws_context *context, const struct lws_context_creation_info *info) { - struct lws_vhost *vh = lws_zalloc(sizeof(*vh), "create vhost"), - **vh1 = &context->vhost_list; + struct lws_vhost *vh, **vh1 = &context->vhost_list; const struct lws_http_mount *mounts; const struct lws_protocols *pcols = info->protocols; #ifdef LWS_WITH_PLUGINS @@ -485,9 +473,19 @@ #endif int n; + + vh = lws_zalloc(sizeof(*vh) +#if defined(LWS_WITH_EVENT_LIBS) + + context->event_loop_ops->evlib_size_vh +#endif + , __func__); if (!vh) return NULL; +#if defined(LWS_WITH_EVENT_LIBS) + vh->evlib_vh = (void *)&vh[1]; +#endif + #if LWS_MAX_SMP > 1 pthread_mutex_init(&vh->lock, NULL); #endif @@ -512,6 +510,12 @@ #if !defined(LWS_PLAT_FREERTOS) && !defined(OPTEE_TA) && !defined(WIN32) vh->bind_iface = info->bind_iface; #endif +#if defined(LWS_WITH_CLIENT) + if (info->connect_timeout_secs) + vh->connect_timeout_secs = info->connect_timeout_secs; + else + vh->connect_timeout_secs = 20; +#endif /* apply the context default lws_retry */ if (info->retry_and_idle_policy) @@ -674,15 +678,18 @@ #ifdef LWS_WITH_PLUGINS if (plugin) { while (plugin) { - for (n = 0; n < plugin->caps.count_protocols; n++) { + const lws_plugin_protocol_t *plpr = + (const lws_plugin_protocol_t *)plugin->hdr; + + for (n = 0; n < plpr->count_protocols; n++) { /* * for compatibility's sake, no pvo implies * allow all protocols */ if (f || lws_vhost_protocol_options(vh, - plugin->caps.protocols[n].name)) { + plpr->protocols[n].name)) { memcpy(&lwsp[m], - &plugin->caps.protocols[n], + &plpr->protocols[n], sizeof(struct lws_protocols)); m++; vh->count_protocols++; @@ -821,7 +828,10 @@ goto bail1; } #endif + +#if defined(LWS_WITH_SYS_ASYNC_DNS) n = !!context->vhost_list; +#endif while (1) { if (!(*vh1)) { @@ -886,7 +896,7 @@ if (context->being_destroyed1) return; - lwsl_info("%s\n", __func__); + lwsl_debug("%s\n", __func__); while (m--) { if (pt->pipe_wsi) @@ -898,6 +908,8 @@ int lws_create_event_pipes(struct lws_context *context) { + struct lws_context_per_thread *pt; + size_t s = sizeof(struct lws); struct lws *wsi; int n; @@ -912,24 +924,35 @@ n = 0; { #endif - if (context->pt[n].pipe_wsi) + pt = &context->pt[n]; + + if (pt->pipe_wsi) return 0; - wsi = lws_zalloc(sizeof(*wsi), "event pipe wsi"); +#if defined(LWS_WITH_EVENT_LIBS) + s += context->event_loop_ops->evlib_size_wsi; +#endif + + wsi = lws_zalloc(s, "event pipe wsi"); if (!wsi) { lwsl_err("%s: Out of mem\n", __func__); return 1; } - wsi->context = context; +#if defined(LWS_WITH_EVENT_LIBS) + wsi->evlib_wsi = (uint8_t *)wsi + sizeof(*wsi); +#endif + wsi->a.context = context; lws_role_transition(wsi, 0, LRS_UNCONNECTED, &role_ops_pipe); - wsi->protocol = NULL; + wsi->a.protocol = NULL; wsi->tsi = n; - wsi->vhost = NULL; + wsi->a.vhost = NULL; wsi->event_pipe = 1; wsi->desc.sockfd = LWS_SOCK_INVALID; context->pt[n].pipe_wsi = wsi; context->count_wsi_allocated++; + lws_pt_lock(pt, __func__); /* -------------- pt { */ + if (!lws_plat_pipe_create(wsi)) { /* * platform code returns 0 if it actually created pipes @@ -945,14 +968,21 @@ if (context->event_loop_ops->sock_accept) if (context->event_loop_ops->sock_accept(wsi)) - return 1; + goto bail; if (__insert_wsi_socket_into_fds(context, wsi)) - return 1; + goto bail; } + + lws_pt_unlock(pt); } return 0; + +bail: + lws_pt_unlock(pt); + + return 1; } void @@ -963,17 +993,17 @@ if (lws_socket_is_valid(wsi->desc.sockfd)) __remove_wsi_socket_from_fds(wsi); - if (!wsi->context->event_loop_ops->destroy_wsi && - wsi->context->event_loop_ops->wsi_logical_close) { - wsi->context->event_loop_ops->wsi_logical_close(wsi); + if (!wsi->a.context->event_loop_ops->destroy_wsi && + wsi->a.context->event_loop_ops->wsi_logical_close) { + wsi->a.context->event_loop_ops->wsi_logical_close(wsi); lws_plat_pipe_close(wsi); return; } - if (wsi->context->event_loop_ops->destroy_wsi) - wsi->context->event_loop_ops->destroy_wsi(wsi); + if (wsi->a.context->event_loop_ops->destroy_wsi) + wsi->a.context->event_loop_ops->destroy_wsi(wsi); lws_plat_pipe_close(wsi); - wsi->context->count_wsi_allocated--; + wsi->a.context->count_wsi_allocated--; lws_free(wsi); } @@ -1091,25 +1121,26 @@ } lws_end_foreach_dll_safe(d, d1); #endif +#if defined(LWS_WITH_DEPRECATED_THINGS) /* * destroy any pending timed events */ while (vh->timed_vh_protocol_list) __lws_timed_callback_remove(vh, vh->timed_vh_protocol_list); - +#endif /* * let the protocols destroy the per-vhost protocol objects */ memset(&wsi, 0, sizeof(wsi)); - wsi.context = vh->context; - wsi.vhost = vh; /* not a real bound wsi */ + wsi.a.context = vh->context; + wsi.a.vhost = vh; /* not a real bound wsi */ protocol = vh->protocols; if (protocol && vh->created_vhost_protocols) { n = 0; while (n < vh->count_protocols) { - wsi.protocol = protocol; + wsi.a.protocol = protocol; if (protocol->callback) protocol->callback(&wsi, LWS_CALLBACK_PROTOCOL_DESTROY, @@ -1132,8 +1163,10 @@ /* add ourselves to the pending destruction list */ - vh->vhost_next = vh->context->vhost_pending_destruction_list; - vh->context->vhost_pending_destruction_list = vh; + if (vh->context->vhost_pending_destruction_list != vh) { + vh->vhost_next = vh->context->vhost_pending_destruction_list; + vh->context->vhost_pending_destruction_list = vh; + } lwsl_info("%s: %p\n", __func__, vh); @@ -1282,7 +1315,7 @@ struct lws *wsi = wsi_from_fd(context, pt->fds[n].fd); if (!wsi) continue; - if (wsi->vhost != v) + if (wsi->a.vhost != v) continue; __lws_close_free_wsi(wsi, @@ -1379,7 +1412,7 @@ if (wsi) { wsi->socket_is_permanently_unusable = 1; lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "ctx deprecate"); - wsi->context->deprecation_pending_listen_close_count++; + wsi->a.context->deprecation_pending_listen_close_count++; /* * other vhosts can share the listen port, they * point to the same wsi. So zap those too. @@ -1423,6 +1456,10 @@ * * This was originally in the client code but since the list is held on the * vhost (to ensure the same client tls ctx is involved) it's cleaner in vhost.c + * + * ACTIVE_CONNS_QUEUED: We're queued on an active connection, set *nwsi to that + * ACTIVE_CONNS_MUXED: We are joining an active mux conn *nwsi as a child + * ACTIVE_CONNS_SOLO: There's no existing conn to join either way */ int @@ -1449,10 +1486,10 @@ } #endif - lws_vhost_lock(wsi->vhost); /* ----------------------------------- { */ + lws_vhost_lock(wsi->a.vhost); /* ----------------------------------- { */ lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, - wsi->vhost->dll_cli_active_conns_owner.head) { + wsi->a.vhost->dll_cli_active_conns_owner.head) { struct lws *w = lws_container_of(d, struct lws, dll_cli_active_conns); @@ -1501,14 +1538,14 @@ if (lwsi_state(w) == LRS_IDLING) { // lwsi_set_state(w, LRS_ESTABLISHED); - _lws_generic_transaction_completed_active_conn(&w); + _lws_generic_transaction_completed_active_conn(&w, 0); } //lwsi_set_state(w, LRS_H1C_ISSUE_HANDSHAKE2); wsi->client_h2_alpn = 1; lws_wsi_h2_adopt(w, wsi); - lws_vhost_unlock(wsi->vhost); /* } ---------- */ + lws_vhost_unlock(wsi->a.vhost); /* } ---------- */ *nwsi = w; @@ -1530,7 +1567,7 @@ lws_dll2_remove(&wsi->dll2_cli_txn_queue); wsi->client_mux_substream = 1; - lws_vhost_unlock(wsi->vhost); /* } ---------- */ + lws_vhost_unlock(wsi->a.vhost); /* } ---------- */ return ACTIVE_CONNS_MUXED; @@ -1555,7 +1592,7 @@ if (lwsi_state(w) == LRS_IDLING) { // lwsi_set_state(w, LRS_ESTABLISHED); - _lws_generic_transaction_completed_active_conn(&w); + _lws_generic_transaction_completed_active_conn(&w, 0); } /* @@ -1563,7 +1600,7 @@ * and wait for our turn at client transaction_complete * to take over parsing the rx. */ - lws_vhost_unlock(wsi->vhost); /* } ---------- */ + lws_vhost_unlock(wsi->a.vhost); /* } ---------- */ *nwsi = w; @@ -1573,7 +1610,7 @@ } lws_end_foreach_dll_safe(d, d1); solo: - lws_vhost_unlock(wsi->vhost); /* } ---------------------------------- */ + lws_vhost_unlock(wsi->a.vhost); /* } ---------------------------------- */ /* there is nobody already connected in the same way */ diff -Nru libwebsockets-4.0.20/lib/core-net/wsi.c libwebsockets-4.1.6/lib/core-net/wsi.c --- libwebsockets-4.0.20/lib/core-net/wsi.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/core-net/wsi.c 2020-12-01 17:40:26.000000000 +0000 @@ -46,34 +46,34 @@ void lws_vhost_bind_wsi(struct lws_vhost *vh, struct lws *wsi) { - if (wsi->vhost == vh) + if (wsi->a.vhost == vh) return; lws_context_lock(vh->context, __func__); /* ---------- context { */ - wsi->vhost = vh; + wsi->a.vhost = vh; vh->count_bound_wsi++; lws_context_unlock(vh->context); /* } context ---------- */ lwsl_debug("%s: vh %s: wsi %s/%s, count_bound_wsi %d\n", __func__, vh->name, wsi->role_ops ? wsi->role_ops->name : "none", - wsi->protocol ? wsi->protocol->name : "none", + wsi->a.protocol ? wsi->a.protocol->name : "none", vh->count_bound_wsi); - assert(wsi->vhost->count_bound_wsi > 0); + assert(wsi->a.vhost->count_bound_wsi > 0); } void lws_vhost_unbind_wsi(struct lws *wsi) { - if (!wsi->vhost) + if (!wsi->a.vhost) return; - lws_context_lock(wsi->context, __func__); /* ---------- context { */ + lws_context_lock(wsi->a.context, __func__); /* ---------- context { */ - assert(wsi->vhost->count_bound_wsi > 0); - wsi->vhost->count_bound_wsi--; + assert(wsi->a.vhost->count_bound_wsi > 0); + wsi->a.vhost->count_bound_wsi--; lwsl_debug("%s: vh %s: count_bound_wsi %d\n", __func__, - wsi->vhost->name, wsi->vhost->count_bound_wsi); + wsi->a.vhost->name, wsi->a.vhost->count_bound_wsi); - if (!wsi->vhost->count_bound_wsi && - wsi->vhost->being_destroyed) { + if (!wsi->a.vhost->count_bound_wsi && + wsi->a.vhost->being_destroyed) { /* * We have closed all wsi that were bound to this vhost * by any pt: nothing can be servicing any wsi belonging @@ -81,11 +81,11 @@ * * Finalize the vh destruction */ - __lws_vhost_destroy2(wsi->vhost); + __lws_vhost_destroy2(wsi->a.vhost); } - wsi->vhost = NULL; + wsi->a.vhost = NULL; - lws_context_unlock(wsi->context); /* } context ---------- */ + lws_context_unlock(wsi->a.context); /* } context ---------- */ } struct lws * @@ -135,7 +135,7 @@ wsi = wsi_from_fd(context, pt->fds[n].fd); if (!wsi) continue; - if (wsi->protocol == protocol) + if (wsi->a.protocol == protocol) protocol->callback(wsi, reason, wsi->user_space, NULL, 0); } @@ -160,9 +160,9 @@ wsi = wsi_from_fd(context, pt->fds[n].fd); if (!wsi) continue; - if (wsi->vhost == vh && (wsi->protocol == protocol || + if (wsi->a.vhost == vh && (wsi->a.protocol == protocol || !protocol)) - wsi->protocol->callback(wsi, reason, + wsi->a.protocol->callback(wsi, reason, wsi->user_space, argp, len); } pt++; @@ -183,8 +183,8 @@ { int n; - for (n = 0; n < wsi->vhost->count_protocols; n++) - if (wsi->vhost->protocols[n].callback(wsi, reason, NULL, in, len)) + for (n = 0; n < wsi->a.vhost->count_protocols; n++) + if (wsi->a.vhost->protocols[n].callback(wsi, reason, NULL, in, len)) return 1; return 0; @@ -200,12 +200,12 @@ if (!wsi) return 1; - wsi->context = vh->context; + wsi->a.context = vh->context; lws_vhost_bind_wsi(vh, wsi); - for (n = 0; n < wsi->vhost->count_protocols; n++) { - wsi->protocol = &vh->protocols[n]; - if (wsi->protocol->callback(wsi, reason, NULL, in, len)) { + for (n = 0; n < wsi->a.vhost->count_protocols; n++) { + wsi->a.protocol = &vh->protocols[n]; + if (wsi->a.protocol->callback(wsi, reason, NULL, in, len)) { lws_free(wsi); return 1; } @@ -220,7 +220,7 @@ int lws_rx_flow_control(struct lws *wsi, int _enable) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; int en = _enable; // h2 ignores rx flow control atm @@ -285,7 +285,7 @@ wsi = wsi_from_fd(context, pt->fds[n].fd); if (!wsi) continue; - if (wsi->protocol == protocol) + if (wsi->a.protocol == protocol) lws_rx_flow_control(wsi, LWS_RXFLOW_ALLOW); } pt++; @@ -364,28 +364,28 @@ const struct lws_protocols * lws_get_protocol(struct lws *wsi) { - return wsi->protocol; + return wsi->a.protocol; } int lws_ensure_user_space(struct lws *wsi) { - if (!wsi->protocol) + if (!wsi->a.protocol) return 0; /* allocate the per-connection user memory (if any) */ - if (wsi->protocol->per_session_data_size && !wsi->user_space) { + if (wsi->a.protocol->per_session_data_size && !wsi->user_space) { wsi->user_space = lws_zalloc( - wsi->protocol->per_session_data_size, "user space"); + wsi->a.protocol->per_session_data_size, "user space"); if (wsi->user_space == NULL) { lwsl_err("%s: OOM\n", __func__); return 1; } } else lwsl_debug("%s: %p protocol pss %lu, user_space=%p\n", __func__, - wsi, (long)wsi->protocol->per_session_data_size, + wsi, (long)wsi->a.protocol->per_session_data_size, wsi->user_space); return 0; } @@ -607,21 +607,27 @@ lws_broadcast(struct lws_context_per_thread *pt, int reason, void *in, size_t len) { struct lws_vhost *v = pt->context->vhost_list; + lws_fakewsi_def_plwsa(pt); int n, ret = 0; - pt->fake_wsi->context = 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) { const struct lws_protocols *p = v->protocols; - pt->fake_wsi->vhost = v; /* not a real bound wsi */ + + plwsa->vhost = v; /* not a real bound wsi */ for (n = 0; n < v->count_protocols; n++) { - pt->fake_wsi->protocol = p; + plwsa->protocol = p; if (p->callback && - p->callback(pt->fake_wsi, reason, NULL, in, len)) + p->callback((struct lws *)plwsa, reason, NULL, in, len)) ret |= 1; p++; } + v = v->vhost_next; } @@ -634,6 +640,13 @@ return wsi->user_space; } +int +lws_wsi_tsi(struct lws *wsi) +{ + return wsi->tsi; +} + + void lws_set_wsi_user(struct lws *wsi, void *data) { @@ -671,13 +684,13 @@ void * lws_get_opaque_user_data(const struct lws *wsi) { - return wsi->opaque_user_data; + return wsi->a.opaque_user_data; } void lws_set_opaque_user_data(struct lws *wsi, void *data) { - wsi->opaque_user_data = data; + wsi->a.opaque_user_data = data; } int @@ -730,19 +743,19 @@ struct lws_vhost * lws_vhost_get(struct lws *wsi) { - return wsi->vhost; + return wsi->a.vhost; } struct lws_vhost * lws_get_vhost(struct lws *wsi) { - return wsi->vhost; + return wsi->a.vhost; } const struct lws_protocols * lws_protocol_get(struct lws *wsi) { - return wsi->protocol; + return wsi->a.protocol; } #if defined(LWS_WITH_UDP) @@ -756,12 +769,12 @@ struct lws_context * lws_get_context(const struct lws *wsi) { - return wsi->context; + return wsi->a.context; } #if defined(LWS_WITH_CLIENT) int -_lws_generic_transaction_completed_active_conn(struct lws **_wsi) +_lws_generic_transaction_completed_active_conn(struct lws **_wsi, char take_vh_lock) { struct lws *wnew, *wsi = *_wsi; @@ -798,7 +811,8 @@ lwsl_info("%s: nothing pipelined waiting\n", __func__); lwsi_set_state(wsi, LRS_IDLING); - lws_set_timeout(wsi, PENDING_TIMEOUT_CLIENT_CONN_IDLE, 5); + lws_set_timeout(wsi, PENDING_TIMEOUT_CLIENT_CONN_IDLE, + wsi->keep_warm_secs); return 0; /* no new transaction right now */ } @@ -808,7 +822,8 @@ * closing ourself */ - lws_vhost_lock(wsi->vhost); + if (take_vh_lock) + lws_vhost_lock(wsi->a.vhost); wnew = lws_container_of(wsi->dll2_cli_txn_queue_owner.head, struct lws, dll2_cli_txn_queue); @@ -819,6 +834,8 @@ assert(lws_socket_is_valid(wsi->desc.sockfd)); + __lws_change_pollfd(wsi, LWS_POLLOUT | LWS_POLLIN, 0); + /* copy the fd */ wnew->desc = wsi->desc; @@ -828,13 +845,32 @@ if (__remove_wsi_socket_from_fds(wsi)) return -1; + + sanity_assert_no_wsi_traces(wsi->a.context, wsi); + sanity_assert_no_sockfd_traces(wsi->a.context, wsi->desc.sockfd); wsi->desc.sockfd = LWS_SOCK_INVALID; + __lws_wsi_remove_from_sul(wsi); + + /* + * ... we're doing some magic here in terms of handing off the socket + * that has been active to a wsi that has not yet itself been active... + * depending on the event lib we may need to give a magic spark to the + * new guy and snuff out the old guy's magic spark at that level as well + */ + +#if defined(LWS_WITH_EVENT_LIBS) + if (wsi->a.context->event_loop_ops->destroy_wsi) + wsi->a.context->event_loop_ops->destroy_wsi(wsi); + if (wsi->a.context->event_loop_ops->sock_accept) + wsi->a.context->event_loop_ops->sock_accept(wnew); +#endif + /* point the fd table entry to new guy */ assert(lws_socket_is_valid(wnew->desc.sockfd)); - if (__insert_wsi_socket_into_fds(wsi->context, wnew)) + if (__insert_wsi_socket_into_fds(wsi->a.context, wnew)) return -1; #if defined(LWS_WITH_TLS) @@ -850,7 +886,7 @@ wnew->cli_hostname_copy = wsi->cli_hostname_copy; wsi->cli_hostname_copy = NULL; - + wnew->keep_warm_secs = wsi->keep_warm_secs; /* * selected queued guy now replaces the original leader on the @@ -859,7 +895,7 @@ lws_dll2_remove(&wsi->dll_cli_active_conns); lws_dll2_add_tail(&wnew->dll_cli_active_conns, - &wsi->vhost->dll_cli_active_conns_owner); + &wsi->a.vhost->dll_cli_active_conns_owner); /* move any queued guys to queue on new active conn */ @@ -874,7 +910,8 @@ } lws_end_foreach_dll_safe(d, d1); - lws_vhost_unlock(wsi->vhost); + if (take_vh_lock) + lws_vhost_unlock(wsi->a.vhost); /* * The original leader who passed on all his powers already can die... @@ -923,12 +960,12 @@ lws_bind_protocol(struct lws *wsi, const struct lws_protocols *p, const char *reason) { -// if (wsi->protocol == p) +// if (wsi->a.protocol == p) // return 0; - const struct lws_protocols *vp = wsi->vhost->protocols, *vpo; + const struct lws_protocols *vp = wsi->a.vhost->protocols, *vpo; - if (wsi->protocol && wsi->protocol_bind_balance) { - wsi->protocol->callback(wsi, + if (wsi->a.protocol && wsi->protocol_bind_balance) { + wsi->a.protocol->callback(wsi, wsi->role_ops->protocol_unbind_cb[!!lwsi_role_server(wsi)], wsi->user_space, (void *)reason, 0); wsi->protocol_bind_balance = 0; @@ -938,17 +975,17 @@ lws_same_vh_protocol_remove(wsi); - wsi->protocol = p; + wsi->a.protocol = p; if (!p) return 0; if (lws_ensure_user_space(wsi)) return 1; - if (p > vp && p < &vp[wsi->vhost->count_protocols]) + if (p > vp && p < &vp[wsi->a.vhost->count_protocols]) lws_same_vh_protocol_insert(wsi, (int)(p - vp)); else { - int n = wsi->vhost->count_protocols; + int n = wsi->a.vhost->count_protocols; int hit = 0; vpo = vp; @@ -963,10 +1000,10 @@ } if (!hit) lwsl_err("%s: %p is not in vhost '%s' protocols list\n", - __func__, p, wsi->vhost->name); + __func__, p, wsi->a.vhost->name); } - if (wsi->protocol->callback(wsi, wsi->role_ops->protocol_bind_cb[ + if (wsi->a.protocol->callback(wsi, wsi->role_ops->protocol_bind_cb[ !!lwsi_role_server(wsi)], wsi->user_space, NULL, 0)) return 1; @@ -998,8 +1035,8 @@ * need to reapply a normal timeout regime to the nwsi */ lws_set_timeout(nwsi, PENDING_TIMEOUT_HTTP_KEEPALIVE_IDLE, - wsi->vhost->keepalive_timeout ? - wsi->vhost->keepalive_timeout : 31); + wsi->a.vhost->keepalive_timeout ? + wsi->a.vhost->keepalive_timeout : 31); } void @@ -1019,6 +1056,8 @@ } nwsi = lws_get_network_wsi(wsi); + if (!nwsi) + return; lwsl_debug("%s: %p %p %d\n", __func__, wsi, nwsi, nwsi->immortal_substream_count); @@ -1034,6 +1073,9 @@ int lws_http_mark_sse(struct lws *wsi) { + if (!wsi) + return 0; + lws_http_headers_detach(wsi); lws_mux_mark_immortal(wsi); @@ -1116,11 +1158,13 @@ lws_wsi_mux_close_children(struct lws *wsi, int reason) { struct lws *wsi2; + struct lws **w; if (!wsi->mux.child_list) return; - lws_start_foreach_llp(struct lws **, w, wsi->mux.child_list) { + w = &wsi->mux.child_list; + while (*w) { lwsl_info(" closing child %p\n", *w); /* disconnect from siblings */ wsi2 = (*w)->mux.sibling_list; @@ -1129,8 +1173,7 @@ (*w)->socket_is_permanently_unusable = 1; __lws_close_free_wsi(*w, reason, "mux child recurse"); *w = wsi2; - continue; - } lws_end_foreach_llp(w, mux.sibling_list); + } } @@ -1170,7 +1213,7 @@ wsi->mux.requested_POLLOUT ? '*' : ' ', wsi, wsi->mux.my_sid, lwsi_state(wsi), wsi->role_ops->name, - wsi->protocol ? wsi->protocol->name : "noprotocol"); + wsi->a.protocol ? wsi->a.protocol->name : "noprotocol"); wsi = wsi->mux.sibling_list; } @@ -1315,7 +1358,7 @@ */ return 0; - return user_callback_handle_rxflow(wsi->protocol->callback, + return user_callback_handle_rxflow(wsi->a.protocol->callback, wsi, LWS_CALLBACK_WSI_TX_CREDIT_GET, wsi->user_space, NULL, (size_t)bump); } @@ -1327,7 +1370,7 @@ { /* we have a transaction queue that wants to pipeline */ - lws_vhost_lock(wsi->vhost); + lws_vhost_lock(wsi->a.vhost); lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, wsi->dll2_cli_txn_queue_owner.head) { @@ -1364,7 +1407,7 @@ } lws_end_foreach_dll_safe(d, d1); - lws_vhost_unlock(wsi->vhost); + lws_vhost_unlock(wsi->a.vhost); return 0; } diff -Nru libwebsockets-4.0.20/lib/core-net/wsi-timeout.c libwebsockets-4.1.6/lib/core-net/wsi-timeout.c --- libwebsockets-4.0.20/lib/core-net/wsi-timeout.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/core-net/wsi-timeout.c 2020-12-01 17:40:26.000000000 +0000 @@ -27,7 +27,7 @@ void __lws_wsi_remove_from_sul(struct lws *wsi) { - //struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + //struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; //lwsl_notice("%s: wsi %p, to %p, hr %p\n", __func__, wsi, // &wsi->sul_timeout.list, &wsi->sul_hrtimer.list); @@ -48,8 +48,8 @@ { struct lws *wsi = lws_container_of(sul, struct lws, sul_hrtimer); - if (wsi->protocol && - wsi->protocol->callback(wsi, LWS_CALLBACK_TIMER, + if (wsi->a.protocol && + wsi->a.protocol->callback(wsi, LWS_CALLBACK_TIMER, wsi->user_space, NULL, 0)) __lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "hrtimer cb errored"); @@ -58,10 +58,11 @@ void __lws_set_timer_usecs(struct lws *wsi, lws_usec_t us) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; wsi->sul_hrtimer.cb = lws_sul_hrtimer_cb; - __lws_sul_insert(&pt->pt_sul_owner, &wsi->sul_hrtimer, us); + __lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], + &wsi->sul_hrtimer, us); } void @@ -78,7 +79,7 @@ lws_sul_wsitimeout_cb(lws_sorted_usec_list_t *sul) { struct lws *wsi = lws_container_of(sul, struct lws, sul_timeout); - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; if (wsi->pending_timeout != PENDING_TIMEOUT_USER_OK) lws_stats_bump(pt, LWSSTATS_C_TIMEOUTS, 1); @@ -117,17 +118,20 @@ (void *)"Timed out waiting SSL", 21); #endif + lws_pt_lock(pt, __func__); __lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "timeout"); + lws_pt_unlock(pt); } void __lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; wsi->sul_timeout.cb = lws_sul_wsitimeout_cb; - __lws_sul_insert(&pt->pt_sul_owner, &wsi->sul_timeout, - ((lws_usec_t)secs) * LWS_US_PER_SEC); + __lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], + &wsi->sul_timeout, + ((lws_usec_t)secs) * LWS_US_PER_SEC); lwsl_debug("%s: %p: %d secs, reason %d\n", __func__, wsi, secs, reason); @@ -137,17 +141,19 @@ void lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs) { - struct lws_context_per_thread *pt = &wsi->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_dll2_remove(&wsi->sul_timeout.list); lws_pt_unlock(pt); if (!secs) - return; + goto bail; if (secs == LWS_TO_KILL_SYNC) { lwsl_debug("synchronously killing %p\n", wsi); + lws_context_unlock(pt->context); lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "to sync kill"); return; @@ -163,12 +169,15 @@ lws_pt_lock(pt, __func__); __lws_set_timeout(wsi, reason, secs); lws_pt_unlock(pt); + +bail: + lws_context_unlock(pt->context); } void lws_set_timeout_us(struct lws *wsi, enum pending_timeout reason, lws_usec_t us) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; lws_pt_lock(pt, __func__); lws_dll2_remove(&wsi->sul_timeout.list); @@ -178,7 +187,8 @@ return; lws_pt_lock(pt, __func__); - __lws_sul_insert(&pt->pt_sul_owner, &wsi->sul_timeout, us); + __lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], + &wsi->sul_timeout, us); lwsl_notice("%s: %p: %llu us, reason %d\n", __func__, wsi, (unsigned long long)us, reason); @@ -187,6 +197,8 @@ lws_pt_unlock(pt); } +#if defined(LWS_WITH_DEPRECATED_THINGS) + /* requires context + vh lock */ int @@ -211,18 +223,16 @@ { struct lws_timed_vh_protocol *tvp = lws_container_of(sul, struct lws_timed_vh_protocol, sul); - struct lws_context_per_thread *pt = - &tvp->vhost->context->pt[tvp->tsi_req]; - - pt->fake_wsi->context = tvp->vhost->context; + lws_fakewsi_def_plwsa(&tvp->vhost->context->pt[0]); - pt->fake_wsi->vhost = tvp->vhost; /* not a real bound wsi */ - pt->fake_wsi->protocol = tvp->protocol; + lws_fakewsi_prep_plwsa_ctx(tvp->vhost->context); + plwsa->vhost = tvp->vhost; /* not a real bound wsi */ + plwsa->protocol = tvp->protocol; lwsl_debug("%s: timed cb: vh %s, protocol %s, reason %d\n", __func__, tvp->vhost->name, tvp->protocol->name, tvp->reason); - tvp->protocol->callback(pt->fake_wsi, tvp->reason, NULL, NULL, 0); + tvp->protocol->callback((struct lws *)plwsa, tvp->reason, NULL, NULL, 0); __lws_timed_callback_remove(tvp->vhost, tvp); } @@ -276,11 +286,13 @@ ((lws_usec_t)secs) * LWS_US_PER_SEC); } +#endif + static void lws_validity_cb(lws_sorted_usec_list_t *sul) { struct lws *wsi = lws_container_of(sul, struct lws, sul_validity); - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; const lws_retry_bo_t *rbo = wsi->retry_policy; /* one of either the ping or hangup validity threshold was crossed */ @@ -308,8 +320,9 @@ assert(rbo->secs_since_valid_hangup > rbo->secs_since_valid_ping); wsi->validity_hup = 1; - __lws_sul_insert(&pt->pt_sul_owner, &wsi->sul_validity, - ((uint64_t)rbo->secs_since_valid_hangup - + __lws_sul_insert_us(&pt->pt_sul_owner[!!wsi->conn_validity_wakesuspend], + &wsi->sul_validity, + ((uint64_t)rbo->secs_since_valid_hangup - rbo->secs_since_valid_ping) * LWS_US_PER_SEC); } @@ -321,7 +334,7 @@ void _lws_validity_confirmed_role(struct lws *wsi) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; const lws_retry_bo_t *rbo = wsi->retry_policy; if (!rbo || !rbo->secs_since_valid_hangup) @@ -339,8 +352,9 @@ rbo->secs_since_valid_ping, wsi->validity_hup); - __lws_sul_insert(&pt->pt_sul_owner, &wsi->sul_validity, - ((uint64_t)(wsi->validity_hup ? + __lws_sul_insert_us(&pt->pt_sul_owner[!!wsi->conn_validity_wakesuspend], + &wsi->sul_validity, + ((uint64_t)(wsi->validity_hup ? rbo->secs_since_valid_hangup : rbo->secs_since_valid_ping)) * LWS_US_PER_SEC); } diff -Nru libwebsockets-4.0.20/lib/drivers/button/lws-button.c libwebsockets-4.1.6/lib/drivers/button/lws-button.c --- libwebsockets-4.0.20/lib/drivers/button/lws-button.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/drivers/button/lws-button.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,532 @@ +/* + * Generic GPIO / irq buttons + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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" + +typedef enum lws_button_classify_states { + LBCS_IDLE, /* nothing happening */ + LBCS_MIN_DOWN_QUALIFY, + + LBCS_ASSESS_DOWN_HOLD, + LBCS_UP_SETTLE1, + LBCS_WAIT_DOUBLECLICK, + LBCS_MIN_DOWN_QUALIFY2, + + LBCS_WAIT_UP, + LBCS_UP_SETTLE2, +} lws_button_classify_states_t; + +/* + * This is the opaque, allocated, non-const, dynamic footprint of the + * button controller + */ + +typedef struct lws_button_state { +#if defined(LWS_PLAT_TIMER_TYPE) + LWS_PLAT_TIMER_TYPE timer; /* bh timer */ + LWS_PLAT_TIMER_TYPE timer_mon; /* monitor timer */ +#endif + const lws_button_controller_t *controller; + struct lws_context *ctx; + short mon_refcount; + lws_button_idx_t enable_bitmap; + lws_button_idx_t state_bitmap; + + uint16_t mon_timer_count; + /* incremented each time the mon timer cb happens */ + + /* lws_button_each_t per button overallocated after this */ +} lws_button_state_t; + +typedef struct lws_button_each { + lws_button_state_t *bcs; + uint16_t mon_timer_comp; + uint16_t mon_timer_repeat; + uint8_t state; + /**^ lws_button_classify_states_t */ + uint8_t isr_pending; +} lws_button_each_t; + +#if defined(LWS_PLAT_TIMER_START) +static const lws_button_regime_t default_regime = { + .ms_min_down = 20, + .ms_min_down_longpress = 300, + .ms_up_settle = 20, + .ms_doubleclick_grace = 120, + .flags = LWSBTNRGMFLAG_CLASSIFY_DOUBLECLICK +}; +#endif + + +/* + * This is happening in interrupt context, we have to schedule a bottom half to + * do the foreground lws_smd queueing, using, eg, a platform timer. + * + * All the buttons point here and use one timer per button controller. An + * interrupt here means, "something happened to one or more buttons" + */ +#if defined(LWS_PLAT_TIMER_START) +void +lws_button_irq_cb_t(void *arg) +{ + lws_button_each_t *each = (lws_button_each_t *)arg; + + each->isr_pending = 1; + LWS_PLAT_TIMER_START(each->bcs->timer); +} +#endif + +/* + * This is the bottom-half scheduled via a timer set in the ISR. From here we + * are allowed to hold mutexes etc. We are coming here because any button + * interrupt arrived, we have to run another timer that tries to put whatever is + * observed on any active button into context and either discard it or arrive at + * a definitive event classification. + */ + +#if defined(LWS_PLAT_TIMER_CB) +static LWS_PLAT_TIMER_CB(lws_button_bh, th) +{ + lws_button_state_t *bcs = LWS_PLAT_TIMER_CB_GET_OPAQUE(th); + lws_button_each_t *each = (lws_button_each_t *)&bcs[1]; + const lws_button_controller_t *bc = bcs->controller; + size_t n; + + /* + * The ISR and bottom-half is shared by all the buttons. Each gpio + * IRQ has an individual opaque ptr pointing to the corresponding + * button's dynamic lws_button_each_t, the ISR marks the button's + * each->isr_pending and schedules this bottom half. + * + * So now the bh timer has fired and something to do, we need to go + * through all the buttons that have isr_pending set and service their + * state. Intermediate states should start / bump the refcount on the + * mon timer. That's refcounted so it only runs when a button down. + */ + + for (n = 0; n < bc->count_buttons; n++) { + + if (!each[n].isr_pending) + continue; + + /* + * Hide what we're about to do from the delicate eyes of the + * IRQ controller... + */ + + bc->gpio_ops->irq_mode(bc->button_map[n].gpio, + LWSGGPIO_IRQ_NONE, NULL, NULL); + + each[n].isr_pending = 0; + + /* + * Force the network around the switch to the + * active level briefly + */ + + bc->gpio_ops->set(bc->button_map[n].gpio, + !!(bc->active_state_bitmap & (1 << n))); + bc->gpio_ops->mode(bc->button_map[n].gpio, LWSGGPIO_FL_WRITE); + + if (each[n].state == LBCS_IDLE) { + /* + * If this is the first sign something happening on this + * button, make sure the monitor timer is running to + * classify its response over time + */ + + each[n].state = LBCS_MIN_DOWN_QUALIFY; + each[n].mon_timer_comp = bcs->mon_timer_count; + + if (!bcs->mon_refcount++) { +#if defined(LWS_PLAT_TIMER_START) + LWS_PLAT_TIMER_START(bcs->timer_mon); +#endif + } + } + + /* + * Just for a us or two inbetween here, we're driving it to the + * level we were informed by the interrupt it had enetered, to + * force to charge on the actual and parasitic network around + * the switch to a deterministic-ish state. + * + * If the switch remains in that state, well, it makes no + * difference; if it was a pre-contact and the charge on the + * network was left indeterminate, this will dispose it to act + * consistently in the short term until the pullup / pulldown + * has time to act on it or the switch comes and forces the + * network charge state itself. + */ + bc->gpio_ops->mode(bc->button_map[n].gpio, LWSGGPIO_FL_READ); + + /* + * We could do a better job manipulating the irq mode according + * to the switch state. But if an interrupt comes and we have + * done that, we can't tell if it's from before or after the + * mode change... ie, we don't know what the interrupt was + * telling us. We can't trust the gpio state if we read it now + * to be related to what the irq from some time before was + * trying to tell us. So always set it back to the same mode + * and accept the limitation. + */ + + bc->gpio_ops->irq_mode(bc->button_map[n].gpio, + bc->active_state_bitmap & (1 << n) ? + LWSGGPIO_IRQ_RISING : + LWSGGPIO_IRQ_FALLING, + lws_button_irq_cb_t, &each[n]); + } +} +#endif + +#if defined(LWS_PLAT_TIMER_CB) +static LWS_PLAT_TIMER_CB(lws_button_mon, th) +{ + lws_button_state_t *bcs = LWS_PLAT_TIMER_CB_GET_OPAQUE(th); + lws_button_each_t *each = (lws_button_each_t *)&bcs[1]; + const lws_button_controller_t *bc = bcs->controller; + const lws_button_regime_t *regime; + const char *event_name; + int comp_age_ms; + char active; + size_t n; + + bcs->mon_timer_count++; + + for (n = 0; n < bc->count_buttons; n++) { + + if (each->state == LBCS_IDLE) { + each++; + continue; + } + + if (bc->button_map[n].regime) + regime = bc->button_map[n].regime; + else + regime = &default_regime; + + comp_age_ms = (bcs->mon_timer_count - each->mon_timer_comp) * + LWS_BUTTON_MON_TIMER_MS; + + active = bc->gpio_ops->read(bc->button_map[n].gpio) ^ + (!(bc->active_state_bitmap & (1 << n))); + + // lwsl_notice("%d\n", each->state); + + switch (each->state) { + case LBCS_MIN_DOWN_QUALIFY: + /* + * We're trying to figure out if the initial down event + * is a glitch, or if it meets the criteria for being + * treated as the definitive start of some kind of click + * action. To get past this, he has to be solidly down + * for the time mentioned in the applied regime (at + * least when we sample it). + * + * Significant bounce at the start will abort this try, + * but if it's really down there will be a subsequent + * solid down period... it will simply restart this flow + * from a new interrupt and pass the filter then. + * + * The "brief drive on edge" strategy considerably + * reduces inconsistencies here. But physical bounce + * will continue to be observed. + */ + + if (!active) { + /* We ignore stuff for a bit after discard */ + each->mon_timer_comp = bcs->mon_timer_count; + each->state = LBCS_UP_SETTLE2; + break; + } + + if (comp_age_ms >= regime->ms_min_down) { + + /* We made it through the initial regime filter, + * the next step is wait and see if this down + * event evolves into a single/double click or + * we can call it as a long-click + */ + + each->mon_timer_repeat = bcs->mon_timer_count; + each->state = LBCS_ASSESS_DOWN_HOLD; + event_name = "down"; + goto emit; + } + break; + + case LBCS_ASSESS_DOWN_HOLD: + + /* + * How long is he going to hold it? If he holds it + * past the long-click threshold, we can call it as a + * long-click and do the up processing afterwards. + */ + if (comp_age_ms >= regime->ms_min_down_longpress) { + /* call it as a longclick */ + event_name = "longclick"; + each->state = LBCS_WAIT_UP; + goto emit; + } + + if (!active) { + /* + * He didn't hold it past the long-click + * threshold... we could end up classifying it + * as either a click or a double-click then. + * + * If double-clicks are not allowed to be + * classified, then we can already classify it + * as a single-click. + */ + if (!(regime->flags & + LWSBTNRGMFLAG_CLASSIFY_DOUBLECLICK)) + goto classify_single; + + /* + * Just wait for the up settle time then start + * looking for a second down. + */ + each->mon_timer_comp = bcs->mon_timer_count; + each->state = LBCS_UP_SETTLE1; + event_name = "up"; + goto emit; + } + + goto stilldown; + + case LBCS_UP_SETTLE1: + if (comp_age_ms > regime->ms_up_settle) + /* + * Just block anything for the up settle time + */ + each->state = LBCS_WAIT_DOUBLECLICK; + break; + + case LBCS_WAIT_DOUBLECLICK: + if (active) { + /* + * He has gone down again inside the regime's + * doubleclick grace period... he's going down + * the double-click path + */ + each->mon_timer_comp = bcs->mon_timer_count; + each->state = LBCS_MIN_DOWN_QUALIFY2; + break; + } + + if (comp_age_ms >= regime->ms_doubleclick_grace) { + /* + * The grace period expired, the second click + * was either not forthcoming at all, or coming + * quick enough to count: we classify it as a + * single-click + */ + + goto classify_single; + } + break; + + case LBCS_MIN_DOWN_QUALIFY2: + if (!active) { + + /* + * He went up again too quickly, classify it + * as a single-click. It could be bounce in + * which case you might want to increase the + * ms_up_settle in the regime + */ +classify_single: + event_name = "click"; + each->mon_timer_comp = bcs->mon_timer_count; + each->state = LBCS_UP_SETTLE2; + goto emit; + } + + if (comp_age_ms == regime->ms_min_down) { + event_name = "down"; + goto emit; + } + + if (comp_age_ms > regime->ms_min_down) { + /* + * It's a double-click + */ + event_name = "doubleclick"; + each->state = LBCS_WAIT_UP; + goto emit; + } + break; + + case LBCS_WAIT_UP: + if (!active) { + /* + * He has stopped pressing it + */ + each->mon_timer_comp = bcs->mon_timer_count; + each->state = LBCS_UP_SETTLE2; + event_name = "up"; + goto emit; + } +stilldown: + if (regime->ms_repeat_down && + (bcs->mon_timer_count - each->mon_timer_repeat) * + LWS_BUTTON_MON_TIMER_MS > regime->ms_repeat_down) { + each->mon_timer_repeat = bcs->mon_timer_count; + event_name = "stilldown"; + goto emit; + } + break; + + case LBCS_UP_SETTLE2: + if (comp_age_ms < regime->ms_up_settle) + break; + + each->state = LBCS_IDLE; + if (!(--bcs->mon_refcount)) { +#if defined(LWS_PLAT_TIMER_STOP) + LWS_PLAT_TIMER_STOP(bcs->timer_mon); +#endif + } + } + + each++; + continue; + +emit: + lws_smd_msg_printf(bcs->ctx, LWSSMDCL_INTERACTION, + "{\"type\":\"button\"," + "\"src\":\"%s/%s\",\"event\":\"%s\"}", + bc->smd_bc_name, + bc->button_map[n].smd_interaction_name, + event_name); + + each++; + } +} +#endif + +struct lws_button_state * +lws_button_controller_create(struct lws_context *ctx, + const lws_button_controller_t *controller) +{ + lws_button_state_t *bcs = lws_zalloc(sizeof(lws_button_state_t) + + (controller->count_buttons * sizeof(lws_button_each_t)), + __func__); + lws_button_each_t *each = (lws_button_each_t *)&bcs[1]; + size_t n; + + if (!bcs) + return NULL; + + bcs->controller = controller; + bcs->ctx = ctx; + + for (n = 0; n < controller->count_buttons; n++) + each[n].bcs = bcs; + +#if defined(LWS_PLAT_TIMER_CREATE) + /* this only runs inbetween a gpio ISR and the bottom half */ + bcs->timer = LWS_PLAT_TIMER_CREATE("bcst", + 1, 0, bcs, (TimerCallbackFunction_t)lws_button_bh); + if (!bcs->timer) + return NULL; + + /* this only runs when a button activity is being classified */ + bcs->timer_mon = LWS_PLAT_TIMER_CREATE("bcmon", LWS_BUTTON_MON_TIMER_MS, + 1, bcs, (TimerCallbackFunction_t) + lws_button_mon); + if (!bcs->timer_mon) + return NULL; +#endif + + return bcs; +} + +void +lws_button_controller_destroy(struct lws_button_state *bcs) +{ + /* disable them all */ + lws_button_enable(bcs, 0, 0); + +#if defined(LWS_PLAT_TIMER_DELETE) + LWS_PLAT_TIMER_DELETE(&bcs->timer); + LWS_PLAT_TIMER_DELETE(&bcs->timer_mon); +#endif + + lws_free(bcs); +} + +lws_button_idx_t +lws_button_get_bit(struct lws_button_state *bcs, const char *name) +{ + const lws_button_controller_t *bc = bcs->controller; + int n; + + for (n = 0; n < bc->count_buttons; n++) + if (!strcmp(name, bc->button_map[n].smd_interaction_name)) + return 1 << n; + + return 0; /* not found */ +} + +void +lws_button_enable(lws_button_state_t *bcs, + lws_button_idx_t _reset, lws_button_idx_t _set) +{ + lws_button_idx_t u = (bcs->enable_bitmap & (~_reset)) | _set; + const lws_button_controller_t *bc = bcs->controller; +#if defined(LWS_PLAT_TIMER_START) + lws_button_each_t *each = (lws_button_each_t *)&bcs[1]; +#endif + int n; + + for (n = 0; n < bcs->controller->count_buttons; n++) { + if (!(bcs->enable_bitmap & (1 << n)) && (u & (1 << n))) { + /* set as input with pullup or pulldown appropriately */ + bc->gpio_ops->mode(bc->button_map[n].gpio, + LWSGGPIO_FL_READ | + ((bc->active_state_bitmap & (1 << n)) ? + LWSGGPIO_FL_PULLDOWN : LWSGGPIO_FL_PULLUP)); +#if defined(LWS_PLAT_TIMER_START) + /* + * This one is becoming enabled... the opaque for the + * ISR is the indvidual lws_button_each_t, they all + * point to the same ISR + */ + bc->gpio_ops->irq_mode(bc->button_map[n].gpio, + bc->active_state_bitmap & (1 << n) ? + LWSGGPIO_IRQ_RISING : + LWSGGPIO_IRQ_FALLING, + lws_button_irq_cb_t, &each[n]); +#endif + } + if ((bcs->enable_bitmap & (1 << n)) && !(u & (1 << n))) + /* this one is becoming disabled */ + bc->gpio_ops->irq_mode(bc->button_map[n].gpio, + LWSGGPIO_IRQ_NONE, NULL, NULL); + } + + bcs->enable_bitmap = u; +} diff -Nru libwebsockets-4.0.20/lib/drivers/button/README.md libwebsockets-4.1.6/lib/drivers/button/README.md --- libwebsockets-4.0.20/lib/drivers/button/README.md 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/drivers/button/README.md 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,156 @@ +# LWS GPIO Button class drivers + +Lws provides an GPIO button controller class, this centralizes handling a set of +up to 31 buttons for resource efficiency. Each controller has two OS timers, +one for interrupt to bottom-half event triggering and another that runs at 5ms +intervals only when one or more button is down. + +Each button has its own active level control and sophisticated state tracking; +each button can apply its own classification regime, to allow for different +physical button characteristics, if not overridden a default one is provided. + +Both the controller and individual buttons specify names that are used in the +JSON events produced when the buttons perform actions. + +## Button electronic to logical event processing + +Buttons are monitored using GPIO interrupts since this is very cheap in the +usual case no interaction is ongoing. There is assumed to be one interrupt +per GPIO, but they are pointed at the same ISR, with an opaque pointer to an +internal struct passed per-interrupt to differentiate them and bind them to a +particular button. + +The interrupt is set for notification of the active-going edge, usually if +the button is pulled-up, that's the downgoing edge only. This avoids any +ambiguity about the interrupt meaning, although oscillation is common around +the transition region when the signal is becoming inactive too. + +An OS timer is used to schedule a bottom-half handler outside of interrupt +context. + +To combat commonly-seen partial charging of the actual and parasitic network +around the button causing drift and oscillation, the bottom-half briefly drives +the button signal to the active level, forcing a more deterministic charge level +if it reached the point the interrupt was triggered. This removes much of the +unpredictable behaviour in the us range. It would be better done in the ISR +but many OS apis cannot perform GPIO operations in interrupt context. + +The bottom-half makes sure a monitoring timer is enabled, by refcount. This +is the engine of the rest of the classification while any button is down. The +monitoring timer happens per OS tick or 5ms, whichever is longer. + +## Declaring button controllers + +An array of button map elements if provided first mapping at least GPIOs to +button names, and also optionally the classification regime for that button. + +Then the button controller definition which points back to the button map. + +``` +static const lws_button_map_t bcm[] = { + { + .gpio = GPIO_NUM_0, + .smd_interaction_name = "user" + }, +}; + +static const lws_button_controller_t bc = { + .smd_bc_name = "bc", + .gpio_ops = &lws_gpio_plat, + .button_map = &bcm[0], + .active_state_bitmap = 0, + .count_buttons = LWS_ARRAY_SIZE(bcm), +}; + + struct lws_button_state *bcs; + + bcs = lws_button_controller_create(context, &bc); + if (!bcs) { + lwsl_err("%s: could not create buttons\n", __func__); + goto spin; + } +``` + +That is all that is needed for init, button events will be issued on lws_smd +when buttons are pressed. + +### Regime settings + +The classification regime is designed to reflect both the user interaction +style and the characteristics of a particular type of button. + +Member|Default|Meaning +---|---|--- +ms_min_down|20ms|Down events shorter than this are ignored +ms_min_down_longpress|300ms|Down events longer than this are reported as a long-click +ms_up_settle|20ms|After the first indication a button is no longer down, the button is ignored for this interval +ms_doubleclick_grace|120ms|The time allowed after a click to see if a second, double-click, is forthcoming +ms_repeat_down|0 / disabled|If held down, interval at which to issue `stilldown` events +flags|LWSBTNRGMFLAG_CLASSIFY_DOUBLECLICK|Control which classifications can apply + +### lws_smd System Message Distribution Events + +The button controller emits system messages of class `LWSSMDCL_INTERACTION`, +using a JSON formatted payload + +``` +{ + "type": "button", + "src": "controller-name/button-name", + "event": "event-name" +} +``` + +For example, `{"type":"button","src":"bc/user","event":"doubleclick"}` + +JSON is used because it is maintainable, extensible, self-documenting and does +not require a central, fragile-against-versioning specification of mappings. +Using button names allows the same code to adapt to different hardware or +button mappings. Button events may be synthesized for test or other purposes +cleanly and clearly. + +All the events are somewhat filtered, too short glitches from EMI or whatever +are not reported. "up" and "down" events are reported for the buttons in case +the intention is the duration of the press is meaningful to the user code, but +more typically the user code wants to consume a higher-level classification of +the interaction, eg, that it can be understood as a single "double-click" event. + +Event name|Meaning +---|--- +down|The button passes a filter for being down, useful for duration-based response +stilldown|The regime can be configured to issue "repeat" notifications at intervals +up|The button has come up, useful for duration-based response +click|The button activity resulted in a classification as a single-click +longclick|The button activity resulted in a classification as a long-click +doubleclick|The button activity resulted in a classification as a double-click + +Since double-click detection requires delaying click reporting until it becomes +clear a second click isn't coming, it is enabled as a possible classification in +the regime structure and the regime structure chosen per-button. + +Typically user code is interested in, eg, a high level classification of what +the button is doing, eg, a "click" event on a specific button. Rather than +perform a JSON parse, these events can be processed as strings cheaply using +`lws_json_simple_strcmp()`, it's dumb enough to be cheap but smart enough to +understand enough JSON semantics to be accurate, while retaining the ability to +change and extend the JSON, eg + +``` + if (!lws_json_simple_strcmp(buf, len, "\"src\":", "bc/user")) { + if (!lws_json_simple_strcmp(buf, len, "\"event\":", "click")) { + ... + } + ... + } +``` + +### Relationship between up / down and classification + +Classification|Sequencing +---|--- +click|down-up-click (it's classified when it went up and cannot be a longclick) +longclick|down-longclick-up (it's classified while still down) +doubleclick|down-up-down-doubleclick-up (classified as soon as second click down long enough) + +If the regime is configured for it, any "down" may be followed by one or more +"stilldown" at intervals if the button is down long enough diff -Nru libwebsockets-4.0.20/lib/drivers/CMakeLists.txt libwebsockets-4.1.6/lib/drivers/CMakeLists.txt --- libwebsockets-4.0.20/lib/drivers/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/drivers/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,30 @@ +list(APPEND SOURCES + drivers/display/lws-display.c + drivers/display/ssd1306-i2c.c + drivers/display/ili9341-spi.c + drivers/i2c/lws-i2c.c + drivers/i2c/bitbang/lws-bb-i2c.c + drivers/spi/lws-spi.c + drivers/spi/bitbang/lws-bb-spi.c + drivers/button/lws-button.c + drivers/led/led-gpio.c + drivers/led/led-seq.c + drivers/pwm/pwm.c + drivers/settings/settings.c +) + +if (LWS_WITH_NETWORK) + list(APPEND SOURCES + drivers/netdev/netdev.c + drivers/netdev/wifi.c) +endif() + +if (LWS_ESP_PLATFORM) + list(APPEND SOURCES + plat/freertos/esp32/drivers/gpio-esp32.c + plat/freertos/esp32/drivers/pwm-esp32.c + ) +endif() + +exports_to_parent_scope() + diff -Nru libwebsockets-4.0.20/lib/drivers/devices/display/ili9341.h libwebsockets-4.1.6/lib/drivers/devices/display/ili9341.h --- libwebsockets-4.0.20/lib/drivers/devices/display/ili9341.h 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/drivers/devices/display/ili9341.h 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,95 @@ +/* + * Private register map for ILI9341 + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + */ + +#if !defined(__LWS_ILI9341_H__) +#define __LWS_ILI9341_H__ + +enum { + + ILI9341_NOP = 0x00, + ILI9341_SWRESET = 0x01, + ILI9341_RDDID = 0x04, + ILI9341_RDDST = 0x09, + + ILI9341_SLPIN = 0x10, + ILI9341_SLPOUT = 0x11, + ILI9341_PTLON = 0x12, + ILI9341_NORON = 0x13, + + ILI9341_RDMODE = 0x0a, + ILI9341_RDMADCTL = 0x0b, + ILI9341_RDPIXFMT = 0x0c, + ILI9341_RDIMGFMT = 0x0d, + ILI9341_RDSELFDIAG = 0x0f, + + ILI9341_INVOFF = 0x20, + ILI9341_INVON = 0x21, + ILI9341_GAMMASET = 0x26, + ILI9341_DISPOFF = 0x28, + ILI9341_DISPON = 0x29, + ILI9341_CASET = 0x2a, + ILI9341_PASET = 0x2b, + ILI9341_RAMWR = 0x2c, + ILI9341_RAMRD = 0x2e, + + ILI9341_PTLAR = 0x30, + ILI9341_VSCRDEF = 0x33, + ILI9341_MADCTL = 0x36, + ILI9341_VSCRSADD = 0x37, + ILI9341_PIXFMT = 0x3a, + + ILI9341_FRMCTR1 = 0xb1, + ILI9341_FRMCTR2 = 0xb2, + ILI9341_FRMCTR3 = 0xb3, + ILI9341_INVCTR = 0xb4, + ILI9341_DFUNCTR = 0xb6, + + ILI9341_PWCTR1 = 0xc0, + ILI9341_PWCTR2 = 0xc1, + ILI9341_PWCTR3 = 0xc2, + ILI9341_PWCTR4 = 0xc3, + ILI9341_PWCTR5 = 0xc4, + ILI9341_VMCTR1 = 0xc5, + ILI9341_VMCTR2 = 0xc7, + ILI9341_FACPUMPRAT = 0xcb, + ILI9341_FACPWCTRB = 0xcf, + + ILI9341_RDID1 = 0xda, + ILI9341_RDID2 = 0xdb, + ILI9341_RDID3 = 0xdc, + ILI9341_RDID4 = 0xdd, + + ILI9341_GMCTRP1 = 0xe0, + ILI9341_GMCTRN1 = 0xe1, + ILI9341_FACPWCTRA = 0xe8, + ILI9341_FACPWCTR1 = 0xea, + ILI9341_FACDRTIMCTRA = 0xed, + + ILI9341_FACSETGAMMACRV = 0xf2, + ILI9341_FACDRTIMCTR = 0xf7, +}; + +#endif + diff -Nru libwebsockets-4.0.20/lib/drivers/devices/display/ssd1306.h libwebsockets-4.1.6/lib/drivers/devices/display/ssd1306.h --- libwebsockets-4.0.20/lib/drivers/devices/display/ssd1306.h 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/drivers/devices/display/ssd1306.h 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,66 @@ +/* + * Private register map for SSD1306 + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + */ + +#if !defined(__LWS_SSD1306_H__) +#define __LWS_SSD1306_H__ + +enum { + SSD1306_SETLOWCOLUMN = 0x00, + SSD1306_SETHIGHCOLUMN = 0x10, + + SSD1306_MEMORYMODE = 0x20, + SSD1306_COLUMNADDR = 0x21, + SSD1306_PAGEADDR = 0x22, + SSD1306_DEACTIVATE_SCROLL = 0x2e, + + SSD1306_SETSTARTLINE = 0x40, + + SSD1306_SETCONTRAST = 0x81, + SSD1306_CHARGEPUMP = 0x8d, + + SSD1306_SEGREMAP = 0xa0, + SSD1306_SETSEGMENTREMAP = 0xa1, + SSD1306_DISPLAYALLON_RESUME = 0xa4, + SSD1306_DISPLAYALLON = 0xa5, + SSD1306_NORMALDISPLAY = 0xa6, + SSD1306_INVERTDISPLAY = 0xa7, + SSD1306_SETMULTIPLEX = 0xa8, + SSD1306_DISPLAYOFF = 0xae, + SSD1306_DISPLAYON = 0xaf, + + SSD1306_COMSCANINC = 0xc0, + SSD1306_COMSCANDEC = 0xc8, + + SSD1306_SETDISPLAYOFFSET = 0xd3, + SSD1306_SETDISPLAYCLOCKDIV = 0xd5, + SSD1306_SETPRECHARGE = 0xd9, + SSD1306_SETCOMPINS = 0xda, + SSD1306_SETVCOMDESELECT = 0xdb, + + SSD1306_NOP = 0xe3, +}; + +#endif + diff -Nru libwebsockets-4.0.20/lib/drivers/display/ili9341-spi.c libwebsockets-4.1.6/lib/drivers/display/ili9341-spi.c --- libwebsockets-4.0.20/lib/drivers/display/ili9341-spi.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/drivers/display/ili9341-spi.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,187 @@ +/* + * lws abstract display implementation for ili9341 on spi + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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 +#include + + +static uint8_t ili9341_320x240_init[] = { + /* + * This provides 70Hz 320x240 at RGB565, we assume im[3:0] is 1110 + * which is 4-bit SPI + */ + + 3, ILI9341_FACPWCTRB, 0x00, 0x83, 0x30, + 4, ILI9341_FACDRTIMCTRA, 0x64, 0x03, 0x12, 0x81, + 3, ILI9341_FACPWCTRA, 0x85, 0x01, 0x79, + 5, ILI9341_FACPUMPRAT, 0x39, 0x2c, 0x00, 0x34, 0x02, + 1, ILI9341_FACDRTIMCTR, 0x20, + 2, ILI9341_FACPWCTR1, 0x00, 0x00, + + 1, ILI9341_PWCTR1, 0x26, + 1, ILI9341_PWCTR2, 0x11, + 2, ILI9341_VMCTR1, 0x35, 0x3e, + 1, ILI9341_VMCTR2, 0xbe, + 1, ILI9341_MADCTL, 0x28, + 1, ILI9341_VSCRSADD, 0x00, + 1, ILI9341_PIXFMT, 0x55, + 2, ILI9341_FRMCTR1, 0x00, 0x1b, + 1, ILI9341_FACSETGAMMACRV, 0x00, + 1, ILI9341_GAMMASET, 0x01, + 15, ILI9341_GMCTRP1, 0x0f, 0x31, 0x2b, 0x0c, 0x0e, 0x08, 0x4e, + 0xf1, 0x37, 0x07, 0x10, 0x03, 0x0e, 0x09, + 0x00, + 15, ILI9341_GMCTRN1, 0x00, 0x0e, 0x14, 0x03, 0x11, 0x07, 0x31, + 0xc1, 0x48, 0x08, 0x0f, 0x0c, 0x31, 0x36, + 0x0f, + 4, ILI9341_DFUNCTR, 0x0a, 0x82, 0x27, 0x00, +}; + +int +lws_display_ili9341_spi_init(const struct lws_display *disp) +{ + const lws_display_ili9341_t *ili = (const lws_display_ili9341_t *)disp; + lws_spi_desc_t desc; + size_t pos = 0; + uint8_t u[8]; + + lwsl_user("%s\n", __func__); + + /* hardware nRESET */ + + if (ili->gpio) { + ili->gpio->mode(ili->reset_gpio, LWSGGPIO_FL_WRITE | + LWSGGPIO_FL_PULLUP); + ili->gpio->set(ili->reset_gpio, 0); + + lws_msleep(1); + ili->gpio->set(ili->reset_gpio, 1); + lws_msleep(1); + } + + /* + * We cut the init table up into transactions... atm we just go with + * the fact that bb spi is synchronous, using async / dma we can't use + * a single desc on the stack like this + */ + + memset(&desc, 0, sizeof(desc)); + desc.count_cmd = 1; + + while (pos < LWS_ARRAY_SIZE(ili9341_320x240_init)) { + desc.count_write = ili9341_320x240_init[pos++]; + desc.src = &ili9341_320x240_init[pos++]; + desc.data = &ili9341_320x240_init[pos]; + pos += desc.count_write; + + ili->spi->queue(ili->spi, &desc); + } + + u[0] = ILI9341_SLPOUT; + desc.src = &u[0]; + desc.count_write = 0; + ili->spi->queue(ili->spi, &desc); + + lws_msleep(5); + + u[0] = ILI9341_DISPON; + ili->spi->queue(ili->spi, &desc); + + return 0; +} + +/* backlight handled by PWM */ + +int +lws_display_ili9341_spi_brightness(const struct lws_display *disp, uint8_t b) +{ + return 0; +} + +int +lws_display_ili9341_spi_blit(const struct lws_display *disp, const uint8_t *src, + lws_display_scalar x, lws_display_scalar y, + lws_display_scalar w, lws_display_scalar h) +{ + const lws_display_ili9341_t *ili = (const lws_display_ili9341_t *)disp; + lws_spi_desc_t desc; + uint8_t u[5]; + + memset(&desc, 0, sizeof(desc)); + desc.count_cmd = 1; + desc.src = &u[0]; + desc.count_write = 0; + + /* + * Blit a line at a time + */ + + while (h--) { + + u[0] = ILI9341_CASET; + desc.data = &u[1]; + u[1] = x; + u[2] = x; + u[3] = w >> 8; + u[4] = w & 0xff; + desc.count_write = 4; + ili->spi->queue(ili->spi, &desc); + + u[0] = ILI9341_PASET; + u[1] = y >> 8; + u[2] = y & 0xff; + u[3] = (y + 1) >> 8; + u[4] = (y + 1) & 0xff; + desc.count_write = 4; + ili->spi->queue(ili->spi, &desc); + + u[0] = ILI9341_RAMWR; + desc.data = src; + desc.count_write = w * 2; + ili->spi->queue(ili->spi, &desc); + src += w * 2; + y++; + } + + return 0; +} + +int +lws_display_ili9341_spi_power(const struct lws_display *disp, int state) +{ + + const lws_display_ili9341_t *ili = (const lws_display_ili9341_t *)disp; + lws_spi_desc_t desc; + uint8_t u[1]; + + memset(&desc, 0, sizeof(desc)); + desc.count_cmd = 1; + desc.data = desc.src = &u[0]; + u[0] = state ? ILI9341_SLPOUT : ILI9341_SLPIN; + ili->spi->queue(ili->spi, &desc); + + /* we're not going to do anything useful for 5ms after this */ + + return 0; +} diff -Nru libwebsockets-4.0.20/lib/drivers/display/lws-display.c libwebsockets-4.1.6/lib/drivers/display/lws-display.c --- libwebsockets-4.0.20/lib/drivers/display/lws-display.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/drivers/display/lws-display.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,132 @@ +/* + * lws abstract display + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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 + +static void +sul_autodim_cb(lws_sorted_usec_list_t *sul) +{ + lws_display_state_t *lds = lws_container_of(sul, lws_display_state_t, + sul_autodim); + int next_ms = -1; + + /* we fire both to dim and to blank... if already in dim state, blank */ + + switch (lds->state) { + case LWSDISPS_BECOMING_ACTIVE: + lws_display_state_set_brightness(lds, lds->disp->bl_active); + lds->state = LWSDISPS_ACTIVE; + next_ms = lds->autodim_ms; + break; + + case LWSDISPS_ACTIVE: + /* active -> autodimmed */ + lds->state = LWSDISPS_AUTODIMMED; + next_ms = lds->off_ms; + lws_display_state_set_brightness(lds, lds->disp->bl_dim); + break; + + case LWSDISPS_AUTODIMMED: + /* dimmed -> OFF */ + lws_display_state_set_brightness(lds, &lws_pwmseq_static_off); + lds->state = LWSDISPS_GOING_OFF; + next_ms = 600; + break; + + case LWSDISPS_GOING_OFF: + /* off dimming completed, actual display OFF */ + lws_display_state_off(lds); + return; + + default: + return; + } + + if (next_ms >= 0) + lws_sul_schedule(lds->ctx, 0, &lds->sul_autodim, sul_autodim_cb, + next_ms * LWS_US_PER_MS); +} + +void +lws_display_state_init(lws_display_state_t *lds, struct lws_context *ctx, + int dim_ms, int off_ms, struct lws_led_state *bl_lcs, + const lws_display_t *disp) +{ + memset(lds, 0, sizeof(*lds)); + + lds->disp = disp; + lds->ctx = ctx; + lds->autodim_ms = dim_ms; + lds->off_ms = off_ms; + lds->bl_lcs = bl_lcs; + lds->state = LWSDISPS_OFF; + + lws_led_transition(lds->bl_lcs, "backlight", &lws_pwmseq_static_off, + &lws_pwmseq_static_on); + + disp->init(disp); +} + +void +lws_display_state_set_brightness(lws_display_state_t *lds, + const lws_led_sequence_def_t *pwmseq) +{ + lws_led_transition(lds->bl_lcs, "backlight", pwmseq, + lds->disp->bl_transition); +} + +void +lws_display_state_active(lws_display_state_t *lds) +{ + int waiting_ms; + + if (lds->state == LWSDISPS_OFF) { + /* power us up */ + lds->disp->power(lds->disp, 1); + lds->state = LWSDISPS_BECOMING_ACTIVE; + waiting_ms = lds->disp->latency_wake_ms; + } else { + + if (lds->state != LWSDISPS_ACTIVE) + lws_display_state_set_brightness(lds, + lds->disp->bl_active); + + lds->state = LWSDISPS_ACTIVE; + waiting_ms = lds->autodim_ms; + } + + /* reset the autodim timer */ + if (waiting_ms >= 0) + lws_sul_schedule(lds->ctx, 0, &lds->sul_autodim, sul_autodim_cb, + waiting_ms * LWS_US_PER_MS); + +} + +void +lws_display_state_off(lws_display_state_t *lds) +{ + lds->disp->power(lds->disp, 0); + lws_sul_cancel(&lds->sul_autodim); + lds->state = LWSDISPS_OFF; +} diff -Nru libwebsockets-4.0.20/lib/drivers/display/README.md libwebsockets-4.1.6/lib/drivers/display/README.md --- libwebsockets-4.0.20/lib/drivers/display/README.md 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/drivers/display/README.md 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,36 @@ +# lws_display + +lws provides a generic "display" object that is independent of the connection +to the display, i2c and spi implementations are provided. + +Its purpose is to provide basic blit, backlight binding to lws_pwm, backlight / +power management and display info like pixels wide and high in a generic way. + +The generic display object `lws_display_t` can be included at the top of a +specific display implementation object, eg, binding it to additional members +to define the actual IO operations to be used, eg, i2c or spi. + +When the display is instantiated, it allocates an additional structure on heap +that contains dynamic information about display state, `lws_display_state_t`. + +## Power state machine + +lws_display objects have convenient power state management using a single lws +sul event loop timer that is managed automatically. + +State|Meaning +---|--- +OFF|The display is in sleep and not showing anything +BECOMING_ACTIVE|The display was asked to come out of sleep and is waiting for .latency_wake_ms befor proceeding to ACTIVE. The backlight if any is off. After the delay, the backlight is sequenced up to `.bl_active` using `.bl_transition` sequencer +ACTIVE|The backlight is ON and the dim timer is running +AUTODIMMED|The dim timer was not told the display was active for `.autodim_ms`, we are at `.bl_dim` brightness. After `.off_ms` we will transition to OFF + +The lws_pwm sequencers are used to provide customizable, smooth transitions for +the backlight, which may be nonlinear. + +## Active notification + +Calling `lws_display_state_active(&lds)` on eg, user interaction causes the +display state to transition to ACTIVE smoothly, taking care of waking the display +and waiting out a display-specific wake period, and sequencing the backlight +transition to active level as specified in the display structure. diff -Nru libwebsockets-4.0.20/lib/drivers/display/ssd1306-i2c.c libwebsockets-4.1.6/lib/drivers/display/ssd1306-i2c.c --- libwebsockets-4.0.20/lib/drivers/display/ssd1306-i2c.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/drivers/display/ssd1306-i2c.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,142 @@ +/* + * lws abstract display implementation for ssd1306 on i2c + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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 +#include + + +static uint8_t ssd1306_128x64_init[] = { + SSD1306_DISPLAYOFF, + SSD1306_SETDISPLAYCLOCKDIV, 0xf0, + SSD1306_SETMULTIPLEX, 64 - 1, + SSD1306_SETDISPLAYOFFSET, 0, + SSD1306_CHARGEPUMP, 0x14, + SSD1306_MEMORYMODE, 0, + SSD1306_SEGREMAP | (0 << 0), + SSD1306_COMSCANDEC, + SSD1306_SETCOMPINS, (1 << 4) | 0x02, + SSD1306_SETCONTRAST, 0, /* start at lowest */ + SSD1306_SETPRECHARGE, (0xf << 4) | (1 << 0), + SSD1306_SETVCOMDESELECT, (4 << 4), + SSD1306_DEACTIVATE_SCROLL, + SSD1306_DISPLAYALLON_RESUME, + SSD1306_NORMALDISPLAY, + SSD1306_DISPLAYON +}; + +int +lws_display_ssd1306_i2c_init(const struct lws_display *disp) +{ + const lws_display_ssd1306_t *si = (const lws_display_ssd1306_t *)disp; + + si->i2c->init(si->i2c); + + if (si->gpio) { + si->gpio->mode(si->reset_gpio, LWSGGPIO_FL_WRITE | + LWSGGPIO_FL_PULLUP); + si->gpio->set(si->reset_gpio, 0); + lws_msleep(1); + si->gpio->set(si->reset_gpio, 1); + lws_msleep(1); + } + + if (lws_i2c_command_list(si->i2c, si->i2c7_address, + ssd1306_128x64_init, + LWS_ARRAY_SIZE(ssd1306_128x64_init))) { + lwsl_err("%s: fail\n", __func__); + return 1; + } + + return 0; +} + +int +lws_display_ssd1306_i2c_contrast(const struct lws_display *disp, uint8_t b) +{ + const lws_display_ssd1306_t *si = (const lws_display_ssd1306_t *)disp; + uint8_t ba[2]; + + ba[0] = SSD1306_SETCONTRAST; + ba[1] = b; + + return lws_i2c_command_list(si->i2c, si->i2c7_address, + ba, LWS_ARRAY_SIZE(ba)); +} + +int +lws_display_ssd1306_i2c_blit(const struct lws_display *disp, const uint8_t *src, + lws_display_scalar x, lws_display_scalar y, + lws_display_scalar w, lws_display_scalar h) +{ + const lws_display_ssd1306_t *si = (const lws_display_ssd1306_t *)disp; + uint8_t ba[6]; + int n, m; + + /* + * The display is arranged in 128x8 bands, with one byte containing + * the 8 vertical pixels of the band. + */ + + if (h < 8) + h = 8; + + ba[0] = SSD1306_COLUMNADDR; + ba[1] = x; + ba[2] = x + w - 1; + ba[3] = SSD1306_PAGEADDR; + ba[4] = y / 8; + ba[5] = ba[4] + (h / 8) - 1; + + if (lws_i2c_command_list(si->i2c, si->i2c7_address, + ba, LWS_ARRAY_SIZE(ba))) { + lwsl_err("%s: fail\n", __func__); + return 1; + } + + for (n = 0; n < (w * h) / 8;) { + lws_bb_i2c_start(si->i2c); + lws_bb_i2c_write(si->i2c, si->i2c7_address << 1); + lws_bb_i2c_write(si->i2c, SSD1306_SETSTARTLINE | y); + + for (m = 0; m < w; m++) + lws_bb_i2c_write(si->i2c, src[n++]); + + lws_bb_i2c_stop(si->i2c); + y += 8; + } + + return 0; +} + +int +lws_display_ssd1306_i2c_power(const struct lws_display *disp, int state) +{ + const lws_display_ssd1306_t *si = (const lws_display_ssd1306_t *)disp; + + if (!state) + return lws_i2c_command(si->i2c, si->i2c7_address, + SSD1306_DISPLAYOFF | !!state); + + return lws_display_ssd1306_i2c_init(disp); +} diff -Nru libwebsockets-4.0.20/lib/drivers/i2c/bitbang/lws-bb-i2c.c libwebsockets-4.1.6/lib/drivers/i2c/bitbang/lws-bb-i2c.c --- libwebsockets-4.0.20/lib/drivers/i2c/bitbang/lws-bb-i2c.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/drivers/i2c/bitbang/lws-bb-i2c.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,135 @@ +/* + * I2C bitbang implementation using generic gpio + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + * This is like an abstract class for gpio, a real implementation provides + * functions for the ops that use the underlying OS gpio arrangements. + */ +#include + +int +lws_bb_i2c_init(const lws_i2c_ops_t *octx) +{ + lws_bb_i2c_t *ctx = (lws_bb_i2c_t *)octx; + + ctx->gpio->mode(ctx->scl, LWSGGPIO_FL_WRITE | LWSGGPIO_FL_READ | LWSGGPIO_FL_PULLUP); + ctx->gpio->mode(ctx->sda, LWSGGPIO_FL_WRITE | LWSGGPIO_FL_READ | LWSGGPIO_FL_PULLUP); + + return 0; +} + +int +lws_bb_i2c_start(const lws_i2c_ops_t *octx) +{ + lws_bb_i2c_t *ctx = (lws_bb_i2c_t *)octx; + + ctx->gpio->set(ctx->sda, 1); + ctx->gpio->set(ctx->scl, 1); + ctx->delay(); + + if (!ctx->gpio->read(ctx->sda)) + return 1; + + ctx->gpio->set(ctx->sda, 0); + ctx->delay(); + ctx->gpio->set(ctx->scl, 0); + + return 0; +} + +void +lws_bb_i2c_stop(const lws_i2c_ops_t *octx) +{ + lws_bb_i2c_t *ctx = (lws_bb_i2c_t *)octx; + + ctx->gpio->set(ctx->sda, 0); + ctx->gpio->set(ctx->scl, 1); + ctx->delay(); + + while (!ctx->gpio->read(ctx->scl)) + ; + + ctx->gpio->set(ctx->sda, 1); + ctx->delay(); +} + +int +lws_bb_i2c_write(const lws_i2c_ops_t *octx, uint8_t data) +{ + lws_bb_i2c_t *ctx = (lws_bb_i2c_t *)octx; + int n; + + for (n = 0; n < 8; n++) { + ctx->gpio->set(ctx->sda, !!(data & (1 << 7))); + ctx->delay(); + ctx->gpio->set(ctx->scl, 1); + ctx->delay(); + data <<= 1; + ctx->gpio->set(ctx->scl, 0); + } + + ctx->gpio->set(ctx->sda, 1); + ctx->delay(); + ctx->gpio->set(ctx->scl, 1); + ctx->delay(); + n = ctx->gpio->read(ctx->sda); + ctx->gpio->set(ctx->scl, 0); + ctx->delay(); + + return !!n; /* 0 = ACKED = OK */ +} + +int +lws_bb_i2c_read(const lws_i2c_ops_t *octx) +{ + lws_bb_i2c_t *ctx = (lws_bb_i2c_t *)octx; + int n, r = 0; + + ctx->gpio->set(ctx->sda, 1); + + for (n = 7; n <= 0; n--) { + ctx->gpio->set(ctx->scl, 0); + ctx->delay(); + ctx->gpio->set(ctx->scl, 1); + ctx->delay(); + if (ctx->gpio->read(ctx->sda)) + r |= 1 << n; + } + ctx->gpio->set(ctx->scl, 0); + + return r; +} + +void +lws_bb_i2c_set_ack(const lws_i2c_ops_t *octx, int ack) +{ + lws_bb_i2c_t *ctx = (lws_bb_i2c_t *)octx; + + ctx->gpio->set(ctx->scl, 0); + ctx->gpio->set(ctx->sda, !!ack); + ctx->delay(); + ctx->gpio->set(ctx->scl, 1); + ctx->delay(); + ctx->gpio->set(ctx->scl, 0); + ctx->delay(); + ctx->gpio->set(ctx->sda, 1); +} diff -Nru libwebsockets-4.0.20/lib/drivers/i2c/lws-i2c.c libwebsockets-4.1.6/lib/drivers/i2c/lws-i2c.c --- libwebsockets-4.0.20/lib/drivers/i2c/lws-i2c.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/drivers/i2c/lws-i2c.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,59 @@ +/* + * Generic I2C + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + * These are generic helpers made up of calls to the i2c driver ops, so they + * just need implementing once like this and are usable for any i2c underlying + * implementation via the ops. + */ + +#include + +int +lws_i2c_command(const lws_i2c_ops_t *ctx, uint8_t ads7, uint8_t c) +{ + if (ctx->start(ctx)) + return 1; + + if (ctx->write(ctx, ads7 << 1)) { + ctx->stop(ctx); + + return 1; + } + + ctx->write(ctx, 0); + ctx->write(ctx, c); + ctx->stop(ctx); + + return 0; +} + +int +lws_i2c_command_list(const lws_i2c_ops_t *ctx, uint8_t ads7, const uint8_t *buf, + size_t len) +{ + while (len--) + if (lws_i2c_command(ctx, ads7, *buf++)) + return 1; + + return 0; +} diff -Nru libwebsockets-4.0.20/lib/drivers/led/led-gpio.c libwebsockets-4.1.6/lib/drivers/led/led-gpio.c --- libwebsockets-4.0.20/lib/drivers/led/led-gpio.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/drivers/led/led-gpio.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,120 @@ +/* + * Generic GPIO led + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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" +#include "drivers/led/private-lib-drivers-led.h" + +#if defined(LWS_PLAT_TIMER_CB) +static LWS_PLAT_TIMER_CB(lws_led_timer_cb, th) +{ + lws_led_state_t *lcs = LWS_PLAT_TIMER_CB_GET_OPAQUE(th); + + lws_seq_timer_handle(lcs); +} +#endif + +struct lws_led_state * +lws_led_gpio_create(const lws_led_ops_t *led_ops) +{ + lws_led_gpio_controller_t *lgc = (lws_led_gpio_controller_t *)led_ops; + /* + * We allocate the main state object, and a 3 x seq dynamic footprint + * for each led, since it may be sequencing the transition between two + * other sequences. + */ + + lws_led_state_t *lcs = lws_zalloc(sizeof(lws_led_state_t) + + (lgc->count_leds * sizeof(lws_led_state_chs_t)), + __func__); + int n; + + if (!lcs) + return NULL; + + lcs->controller = lgc; + +#if defined(LWS_PLAT_TIMER_CREATE) + lcs->timer = LWS_PLAT_TIMER_CREATE("leds", + LWS_LED_SEQUENCER_UPDATE_INTERVAL_MS, 1, lcs, + (TimerCallbackFunction_t)lws_led_timer_cb); + if (!lcs->timer) + return NULL; +#endif + + for (n = 0; n < lgc->count_leds; n++) { + const lws_led_gpio_map_t *map = &lgc->led_map[n]; + + if (map->pwm_ops) { + lgc->gpio_ops->mode(map->gpio, LWSGGPIO_FL_READ); + lgc->gpio_ops->set(map->gpio, 0); + } else { + lgc->gpio_ops->mode(map->gpio, LWSGGPIO_FL_WRITE); + lgc->gpio_ops->set(map->gpio, + !lgc->led_map[n].active_level); + } + } + + return lcs; +} + +void +lws_led_gpio_destroy(struct lws_led_state *lcs) +{ +#if defined(LWS_PLAT_TIMER_DELETE) + LWS_PLAT_TIMER_DELETE(&lcs->timer); +#endif + lws_free(lcs); +} + +int +lws_led_gpio_lookup(const struct lws_led_ops *lo, const char *name) +{ + const lws_led_gpio_controller_t *lgc = (lws_led_gpio_controller_t *)lo; + int n; + + for (n = 0; n < lgc->count_leds; n++) + if (!strcmp(name, lgc->led_map[n].name)) + return n; + + return -1; +} + +void +lws_led_gpio_intensity(const struct lws_led_ops *lo, const char *name, + lws_led_intensity_t inten) +{ + const lws_led_gpio_controller_t *lgc = (lws_led_gpio_controller_t *)lo; + int idx = lws_led_gpio_lookup(lo, name); + const lws_led_gpio_map_t *map; + + if (idx < 0) + return; + + map = &lgc->led_map[idx]; + + if (map->pwm_ops) + map->pwm_ops->intensity(map->pwm_ops, map->gpio, inten); + else + lgc->gpio_ops->set(map->gpio, + (!!map->active_level) ^ !(inten & 0x8000)); +} diff -Nru libwebsockets-4.0.20/lib/drivers/led/led-seq.c libwebsockets-4.1.6/lib/drivers/led/led-seq.c --- libwebsockets-4.0.20/lib/drivers/led/led-seq.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/drivers/led/led-seq.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,200 @@ +/* + * Generic GPIO led + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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" + +#include "drivers/led/private-lib-drivers-led.h" + +/* + * 64 entry interpolated CIE correction + * https://en.wikipedia.org/wiki/Lightness + */ + +uint16_t cie[] = { + 0, 113, 227, 340, 454, 568, 688, 824, 976, 1146, + 1335, 1543, 1772, 2023, 2296, 2592, 2914, 3260, 3633, 4034, + 4463, 4921, 5409, 5929, 6482, 7067, 7687, 8341, 9032, 9761, + 10527, 11332, 12178, 13064, 13993, 14964, 15980, 17040, 18146, 19299, + 20500, 21750, 23049, 24400, 25802, 27256, 28765, 30328, 31946, 33622, + 35354, 37146, 38996, 40908, 42881, 44916, 47014, 49177, 51406, 53700, + 56062, 58492, 60992, 63561, + 65535 /* for interpolation */ +}; + +/* + * This is the default intensity correction function, it can be overridden + * per-led to eg, normalize intensity of different leds + */ + +static lws_led_intensity_t +cie_antilog(lws_led_intensity_t lin) +{ + return (cie[lin >> 10] * (0x3ff - (lin & 0x3ff)) + + cie[(lin >> 10) + 1] * (lin & 0x3ff)) / 0x3ff; +} + +static void +lws_seq_advance(lws_led_state_t *lcs, lws_led_state_ch_t *ch) +{ + if (!ch->seq) + return; + + if (ch->phase_budget != LWS_SEQ_LEDPHASE_TOTAL_ENDLESS && + (ch->phase_budget < ch->step || !ch->phase_budget)) { + + /* we are done */ + + ch->seq = NULL; + if (!(--lcs->timer_refcount)) { +#if defined(LWS_PLAT_TIMER_STOP) + LWS_PLAT_TIMER_STOP(lcs->timer); +#endif + } + + return; + } + + ch->ph += ch->step; + if (ch->phase_budget != LWS_SEQ_LEDPHASE_TOTAL_ENDLESS) + ch->phase_budget -= ch->step; +} + +static lws_led_intensity_t +lws_seq_sample(const lws_led_gpio_map_t *map, lws_led_state_chs_t *chs) +{ + unsigned int i; + + if (chs->seqs[LLSI_CURR].seq) + chs->seqs[LLSI_CURR].last = chs->seqs[LLSI_CURR].seq-> + func(chs->seqs[LLSI_CURR].ph); + + if (chs->seqs[LLSI_TRANS].seq) { + /* + * If a transition is ongoing, we need to use the transition + * intensity as the mixing factor between the still-live current + * and newly-live next sequences + */ + chs->seqs[LLSI_TRANS].last = chs->seqs[LLSI_TRANS].seq-> + func(chs->seqs[LLSI_TRANS].ph); + + if (chs->seqs[LLSI_NEXT].seq) + chs->seqs[LLSI_NEXT].last = chs->seqs[LLSI_NEXT].seq-> + func(chs->seqs[LLSI_NEXT].ph); + + i = (lws_led_intensity_t)((( + (unsigned int)chs->seqs[LLSI_CURR].last * + (65535 - chs->seqs[LLSI_TRANS].last) >> 16) + + (((unsigned int)chs->seqs[LLSI_NEXT].last * + (unsigned int)chs->seqs[LLSI_TRANS].last) >> 16))); + } else + i = chs->seqs[LLSI_CURR].last; + + return map->intensity_correction ? map->intensity_correction(i) : + cie_antilog((lws_led_intensity_t)i); +} + +void +lws_seq_timer_handle(lws_led_state_t *lcs) +{ + lws_led_gpio_controller_t *lgc = lcs->controller; + lws_led_state_chs_t *chs = (lws_led_state_chs_t *)&lcs[1]; + const lws_led_gpio_map_t *map = &lgc->led_map[0]; + unsigned int n; + + for (n = 0; n < lgc->count_leds; n++) { + + lgc->led_ops.intensity(&lgc->led_ops, map->name, + lws_seq_sample(map, chs)); + + lws_seq_advance(lcs, &chs->seqs[LLSI_CURR]); + + if (chs->seqs[LLSI_TRANS].seq) { + lws_seq_advance(lcs, &chs->seqs[LLSI_NEXT]); + lws_seq_advance(lcs, &chs->seqs[LLSI_TRANS]); + + /* + * When we finished the transition, we can make the + * "next" sequence the current sequence and no need for + * a "next" or a transition any more. + */ + + if (!chs->seqs[LLSI_TRANS].seq) { + chs->seqs[LLSI_CURR] = chs->seqs[LLSI_NEXT]; + chs->seqs[LLSI_NEXT].seq = NULL; + } + } + + map++; + chs++; + } +} + +static int +lws_led_set_chs_seq(struct lws_led_state *lcs, lws_led_state_ch_t *dest, + const lws_led_sequence_def_t *def) +{ + int steps; + + dest->seq = def; + dest->ph = def->ledphase_offset; + dest->phase_budget = def->ledphase_total; + + /* + * We need to compute the incremental phase angle step to cover the + * total number of phases in the indicated ms, incrementing at the + * timer rate of LWS_LED_SEQUENCER_UPDATE_RATE_HZ. Eg, + * + * 65536 phase steps (one cycle) in 2000ms at 30Hz timer rate means we + * will update 2000ms / 33ms = 60 times, so we must step at at + * 65536 / 60 = 1092 phase angle resolution + */ + + steps = def->ms / LWS_LED_SEQUENCER_UPDATE_INTERVAL_MS; + dest->step = (def->ledphase_total != LWS_SEQ_LEDPHASE_TOTAL_ENDLESS ? + def->ledphase_total : LWS_LED_FUNC_PHASE) / (steps ? steps : 1); + + if (!lcs->timer_refcount++) { +#if defined(LWS_PLAT_TIMER_START) + LWS_PLAT_TIMER_START(lcs->timer); +#endif + } + + return steps; +} + +int +lws_led_transition(struct lws_led_state *lcs, const char *name, + const lws_led_sequence_def_t *next, + const lws_led_sequence_def_t *trans) +{ + lws_led_state_chs_t *chs = (lws_led_state_chs_t *)&lcs[1]; + int index = lws_led_gpio_lookup(&lcs->controller->led_ops, name); + + if (index < 0) + return 1; + + lws_led_set_chs_seq(lcs, &chs[index].seqs[LLSI_TRANS], trans); + lws_led_set_chs_seq(lcs, &chs[index].seqs[LLSI_NEXT], next); + + return 0; +} diff -Nru libwebsockets-4.0.20/lib/drivers/led/private-lib-drivers-led.h libwebsockets-4.1.6/lib/drivers/led/private-lib-drivers-led.h --- libwebsockets-4.0.20/lib/drivers/led/private-lib-drivers-led.h 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/drivers/led/private-lib-drivers-led.h 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,39 @@ +/* + * Generic GPIO led + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + */ + +typedef struct lws_led_state +{ +#if defined(LWS_PLAT_TIMER_TYPE) + LWS_PLAT_TIMER_TYPE timer; +#endif + + lws_led_gpio_controller_t *controller; + int timer_refcount; +} lws_led_state_t; + +void +lws_seq_timer_handle(lws_led_state_t *lcs); + +int +lws_led_gpio_lookup(const struct lws_led_ops *lo, const char *name); diff -Nru libwebsockets-4.0.20/lib/drivers/led/README.md libwebsockets-4.1.6/lib/drivers/led/README.md --- libwebsockets-4.0.20/lib/drivers/led/README.md 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/drivers/led/README.md 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,155 @@ +# lws_led gpio and pwm class drivers + +Lws provides an abstract led controller class that can bind an array of LEDs +to gpio and pwm controllers, and automatically handled pwm sequencers. + +Lumience intensity is corrected for IEC curves to match perceptual intensity, +and the correction can be overridden per led for curve adaptation matching. + +Intensity is normalized to a 16-bit scale, when controlled by a GPIO b15 is +significant and the rest ignored. When controlled by PWM, as many bits from +b15 down are significant as the PWM arrangements can represent. + +The PWM sequencers use arbitrary function generation callbacks on a normalized +16-bit phase space, they can choose how much to interpolate and how much to put +in a table, a 64-sample, 16-bit sine function is provided along with 16-bit +linear sawtooth. + +Changing the sequencer is subject to a third transition function sequencer, this +can for example mix the transition linearly over, eg, 500ms so the leds look +very smooth. + +## Defining an led controller + +An array of inidividual LED information is provided first, and referenced by +the LED controller definintion. Leds are named so code does not introduce +dependencies on specific implementations. + +``` +static const lws_led_gpio_map_t lgm[] = { + { + .name = "alert", + .gpio = GPIO_NUM_25, + .pwm_ops = &pwm_ops, + .active_level = 1, + }, +}; + +static const lws_led_gpio_controller_t lgc = { + .led_ops = lws_led_gpio_ops, + .gpio_ops = &lws_gpio_plat, + .led_map = &lgm[0], + .count_leds = LWS_ARRAY_SIZE(lgm) +}; + + struct lws_led_state *lls; + + lls = lgc.led_ops.create(&lgc.led_ops); + if (!lls) { + lwsl_err("%s: could not create led\n", __func__); + goto spin; + } + +``` + +For GPIO control, the active level of the GPIO to light the LED may be set. + +Each LED may bind to a pwm controller, in which case setting the intensity +programs the pwm controller corresponding to the GPIO. + +## Setting the intensity directly + +``` + lgc.led_ops.intensity(&lgc.led_ops, "alert", 0); +``` + +## Defining Sequencer + +Some common sequencers are provided out of the box, you can also define your +own arbitrary ones. + +The main point is sequencers have a function that returns an intensity for each +of 65536 phase steps in its cycle. For example, this is the linear function +that is included + +``` +lws_led_intensity_t +lws_led_func_linear(lws_led_seq_phase_t n) +{ + return (lws_led_intensity_t)n; +} +``` + +It simply returns an intensity between 0 - 65535 matching the phase angle of +0 - 65535 that it was given, so it's a sawtooth ramp. + +An interpolated sine function is also provided that returns an intensity +between 0 - 65535 reflecting one cycle of sine wave for the phase angle of 0 - +65535. + +These functions are packaged into sequencer structures like this + +``` +const lws_led_sequence_def_t lws_pwmseq_sine_endless_fast = { + .func = lws_led_func_sine, + .ledphase_offset = 0, /* already at 0 amp at 0 phase */ + .ledphase_total = LWS_SEQ_LEDPHASE_TOTAL_ENDLESS, + .ms = 750 +}; +``` + +This "endless" sequencer cycles through the sine function at 750ms per cycle. +Non-endless sequencers have a specific start and end in the phase space, eg + +``` +const lws_led_sequence_def_t lws_pwmseq_sine_up = { + .func = lws_led_func_sine, + .ledphase_offset = 0, /* already at 0 amp at 0 phase */ + .ledphase_total = LWS_LED_FUNC_PHASE / 2, /* 180 degree ./^ */ + .ms = 300 +}; +``` + +... this one traverses 180 degrees of the sine wave starting from 0 and ending +at full intensity, over 300ms. + +A commonly-used, provided one is like this, as used in the next section + +``` +const lws_led_sequence_def_t lws_pwmseq_linear_wipe = { + .func = lws_led_func_linear, + .ledphase_offset = 0, + .ledphase_total = LWS_LED_FUNC_PHASE - 1, + .ms = 300 +}; +``` + +## Setting the intensity using sequencer transitions + +The main api for high level sequenced control is + +``` +int +lws_led_transition(struct lws_led_state *lcs, const char *name, + const lws_led_sequence_def_t *next, + const lws_led_sequence_def_t *trans); +``` + +This fades from the current sequence to a new sequence, using `trans` sequencer +intensity as the mix factor. `trans` is typically `lws_pwmseq_linear_wipe`, +fading between the current and new linearly over 300ms. At the end of the +`trans` sequence, the new sequence simply replaces the current one and the +transition is completed. + +Sequencers use a single 30Hz OS timer while any sequence is active. + +exported sequencer symbol|description +---|--- +lws_pwmseq_sine_endless_slow|continuous 100% sine, 1.5s cycle +lws_pwmseq_sine_endless_fast|continuous 100% sine, 0.75s cycle +lws_pwmseq_linear_wipe|single 0 - 100% ramp over 0.3s +lws_pwmseq_sine_up|single 0 - 100% using sine curve over 0.3s +lws_pwmseq_sine_down|single 100% - 0 using sine curve over 0.3s +lws_pwmseq_static_on|100% static +lws_pwmseq_static_half|50% static +lws_pwmseq_static_off|0% static diff -Nru libwebsockets-4.0.20/lib/drivers/netdev/netdev.c libwebsockets-4.1.6/lib/drivers/netdev/netdev.c --- libwebsockets-4.0.20/lib/drivers/netdev/netdev.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/drivers/netdev/netdev.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,272 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2020 Andy Green + * + * 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 + +static const lws_struct_map_t lsm_wifi_creds[] = { + LSM_CARRAY (lws_wifi_creds_t, ssid, "ssid"), + LSM_CARRAY (lws_wifi_creds_t, passphrase, "passphrase"), + LSM_UNSIGNED (lws_wifi_creds_t, alg, "alg"), + LSM_STRING_PTR (lws_wifi_creds_t, bssid, "bssid"), +}; + +static const lws_struct_map_t lsm_netdev_credentials[] = { + LSM_LIST (lws_netdevs_t, owner_creds, lws_wifi_creds_t, list, + NULL, lsm_wifi_creds, "credentials"), +}; + +static const lws_struct_map_t lsm_netdev_schema[] = { + LSM_SCHEMA (lws_netdevs_t, NULL, lsm_netdev_credentials, + "lws-netdev-creds"), +}; + + +//LSM_CHILD_PTR (lws_netdev_instance_wifi_t, ap_cred, lws_wifi_creds_t, +// NULL, lsm_wifi_creds, "ap_cred"), +//LSM_STRING_PTR (lws_netdev_instance_wifi_t, ap_ip, "ap_ip"), + +int +lws_netdev_credentials_settings_set(lws_netdevs_t *nds) +{ + lws_struct_serialize_t *js; + size_t w = 0, max = 2048; + int n, r = 1; + uint8_t *buf; + + buf = lws_malloc(max, __func__); /* length should be computed */ + + js = lws_struct_json_serialize_create(lsm_netdev_schema, + LWS_ARRAY_SIZE(lsm_netdev_schema), 0, nds); + if (!js) + goto bail; + + n = lws_struct_json_serialize(js, buf, max, &w); + lws_struct_json_serialize_destroy(&js); + if (n != LSJS_RESULT_FINISH) + goto bail; + + lwsl_notice("%s: setting %s\n", __func__, buf); + + if (!lws_settings_plat_set(nds->si, "netdev.creds", buf, w)) + r = 0; + +bail: + if (r) + lwsl_err("%s: failed\n", __func__); + lws_free(buf); + + return r; +} + +int +lws_netdev_credentials_settings_get(lws_netdevs_t *nds) +{ + struct lejp_ctx ctx; + lws_struct_args_t a; + size_t l = 0; + uint8_t *buf; + int m; + + memset(&a, 0, sizeof(a)); + + if (lws_settings_plat_get(nds->si, "netdev.creds", NULL, &l)) { + lwsl_notice("%s: not in settings\n", __func__); + return 1; + } + + buf = lws_malloc(l, __func__); + if (!buf) + return 1; + + if (lws_settings_plat_get(nds->si, "netdev.creds", buf, &l)) { + lwsl_err("%s: unexpected settings get fail\n", __func__); + goto bail; + } + + a.map_st[0] = lsm_netdev_schema; + a.map_entries_st[0] = LWS_ARRAY_SIZE(lsm_netdev_schema); + a.ac_block_size = 512; + + lws_struct_json_init_parse(&ctx, NULL, &a); + m = lejp_parse(&ctx, (uint8_t *)buf, l); + lws_free(buf); + if (m < 0 || !a.dest) { + lwsl_notice("%s: JSON decode failed '%s'\n", + __func__, lejp_error_to_string(m)); + goto bail1; + } + + /* + * Forcibly set the state of the nds creds owner to the synthesized + * one in the ac, and keep the ac for as long as we keep the creds out + */ + nds->owner_creds = ((lws_netdevs_t *)a.dest)->owner_creds; + nds->ac_creds = a.ac; + + return 0; + +bail: + lws_free(buf); +bail1: + lwsac_free(&a.ac); + + return 1; +} + +lws_wifi_creds_t * +lws_netdev_credentials_find(lws_netdevs_t *netdevs, const char *ssid, + const uint8_t *bssid) +{ + lws_start_foreach_dll(struct lws_dll2 *, p, lws_dll2_get_head( + &netdevs->owner_creds)) { + lws_wifi_creds_t *w = lws_container_of(p, lws_wifi_creds_t, list); + + if (!strcmp(ssid, (const char *)&w[1]) && + !memcmp(bssid, w->bssid, 6)) + return w; + + } lws_end_foreach_dll(p); + + return NULL; +} + +lws_netdev_instance_t * +lws_netdev_find(lws_netdevs_t *netdevs, const char *ifname) +{ + lws_start_foreach_dll(struct lws_dll2 *, p, lws_dll2_get_head( + &netdevs->owner)) { + lws_netdev_instance_t *ni = lws_container_of(p, + lws_netdev_instance_t, list); + + if (!strcmp(ifname, ni->name)) + return ni; + + } lws_end_foreach_dll(p); + + return NULL; +} + +/* + * Context forwards NETWORK related smd here, in lws thread context + */ + +int +lws_netdev_smd_cb(void *opaque, lws_smd_class_t _class, lws_usec_t timestamp, + void *buf, size_t len) +{ + struct lws_context *ctx = (struct lws_context *)opaque; + const char *iface; + char setname[16]; + size_t al = 0; + + /* deal with anything from whole-network perspective */ + + /* pass through netdev-specific messages to correct platform handler */ + + iface = lws_json_simple_find(buf, len, "\"if\":", &al); + if (!iface) + return 0; + + lws_start_foreach_dll(struct lws_dll2 *, p, lws_dll2_get_head( + &ctx->netdevs.owner)) { + lws_netdev_instance_t *ni = lws_container_of( + p, lws_netdev_instance_t, list); + + if (!strncmp(ni->name, iface, al)) { + + /* + * IP assignment on our netif? We can deal with marking + * the last successful association generically... + */ + + if (ni->type == LWSNDTYP_WIFI && + !lws_json_simple_strcmp(buf, len, "\"type\":", + "ipacq")) { + const char *ev = lws_json_simple_find(buf, len, + "\"ipv4\":", &al); + lws_netdev_instance_wifi_t *wnd = + (lws_netdev_instance_wifi_t *)ni; + + if (!ev) + return 0; + + lws_snprintf(setname, sizeof(setname), + "netdev.last.%s", iface); + + lws_settings_plat_printf(ctx->netdevs.si, + setname, "{\"ssid\":\"%s\",\"bssid\":" + "\"%02X%02X%02X%02X%02X%02X\"}", + wnd->current_attempt_ssid, + wnd->current_attempt_bssid[0], + wnd->current_attempt_bssid[1], + wnd->current_attempt_bssid[2], + wnd->current_attempt_bssid[3], + wnd->current_attempt_bssid[4], + wnd->current_attempt_bssid[5]); + } + + /* + * Pass it through to related netdev instance for + * private actions + */ + + return ni->ops->event(ni, timestamp, buf, len); + } + + } lws_end_foreach_dll(p); + + return 0; +} + +/* + * This is the generic part of the netdev instance initialization that's always + * the same, regardless of the netdev type + */ + +void +lws_netdev_instance_create(lws_netdev_instance_t *ni, struct lws_context *ctx, + const lws_netdev_ops_t *ops, const char *name, + void *platinfo) +{ + ni->ops = ops; + ni->name = name; + ni->platinfo = platinfo; + + /* add us to the list of active netdevs */ + + lws_dll2_add_tail(&ni->list, &ctx->netdevs.owner); +} + +void +lws_netdev_instance_remove_destroy(struct lws_netdev_instance *ni) +{ + lws_dll2_remove(&ni->list); + lws_free(ni); +} + +lws_netdevs_t * +lws_netdevs_from_ctx(struct lws_context *ctx) +{ + return &ctx->netdevs; +} diff -Nru libwebsockets-4.0.20/lib/drivers/netdev/wifi.c libwebsockets-4.1.6/lib/drivers/netdev/wifi.c --- libwebsockets-4.0.20/lib/drivers/netdev/wifi.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/drivers/netdev/wifi.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,243 @@ +/* + * libwebsockets - lws_netdev_wifi generic state handling + * + * Copyright (C) 2010 - 2020 Andy Green + * + * 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. + * + * The generic wifi netdevs follow a + */ + +#include "private-lib-core.h" + +int +lws_netdev_wifi_rssi_sort_compare(const lws_dll2_t *d, const lws_dll2_t *i) +{ + const lws_wifi_sta_t *wsd = (const lws_wifi_sta_t *)d, + *wsi = (const lws_wifi_sta_t *)i; + return rssi_averaged(wsd) > rssi_averaged(wsi); +} + +void +lws_netdev_wifi_scan_empty(lws_netdev_instance_wifi_t *wnd) +{ + lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1, lws_dll2_get_head( + &wnd->scan)) { + lws_wifi_sta_t *s = lws_container_of(p, lws_wifi_sta_t, list); + + lws_dll2_remove(p); + lws_free(s); + + } lws_end_foreach_dll_safe(p, p1); +} + +void +lws_netdev_wifi_scan(lws_sorted_usec_list_t *sul) +{ + lws_netdev_instance_wifi_t *wnd = lws_container_of(sul, + lws_netdev_instance_wifi_t, sul_scan); + + wnd->inst.ops->scan(&wnd->inst); +} + +lws_wifi_sta_t * +lws_netdev_wifi_scan_find(lws_netdev_instance_wifi_t *wnd, const char *ssid, + const uint8_t *bssid) +{ + lws_start_foreach_dll(struct lws_dll2 *, p, lws_dll2_get_head( + &wnd->scan)) { + lws_wifi_sta_t *w = lws_container_of(p, lws_wifi_sta_t, list); + + if (!strcmp(ssid, (const char *)&w[1]) && + !memcmp(bssid, w->bssid, 6)) + return w; + + } lws_end_foreach_dll(p); + + return NULL; +} + +int +lws_netdev_wifi_scan_select(lws_netdev_instance_wifi_t *wnd) +{ + lws_netdevs_t *netdevs = lws_netdevs_from_ndi(&wnd->inst); + struct lws_context *cx = lws_context_from_netdevs(netdevs); + uint32_t least_recent = 0xffffffff; + lws_wifi_creds_t *pc = NULL; + lws_wifi_sta_t *pw = NULL; + + /* + * Trim enough of the lowest RSSI guys in order to get us below the + * limit we are allowed to keep track of... + */ + + while (wnd->scan.count > LWS_WIFI_MAX_SCAN_TRACK) { + struct lws_dll2 *p = lws_dll2_get_tail(&wnd->scan); + lws_wifi_sta_t *w = lws_container_of(p, lws_wifi_sta_t, list); + + lws_dll2_remove(p); + lws_free(w); + } + + /* + * ... let's dump what's left + */ + + lws_start_foreach_dll(struct lws_dll2 *, p, lws_dll2_get_head( + &wnd->scan)) { + lws_wifi_sta_t *w = lws_container_of(p, lws_wifi_sta_t, list); + + lwsl_notice("%s: %s, %02X:%02X:%02X:%02X:%02X:%02X, ch %d, rssi %d\n", + __func__, (const char *)&w[1], w->bssid[0], + w->bssid[1], w->bssid[2], w->bssid[3], w->bssid[4], + w->bssid[5], w->ch, rssi_averaged(w)); + + } lws_end_foreach_dll(p); + + /* + * make sure we have our device's connection credentials at hand + */ + + if (!netdevs->ac_creds && + lws_netdev_credentials_settings_get(netdevs)) + return 0; + netdevs->refcount_creds++; + + /* + * Let's go through each starting from the best RSSI seeing if we + * have credentials... if we do, pick the one we least-recently tried + */ + + lws_start_foreach_dll(struct lws_dll2 *, p1, wnd->scan.head) { + lws_wifi_sta_t *w = lws_container_of(p1, lws_wifi_sta_t, list); + + lws_start_foreach_dll(struct lws_dll2 *, q, + netdevs->owner_creds.head) { + lws_wifi_creds_t *c = lws_container_of(q, + lws_wifi_creds_t, + list); + + if (!strcmp((const char *)&w[1], c->ssid) && + w->last_seen < least_recent) { + /* + * Not <= so we stick with higher RSSI when + * all 0 + */ + pc = c; + pw = w; + least_recent = w->last_seen; + } + + } lws_end_foreach_dll(q); + + } lws_end_foreach_dll(p1); + + + if (least_recent != 0xffffffff) { + /* + * We picked one to try... note what we're trying so we can + * record it in settings as last successful + */ + lws_strncpy(wnd->current_attempt_ssid, (const char *)&pw[1], + sizeof(wnd->current_attempt_ssid)); + memcpy(wnd->current_attempt_bssid, pw->bssid, LWS_ETH_ALEN); + wnd->inst.ops->connect(&wnd->inst, pc->ssid, pc->passphrase, + pw->bssid); + } else { + /* + * We couldn't see anyone we recognized on this scan, let's + * rescan in a bit + */ + + lwsl_notice("%s: nothing usable in scan, redoing in 3s\n", __func__); + lws_sul_schedule(cx, 0, &wnd->sul_scan, lws_netdev_wifi_scan, + 3 * LWS_US_PER_SEC); + } + + if (!--netdevs->refcount_creds) { + lws_dll2_owner_clear(&netdevs->owner_creds); + lwsac_free(&netdevs->ac_creds); + } + + return 0; +} + +/* + * Initially our best bet is just try to reconnect to whatever we last + * succeeded to connect to + */ + +int +lws_netdev_wifi_redo_last(lws_netdev_instance_wifi_t *wnd) +{ + lws_netdevs_t *netdevs = lws_netdevs_from_ndi(&wnd->inst); + uint8_t buf[256], bssid[LWS_ETH_ALEN]; + const char *ssid, *pp = "", *pb; + char setname[16], ssid_copy[33]; + size_t l = sizeof(buf), al; + lws_wifi_creds_t *cred; + + /* + * Let's try to retreive the last successful connect info for this + * netdev + */ + + lws_snprintf(setname, sizeof(setname), "netdev.last.%s", wnd->inst.name); + if (lws_settings_plat_get(netdevs->si, setname, buf, &l)) + return 1; + + lwsl_notice("%s: last successful %s\n", __func__, buf); + + ssid = lws_json_simple_find((const char *)buf, l, "\"ssid\":", &al); + if (!ssid || al > 32) + return 1; + + memcpy(ssid_copy, ssid, al); + ssid_copy[al + 1] = '\0'; + + pb = lws_json_simple_find((const char *)buf, l, "\"bssid\":", &al); + if (!pb) + return 1; + lws_hex_to_byte_array(pb, bssid, sizeof(bssid)); + + /* + * make sure we have our device's connection credentials at hand + */ + + if (!netdevs->ac_creds && + lws_netdev_credentials_settings_get(netdevs)) + return 1; + netdevs->refcount_creds++; + + cred = lws_netdev_credentials_find(netdevs, ssid_copy, bssid); + if (cred) + pp = cred->passphrase; + + lws_strncpy(wnd->current_attempt_ssid, ssid_copy, + sizeof(wnd->current_attempt_ssid)); + memcpy(wnd->current_attempt_bssid, bssid, LWS_ETH_ALEN); + wnd->inst.ops->connect(&wnd->inst, ssid_copy, pp, bssid); + + if (!--netdevs->refcount_creds) { + lws_dll2_owner_clear(&netdevs->owner_creds); + lwsac_free(&netdevs->ac_creds); + } + + return 0; +} diff -Nru libwebsockets-4.0.20/lib/drivers/pwm/pwm.c libwebsockets-4.1.6/lib/drivers/pwm/pwm.c --- libwebsockets-4.0.20/lib/drivers/pwm/pwm.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/drivers/pwm/pwm.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,156 @@ +/* + * Generic GPIO led + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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" + +static const lws_led_intensity_t sineq16[] = { + + /* + * Quadrant at sin(270) in 16 samples, normalized so + * -1 == 0 and 0 == 32767 + */ + + 0, 158, 630, 1411, 2494, 3869, 5522, 7437, + 9597, 11980, 14562, 17321, 20228, 23225, 26374, 29555, + 32767 /* to interpolate against */ +}; + +/* + * Elaborate the 90 degree phase table to 360 degrees and offset to +32768, + * notice for the last sample we have to interpolate against a 17th sample + * reflecting full scale to avoid clipping due to interpolation against the + * 16th sample again + */ + +static lws_led_intensity_t +sine_lu(int n, int next) +{ + switch ((n >> 4) & 3) { + case 1: + /* forwards */ + return 32768 + sineq16[(n & 15) + next]; + case 2: + /* scan it backwards */ + return 32768 + sineq16[15 - (n & 15) + (!next)]; + case 3: + /* forwards */ + return 32768 - sineq16[(n & 15) + next]; + default: + /* scan it backwards */ + return 32768 - sineq16[15 - (n & 15) + (!next)]; + } +} + +/* + * The normalized phase resolution is 16-bit, however much table you decide to + * have needs interpolating or indexing in a reduced number of significant + * phase bits if it doesn't have the same phase resolution. + * + * In this sine table we have a 16 x 15-bit sample quadrant reflected 4 times + * to make 360 degrees, so 64 accurate sample points, with the rest of the + * intermediate phases generated by linear interpolation. That probably would + * sound a bit funky, but for modulating light dynamically it's more than + * enough. + */ + +lws_led_intensity_t +lws_led_func_sine(lws_led_seq_phase_t n) +{ + /* + * 2: quadrant + * 4: table entry in quadrant + * 10: interp (LSB) + */ + + return (sine_lu(n >> 10, 0) * (0x3ff - (n & 0x3ff)) + + sine_lu(n >> 10, 1) * (n & 0x3ff)) / 0x3ff; +} + +lws_led_intensity_t +lws_led_func_linear(lws_led_seq_phase_t n) +{ + return (lws_led_intensity_t)n; +} + + +static lws_led_intensity_t +lws_led_func_static(lws_led_seq_phase_t n) +{ + return ((int)n * LWS_LED_MAX_INTENSITY) / 2; +} + +const lws_led_sequence_def_t lws_pwmseq_static_off = { + .func = lws_led_func_static, + .ledphase_offset = 0, + .ledphase_total = 0, + .ms = 0 +}; + +const lws_led_sequence_def_t lws_pwmseq_static_half = { + .func = lws_led_func_static, + .ledphase_offset = 1, + .ledphase_total = 0, + .ms = 0 +}; + +const lws_led_sequence_def_t lws_pwmseq_static_on = { + .func = lws_led_func_static, + .ledphase_offset = 2, + .ledphase_total = 0, + .ms = 0 +}; + +const lws_led_sequence_def_t lws_pwmseq_sine_up = { + .func = lws_led_func_sine, + .ledphase_offset = 0, /* already at 0 amp at 0 phase */ + .ledphase_total = LWS_LED_FUNC_PHASE / 2, /* 180 degree ./^ */ + .ms = 300 +}; + +const lws_led_sequence_def_t lws_pwmseq_sine_down = { + .func = lws_led_func_sine, + .ledphase_offset = LWS_LED_FUNC_PHASE / 2, /* start at peak */ + .ledphase_total = LWS_LED_FUNC_PHASE / 2, /* 180 degree ./^ */ + .ms = 300 +}; + +const lws_led_sequence_def_t lws_pwmseq_linear_wipe = { + .func = lws_led_func_linear, + .ledphase_offset = 0, + .ledphase_total = LWS_LED_FUNC_PHASE - 1, + .ms = 300 +}; + +const lws_led_sequence_def_t lws_pwmseq_sine_endless_slow = { + .func = lws_led_func_sine, + .ledphase_offset = 0, /* already at 0 amp at 0 phase */ + .ledphase_total = LWS_SEQ_LEDPHASE_TOTAL_ENDLESS, + .ms = 1500 +}; + +const lws_led_sequence_def_t lws_pwmseq_sine_endless_fast = { + .func = lws_led_func_sine, + .ledphase_offset = 0, /* already at 0 amp at 0 phase */ + .ledphase_total = LWS_SEQ_LEDPHASE_TOTAL_ENDLESS, + .ms = 750 +}; diff -Nru libwebsockets-4.0.20/lib/drivers/README.md libwebsockets-4.1.6/lib/drivers/README.md --- libwebsockets-4.0.20/lib/drivers/README.md 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/drivers/README.md 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,44 @@ +# lws meta-drivers + +Although drivers in lws (enabled in cmake by `LWS_WITH_DRIVERS`) provide +actual drivers for some devices like I2C OLED controllers, their main job is +to conceal from user code the underlying OS APIs being used to interface +to the SoC hardware assets. + +CMake already allows lws to be platform-agnostic for build, the plat adaptations +allow lws to be platform-agnostic within itself for runtime. The lws +drivers intend to extend that agnosticism to user code. + +Using this technique on supported OSes frees the user code from dependencies +on the underlying OS choice... for example, although ESP32 is very good, it +comes with a highly specific set of apis in esp-idf that mean your code is +locked in to esp-idf if you follow them. Esp-idf uses freertos apis for things +like OS timers, again if you follow those you are locked into freertos, the +end result is your work is non-portable to other platforms and completely +dependent on esp. + +LWS drivers provide a thin wrapper to eliminate the OS dependencies while +still taking advantage of the work, drivers and maintenance of the underlying +OS layer without duplicating them, but bringing the flexibility to retarget +your work to other scenarios... for example, there is a generic gpio object +subclassed for specific implementations, an i2c object which may be subclassed +to use OS drivers or bitbang using the generic gpio object, buttons on top of +generic gpio, led class that can use generic gpio or pwm interchangeably, +platform-specific gpio, i2c, pwm implementations that can be used at the generic +level are defined to use underlying OS native apis and drivers. + +## Building on the next layer up + +At these generic objects like buttons or led controllers, there is a stable +codebase used by multiple implementations and the intention is to provide +best-of-breed features there generically, like + + - sophisticated button press debounce and classification + + - high quality transitions and log-response compensation and mixing for led pwm + + - display dimming timers, blanking timers, generic interaction detection to unblank + +which are automatically available on top of any implementation that is ported to +lws drivers. + diff -Nru libwebsockets-4.0.20/lib/drivers/settings/settings.c libwebsockets-4.1.6/lib/drivers/settings/settings.c --- libwebsockets-4.0.20/lib/drivers/settings/settings.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/drivers/settings/settings.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,69 @@ +/* + * lws_settings + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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 + +lws_settings_instance_t * +lws_settings_init(const lws_settings_ops_t *so, void *opaque_plat) +{ + lws_settings_instance_t *si = lws_zalloc(sizeof(*si), __func__); + + if (!si) + return NULL; + + si->so = so; + si->opaque_plat = opaque_plat; + + return si; +} + +void +lws_settings_deinit(lws_settings_instance_t **si) +{ + lws_free(*si); + *si = NULL; +} + +int +lws_settings_plat_printf(lws_settings_instance_t *si, const char *name, + const char *format, ...) +{ + va_list ap; + uint8_t *p; + int n; + + va_start(ap, format); + n = vsnprintf(NULL, 0, format, ap); + va_end(ap); + + p = lws_malloc(n + 2, __func__); + va_start(ap, format); + vsnprintf((char *)p, n + 2, format, ap); + va_end(ap); + + n = si->so->set(si, name, p, n); + lws_free(p); + + return n; +} diff -Nru libwebsockets-4.0.20/lib/drivers/spi/bitbang/lws-bb-spi.c libwebsockets-4.1.6/lib/drivers/spi/bitbang/lws-bb-spi.c --- libwebsockets-4.0.20/lib/drivers/spi/bitbang/lws-bb-spi.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/drivers/spi/bitbang/lws-bb-spi.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,126 @@ +/* + * SPI bitbang implementation using generic gpio + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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 + +int +lws_bb_spi_init(const lws_spi_ops_t *octx) +{ + lws_bb_spi_t *ctx = (lws_bb_spi_t *)octx; + int n; + + for (n = 0; n < LWS_SPI_BB_MAX_CH; n++) { + if (ctx->flags & (1 << n)) + ctx->gpio->mode(ctx->ncs[n], LWSGGPIO_FL_WRITE); + if (ctx->flags & (1 << (n + 4))) + ctx->gpio->mode(ctx->ncmd[n], LWSGGPIO_FL_WRITE); + } + + ctx->gpio->mode(ctx->clk, LWSGGPIO_FL_WRITE | + ((octx->bus_mode & LWSSPIMODE_CPOL) ? + 0 : LWSGGPIO_FL_START_LOW)); + ctx->gpio->mode(ctx->mosi, LWSGGPIO_FL_WRITE | LWSGGPIO_FL_START_LOW); + ctx->gpio->mode(ctx->miso, LWSGGPIO_FL_READ | LWSGGPIO_FL_PULLUP); + + return 0; +} + +/* if active, prepare DnC before this and call separately for Cmd / Data */ + +static void +lws_bb_spi_write(lws_bb_spi_t *ctx, const uint8_t *buf, size_t len) +{ + uint8_t u, inv = !!(ctx->bb_ops.bus_mode & LWSSPIMODE_CPOL); + + while (len--) { + int n; + + u = *buf++; + + for (n = 0; n < 4; n++) { + ctx->gpio->set(ctx->clk, inv); + ctx->gpio->set(ctx->mosi, !!(u & 0x80)); + ctx->gpio->set(ctx->clk, !inv); + ctx->gpio->set(ctx->clk, inv); + ctx->gpio->set(ctx->mosi, !!(u & 0x40)); + ctx->gpio->set(ctx->clk, !inv); + u <<= 2; + } + } + + ctx->gpio->set(ctx->clk, 0 ^ inv); +} + +static void +lws_bb_spi_read(lws_bb_spi_t *ctx, uint8_t *buf, size_t len) +{ + uint8_t u, inv = !!(ctx->bb_ops.bus_mode & LWSSPIMODE_CPOL); + + while (len--) { + int n; + + for (n = 0; n < 8; n++) { + ctx->gpio->set(ctx->clk, inv); + u = (u << 1) | !!ctx->gpio->read(ctx->miso); + ctx->gpio->set(ctx->mosi, !!(u & 0x80)); + ctx->gpio->set(ctx->clk, !inv); + } + *buf++ = u; + } + + ctx->gpio->set(ctx->clk, 0 ^ inv); +} + +int +lws_bb_spi_queue(const lws_spi_ops_t *octx, const lws_spi_desc_t *desc) +{ + lws_bb_spi_t *ctx = (lws_bb_spi_t *)octx; + const uint8_t *src = desc->src; + + /* clock to idle */ + ctx->gpio->set(ctx->clk, 0 ^ !!(octx->bus_mode & LWSSPIMODE_CPOL)); + /* enable nCS */ + ctx->gpio->set(ctx->ncs[desc->channel], 0); + + if (desc->count_cmd) { + ctx->gpio->set(ctx->ncmd[desc->channel], 0); + lws_bb_spi_write(ctx, src, desc->count_cmd); + ctx->gpio->set(ctx->ncmd[desc->channel], 1); + + src += desc->count_cmd; + } + + if (desc->count_write) + lws_bb_spi_write(ctx, desc->data, desc->count_write); + + if (desc->count_read) + lws_bb_spi_read(ctx, desc->dest, desc->count_read); + + /* disable nCS */ + ctx->gpio->set(ctx->ncs[desc->channel], 1); + + /* clock to idle */ + ctx->gpio->set(ctx->clk, 0 ^ !!(octx->bus_mode & LWSSPIMODE_CPOL)); + + return 0; +} diff -Nru libwebsockets-4.0.20/lib/drivers/spi/lws-spi.c libwebsockets-4.1.6/lib/drivers/spi/lws-spi.c --- libwebsockets-4.0.20/lib/drivers/spi/lws-spi.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/drivers/spi/lws-spi.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,26 @@ +/* + * Generic SPI + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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 + diff -Nru libwebsockets-4.0.20/lib/event-libs/CMakeLists.txt libwebsockets-4.1.6/lib/event-libs/CMakeLists.txt --- libwebsockets-4.0.20/lib/event-libs/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/event-libs/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,102 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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_directories(.) + +macro(create_evlib_plugin PLUGIN_NAME MAIN_SRC PLUGIN_HDR EVLIB) + + set(PLUGIN_SRCS ${MAIN_SRC}) + + source_group("Headers Private" FILES ${PLUGIN_HDR}) + source_group("Sources" FILES ${MAIN_SRC}) + add_library(websockets-${PLUGIN_NAME} SHARED ${MAIN_SRC} ${PLUGIN_HDR}) + + if (APPLE) + set_property(TARGET websockets-${PLUGIN_NAME} PROPERTY MACOSX_RPATH YES) + endif() + + foreach(libpath ${LWS_DEP_LIB_PATHS}) + target_link_directories(${TEST_NAME} ${libpath}) + endforeach() + + target_link_libraries(websockets-${PLUGIN_NAME} websockets_shared ${EVLIB}) + add_dependencies(websockets-${PLUGIN_NAME} websockets_shared) + + target_include_directories(websockets-${PLUGIN_NAME} PRIVATE + ${PLUGIN_INCLUDE} ${LWS_LIB_BUILD_INC_PATHS}) + + # Set test app specific defines. + # set_property(TARGET ${PLUGIN_NAME} + # PROPERTY COMPILE_DEFINITIONS + # INSTALL_DATADIR="${CMAKE_INSTALL_PREFIX}/evlib-plugins" + #) + + set(CMAKE_POSITION_INDEPENDENT_CODE ON) + + install(TARGETS websockets-${PLUGIN_NAME} + EXPORT LibwebsocketsTargets + LIBRARY DESTINATION "${LWS_INSTALL_LIB_DIR}${LIB_SUFFIX}" + COMPONENT ${PLUGIN_NAME}) + + list(APPEND EVLIB_PLUGINS_LIST websockets-${PLUGIN_NAME}) + +endmacro() + +# +# poll support gets built into the lib as the default +# + +if (LWS_WITH_POLL) + add_subdir_include_directories(poll) +endif() + +if (LWS_WITH_LIBUV OR LWS_WITH_LIBUV_INTERNAL) + add_subdir_include_directories(libuv) + set(LWS_HAVE_UV_VERSION_H ${LWS_HAVE_UV_VERSION_H} PARENT_SCOPE) + set(LWS_HAVE_NEW_UV_VERSION_H ${LWS_HAVE_NEW_UV_VERSION_H} PARENT_SCOPE) +endif() + +if (LWS_WITH_LIBEVENT) + add_subdir_include_directories(libevent) +endif() + +if (LWS_WITH_GLIB) + add_subdir_include_directories(glib) +endif() + +if (LWS_WITH_LIBEV) + add_subdir_include_directories(libev) + set(LWS_HAVE_EVBACKEND_LINUXAIO ${LWS_HAVE_EVBACKEND_LINUXAIO} PARENT_SCOPE) + set(LWS_HAVE_EVBACKEND_IOURING ${LWS_HAVE_EVBACKEND_IOURING} PARENT_SCOPE) +endif() + + + +# +# Keep explicit parent scope exports at end +# + +export_to_parent_intermediate() +set(EVLIB_PLUGINS_LIST ${EVLIB_PLUGINS_LIST} PARENT_SCOPE) + diff -Nru libwebsockets-4.0.20/lib/event-libs/glib/CMakeLists.txt libwebsockets-4.1.6/lib/event-libs/glib/CMakeLists.txt --- libwebsockets-4.0.20/lib/event-libs/glib/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/event-libs/glib/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,77 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +set(LWS_GLIB_INCLUDE_DIRS CACHE PATH "Path to the glib include directory") +set(LWS_GLIB_LIBRARIES CACHE PATH "Path to the glib library") + +include (FindPkgConfig) +if (NOT GLIB_FOUND) + find_path(GLIB_INCLUDE_DIRS NAMES glib-2.0/glib.h) + find_library(GLIB_LIBRARIES NAMES glib-2.0) + if (GLIB_INCLUDE_DIRS AND GLIB_LIBRARIES) + set(GLIB_FOUND) + endif() + if (GLIB_INCLUDE_DIRS) + set(GLIB_INCLUDE_DIRS "${GLIB_INCLUDE_DIRS}/glib-2.0" PARENT_SCOPE) + endif() +endif() +PKG_SEARCH_MODULE(LWS_GLIB2 glib-2.0) +if (LWS_GLIB2_FOUND) + list(APPEND GLIB_INCLUDE_DIRS "${LWS_GLIB2_INCLUDE_DIRS}") +endif() + +message("glib include dir: ${GLIB_INCLUDE_DIRS}") +message("glib libraries: ${GLIB_LIBRARIES}") +include_directories("${GLIB_INCLUDE_DIRS}") + +if (LWS_WITH_EVLIB_PLUGINS) + + create_evlib_plugin(evlib_glib + glib.c + private-lib-event-libs-glib.h + ${GLIB_LIBRARIES}) + +else() + + list(APPEND LIB_LIST ${GLIB_LIBRARIES}) + + if (LWS_WITH_NETWORK) + list(APPEND SOURCES + event-libs/glib/glib.c) + endif() + +endif() +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() diff -Nru libwebsockets-4.0.20/lib/event-libs/glib/glib.c libwebsockets-4.1.6/lib/event-libs/glib/glib.c --- libwebsockets-4.0.20/lib/event-libs/glib/glib.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/event-libs/glib/glib.c 2020-12-01 17:40:26.000000000 +0000 @@ -26,11 +26,26 @@ #include -#define wsi_to_subclass(_w) ((_w)->w_read.glib.source) +#include "private-lib-event-libs-glib.h" + +#if !defined(G_SOURCE_FUNC) +#define G_SOURCE_FUNC(f) ((GSourceFunc) (void (*)(void)) (f)) +#endif + +#define pt_to_priv_glib(_pt) ((struct lws_pt_eventlibs_glib *)(_pt)->evlib_pt) +#define wsi_to_priv_glib(_w) ((struct lws_wsi_eventlibs_glib *)(_w)->evlib_wsi) + +#define wsi_to_subclass(_w) (wsi_to_priv_glib(_w)->w_read.source) #define wsi_to_gsource(_w) ((GSource *)wsi_to_subclass(_w)) -#define pt_to_loop(_pt) ((_pt)->glib.loop) +#define pt_to_loop(_pt) (pt_to_priv_glib(_pt)->loop) #define pt_to_g_main_context(_pt) g_main_loop_get_context(pt_to_loop(_pt)) +#define lws_gs_valid(t) (t.gs) +#define lws_gs_destroy(t) if (lws_gs_valid(t)) { \ + g_source_destroy(t.gs); \ + g_source_unref(t.gs); \ + t.gs = NULL; t.tag = 0; } + static gboolean lws_glib_idle_timer_cb(void *p); @@ -58,17 +73,17 @@ static int lws_glib_set_idle(struct lws_context_per_thread *pt) { - GSource *gis; - - if (pt->glib.idle_tag) + if (lws_gs_valid(pt_to_priv_glib(pt)->idle)) return 0; - gis = g_idle_source_new(); - if (!gis) + pt_to_priv_glib(pt)->idle.gs = g_idle_source_new(); + if (!pt_to_priv_glib(pt)->idle.gs) return 1; - g_source_set_callback(gis, lws_glib_idle_timer_cb, pt, NULL); - pt->glib.idle_tag = g_source_attach(gis, pt_to_g_main_context(pt)); + g_source_set_callback(pt_to_priv_glib(pt)->idle.gs, + lws_glib_idle_timer_cb, pt, NULL); + pt_to_priv_glib(pt)->idle.tag = g_source_attach( + pt_to_priv_glib(pt)->idle.gs, pt_to_g_main_context(pt)); return 0; } @@ -76,14 +91,17 @@ static int lws_glib_set_timeout(struct lws_context_per_thread *pt, unsigned int ms) { - GSource *gts; + lws_gs_destroy(pt_to_priv_glib(pt)->hrtimer); - gts = g_timeout_source_new(ms); - if (!gts) + pt_to_priv_glib(pt)->hrtimer.gs = g_timeout_source_new(ms); + if (!pt_to_priv_glib(pt)->hrtimer.gs) return 1; - g_source_set_callback(gts, lws_glib_hrtimer_cb, pt, NULL); - pt->glib.hrtimer_tag = g_source_attach(gts, pt_to_g_main_context(pt)); + g_source_set_callback(pt_to_priv_glib(pt)->hrtimer.gs, + lws_glib_hrtimer_cb, pt, NULL); + pt_to_priv_glib(pt)->hrtimer.tag = g_source_attach( + pt_to_priv_glib(pt)->hrtimer.gs, + pt_to_g_main_context(pt)); return 0; } @@ -117,13 +135,13 @@ lwsl_debug("%s: wsi %p: fd %d, events %d\n", __func__, sub->wsi, eventfd.fd, eventfd.revents); - pt = &sub->wsi->context->pt[(int)sub->wsi->tsi]; + pt = &sub->wsi->a.context->pt[(int)sub->wsi->tsi]; if (pt->is_destroyed) return G_SOURCE_CONTINUE; - lws_service_fd_tsi(sub->wsi->context, &eventfd, sub->wsi->tsi); + lws_service_fd_tsi(sub->wsi->a.context, &eventfd, sub->wsi->tsi); - if (!pt->glib.idle_tag) + if (!lws_gs_valid(pt_to_priv_glib(pt)->idle)) lws_glib_set_idle(pt); if (pt->destroy_self) @@ -153,7 +171,11 @@ lws_usec_t us; lws_pt_lock(pt, __func__); - us = __lws_sul_service_ripe(&pt->pt_sul_owner, lws_now_usecs()); + + lws_gs_destroy(pt_to_priv_glib(pt)->hrtimer); + + us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS, + lws_now_usecs()); if (us) { ms = us / LWS_US_PER_MS; if (!ms) @@ -201,7 +223,7 @@ * We reenable the idle callback on the next network or scheduled event */ - pt->glib.idle_tag = 0; + lws_gs_destroy(pt_to_priv_glib(pt)->idle); return FALSE; } @@ -226,12 +248,12 @@ elops_init_context_glib(struct lws_context *context, const struct lws_context_creation_info *info) { - int n; +// int n; context->eventlib_signal_cb = info->signal_cb; - for (n = 0; n < context->count_threads; n++) - context->pt[n].w_sigint.context = context; +// for (n = 0; n < context->count_threads; n++) +// pt_to_priv_glib(&context->pt[n])->w_sigint.context = context; return 0; } @@ -239,7 +261,8 @@ static int elops_accept_glib(struct lws *wsi) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; + struct lws_wsi_eventlibs_glib *wsipr = wsi_to_priv_glib(wsi); int fd; assert(!wsi_to_subclass(wsi)); @@ -250,7 +273,7 @@ if (!wsi_to_subclass(wsi)) return 1; - wsi->w_read.context = wsi->context; + wsipr->w_read.context = wsi->a.context; wsi_to_subclass(wsi)->wsi = wsi; if (wsi->role_ops->file_handle) @@ -260,10 +283,10 @@ wsi_to_subclass(wsi)->tag = g_source_add_unix_fd(wsi_to_gsource(wsi), fd, (GIOCondition)LWS_POLLIN); - wsi->w_read.actual_events = LWS_POLLIN; + wsipr->w_read.actual_events = LWS_POLLIN; g_source_set_callback(wsi_to_gsource(wsi), - G_SOURCE_FUNC(lws_service_fd), wsi->context, NULL); + G_SOURCE_FUNC(lws_service_fd), wsi->a.context, NULL); g_source_attach(wsi_to_gsource(wsi), pt_to_g_main_context(pt)); @@ -274,6 +297,7 @@ elops_init_pt_glib(struct lws_context *context, void *_loop, int tsi) { struct lws_context_per_thread *pt = &context->pt[tsi]; + struct lws_pt_eventlibs_glib *ptpr = pt_to_priv_glib(pt); struct lws_vhost *vh = context->vhost_list; GMainLoop *loop = (GMainLoop *)_loop; @@ -288,7 +312,7 @@ return -1; } - pt->glib.loop = loop; + ptpr->loop = loop; /* * Initialize all events with the listening sockets @@ -309,7 +333,7 @@ if (pt->event_loop_foreign) return 0; - pt->glib.sigint_tag = g_unix_signal_add(SIGINT, + ptpr->sigint.tag = g_unix_signal_add(SIGINT, G_SOURCE_FUNC(lws_glib_sigint_cb), pt); return 0; @@ -322,10 +346,15 @@ static void elops_io_glib(struct lws *wsi, int flags) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; - GIOCondition cond = wsi->w_read.actual_events | G_IO_ERR; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; + struct lws_wsi_eventlibs_glib *wsipr = wsi_to_priv_glib(wsi); + GIOCondition cond = wsipr->w_read.actual_events | G_IO_ERR; - if (!pt_to_loop(pt) || wsi->context->being_destroyed || pt->is_destroyed) + if (!pt_to_loop(pt) || wsi->a.context->being_destroyed || + pt->is_destroyed) + return; + + if (!wsi_to_subclass(wsi)) return; /* @@ -347,7 +376,7 @@ cond |= G_IO_OUT; } - wsi->w_read.actual_events = cond; + wsipr->w_read.actual_events = cond; lwsl_debug("%s: wsi %p, fd %d, 0x%x/0x%x\n", __func__, wsi, wsi->desc.sockfd, flags, (int)cond); @@ -373,7 +402,7 @@ if (!wsi) return; - pt = &wsi->context->pt[(int)wsi->tsi]; + pt = &wsi->a.context->pt[(int)wsi->tsi]; if (pt->is_destroyed) return; @@ -387,6 +416,7 @@ } g_source_destroy(wsi_to_gsource(wsi)); + g_source_unref(wsi_to_gsource(wsi)); wsi_to_subclass(wsi) = NULL; } @@ -394,6 +424,7 @@ elops_destroy_pt_glib(struct lws_context *context, int tsi) { struct lws_context_per_thread *pt = &context->pt[tsi]; + struct lws_pt_eventlibs_glib *ptpr = pt_to_priv_glib(pt); struct lws_vhost *vh = context->vhost_list; if (!pt_to_loop(pt)) @@ -409,12 +440,12 @@ vh = vh->vhost_next; } - if (pt->glib.hrtimer_tag) - g_source_remove(pt->glib.hrtimer_tag); + lws_gs_destroy(ptpr->idle); + lws_gs_destroy(ptpr->hrtimer); if (!pt->event_loop_foreign) { g_main_loop_quit(pt_to_loop(pt)); - g_source_remove(pt->glib.sigint_tag); + lws_gs_destroy(ptpr->sigint); g_main_loop_unref(pt_to_loop(pt)); } @@ -444,7 +475,7 @@ return 0; } -struct lws_event_loop_ops event_loop_ops_glib = { +static const struct lws_event_loop_ops event_loop_ops_glib = { /* name */ "glib", /* init_context */ elops_init_context_glib, /* destroy_context1 */ NULL, @@ -461,4 +492,22 @@ /* destroy wsi */ elops_destroy_wsi_glib, /* flags */ LELOF_DESTROY_FINAL, + + /* evlib_size_ctx */ 0, + /* evlib_size_pt */ sizeof(struct lws_pt_eventlibs_glib), + /* evlib_size_vh */ 0, + /* evlib_size_wsi */ sizeof(struct lws_io_watcher_glib), +}; + +#if defined(LWS_WITH_EVLIB_PLUGINS) +LWS_VISIBLE +#endif +const lws_plugin_evlib_t evlib_glib = { + .hdr = { + "glib event loop", + "lws_evlib_plugin", + LWS_PLUGIN_API_MAGIC + }, + + .ops = &event_loop_ops_glib }; diff -Nru libwebsockets-4.0.20/lib/event-libs/glib/private-lib-event-libs-glib.h libwebsockets-4.1.6/lib/event-libs/glib/private-lib-event-libs-glib.h --- libwebsockets-4.0.20/lib/event-libs/glib/private-lib-event-libs-glib.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/event-libs/glib/private-lib-event-libs-glib.h 2020-12-01 17:40:26.000000000 +0000 @@ -23,14 +23,26 @@ */ #if defined(LWS_WITH_GLIB) +#if defined(__APPLE__) +#include +#else #include +#endif #endif /* LWS_WITH_GLIB */ +typedef struct lws_glib_tag { + GSource *gs; + guint tag; +} lws_glib_tag_t; + struct lws_pt_eventlibs_glib { - GMainLoop *loop; - guint hrtimer_tag; - guint sigint_tag; - guint idle_tag; + GMainLoop *loop; + + lws_glib_tag_t hrtimer; + lws_glib_tag_t sigint; + lws_glib_tag_t idle; + + //struct lws_signal_watcher_libuv w_sigint; }; struct lws_io_watcher_glib_subclass { @@ -45,10 +57,11 @@ struct lws_io_watcher_glib { struct lws_io_watcher_glib_subclass *source; /* these are created and destroyed by glib */ + struct lws_context *context; + uint8_t actual_events; }; -struct lws_context_eventlibs_glib { - //int placeholder; +struct lws_wsi_eventlibs_glib { + struct lws_io_watcher_glib w_read; }; -extern struct lws_event_loop_ops event_loop_ops_glib; diff -Nru libwebsockets-4.0.20/lib/event-libs/libev/CMakeLists.txt libwebsockets-4.1.6/lib/event-libs/libev/CMakeLists.txt --- libwebsockets-4.0.20/lib/event-libs/libev/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/event-libs/libev/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,88 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +set(LWS_LIBEV_LIBRARIES CACHE PATH "Path to the libev library") +set(LWS_LIBEV_INCLUDE_DIRS CACHE PATH "Path to the libev include directory") + +if (NOT LIBEV_FOUND) + find_path(LIBEV_INCLUDE_DIRS NAMES ev.h) + find_library(LIBEV_LIBRARIES NAMES ev) +endif() +message("libev include dir: ${LIBEV_INCLUDE_DIRS}") +message("libev libraries: ${LIBEV_LIBRARIES}") +include_directories("${LIBEV_INCLUDE_DIRS}") + +if ("${LWS_LIBEV_LIBRARIES}" STREQUAL "" OR "${LWS_LIBEV_INCLUDE_DIRS}" STREQUAL "") +else() + set(LIBEV_LIBRARIES ${LWS_LIBEV_LIBRARIES}) + set(LIBEV_INCLUDE_DIRS ${LWS_LIBEV_INCLUDE_DIRS}) +endif() + +if (LWS_WITH_EVLIB_PLUGINS) + + create_evlib_plugin( + evlib_ev + libev.c + private-lib-event-libs-libev.h + ${LIBEV_LIBRARIES}) + +else() + + list(APPEND LIB_LIST ${LIBEV_LIBRARIES}) + + list(APPEND SOURCES + event-libs/libev/libev.c) +# see README.build.md for discussion of why of the supported event libs, +# only libev cannot cope with -Werror + set_source_files_properties(event-libs/libev/libev.c + PROPERTIES COMPILE_FLAGS "-Wno-error" ) +endif() + +set(CMAKE_REQUIRED_LIBRARIES ${LIB_LIST}) + +CHECK_C_SOURCE_COMPILES( + "#include + int main(int argc, char **argv) { return EVBACKEND_LINUXAIO; } + " LWS_HAVE_EVBACKEND_LINUXAIO) + +CHECK_C_SOURCE_COMPILES( + "#include + int main(int argc, char **argv) { return EVBACKEND_IOURING; } + " LWS_HAVE_EVBACKEND_IOURING) + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() +set(LWS_HAVE_EVBACKEND_LINUXAIO ${LWS_HAVE_EVBACKEND_LINUXAIO} PARENT_SCOPE) +set(LWS_HAVE_EVBACKEND_IOURING ${LWS_HAVE_EVBACKEND_IOURING} PARENT_SCOPE) diff -Nru libwebsockets-4.0.20/lib/event-libs/libev/libev.c libwebsockets-4.1.6/lib/event-libs/libev/libev.c --- libwebsockets-4.0.20/lib/event-libs/libev/libev.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/event-libs/libev/libev.c 2020-12-01 17:40:26.000000000 +0000 @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2020 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -23,19 +23,26 @@ */ #include "private-lib-core.h" +#include "private-lib-event-libs-libev.h" + +#define pt_to_priv_ev(_pt) ((struct lws_pt_eventlibs_libev *)(_pt)->evlib_pt) +#define vh_to_priv_ev(_vh) ((struct lws_vh_eventlibs_libev *)(_vh)->evlib_vh) +#define wsi_to_priv_ev(_w) ((struct lws_wsi_eventlibs_libev *)(_w)->evlib_wsi) static void lws_ev_hrtimer_cb(struct ev_loop *loop, struct ev_timer *watcher, int revents) { - struct lws_context_per_thread *pt = - (struct lws_context_per_thread *)watcher->data; + struct lws_pt_eventlibs_libev *ptpr = lws_container_of(watcher, + struct lws_pt_eventlibs_libev, hrtimer); + struct lws_context_per_thread *pt = ptpr->pt; lws_usec_t us; lws_pt_lock(pt, __func__); - us = __lws_sul_service_ripe(&pt->pt_sul_owner, lws_now_usecs()); + us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS, + lws_now_usecs()); if (us) { - ev_timer_set(&pt->ev.hrtimer, ((float)us) / 1000000.0, 0); - ev_timer_start(pt->ev.io_loop, &pt->ev.hrtimer); + ev_timer_set(&ptpr->hrtimer, ((float)us) / 1000000.0, 0); + ev_timer_start(ptpr->io_loop, &ptpr->hrtimer); } lws_pt_unlock(pt); } @@ -43,10 +50,11 @@ static void lws_ev_idle_cb(struct ev_loop *loop, struct ev_idle *handle, int revents) { - struct lws_context_per_thread *pt = lws_container_of(handle, - struct lws_context_per_thread, ev.idle); - lws_usec_t us; + struct lws_pt_eventlibs_libev *ptpr = lws_container_of(handle, + struct lws_pt_eventlibs_libev, idle); + struct lws_context_per_thread *pt = ptpr->pt; int reschedule = 0; + lws_usec_t us; lws_service_do_ripe_rxflow(pt); @@ -60,10 +68,11 @@ /* account for hrtimer */ lws_pt_lock(pt, __func__); - us = __lws_sul_service_ripe(&pt->pt_sul_owner, lws_now_usecs()); + us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS, + lws_now_usecs()); if (us) { - ev_timer_set(&pt->ev.hrtimer, ((float)us) / 1000000.0, 0); - ev_timer_start(pt->ev.io_loop, &pt->ev.hrtimer); + ev_timer_set(&ptpr->hrtimer, ((float)us) / 1000000.0, 0); + ev_timer_start(ptpr->io_loop, &ptpr->hrtimer); } lws_pt_unlock(pt); @@ -78,9 +87,10 @@ static void lws_accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents) { - struct lws_io_watcher *lws_io = lws_container_of(watcher, - struct lws_io_watcher, ev.watcher); + struct lws_io_watcher_libev *lws_io = lws_container_of(watcher, + struct lws_io_watcher_libev, watcher); struct lws_context *context = lws_io->context; + struct lws_pt_eventlibs_libev *ptpr; struct lws_context_per_thread *pt; struct lws_pollfd eventfd; struct lws *wsi; @@ -103,10 +113,11 @@ wsi = wsi_from_fd(context, watcher->fd); pt = &context->pt[(int)wsi->tsi]; + ptpr = pt_to_priv_ev(pt); lws_service_fd_tsi(context, &eventfd, (int)wsi->tsi); - ev_idle_start(pt->ev.io_loop, &pt->ev.idle); + ev_idle_start(ptpr->io_loop, &ptpr->idle); } void @@ -126,7 +137,8 @@ elops_init_pt_ev(struct lws_context *context, void *_loop, int tsi) { struct lws_context_per_thread *pt = &context->pt[tsi]; - struct ev_signal *w_sigint = &context->pt[tsi].w_sigint.ev.watcher; + struct lws_pt_eventlibs_libev *ptpr = pt_to_priv_ev(pt); + struct ev_signal *w_sigint = &ptpr->w_sigint.watcher; struct ev_loop *loop = (struct ev_loop *)_loop; struct lws_vhost *vh = context->vhost_list; const char *backend_name; @@ -135,6 +147,8 @@ lwsl_info("%s: loop %p\n", __func__, _loop); + ptpr->pt = pt; + if (!loop) loop = ev_loop_new(0); else @@ -146,7 +160,7 @@ return -1; } - pt->ev.io_loop = loop; + ptpr->io_loop = loop; /* * Initialize the accept w_accept with all the listening sockets @@ -154,13 +168,17 @@ */ while (vh) { if (vh->lserv_wsi) { - vh->lserv_wsi->w_read.context = context; - vh->w_accept.context = context; + struct lws_wsi_eventlibs_libev *w = + wsi_to_priv_ev(vh->lserv_wsi); - ev_io_init(&vh->w_accept.ev.watcher, lws_accept_cb, - vh->lserv_wsi->desc.sockfd, EV_READ); - ev_io_start(loop, &vh->w_accept.ev.watcher); + w->w_read.context = context; + w->w_write.context = context; + vh_to_priv_ev(vh)->w_accept.context = context; + ev_io_init(&vh_to_priv_ev(vh)->w_accept.watcher, + lws_accept_cb, + vh->lserv_wsi->desc.sockfd, EV_READ); + ev_io_start(loop, &vh_to_priv_ev(vh)->w_accept.watcher); } vh = vh->vhost_next; } @@ -210,10 +228,10 @@ lwsl_info(" libev backend: %s\n", backend_name); (void)backend_name; - ev_timer_init(&pt->ev.hrtimer, lws_ev_hrtimer_cb, 0, 0); - pt->ev.hrtimer.data = pt; + ev_timer_init(&ptpr->hrtimer, lws_ev_hrtimer_cb, 0, 0); + ptpr->hrtimer.data = pt; - ev_idle_init(&pt->ev.idle, lws_ev_idle_cb); + ev_idle_init(&ptpr->idle, lws_ev_idle_cb); return status; } @@ -222,21 +240,23 @@ elops_destroy_pt_ev(struct lws_context *context, int tsi) { struct lws_context_per_thread *pt = &context->pt[tsi]; + struct lws_pt_eventlibs_libev *ptpr = pt_to_priv_ev(pt); struct lws_vhost *vh = context->vhost_list; while (vh) { if (vh->lserv_wsi) - ev_io_stop(pt->ev.io_loop, &vh->w_accept.ev.watcher); + ev_io_stop(ptpr->io_loop, + &vh_to_priv_ev(vh)->w_accept.watcher); vh = vh->vhost_next; } /* static assets */ - ev_timer_stop(pt->ev.io_loop, &pt->ev.hrtimer); - ev_idle_stop(pt->ev.io_loop, &pt->ev.idle); + ev_timer_stop(ptpr->io_loop, &ptpr->hrtimer); + ev_idle_stop(ptpr->io_loop, &ptpr->idle); if (!pt->event_loop_foreign) - ev_signal_stop(pt->ev.io_loop, &pt->w_sigint.ev.watcher); + ev_signal_stop(ptpr->io_loop, &ptpr->w_sigint.watcher); } static int @@ -248,7 +268,7 @@ context->eventlib_signal_cb = info->signal_cb; for (n = 0; n < context->count_threads; n++) - context->pt[n].w_sigint.context = context; + pt_to_priv_ev(&context->pt[n])->w_sigint.context = context; return 0; } @@ -256,18 +276,21 @@ static int elops_accept_ev(struct lws *wsi) { + struct lws_wsi_eventlibs_libev *w = wsi_to_priv_ev(wsi); int fd; + lwsl_notice("%s\n", __func__); + if (wsi->role_ops->file_handle) fd = wsi->desc.filefd; else fd = wsi->desc.sockfd; - wsi->w_read.context = wsi->context; - wsi->w_write.context = wsi->context; + w->w_read.context = wsi->a.context; + w->w_write.context = wsi->a.context; - ev_io_init(&wsi->w_read.ev.watcher, lws_accept_cb, fd, EV_READ); - ev_io_init(&wsi->w_write.ev.watcher, lws_accept_cb, fd, EV_WRITE); + ev_io_init(&w->w_read.watcher, lws_accept_cb, fd, EV_READ); + ev_io_init(&w->w_write.watcher, lws_accept_cb, fd, EV_WRITE); return 0; } @@ -275,9 +298,15 @@ static void elops_io_ev(struct lws *wsi, int flags) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; + struct lws_pt_eventlibs_libev *ptpr = pt_to_priv_ev(pt); + struct lws_wsi_eventlibs_libev *w = wsi_to_priv_ev(wsi); + + lwsl_notice("%s: wsi %p %s flags 0x%x %p %d\n", __func__, + wsi, wsi->role_ops->name, flags, + ptpr->io_loop, pt->is_destroyed); - if (!pt->ev.io_loop || pt->is_destroyed) + if (!ptpr->io_loop || pt->is_destroyed) return; assert((flags & (LWS_EV_START | LWS_EV_STOP)) && @@ -285,14 +314,14 @@ if (flags & LWS_EV_START) { if (flags & LWS_EV_WRITE) - ev_io_start(pt->ev.io_loop, &wsi->w_write.ev.watcher); + ev_io_start(ptpr->io_loop, &w->w_write.watcher); if (flags & LWS_EV_READ) - ev_io_start(pt->ev.io_loop, &wsi->w_read.ev.watcher); + ev_io_start(ptpr->io_loop, &w->w_read.watcher); } else { if (flags & LWS_EV_WRITE) - ev_io_stop(pt->ev.io_loop, &wsi->w_write.ev.watcher); + ev_io_stop(ptpr->io_loop, &w->w_write.watcher); if (flags & LWS_EV_READ) - ev_io_stop(pt->ev.io_loop, &wsi->w_read.ev.watcher); + ev_io_stop(ptpr->io_loop, &w->w_read.watcher); } if (pt->destroy_self) @@ -302,14 +331,15 @@ static void elops_run_pt_ev(struct lws_context *context, int tsi) { - if (context->pt[tsi].ev.io_loop) - ev_run(context->pt[tsi].ev.io_loop, 0); + if (pt_to_priv_ev(&context->pt[tsi])->io_loop) + ev_run(pt_to_priv_ev(&context->pt[tsi])->io_loop, 0); } static int elops_destroy_context2_ev(struct lws_context *context) { struct lws_context_per_thread *pt; + struct lws_pt_eventlibs_libev *ptpr; int n, m; lwsl_debug("%s\n", __func__); @@ -318,21 +348,22 @@ int budget = 1000; pt = &context->pt[n]; + ptpr = pt_to_priv_ev(pt); /* only for internal loops... */ - if (pt->event_loop_foreign || !pt->ev.io_loop) + if (pt->event_loop_foreign || !ptpr->io_loop) continue; if (!context->finalize_destroy_after_internal_loops_stopped) { - ev_break(pt->ev.io_loop, EVBREAK_ONE); + ev_break(ptpr->io_loop, EVBREAK_ONE); continue; } while (budget-- && - (m = ev_run(pt->ev.io_loop, 0))) + (m = ev_run(ptpr->io_loop, 0))) ; - ev_loop_destroy(pt->ev.io_loop); + ev_loop_destroy(ptpr->io_loop); } return 0; @@ -341,6 +372,7 @@ static int elops_init_vhost_listen_wsi_ev(struct lws *wsi) { + struct lws_wsi_eventlibs_libev *w; int fd; if (!wsi) { @@ -348,16 +380,17 @@ return 0; } - wsi->w_read.context = wsi->context; - wsi->w_write.context = wsi->context; + w = wsi_to_priv_ev(wsi); + w->w_read.context = wsi->a.context; + w->w_write.context = wsi->a.context; if (wsi->role_ops->file_handle) fd = wsi->desc.filefd; else fd = wsi->desc.sockfd; - ev_io_init(&wsi->w_read.ev.watcher, lws_accept_cb, fd, EV_READ); - ev_io_init(&wsi->w_write.ev.watcher, lws_accept_cb, fd, EV_WRITE); + ev_io_init(&w->w_read.watcher, lws_accept_cb, fd, EV_READ); + //ev_io_init(&w->w_write.watcher, lws_accept_cb, fd, EV_WRITE); elops_io_ev(wsi, LWS_EV_START | LWS_EV_READ); @@ -367,13 +400,15 @@ static void elops_destroy_wsi_ev(struct lws *wsi) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; + struct lws_pt_eventlibs_libev *ptpr = pt_to_priv_ev(pt); + struct lws_wsi_eventlibs_libev *w = wsi_to_priv_ev(wsi); - ev_io_stop(pt->ev.io_loop, &wsi->w_read.ev.watcher); - ev_io_stop(pt->ev.io_loop, &wsi->w_write.ev.watcher); + ev_io_stop(ptpr->io_loop, &w->w_read.watcher); + ev_io_stop(ptpr->io_loop, &w->w_write.watcher); } -struct lws_event_loop_ops event_loop_ops_ev = { +static const struct lws_event_loop_ops event_loop_ops_ev = { /* name */ "libev", /* init_context */ elops_init_context_ev, /* destroy_context1 */ NULL, @@ -390,4 +425,22 @@ /* destroy wsi */ elops_destroy_wsi_ev, /* flags */ 0, + + /* evlib_size_ctx */ 0, + /* evlib_size_pt */ sizeof(struct lws_pt_eventlibs_libev), + /* evlib_size_vh */ sizeof(struct lws_vh_eventlibs_libev), + /* evlib_size_wsi */ sizeof(struct lws_wsi_eventlibs_libev), +}; + +#if defined(LWS_WITH_EVLIB_PLUGINS) +LWS_VISIBLE +#endif +const lws_plugin_evlib_t evlib_ev = { + .hdr = { + "libev event loop", + "lws_evlib_plugin", + LWS_PLUGIN_API_MAGIC + }, + + .ops = &event_loop_ops_ev }; diff -Nru libwebsockets-4.0.20/lib/event-libs/libev/private-lib-event-libs-libev.h libwebsockets-4.1.6/lib/event-libs/libev/private-lib-event-libs-libev.h --- libwebsockets-4.0.20/lib/event-libs/libev/private-lib-event-libs-libev.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/event-libs/libev/private-lib-event-libs-libev.h 2020-12-01 17:40:26.000000000 +0000 @@ -33,22 +33,30 @@ (--(LWS_UV_REFCOUNT_STATIC_HANDLE_TO_CONTEXT(_x)-> \ count_event_loop_static_asset_handles)) +struct lws_signal_watcher_libev { + ev_signal watcher; + struct lws_context *context; +}; + struct lws_pt_eventlibs_libev { struct ev_loop *io_loop; struct ev_timer hrtimer; struct ev_idle idle; + struct lws_signal_watcher_libev w_sigint; + struct lws_context_per_thread *pt; }; struct lws_io_watcher_libev { ev_io watcher; + struct lws_context *context; }; -struct lws_signal_watcher_libev { - ev_signal watcher; +struct lws_vh_eventlibs_libev { + struct lws_io_watcher_libev w_accept; }; -struct lws_context_eventlibs_libev { - int placeholder; +struct lws_wsi_eventlibs_libev { + struct lws_io_watcher_libev w_read; + struct lws_io_watcher_libev w_write; }; -extern struct lws_event_loop_ops event_loop_ops_ev; diff -Nru libwebsockets-4.0.20/lib/event-libs/libevent/CMakeLists.txt libwebsockets-4.1.6/lib/event-libs/libevent/CMakeLists.txt --- libwebsockets-4.0.20/lib/event-libs/libevent/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/event-libs/libevent/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,72 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +set(LWS_LIBEVENT_INCLUDE_DIRS CACHE PATH "Path to the libevent include directory") +set(LWS_LIBEVENT_LIBRARIES CACHE PATH "Path to the libevent library") + +if (NOT LIBEVENT_FOUND) + find_path(LIBEVENT_INCLUDE_DIRS NAMES event2/event.h) + find_library(LIBEVENT_LIBRARIES NAMES event) +endif() +message("libevent include dir: ${LIBEVENT_INCLUDE_DIRS}") +message("libevent libraries: ${LIBEVENT_LIBRARIES}") +include_directories("${LIBEVENT_INCLUDE_DIRS}") + +if ("${LWS_LIBEVENT_LIBRARIES}" STREQUAL "" OR "${LWS_LIBEVENT_INCLUDE_DIRS}" STREQUAL "") +else() + set(LIBEVENT_LIBRARIES ${LWS_LIBEVENT_LIBRARIES}) + set(LIBEVENT_INCLUDE_DIRS ${LWS_LIBEVENT_INCLUDE_DIRS}) +endif() + + +if (LWS_WITH_EVLIB_PLUGINS) + + create_evlib_plugin(evlib_event + libevent.c + private-lib-event-libs-libevent.h + ${LIBEVENT_LIBRARIES}) + +else() + + list(APPEND LIB_LIST ${LIBEVENT_LIBRARIES}) + set(LIBEVENT_FOUND 1 PARENT_SCOPE) + if (LWS_WITH_NETWORK) + list(APPEND SOURCES + event-libs/libevent/libevent.c) + endif() +endif() + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() diff -Nru libwebsockets-4.0.20/lib/event-libs/libevent/libevent.c libwebsockets-4.1.6/lib/event-libs/libevent/libevent.c --- libwebsockets-4.0.20/lib/event-libs/libevent/libevent.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/event-libs/libevent/libevent.c 2020-12-01 17:40:26.000000000 +0000 @@ -23,28 +23,35 @@ */ #include "private-lib-core.h" +#include "private-lib-event-libs-libevent.h" + +#define pt_to_priv_event(_pt) ((struct lws_pt_eventlibs_libevent *)(_pt)->evlib_pt) +#define wsi_to_priv_event(_w) ((struct lws_wsi_eventlibs_libevent *)(_w)->evlib_wsi) static void -lws_event_hrtimer_cb(int fd, short event, void *p) +lws_event_hrtimer_cb(evutil_socket_t fd, short event, void *p) { struct lws_context_per_thread *pt = (struct lws_context_per_thread *)p; + struct lws_pt_eventlibs_libevent *ptpr = pt_to_priv_event(pt); struct timeval tv; lws_usec_t us; lws_pt_lock(pt, __func__); - us = __lws_sul_service_ripe(&pt->pt_sul_owner, lws_now_usecs()); + us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS, + lws_now_usecs()); if (us) { tv.tv_sec = us / LWS_US_PER_SEC; tv.tv_usec = us - (tv.tv_sec * LWS_US_PER_SEC); - evtimer_add(pt->event.hrtimer, &tv); + evtimer_add(ptpr->hrtimer, &tv); } lws_pt_unlock(pt); } static void -lws_event_idle_timer_cb(int fd, short event, void *p) +lws_event_idle_timer_cb(evutil_socket_t fd, short event, void *p) { struct lws_context_per_thread *pt = (struct lws_context_per_thread *)p; + struct lws_pt_eventlibs_libevent *ptpr = pt_to_priv_event(pt); struct timeval tv; lws_usec_t us; @@ -65,7 +72,7 @@ tv.tv_sec = 0; tv.tv_usec = 1000; - evtimer_add(pt->event.idle_timer, &tv); + evtimer_add(ptpr->idle_timer, &tv); return; } @@ -76,15 +83,15 @@ /* account for hrtimer */ lws_pt_lock(pt, __func__); - us = __lws_sul_service_ripe(&pt->pt_sul_owner, lws_now_usecs()); + us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS, + lws_now_usecs()); if (us) { tv.tv_sec = us / LWS_US_PER_SEC; tv.tv_usec = us - (tv.tv_sec * LWS_US_PER_SEC); - evtimer_add(pt->event.hrtimer, &tv); + evtimer_add(ptpr->hrtimer, &tv); } lws_pt_unlock(pt); - if (pt->destroy_self) lws_context_destroy(pt->context); } @@ -92,7 +99,8 @@ static void lws_event_cb(evutil_socket_t sock_fd, short revents, void *ctx) { - struct lws_io_watcher *lws_io = (struct lws_io_watcher *)ctx; + struct lws_signal_watcher_libevent *lws_io = + (struct lws_signal_watcher_libevent *)ctx; struct lws_context *context = lws_io->context; struct lws_context_per_thread *pt; struct lws_pollfd eventfd; @@ -134,6 +142,7 @@ lws_service_fd_tsi(context, &eventfd, wsi->tsi); if (pt->destroy_self) { + lwsl_notice("%s: pt destroy self coming true\n", __func__); lws_context_destroy(pt->context); return; } @@ -142,14 +151,14 @@ tv.tv_sec = 0; tv.tv_usec = 1000; - evtimer_add(pt->event.idle_timer, &tv); + evtimer_add(pt_to_priv_event(pt)->idle_timer, &tv); } void lws_event_sigint_cb(evutil_socket_t sock_fd, short revents, void *ctx) { struct lws_context_per_thread *pt = ctx; - struct event *signal = (struct event *)ctx; + struct event *signal = pt_to_priv_event(pt)->w_sigint.watcher; if (pt->context->eventlib_signal_cb) { pt->context->eventlib_signal_cb((void *)(lws_intptr_t)sock_fd, @@ -158,16 +167,16 @@ return; } if (!pt->event_loop_foreign) - event_base_loopbreak(pt->event.io_loop); + event_base_loopbreak(pt_to_priv_event(pt)->io_loop); } - static int elops_init_pt_event(struct lws_context *context, void *_loop, int tsi) { struct lws_vhost *vh = context->vhost_list; struct event_base *loop = (struct event_base *)_loop; struct lws_context_per_thread *pt = &context->pt[tsi]; + struct lws_pt_eventlibs_libevent *ptpr = pt_to_priv_event(pt); lwsl_info("%s: loop %p\n", __func__, _loop); @@ -182,7 +191,7 @@ return -1; } - pt->event.io_loop = loop; + ptpr->io_loop = loop; /* * Initialize all events with the listening sockets @@ -191,23 +200,26 @@ while (vh) { if (vh->lserv_wsi) { - vh->lserv_wsi->w_read.context = context; - vh->lserv_wsi->w_read.event.watcher = event_new( + struct lws_io_watcher_libevent *w_read = + &(wsi_to_priv_event(vh->lserv_wsi)->w_read); + + w_read->context = context; + w_read->watcher = event_new( loop, vh->lserv_wsi->desc.sockfd, (EV_READ | EV_PERSIST), lws_event_cb, - &vh->lserv_wsi->w_read); - event_add(vh->lserv_wsi->w_read.event.watcher, NULL); - vh->lserv_wsi->w_read.event.set = 1; + w_read); + event_add(w_read->watcher, NULL); + w_read->set = 1; } vh = vh->vhost_next; } /* static event loop objects */ - pt->event.hrtimer = event_new(loop, -1, EV_PERSIST, + ptpr->hrtimer = event_new(loop, -1, EV_PERSIST, lws_event_hrtimer_cb, pt); - pt->event.idle_timer = event_new(loop, -1, 0, + ptpr->idle_timer = event_new(loop, -1, 0, lws_event_idle_timer_cb, pt); /* Register the signal watcher unless it's a foreign loop */ @@ -215,9 +227,9 @@ if (pt->event_loop_foreign) return 0; - pt->w_sigint.event.watcher = evsignal_new(loop, SIGINT, + ptpr->w_sigint.watcher = evsignal_new(loop, SIGINT, lws_event_sigint_cb, pt); - event_add(pt->w_sigint.event.watcher, NULL); + event_add(ptpr->w_sigint.watcher, NULL); return 0; } @@ -231,7 +243,7 @@ context->eventlib_signal_cb = info->signal_cb; for (n = 0; n < context->count_threads; n++) - context->pt[n].w_sigint.context = context; + pt_to_priv_event(&context->pt[n])->w_sigint.context = context; return 0; } @@ -241,23 +253,26 @@ { struct lws_context *context = lws_get_context(wsi); struct lws_context_per_thread *pt; - int fd; + struct lws_pt_eventlibs_libevent *ptpr; + struct lws_wsi_eventlibs_libevent *wpr = wsi_to_priv_event(wsi); + evutil_socket_t fd; - wsi->w_read.context = context; - wsi->w_write.context = context; + wpr->w_read.context = context; + wpr->w_write.context = context; // Initialize the event pt = &context->pt[(int)wsi->tsi]; + ptpr = pt_to_priv_event(pt); if (wsi->role_ops->file_handle) - fd = wsi->desc.filefd; + fd = (ev_intptr_t) wsi->desc.filefd; else fd = wsi->desc.sockfd; - wsi->w_read.event.watcher = event_new(pt->event.io_loop, fd, - (EV_READ | EV_PERSIST), lws_event_cb, &wsi->w_read); - wsi->w_write.event.watcher = event_new(pt->event.io_loop, fd, - (EV_WRITE | EV_PERSIST), lws_event_cb, &wsi->w_write); + wpr->w_read.watcher = event_new(ptpr->io_loop, fd, + (EV_READ | EV_PERSIST), lws_event_cb, &wpr->w_read); + wpr->w_write.watcher = event_new(ptpr->io_loop, fd, + (EV_WRITE | EV_PERSIST), lws_event_cb, &wpr->w_write); return 0; } @@ -265,9 +280,11 @@ static void elops_io_event(struct lws *wsi, int flags) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; + struct lws_pt_eventlibs_libevent *ptpr = pt_to_priv_event(pt); + struct lws_wsi_eventlibs_libevent *wpr = wsi_to_priv_event(wsi); - if (!pt->event.io_loop || wsi->context->being_destroyed || + if (!ptpr->io_loop || wsi->a.context->being_destroyed || pt->is_destroyed) return; @@ -275,24 +292,24 @@ (flags & (LWS_EV_READ | LWS_EV_WRITE))); if (flags & LWS_EV_START) { - if ((flags & LWS_EV_WRITE) && !wsi->w_write.event.set) { - event_add(wsi->w_write.event.watcher, NULL); - wsi->w_write.event.set = 1; + if ((flags & LWS_EV_WRITE) && !wpr->w_write.set) { + event_add(wpr->w_write.watcher, NULL); + wpr->w_write.set = 1; } - if ((flags & LWS_EV_READ) && !wsi->w_read.event.set) { - event_add(wsi->w_read.event.watcher, NULL); - wsi->w_read.event.set = 1; + if ((flags & LWS_EV_READ) && !wpr->w_read.set) { + event_add(wpr->w_read.watcher, NULL); + wpr->w_read.set = 1; } } else { - if ((flags & LWS_EV_WRITE) && wsi->w_write.event.set) { - event_del(wsi->w_write.event.watcher); - wsi->w_write.event.set = 0; + if ((flags & LWS_EV_WRITE) && wpr->w_write.set) { + event_del(wpr->w_write.watcher); + wpr->w_write.set = 0; } - if ((flags & LWS_EV_READ) && wsi->w_read.event.set) { - event_del(wsi->w_read.event.watcher); - wsi->w_read.event.set = 0; + if ((flags & LWS_EV_READ) && wpr->w_read.set) { + event_del(wpr->w_read.watcher); + wpr->w_read.set = 0; } } } @@ -301,19 +318,21 @@ elops_run_pt_event(struct lws_context *context, int tsi) { /* Run / Dispatch the event_base loop */ - if (context->pt[tsi].event.io_loop) - event_base_dispatch(context->pt[tsi].event.io_loop); + if (pt_to_priv_event(&context->pt[tsi])->io_loop) + event_base_dispatch( + pt_to_priv_event(&context->pt[tsi])->io_loop); } static void elops_destroy_pt_event(struct lws_context *context, int tsi) { struct lws_context_per_thread *pt = &context->pt[tsi]; + struct lws_pt_eventlibs_libevent *ptpr = pt_to_priv_event(pt); struct lws_vhost *vh = context->vhost_list; lwsl_info("%s\n", __func__); - if (!pt->event.io_loop) + if (!ptpr->io_loop) return; /* @@ -321,21 +340,24 @@ */ while (vh) { if (vh->lserv_wsi) { - event_free(vh->lserv_wsi->w_read.event.watcher); - vh->lserv_wsi->w_read.event.watcher = NULL; - event_free(vh->lserv_wsi->w_write.event.watcher); - vh->lserv_wsi->w_write.event.watcher = NULL; + struct lws_wsi_eventlibs_libevent *w = + wsi_to_priv_event(vh->lserv_wsi); + + event_free(w->w_read.watcher); + w->w_read.watcher = NULL; + event_free(w->w_write.watcher); + w->w_write.watcher = NULL; } vh = vh->vhost_next; } - event_free(pt->event.hrtimer); - event_free(pt->event.idle_timer); + event_free(ptpr->hrtimer); + event_free(ptpr->idle_timer); if (!pt->event_loop_foreign) { - event_del(pt->w_sigint.event.watcher); - event_free(pt->w_sigint.event.watcher); - event_base_loopexit(pt->event.io_loop, NULL); + event_del(ptpr->w_sigint.watcher); + event_free(ptpr->w_sigint.watcher); + event_base_loopexit(ptpr->io_loop, NULL); // event_base_free(pt->event.io_loop); // pt->event.io_loop = NULL; lwsl_notice("%s: set to exit loop\n", __func__); @@ -346,22 +368,25 @@ elops_destroy_wsi_event(struct lws *wsi) { struct lws_context_per_thread *pt; + struct lws_wsi_eventlibs_libevent *w; if (!wsi) return; - pt = &wsi->context->pt[(int)wsi->tsi]; + pt = &wsi->a.context->pt[(int)wsi->tsi]; if (pt->is_destroyed) return; - if (wsi->w_read.event.watcher) { - event_free(wsi->w_read.event.watcher); - wsi->w_read.event.watcher = NULL; + w = wsi_to_priv_event(wsi); + + if (w->w_read.watcher) { + event_free(w->w_read.watcher); + w->w_read.watcher = NULL; } - if (wsi->w_write.event.watcher) { - event_free(wsi->w_write.event.watcher); - wsi->w_write.event.watcher = NULL; + if (w->w_write.watcher) { + event_free(w->w_write.watcher); + w->w_write.watcher = NULL; } } @@ -377,29 +402,33 @@ elops_init_vhost_listen_wsi_event(struct lws *wsi) { struct lws_context_per_thread *pt; - int fd; + struct lws_pt_eventlibs_libevent *ptpr; + struct lws_wsi_eventlibs_libevent *w; + evutil_socket_t fd; if (!wsi) { assert(0); return 0; } - wsi->w_read.context = wsi->context; - wsi->w_write.context = wsi->context; + w = wsi_to_priv_event(wsi); + + w->w_read.context = wsi->a.context; + w->w_write.context = wsi->a.context; - pt = &wsi->context->pt[(int)wsi->tsi]; + pt = &wsi->a.context->pt[(int)wsi->tsi]; + ptpr = pt_to_priv_event(pt); if (wsi->role_ops->file_handle) - fd = wsi->desc.filefd; + fd = (evutil_socket_t) wsi->desc.filefd; else fd = wsi->desc.sockfd; - wsi->w_read.event.watcher = event_new(pt->event.io_loop, fd, - (EV_READ | EV_PERSIST), - lws_event_cb, &wsi->w_read); - wsi->w_write.event.watcher = event_new(pt->event.io_loop, fd, - (EV_WRITE | EV_PERSIST), - lws_event_cb, &wsi->w_write); + w->w_read.watcher = event_new(ptpr->io_loop, fd, (EV_READ | EV_PERSIST), + lws_event_cb, &w->w_read); + w->w_write.watcher = event_new(ptpr->io_loop, fd, + (EV_WRITE | EV_PERSIST), + lws_event_cb, &w->w_write); elops_io_event(wsi, LWS_EV_START | LWS_EV_READ); @@ -410,6 +439,7 @@ elops_destroy_context2_event(struct lws_context *context) { struct lws_context_per_thread *pt; + struct lws_pt_eventlibs_libevent *ptpr; int n, m; lwsl_debug("%s: in\n", __func__); @@ -418,31 +448,31 @@ int budget = 1000; pt = &context->pt[n]; + ptpr = pt_to_priv_event(pt); /* only for internal loops... */ - if (pt->event_loop_foreign || !pt->event.io_loop) + if (pt->event_loop_foreign || !ptpr->io_loop) continue; if (!context->finalize_destroy_after_internal_loops_stopped) { - event_base_loopexit(pt->event.io_loop, NULL); + event_base_loopexit(ptpr->io_loop, NULL); continue; } while (budget-- && - (m = event_base_loop(pt->event.io_loop, EVLOOP_NONBLOCK))) + (m = event_base_loop(ptpr->io_loop, EVLOOP_NONBLOCK))) ; #if 0 if (m) { lwsl_err("%s: tsi %d: NOT everything closed\n", __func__, n); - event_base_dump_events(pt->event.io_loop, stderr); + event_base_dump_events(ptpr->io_loop, stderr); } else lwsl_debug("%s: %d: everything closed OK\n", __func__, n); #endif lwsl_err("%s: event_base_free\n", __func__); - event_base_free(pt->event.io_loop); - pt->event.io_loop = NULL; - + event_base_free(ptpr->io_loop); + ptpr->io_loop = NULL; } lwsl_debug("%s: out\n", __func__); @@ -450,7 +480,7 @@ return 0; } -struct lws_event_loop_ops event_loop_ops_event = { +static const struct lws_event_loop_ops event_loop_ops_event = { /* name */ "libevent", /* init_context */ elops_init_context_event, /* destroy_context1 */ NULL, @@ -467,4 +497,22 @@ /* destroy wsi */ elops_destroy_wsi_event, /* flags */ 0, + + /* evlib_size_ctx */ 0, + /* evlib_size_pt */ sizeof(struct lws_pt_eventlibs_libevent), + /* evlib_size_vh */ 0, + /* evlib_size_wsi */ sizeof(struct lws_wsi_eventlibs_libevent), +}; + +#if defined(LWS_WITH_EVLIB_PLUGINS) +LWS_VISIBLE +#endif +const lws_plugin_evlib_t evlib_event = { + .hdr = { + "libevent event loop", + "lws_evlib_plugin", + LWS_PLUGIN_API_MAGIC + }, + + .ops = &event_loop_ops_event }; diff -Nru libwebsockets-4.0.20/lib/event-libs/libevent/private-lib-event-libs-libevent.h libwebsockets-4.1.6/lib/event-libs/libevent/private-lib-event-libs-libevent.h --- libwebsockets-4.0.20/lib/event-libs/libevent/private-lib-event-libs-libevent.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/event-libs/libevent/private-lib-event-libs-libevent.h 2020-12-01 17:40:26.000000000 +0000 @@ -24,23 +24,26 @@ #include +struct lws_signal_watcher_libevent { + struct event *watcher; + struct lws_context *context; +}; + struct lws_pt_eventlibs_libevent { struct event_base *io_loop; struct event *hrtimer; struct event *idle_timer; + struct lws_signal_watcher_libevent w_sigint; }; struct lws_io_watcher_libevent { struct event *watcher; + struct lws_context *context; + uint8_t actual_events; char set; }; -struct lws_signal_watcher_libevent { - struct event *watcher; -}; - -struct lws_context_eventlibs_libevent { - int placeholder; +struct lws_wsi_eventlibs_libevent { + struct lws_io_watcher_libevent w_read; + struct lws_io_watcher_libevent w_write; }; - -extern struct lws_event_loop_ops event_loop_ops_event; diff -Nru libwebsockets-4.0.20/lib/event-libs/libuv/CMakeLists.txt libwebsockets-4.1.6/lib/event-libs/libuv/CMakeLists.txt --- libwebsockets-4.0.20/lib/event-libs/libuv/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/event-libs/libuv/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,85 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +set(LWS_LIBUV_LIBRARIES CACHE PATH "Path to the libuv library") +set(LWS_LIBUV_INCLUDE_DIRS CACHE PATH "Path to the libuv include directory") + +if ("${LWS_LIBUV_LIBRARIES}" STREQUAL "" OR "${LWS_LIBUV_INCLUDE_DIRS}" STREQUAL "") + if (NOT LIBUV_FOUND) + find_path(LIBUV_INCLUDE_DIRS NAMES uv.h) + find_library(LIBUV_LIBRARIES NAMES uv) + endif() +else() + set(LIBUV_LIBRARIES ${LWS_LIBUV_LIBRARIES}) + set(LIBUV_INCLUDE_DIRS ${LWS_LIBUV_INCLUDE_DIRS}) +endif() + +message("libuv include dir: ${LIBUV_INCLUDE_DIRS}") +message("libuv libraries: ${LIBUV_LIBRARIES}") + +include_directories("${LIBUV_INCLUDE_DIRS}") + +CHECK_INCLUDE_FILE(uv-version.h LWS_HAVE_UV_VERSION_H) + # libuv changed the location in 1.21.0. Retain both + # checks temporarily to ensure a smooth transition. + if (NOT LWS_HAVE_UV_VERSION_H) + CHECK_INCLUDE_FILE(uv/version.h LWS_HAVE_NEW_UV_VERSION_H) + endif() + + if (LWS_WITH_EVLIB_PLUGINS AND LWS_WITH_LIBUV) + + create_evlib_plugin(evlib_uv + libuv.c + private-lib-event-libs-libuv.h + ${LIBUV_LIBRARIES}) + endif() + + # wanting libuv in the library is a separate question than + # wanting libuv as a selectable event loop plugin + # we only came here because LWS_WITH_LIBUV or LWS_WITH_LIBUV_INTERNAL + + if ((NOT LWS_WITH_EVLIB_PLUGINS) OR LWS_WITH_LIBUV_INTERNAL) + list(APPEND LIB_LIST ${LIBUV_LIBRARIES}) + + if (LWS_WITH_NETWORK) + list(APPEND SOURCES + event-libs/libuv/libuv.c) + endif() + endif() + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() +set(LWS_HAVE_UV_VERSION_H ${LWS_HAVE_UV_VERSION_H} PARENT_SCOPE) +set(LWS_HAVE_NEW_UV_VERSION_H ${LWS_HAVE_NEW_UV_VERSION_H} PARENT_SCOPE) diff -Nru libwebsockets-4.0.20/lib/event-libs/libuv/libuv.c libwebsockets-4.1.6/lib/event-libs/libuv/libuv.c --- libwebsockets-4.0.20/lib/event-libs/libuv/libuv.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/event-libs/libuv/libuv.c 2020-12-01 17:40:26.000000000 +0000 @@ -23,6 +23,10 @@ */ #include "private-lib-core.h" +#include "private-lib-event-libs-libuv.h" + +#define pt_to_priv_uv(_pt) ((struct lws_pt_eventlibs_libuv *)(_pt)->evlib_pt) +#define wsi_to_priv_uv(_w) ((struct lws_wsi_eventlibs_libuv *)(_w)->evlib_wsi) static void lws_uv_sultimer_cb(uv_timer_t *timer @@ -31,16 +35,20 @@ #endif ) { - struct lws_context_per_thread *pt = lws_container_of(timer, - struct lws_context_per_thread, uv.sultimer); + struct lws_pt_eventlibs_libuv *ptpr = lws_container_of(timer, + struct lws_pt_eventlibs_libuv, sultimer); + struct lws_context_per_thread *pt = ptpr->pt; lws_usec_t us; + lws_context_lock(pt->context, __func__); lws_pt_lock(pt, __func__); - us = __lws_sul_service_ripe(&pt->pt_sul_owner, lws_now_usecs()); + us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS, + lws_now_usecs()); if (us) - uv_timer_start(&pt->uv.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_pt_unlock(pt); + lws_context_unlock(pt->context); } static void @@ -49,13 +57,16 @@ , int status #endif ) -{ - struct lws_context_per_thread *pt = lws_container_of(handle, - struct lws_context_per_thread, uv.idle); +{ struct lws_pt_eventlibs_libuv *ptpr = lws_container_of(handle, + struct lws_pt_eventlibs_libuv, idle); + struct lws_context_per_thread *pt = ptpr->pt; lws_usec_t us; 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? */ @@ -65,27 +76,32 @@ /* account for sultimer */ - lws_pt_lock(pt, __func__); - us = __lws_sul_service_ripe(&pt->pt_sul_owner, lws_now_usecs()); + us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS, + lws_now_usecs()); if (us) - uv_timer_start(&pt->uv.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_pt_unlock(pt); /* there is nobody who needs service forcing, shut down idle */ uv_idle_stop(handle); + + lws_pt_unlock(pt); + lws_context_unlock(pt->context); } static void lws_io_cb(uv_poll_t *watcher, int status, int revents) { struct lws *wsi = (struct lws *)((uv_handle_t *)watcher)->data; - struct lws_context *context = wsi->context; + struct lws_context *context = wsi->a.context; struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; struct lws_pollfd eventfd; + lws_context_lock(pt->context, __func__); + lws_pt_lock(pt, __func__); + if (pt->is_destroyed) - return; + goto bail; #if defined(WIN32) || defined(_WIN32) eventfd.fd = watcher->socket; @@ -103,7 +119,7 @@ * You might want to return; instead of servicing the fd in * some cases */ if (status == UV_EAGAIN) - return; + goto bail; eventfd.events |= LWS_POLLHUP; eventfd.revents |= LWS_POLLHUP; @@ -117,6 +133,10 @@ eventfd.revents |= LWS_POLLOUT; } } + + lws_pt_unlock(pt); + lws_context_unlock(pt->context); + lws_service_fd_tsi(context, &eventfd, wsi->tsi); if (pt->destroy_self) { @@ -124,7 +144,12 @@ return; } - uv_idle_start(&pt->uv.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); } /* @@ -159,7 +184,7 @@ pt = &context->pt[m]; if (pt->pipe_wsi) { - uv_poll_stop(pt->pipe_wsi->w_read.uv.pwatcher); + uv_poll_stop(wsi_to_priv_uv(pt->pipe_wsi)->w_read.pwatcher); lws_destroy_event_pipe(pt->pipe_wsi); pt->pipe_wsi = NULL; } @@ -229,8 +254,8 @@ for (n = 0; n < context->count_threads; n++) { struct lws_context_per_thread *pt = &context->pt[n]; - if (pt->uv.io_loop && !pt->event_loop_foreign) - uv_stop(pt->uv.io_loop); + if (pt_to_priv_uv(pt)->io_loop && !pt->event_loop_foreign) + uv_stop(pt_to_priv_uv(pt)->io_loop); } if (!context->pt[0].event_loop_foreign) { @@ -284,8 +309,8 @@ void lws_libuv_stop_without_kill(const struct lws_context *context, int tsi) { - if (context->pt[tsi].uv.io_loop) - uv_stop(context->pt[tsi].uv.io_loop); + if (pt_to_priv_uv(&context->pt[tsi])->io_loop) + uv_stop(pt_to_priv_uv(&context->pt[tsi])->io_loop); } @@ -293,8 +318,8 @@ uv_loop_t * lws_uv_getloop(struct lws_context *context, int tsi) { - if (context->pt[tsi].uv.io_loop) - return context->pt[tsi].uv.io_loop; + if (pt_to_priv_uv(&context->pt[tsi])->io_loop) + return pt_to_priv_uv(&context->pt[tsi])->io_loop; return NULL; } @@ -302,7 +327,7 @@ int lws_libuv_check_watcher_active(struct lws *wsi) { - uv_handle_t *h = (uv_handle_t *)wsi->w_read.uv.pwatcher; + uv_handle_t *h = (uv_handle_t *)wsi_to_priv_uv(wsi)->w_read.pwatcher; if (!h) return 0; @@ -310,169 +335,6 @@ return uv_is_active(h); } - -#if defined(LWS_WITH_PLUGINS) && (UV_VERSION_MAJOR > 0) - -int -lws_uv_plugins_init(struct lws_context *context, const char * const *d) -{ - struct lws_plugin_capability lcaps; - struct lws_plugin *plugin; - lws_plugin_init_func initfunc; - int m, ret = 0; - void *v; - uv_dirent_t dent; - uv_fs_t req; - char path[256]; - uv_lib_t lib; - int pofs = 0; - -#if defined(__MINGW32__) || !defined(WIN32) - pofs = 3; -#endif - - lib.errmsg = NULL; - lib.handle = NULL; - - uv_loop_init(&context->uv.loop); - - lwsl_notice(" Plugins:\n"); - - while (d && *d) { - - lwsl_notice(" Scanning %s\n", *d); - m =uv_fs_scandir(&context->uv.loop, &req, *d, 0, NULL); - if (m < 1) { - lwsl_err("Scandir on %s failed\n", *d); - return 1; - } - - while (uv_fs_scandir_next(&req, &dent) != UV_EOF) { - if (strlen(dent.name) < 7) - continue; - - lwsl_notice(" %s\n", dent.name); - - lws_snprintf(path, sizeof(path) - 1, "%s/%s", *d, - dent.name); - if (uv_dlopen(path, &lib)) { - uv_dlerror(&lib); - lwsl_err("Error loading DSO: %s\n", lib.errmsg); - uv_dlclose(&lib); - goto bail; - } - - /* we could open it, can we get his init function? */ - -#if !defined(WIN32) && !defined(__MINGW32__) - m = lws_snprintf(path, sizeof(path) - 1, "init_%s", - dent.name + pofs /* snip lib... */); - path[m - 3] = '\0'; /* snip the .so */ -#else - m = lws_snprintf(path, sizeof(path) - 1, "init_%s", - dent.name + pofs); - path[m - 4] = '\0'; /* snip the .dll */ -#endif - if (uv_dlsym(&lib, path, &v)) { - uv_dlerror(&lib); - lwsl_err("%s: Failed to get '%s' on %s: %s\n", - __func__, path, dent.name, lib.errmsg); - uv_dlclose(&lib); - goto bail; - } - initfunc = (lws_plugin_init_func)v; - lcaps.api_magic = LWS_PLUGIN_API_MAGIC; - m = initfunc(context, &lcaps); - if (m) { - lwsl_err("Init %s failed %d\n", dent.name, m); - goto skip; - } - - plugin = lws_malloc(sizeof(*plugin), "plugin"); - if (!plugin) { - uv_dlclose(&lib); - lwsl_err("OOM\n"); - goto bail; - } - plugin->list = context->plugin_list; - context->plugin_list = plugin; - lws_strncpy(plugin->name, dent.name, sizeof(plugin->name)); - plugin->lib = lib; - plugin->caps = lcaps; - context->plugin_protocol_count += lcaps.count_protocols; - context->plugin_extension_count += lcaps.count_extensions; - - continue; - -skip: - uv_dlclose(&lib); - } -bail: - uv_fs_req_cleanup(&req); - d++; - } - - return ret; -} - -int -lws_uv_plugins_destroy(struct lws_context *context) -{ - struct lws_plugin *plugin = context->plugin_list, *p; - lws_plugin_destroy_func func; - char path[256]; - int pofs = 0; - void *v; - int m; - -#if defined(__MINGW32__) || !defined(WIN32) - pofs = 3; -#endif - - if (!plugin) - return 0; - - while (plugin) { - p = plugin; - -#if !defined(WIN32) && !defined(__MINGW32__) - m = lws_snprintf(path, sizeof(path) - 1, "destroy_%s", - plugin->name + pofs); - path[m - 3] = '\0'; -#else - m = lws_snprintf(path, sizeof(path) - 1, "destroy_%s", - plugin->name + pofs); - path[m - 4] = '\0'; -#endif - - if (uv_dlsym(&plugin->lib, path, &v)) { - uv_dlerror(&plugin->lib); - lwsl_err("Failed to get %s on %s: %s", path, - plugin->name, plugin->lib.errmsg); - } else { - func = (lws_plugin_destroy_func)v; - m = func(context); - if (m) - lwsl_err("Destroying %s failed %d\n", - plugin->name, m); - } - - uv_dlclose(&p->lib); - plugin = p->list; - p->list = NULL; - free(p); - } - - context->plugin_list = NULL; - - while (uv_loop_close(&context->uv.loop)) - ; - - return 0; -} - -#endif - static int elops_init_context_uv(struct lws_context *context, const struct lws_context_creation_info *info) @@ -482,7 +344,7 @@ context->eventlib_signal_cb = info->signal_cb; for (n = 0; n < context->count_threads; n++) - context->pt[n].w_sigint.context = context; + pt_to_priv_uv(&context->pt[n])->w_sigint.context = context; return 0; } @@ -501,7 +363,7 @@ if (!pt->event_loop_foreign) { - while (budget-- && (m = uv_run(pt->uv.io_loop, + while (budget-- && (m = uv_run(pt_to_priv_uv(pt)->io_loop, UV_RUN_NOWAIT))) ; if (m) @@ -526,15 +388,15 @@ /* only for internal loops... */ - if (!pt->event_loop_foreign && pt->uv.io_loop) { + if (!pt->event_loop_foreign && pt_to_priv_uv(pt)->io_loop) { internal = 1; if (!context->finalize_destroy_after_internal_loops_stopped) - uv_stop(pt->uv.io_loop); + uv_stop(pt_to_priv_uv(pt)->io_loop); else { #if UV_VERSION_MAJOR > 0 - uv_loop_close(pt->uv.io_loop); + uv_loop_close(pt_to_priv_uv(pt)->io_loop); #endif - lws_free_set_NULL(pt->uv.io_loop); + lws_free_set_NULL(pt_to_priv_uv(pt)->io_loop); } } } @@ -545,14 +407,15 @@ static int elops_wsi_logical_close_uv(struct lws *wsi) { - if (!lws_socket_is_valid(wsi->desc.sockfd)) + if (!lws_socket_is_valid(wsi->desc.sockfd) && + wsi->role_ops && strcmp(wsi->role_ops->name, "raw-file")) return 0; if (wsi->listener || wsi->event_pipe) { lwsl_debug("%s: %p: %d %d stop listener / pipe poll\n", __func__, wsi, wsi->listener, wsi->event_pipe); - if (wsi->w_read.uv.pwatcher) - uv_poll_stop(wsi->w_read.uv.pwatcher); + if (wsi_to_priv_uv(wsi)->w_read.pwatcher) + uv_poll_stop(wsi_to_priv_uv(wsi)->w_read.pwatcher); } lwsl_debug("%s: lws_libuv_closehandle: wsi %p\n", __func__, wsi); /* @@ -586,7 +449,7 @@ static void elops_close_handle_manually_uv(struct lws *wsi) { - uv_handle_t *h = (uv_handle_t *)wsi->w_read.uv.pwatcher; + uv_handle_t *h = (uv_handle_t *)wsi_to_priv_uv(wsi)->w_read.pwatcher; lwsl_debug("%s: lws_libuv_closehandle: wsi %p\n", __func__, wsi); @@ -602,7 +465,7 @@ */ wsi->desc.sockfd = LWS_SOCK_INVALID; - wsi->w_read.uv.pwatcher = NULL; + wsi_to_priv_uv(wsi)->w_read.pwatcher = NULL; wsi->told_event_loop_closed = 1; uv_close(h, lws_libuv_closewsi_m); @@ -611,24 +474,23 @@ static int elops_accept_uv(struct lws *wsi) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; + struct lws_io_watcher_libuv *w_read = &wsi_to_priv_uv(wsi)->w_read; - wsi->w_read.context = wsi->context; + w_read->context = wsi->a.context; - wsi->w_read.uv.pwatcher = - lws_malloc(sizeof(*wsi->w_read.uv.pwatcher), "uvh"); - if (!wsi->w_read.uv.pwatcher) + w_read->pwatcher = lws_malloc(sizeof(*w_read->pwatcher), "uvh"); + if (!w_read->pwatcher) return -1; if (wsi->role_ops->file_handle) - uv_poll_init(pt->uv.io_loop, wsi->w_read.uv.pwatcher, + uv_poll_init(pt_to_priv_uv(pt)->io_loop, w_read->pwatcher, (int)(lws_intptr_t)wsi->desc.filefd); else - uv_poll_init_socket(pt->uv.io_loop, - wsi->w_read.uv.pwatcher, - wsi->desc.sockfd); + uv_poll_init_socket(pt_to_priv_uv(pt)->io_loop, + w_read->pwatcher, wsi->desc.sockfd); - ((uv_handle_t *)wsi->w_read.uv.pwatcher)->data = (void *)wsi; + ((uv_handle_t *)w_read->pwatcher)->data = (void *)wsi; return 0; } @@ -636,15 +498,15 @@ static void elops_io_uv(struct lws *wsi, int flags) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; - struct lws_io_watcher *w = &wsi->w_read; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; + struct lws_io_watcher_libuv *w = &(wsi_to_priv_uv(wsi)->w_read); int current_events = w->actual_events & (UV_READABLE | UV_WRITABLE); lwsl_debug("%s: %p: %d\n", __func__, wsi, flags); /* w->context is set after the loop is initialized */ - if (!pt->uv.io_loop || !w->context) { + if (!pt_to_priv_uv(pt)->io_loop || !w->context) { lwsl_info("%s: no io loop yet\n", __func__); return; } @@ -655,8 +517,8 @@ assert(0); } - if (!w->uv.pwatcher || wsi->told_event_loop_closed) { - lwsl_err("%s: no watcher\n", __func__); + if (!w->pwatcher || wsi->told_event_loop_closed) { + lwsl_info("%s: no watcher\n", __func__); return; } @@ -668,7 +530,7 @@ if (flags & LWS_EV_READ) current_events |= UV_READABLE; - uv_poll_start(w->uv.pwatcher, current_events, lws_io_cb); + uv_poll_start(w->pwatcher, current_events, lws_io_cb); } else { if (flags & LWS_EV_WRITE) current_events &= ~UV_WRITABLE; @@ -677,10 +539,9 @@ current_events &= ~UV_READABLE; if (!(current_events & (UV_READABLE | UV_WRITABLE))) - uv_poll_stop(w->uv.pwatcher); + uv_poll_stop(w->pwatcher); else - uv_poll_start(w->uv.pwatcher, current_events, - lws_io_cb); + uv_poll_start(w->pwatcher, current_events, lws_io_cb); } w->actual_events = current_events; @@ -690,26 +551,29 @@ elops_init_vhost_listen_wsi_uv(struct lws *wsi) { struct lws_context_per_thread *pt; + struct lws_io_watcher_libuv *w_read; int n; if (!wsi) return 0; - if (wsi->w_read.context) + + w_read = &wsi_to_priv_uv(wsi)->w_read; + + if (w_read->context) return 0; - pt = &wsi->context->pt[(int)wsi->tsi]; - if (!pt->uv.io_loop) + pt = &wsi->a.context->pt[(int)wsi->tsi]; + if (!pt_to_priv_uv(pt)->io_loop) return 0; - wsi->w_read.context = wsi->context; + w_read->context = wsi->a.context; - wsi->w_read.uv.pwatcher = - lws_malloc(sizeof(*wsi->w_read.uv.pwatcher), "uvh"); - if (!wsi->w_read.uv.pwatcher) + w_read->pwatcher = lws_malloc(sizeof(*w_read->pwatcher), "uvh"); + if (!w_read->pwatcher) return -1; - n = uv_poll_init_socket(pt->uv.io_loop, wsi->w_read.uv.pwatcher, - wsi->desc.sockfd); + n = uv_poll_init_socket(pt_to_priv_uv(pt)->io_loop, + w_read->pwatcher, wsi->desc.sockfd); if (n) { lwsl_err("uv_poll_init failed %d, sockfd=%p\n", n, (void *)(lws_intptr_t)wsi->desc.sockfd); @@ -717,7 +581,7 @@ return -1; } - ((uv_handle_t *)wsi->w_read.uv.pwatcher)->data = (void *)wsi; + ((uv_handle_t *)w_read->pwatcher)->data = (void *)wsi; elops_io_uv(wsi, LWS_EV_START | LWS_EV_READ); @@ -727,8 +591,8 @@ static void elops_run_pt_uv(struct lws_context *context, int tsi) { - if (context->pt[tsi].uv.io_loop) - uv_run(context->pt[tsi].uv.io_loop, 0); + if (pt_to_priv_uv(&context->pt[tsi])->io_loop) + uv_run(pt_to_priv_uv(&context->pt[tsi])->io_loop, 0); } static void @@ -742,7 +606,7 @@ if (!lws_check_opt(context->options, LWS_SERVER_OPTION_LIBUV)) return; - if (!pt->uv.io_loop) + if (!pt_to_priv_uv(pt)->io_loop) return; if (pt->event_loop_destroy_processing_done) @@ -751,7 +615,7 @@ pt->event_loop_destroy_processing_done = 1; if (!pt->event_loop_foreign) { - uv_signal_stop(&pt->w_sigint.uv.watcher); + uv_signal_stop(&pt_to_priv_uv(pt)->w_sigint.watcher); ns = LWS_ARRAY_SIZE(sigs); if (lws_check_opt(context->options, @@ -759,18 +623,18 @@ ns = 2; for (m = 0; m < ns; m++) { - uv_signal_stop(&pt->uv.signals[m]); - uv_close((uv_handle_t *)&pt->uv.signals[m], + uv_signal_stop(&pt_to_priv_uv(pt)->signals[m]); + uv_close((uv_handle_t *)&pt_to_priv_uv(pt)->signals[m], lws_uv_close_cb_sa); } } else lwsl_debug("%s: not closing pt signals\n", __func__); - uv_timer_stop(&pt->uv.sultimer); - uv_close((uv_handle_t *)&pt->uv.sultimer, lws_uv_close_cb_sa); + uv_timer_stop(&pt_to_priv_uv(pt)->sultimer); + uv_close((uv_handle_t *)&pt_to_priv_uv(pt)->sultimer, lws_uv_close_cb_sa); - uv_idle_stop(&pt->uv.idle); - uv_close((uv_handle_t *)&pt->uv.idle, lws_uv_close_cb_sa); + uv_idle_stop(&pt_to_priv_uv(pt)->idle); + uv_close((uv_handle_t *)&pt_to_priv_uv(pt)->idle, lws_uv_close_cb_sa); } /* @@ -784,11 +648,14 @@ elops_init_pt_uv(struct lws_context *context, void *_loop, int tsi) { struct lws_context_per_thread *pt = &context->pt[tsi]; + struct lws_pt_eventlibs_libuv *ptpriv = pt_to_priv_uv(pt); struct lws_vhost *vh = context->vhost_list; int status = 0, n, ns, first = 1; uv_loop_t *loop = (uv_loop_t *)_loop; - if (!pt->uv.io_loop) { + ptpriv->pt = pt; + + if (!ptpriv->io_loop) { if (!loop) { loop = lws_malloc(sizeof(*loop), "libuv loop"); if (!loop) { @@ -807,10 +674,10 @@ pt->event_loop_foreign = 1; } - pt->uv.io_loop = loop; - uv_idle_init(loop, &pt->uv.idle); - LWS_UV_REFCOUNT_STATIC_HANDLE_NEW(&pt->uv.idle, context); - + ptpriv->io_loop = loop; + uv_idle_init(loop, &ptpriv->idle); + LWS_UV_REFCOUNT_STATIC_HANDLE_NEW(&ptpriv->idle, context); + uv_idle_start(&ptpriv->idle, lws_uv_idle); ns = LWS_ARRAY_SIZE(sigs); if (lws_check_opt(context->options, @@ -818,13 +685,13 @@ ns = 2; if (!pt->event_loop_foreign) { - assert(ns <= (int)LWS_ARRAY_SIZE(pt->uv.signals)); + assert(ns <= (int)LWS_ARRAY_SIZE(ptpriv->signals)); for (n = 0; n < ns; n++) { - uv_signal_init(loop, &pt->uv.signals[n]); - LWS_UV_REFCOUNT_STATIC_HANDLE_NEW(&pt->uv.signals[n], + uv_signal_init(loop, &ptpriv->signals[n]); + LWS_UV_REFCOUNT_STATIC_HANDLE_NEW(&ptpriv->signals[n], context); - pt->uv.signals[n].data = pt->context; - uv_signal_start(&pt->uv.signals[n], + ptpriv->signals[n].data = pt->context; + uv_signal_start(&ptpriv->signals[n], lws_uv_signal_handler, sigs[n]); } } @@ -847,8 +714,8 @@ if (!first) return status; - uv_timer_init(pt->uv.io_loop, &pt->uv.sultimer); - LWS_UV_REFCOUNT_STATIC_HANDLE_NEW(&pt->uv.sultimer, context); + uv_timer_init(ptpriv->io_loop, &ptpriv->sultimer); + LWS_UV_REFCOUNT_STATIC_HANDLE_NEW(&ptpriv->sultimer, context); return status; } @@ -865,12 +732,15 @@ lwsl_info("%s: %p\n", __func__, wsi); + lws_context_lock(context, __func__); + /* * We get called back here for every wsi that closes */ #if defined(LWS_WITH_SERVER) - if (wsi->role_ops == &role_ops_listen && wsi->context->deprecated) { + if (wsi->role_ops && !strcmp(wsi->role_ops->name, "listen") && + wsi->a.context->deprecated) { lspd = 1; context->deprecation_pending_listen_close_count--; if (!context->deprecation_pending_listen_close_count) @@ -924,17 +794,22 @@ if (!context->count_event_loop_static_asset_handles && context->pt[0].event_loop_foreign) { lwsl_info("%s: call lws_context_destroy2\n", __func__); + lws_context_unlock(context); lws_context_destroy2(context); + return; } } + + lws_context_unlock(context); } void lws_libuv_closehandle(struct lws *wsi) { uv_handle_t* handle; + struct lws_io_watcher_libuv *w_read = &wsi_to_priv_uv(wsi)->w_read; - if (!wsi->w_read.uv.pwatcher) + if (!w_read->pwatcher) return; if (wsi->told_event_loop_closed) { @@ -951,16 +826,16 @@ * handle->data. */ - handle = (uv_handle_t *)wsi->w_read.uv.pwatcher; + handle = (uv_handle_t *)w_read->pwatcher; /* ensure we can only do this once */ - wsi->w_read.uv.pwatcher = NULL; + w_read->pwatcher = NULL; uv_close(handle, lws_libuv_closewsi); } -struct lws_event_loop_ops event_loop_ops_uv = { +static const struct lws_event_loop_ops event_loop_ops_uv = { /* name */ "libuv", /* init_context */ elops_init_context_uv, /* destroy_context1 */ elops_destroy_context1_uv, @@ -977,4 +852,23 @@ /* destroy wsi */ NULL, /* flags */ 0, + + /* evlib_size_ctx */ sizeof(struct lws_context_eventlibs_libuv), + /* evlib_size_pt */ sizeof(struct lws_pt_eventlibs_libuv), + /* evlib_size_vh */ 0, + /* evlib_size_wsi */ sizeof(struct lws_io_watcher_libuv), }; + +#if defined(LWS_WITH_EVLIB_PLUGINS) +LWS_VISIBLE +#endif +const lws_plugin_evlib_t evlib_uv = { + .hdr = { + "libuv event loop", + "lws_evlib_plugin", + LWS_PLUGIN_API_MAGIC + }, + + .ops = &event_loop_ops_uv +}; + diff -Nru libwebsockets-4.0.20/lib/event-libs/libuv/private-lib-event-libs-libuv.h libwebsockets-4.1.6/lib/event-libs/libuv/private-lib-event-libs-libuv.h --- libwebsockets-4.0.20/lib/event-libs/libuv/private-lib-event-libs-libuv.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/event-libs/libuv/private-lib-event-libs-libuv.h 2020-12-01 17:40:26.000000000 +0000 @@ -46,11 +46,18 @@ (--(LWS_UV_REFCOUNT_STATIC_HANDLE_TO_CONTEXT(_x)-> \ count_event_loop_static_asset_handles)) +struct lws_signal_watcher_libuv { + uv_signal_t watcher; + struct lws_context *context; +}; + struct lws_pt_eventlibs_libuv { uv_loop_t *io_loop; + struct lws_context_per_thread *pt; uv_signal_t signals[8]; uv_timer_t sultimer; uv_idle_t idle; + struct lws_signal_watcher_libuv w_sigint; }; struct lws_context_eventlibs_libuv { @@ -59,14 +66,14 @@ struct lws_io_watcher_libuv { uv_poll_t *pwatcher; + struct lws_context *context; + uint8_t actual_events; }; -struct lws_signal_watcher_libuv { - uv_signal_t watcher; +struct lws_wsi_eventlibs_libuv { + struct lws_io_watcher_libuv w_read; }; -extern struct lws_event_loop_ops event_loop_ops_uv; - uv_loop_t * lws_uv_getloop(struct lws_context *context, int tsi); diff -Nru libwebsockets-4.0.20/lib/event-libs/poll/CMakeLists.txt libwebsockets-4.1.6/lib/event-libs/poll/CMakeLists.txt --- libwebsockets-4.0.20/lib/event-libs/poll/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/event-libs/poll/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,42 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - includes via include_directories +# +# and keep everything else private + +include_directories(../poll) + +if (LWS_WITH_NETWORK) + list(APPEND SOURCES + event-libs/poll/poll.c) +endif() + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() diff -Nru libwebsockets-4.0.20/lib/event-libs/poll/poll.c libwebsockets-4.1.6/lib/event-libs/poll/poll.c --- libwebsockets-4.0.20/lib/event-libs/poll/poll.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/event-libs/poll/poll.c 2020-12-01 17:40:26.000000000 +0000 @@ -19,12 +19,11 @@ * 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. - * - * This is included from private-lib-core.h if LWS_ROLE_WS + * IN THE SOFTWARE */ #include +#include "private-lib-event-libs-poll.h" struct lws_event_loop_ops event_loop_ops_poll = { /* name */ "poll", @@ -43,4 +42,19 @@ /* destroy wsi */ NULL, /* flags */ LELOF_ISPOLL, + + /* evlib_size_ctx */ 0, + /* evlib_size_pt */ 0, + /* evlib_size_vh */ 0, + /* evlib_size_wsi */ 0, +}; + +const lws_plugin_evlib_t evlib_poll = { + .hdr = { + "poll", + "lws_evlib_plugin", + LWS_PLUGIN_API_MAGIC + }, + + .ops = &event_loop_ops_poll }; diff -Nru libwebsockets-4.0.20/lib/event-libs/private-lib-event-libs.h libwebsockets-4.1.6/lib/event-libs/private-lib-event-libs.h --- libwebsockets-4.0.20/lib/event-libs/private-lib-event-libs.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/event-libs/private-lib-event-libs.h 2020-12-01 17:40:26.000000000 +0000 @@ -60,27 +60,9 @@ void (*destroy_wsi)(struct lws *wsi); uint8_t flags; -}; - -/* bring in event libs private declarations */ - -#if defined(LWS_WITH_POLL) -#include "private-lib-event-libs-poll.h" -#endif - -#if defined(LWS_WITH_LIBUV) -#include "private-lib-event-libs-libuv.h" -#endif - -#if defined(LWS_WITH_LIBEVENT) -#include "private-lib-event-libs-libevent.h" -#endif - -#if defined(LWS_WITH_GLIB) -#include "private-lib-event-libs-glib.h" -#endif - -#if defined(LWS_WITH_LIBEV) -#include "private-lib-event-libs-libev.h" -#endif + uint16_t evlib_size_ctx; + uint16_t evlib_size_pt; + uint16_t evlib_size_vh; + uint16_t evlib_size_wsi; +}; diff -Nru libwebsockets-4.0.20/lib/event-libs/README.md libwebsockets-4.1.6/lib/event-libs/README.md --- libwebsockets-4.0.20/lib/event-libs/README.md 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/event-libs/README.md 2020-12-01 17:40:26.000000000 +0000 @@ -2,12 +2,30 @@ ### Introduction -By default lws has built-in support for POSIX poll() as the event loop. +By default lws has built-in support for POSIX poll() as the event loop on unix, +and native WSA on windows. -However either to get access to epoll() or other platform specific better -poll waits, or to integrate with existing applications already using a -specific event loop, it can be desirable for lws to use another external -event library, like libuv, libevent or libev. +To get access to epoll() or other platform specific better poll waits, or to +integrate with existing applications already using a specific event loop, it can +be desirable for lws to use another external event library, like libuv, glib, +libevent or libev. + +Lws supports wholesale replacement of its wait selectable at runtime, either by +building support for one or more event lib into the libwebsockets library, or by +building runtime-loadable plugins. CMake symbol `LWS_WITH_EVLIB_PLUGINS` +decides if the support is built as plugins or included into the lws lib. + +Due to their history libevent and libev have conflicting defines in the same +namespace and cannot be built together if included into the lib, however when +built as plugins they are built separately without problems. +See ./READMEs/README.event-libs.md for more details. + +Despite it may be more work, lws event lib implementations must support +"foreign" loops cleanly, that is integration with an already-existing loop and +the ability to destroy the lws_context without stopping or leaving the foreign +loop in any different state than when lws found it. For most loops this is +fairly simple, but with libuv async close, it required refcounting lws libuv +handles and deferring the actual destroy until they were all really closed. ### Code placement @@ -15,89 +33,114 @@ ### Allowing control over enabling event libs -All event libs should add a cmake define `LWS_WITH_**lib name**` and make its build -dependent on it in CMakeLists.txt. Export the cmakedefine in `./cmake/lws_config.h.in` -as well so user builds can understand if the event lib is available in the lws build it is -trying to bind to. +All event libs should add a cmake define `LWS_WITH_**lib name**` and make its +build dependent on it in CMakeLists.txt. Export the cmakedefine in +`./cmake/lws_config.h.in` as well so user builds can understand if the event +lib is available in the lws build it is trying to bind to. -If the event lib is disabled in cmake, nothing in its directory is built or referenced. +If the event lib is disabled in cmake, nothing in its directory is built or +referenced. ### Event loop ops struct -The event lib support is defined by `struct lws_event_loop_ops` in `lib/event-libs/private-lib-event-libs.h`, -each event lib support instantiates one of these and fills in the appropriate ops -callbacks to perform its job. By convention that lives in +The event lib support is defined by `struct lws_event_loop_ops` in +`lib/event-libs/private-lib-event-libs.h`, +each event lib support instantiates one of these and fills in the appropriate +ops callbacks to perform its job. By convention that lives in `./lib/event-libs/**lib name**/**lib_name**.c`. +The ops struct must be public, not static, and must be named using `**lib_name**`, +eg + +``` +``` + ### Private event lib declarations -Truly private declarations for the event lib can go in the event-libs directory as you like. -However when the declarations must be accessible to other things in lws build, eg, -the event lib support adds members to `struct lws` when enabled, they should be in the -event lib support directory in a file `private-lib-event-libs-myeventlib.h`. - -Search for "bring in event libs private declarations" in `./lib/core/private-lib-core.h -and add your private event lib support file there following the style used for the other -event libs, eg, +Truly private declarations for the event lib support that are only referenced by +that code can go in the event-libs directory as you like. The convention is +they should be in the event lib support directory in a file +`private-lib-event-libs-**lib name**.h`. + +### Integration with lws + +There are a couple of places to add refererences in ./lib/core/context.c, in a +table of context creation time server option flags mapped to the **lib_name**, +used for plugin mode, like this... + +``` +#if defined(LWS_WITH_EVLIB_PLUGINS) && defined(LWS_WITH_EVENT_LIBS) +static const struct lws_evlib_map { + uint64_t flag; + const char *name; +} map[] = { + { LWS_SERVER_OPTION_LIBUV, "evlib_uv" }, + { LWS_SERVER_OPTION_LIBEVENT, "evlib_event" }, + { LWS_SERVER_OPTION_GLIB, "evlib_glib" }, + { LWS_SERVER_OPTION_LIBEV, "evlib_ev" }, +}; +``` + +and for backwards compatibility add a stanza to the built-in checks like this ``` #if defined(LWS_WITH_LIBUV) - #include "event-libs/libuv/private-lib-event-libs-libuv.h" + if (lws_check_opt(info->options, LWS_SERVER_OPTION_LIBUV)) { + extern const lws_plugin_evlib_t evlib_uv; + plev = &evlib_uv; + } #endif ``` -If the event lib support is disabled at cmake, nothing from its private.h should be used anywhere. +Both entries are the way the main libs hook up to the selected event lib ops +struct at runtime. ### Integrating event lib assets to lws -If your event lib needs special storage in lws objects, that's no problem. But to keep -things sane, there are some rules. - - - declare a "container struct" in your private.h for everything, eg, the libuv event - lib support need to add its own assets in the perthread struct, it declares in its private.h +Declare "container structs" in your private....h for anything you need at +wsi, pt, vhost and context levels, eg, the libuv event lib support need to +add its own assets in the perthread struct, it declares in its private....h ``` struct lws_pt_eventlibs_libuv { uv_loop_t *io_loop; + struct lws_context_per_thread *pt; uv_signal_t signals[8]; - uv_timer_t timeout_watcher; - uv_timer_t hrtimer; + uv_timer_t sultimer; uv_idle_t idle; + struct lws_signal_watcher_libuv w_sigint; }; ``` - - add your event lib content in one place in the related lws struct, protected by `#if defined(LWS_WITH_**lib name**)`, - eg, again for LWS_WITH_LIBUV +this is completely private and opaque, but in the ops struct there are provided +four entries to export the sizes of these event-lib specific objects ``` -struct lws_context_per_thread { - -... - -#if defined(LWS_WITH_LIBUV) - struct lws_pt_eventlibs_libuv uv; -#endif - ... + /* evlib_size_ctx */ sizeof(struct lws_context_eventlibs_libuv), + /* evlib_size_pt */ sizeof(struct lws_pt_eventlibs_libuv), + /* evlib_size_vh */ 0, + /* evlib_size_wsi */ sizeof(struct lws_io_watcher_libuv), +}; ``` -### Adding to lws available event libs list +If the particular event lib doesn't need to have a private footprint in an +object, it can just set the size it needs there to 0. -Edit the NULL-terminated array `available_event_libs` at the top of `./lib/context.c` to include -a pointer to your new event lib support's ops struct, following the style already there. +When the context, pts, vhosts or wsis are created in lws, they over-allocate +to also allow for the event lib object, and set a pointer in the lws object +being created to point at the over-allocation. For example for the wsi ``` -const struct lws_event_loop_ops *available_event_libs[] = { -#if defined(LWS_WITH_POLL) - &event_loop_ops_poll, +#if defined(LWS_WITH_EVENT_LIBS) + void *evlib_wsi; /* overallocated */ #endif -#if defined(LWS_WITH_LIBUV) - &event_loop_ops_uv, -#endif -... ``` -This is used to provide a list of avilable configured backends. +and similarly there are `evlib_pt` and so on for those objects, usable by the +event lib and opaque to everyone else. Once the event lib is selected at +runtime, all of these objects are guaranteed to have the right size object at +`wsi->evlib_wsi` initialized to zeroes. ### Enabling event lib adoption @@ -112,13 +155,15 @@ ### Destruction -Ending the event loop is generally a bit tricky, because if the event loop is internal -to the lws context, you cannot destroy it while the event loop is running. - -Don't add special exports... we tried that, it's a huge mess. The same user code should be able -work with any of the event loops including poll. - -The solution we found was hide the different processing necessary for the different cases in -lws_destroy_context(). To help with that there are ops available at two different places in -the context destroy processing. +Ending the event loop is generally a bit tricky, because if the event loop is +internal to the lws context, you cannot destroy it while the event loop is +running. + +Don't add special exports... we tried that, it's a huge mess. The same user +code should be able work with any of the event loops including poll. + +The solution we found was hide the different processing necessary for the +different cases in `lws_destroy_context()`. To help with that there are event +lib ops available that will be called at two different places in the context +destroy processing. diff -Nru libwebsockets-4.0.20/lib/jose/CMakeLists.txt libwebsockets-4.1.6/lib/jose/CMakeLists.txt --- libwebsockets-4.0.20/lib/jose/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/jose/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,46 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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_directories(. ./jwe ./jws ./jwk) + +if (LWS_WITH_JOSE) + list(APPEND SOURCES + jose/jwk/jwk.c + jose/jws/jose.c + jose/jws/jws.c + jose/jwe/jwe.c + jose/jwe/enc/aescbc.c + jose/jwe/enc/aesgcm.c + jose/jwe/enc/aeskw.c + jose/jwe/jwe-rsa-aescbc.c + jose/jwe/jwe-rsa-aesgcm.c + jose/jwe/jwe-ecdh-es-aeskw.c + ) +endif() + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() diff -Nru libwebsockets-4.0.20/lib/jose/jwe/enc/aescbc.c libwebsockets-4.1.6/lib/jose/jwe/enc/aescbc.c --- libwebsockets-4.0.20/lib/jose/jwe/enc/aescbc.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/jose/jwe/enc/aescbc.c 2020-12-01 17:40:26.000000000 +0000 @@ -29,7 +29,7 @@ lws_jwe_encrypt_cbc_hs(struct lws_jwe *jwe, uint8_t *cek, uint8_t *aad, int aad_len) { - int n, hlen = lws_genhmac_size(jwe->jose.enc_alg->hmac_type); + int n, hlen = (int)lws_genhmac_size(jwe->jose.enc_alg->hmac_type); uint8_t digest[LWS_GENHASH_LARGEST]; struct lws_gencrypto_keyelem el; struct lws_genhmac_ctx hmacctx; @@ -100,7 +100,7 @@ NULL, NULL, LWS_AES_CBC_BLOCKLEN); paddedlen = lws_gencrypto_padded_length(LWS_AES_CBC_BLOCKLEN, jwe->jws.map.len[LJWE_CTXT]); - jwe->jws.map.len[LJWE_CTXT] = paddedlen; + jwe->jws.map.len[LJWE_CTXT] = (uint32_t)paddedlen; lws_genaes_destroy(&aesctx, (uint8_t *)jwe->jws.map.buf[LJWE_CTXT] + paddedlen - LWS_AES_CBC_BLOCKLEN, LWS_AES_CBC_BLOCKLEN); if (n) { @@ -162,7 +162,7 @@ lws_jwe_auth_and_decrypt_cbc_hs(struct lws_jwe *jwe, uint8_t *enc_cek, uint8_t *aad, int aad_len) { - int n, hlen = lws_genhmac_size(jwe->jose.enc_alg->hmac_type); + int n, hlen = (int)lws_genhmac_size(jwe->jose.enc_alg->hmac_type); uint8_t digest[LWS_GENHASH_LARGEST]; struct lws_gencrypto_keyelem el; struct lws_genhmac_ctx hmacctx; diff -Nru libwebsockets-4.0.20/lib/jose/jwe/enc/aeskw.c libwebsockets-4.1.6/lib/jose/jwe/enc/aeskw.c --- libwebsockets-4.0.20/lib/jose/jwe/enc/aeskw.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/jose/jwe/enc/aeskw.c 2020-12-01 17:40:26.000000000 +0000 @@ -41,7 +41,7 @@ /* we are wrapping a key, so size for the worst case after wrap */ uint8_t enc_cek[LWS_JWE_LIMIT_KEY_ELEMENT_BYTES + LWS_JWE_RFC3394_OVERHEAD_BYTES]; - int n, m, hlen = lws_genhmac_size(jwe->jose.enc_alg->hmac_type), + int n, m, hlen = (int)lws_genhmac_size(jwe->jose.enc_alg->hmac_type), ot = *temp_len; if (jwe->jws.jwk->kty != LWS_GENCRYPTO_KTY_OCT) { diff -Nru libwebsockets-4.0.20/lib/jose/jwe/jwe.c libwebsockets-4.1.6/lib/jose/jwe/jwe.c --- libwebsockets-4.0.20/lib/jose/jwe/jwe.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/jose/jwe/jwe.c 2020-12-01 17:40:26.000000000 +0000 @@ -148,7 +148,7 @@ lejp_construct(&jctx, lws_jwe_json_cb, &args, jwe_json, LWS_ARRAY_SIZE(jwe_json)); - m = (int)(signed char)lejp_parse(&jctx, (uint8_t *)buf, len); + m = lejp_parse(&jctx, (uint8_t *)buf, len); lejp_destruct(&jctx); if (m < 0) { lwsl_notice("%s: parse returned %d\n", __func__, m); @@ -209,7 +209,7 @@ lws_jwa_concat_kdf(struct lws_jwe *jwe, int direct, uint8_t *out, const uint8_t *shared_secret, int sslen) { - int hlen = lws_genhash_size(LWS_GENHASH_TYPE_SHA256), aidlen; + int hlen = (int)lws_genhash_size(LWS_GENHASH_TYPE_SHA256), aidlen; struct lws_genhash_ctx hash_ctx; uint32_t ctr = 1, t; const char *aid; @@ -236,7 +236,7 @@ */ aid = direct ? jwe->jose.enc_alg->alg : jwe->jose.alg->alg; - aidlen = strlen(aid); + aidlen = (int)strlen(aid); /* * PartyUInfo (PartyVInfo is the same deal) @@ -284,7 +284,7 @@ /* Z */ lws_genhash_update(&hash_ctx, shared_secret, sslen) || /* other info */ - lws_genhash_update(&hash_ctx, be32(strlen(aid), &t), 4) || + lws_genhash_update(&hash_ctx, be32((uint32_t)strlen(aid), &t), 4) || lws_genhash_update(&hash_ctx, aid, aidlen) || lws_genhash_update(&hash_ctx, be32(jwe->jose.e[LJJHI_APU].len, &t), 4) || @@ -541,7 +541,7 @@ *out++ = '\0'; out_len -= n; - return orig - out_len; + return (int)(orig - out_len); } int @@ -578,9 +578,9 @@ if (!jwe->jose.alg || !jwe->jose.alg->alg) goto bail; - p += lws_snprintf(p, end - p, "{\"alg\":\"%s\",\"jwk\":", + p += lws_snprintf(p, lws_ptr_diff(end, p), "{\"alg\":\"%s\",\"jwk\":", jwe->jose.alg->alg); - m = end - p; + m = lws_ptr_diff(end, p); n = lws_jwk_export(&jwe->jwk, 0, p, &m); if (n < 0) { lwsl_notice("failed to export jwk\n"); @@ -647,7 +647,7 @@ free(buf); - return p1 - out; + return lws_ptr_diff(p1, out); bail: lws_jws_destroy(&jws); @@ -782,7 +782,7 @@ p1 += lws_snprintf(p1, end1 - p1, "\n}\n"); - return p1 - out; + return lws_ptr_diff(p1, out); bail: lws_jws_destroy(&jwe->jws); diff -Nru libwebsockets-4.0.20/lib/jose/jwe/jwe-ecdh-es-aeskw.c libwebsockets-4.1.6/lib/jose/jwe/jwe-ecdh-es-aeskw.c --- libwebsockets-4.0.20/lib/jose/jwe/jwe-ecdh-es-aeskw.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/jose/jwe/jwe-ecdh-es-aeskw.c 2020-12-01 17:40:26.000000000 +0000 @@ -203,7 +203,7 @@ derived[LWS_JWE_LIMIT_KEY_ELEMENT_BYTES]; int m, n, ret = -1, ot = *temp_len, ss_len = sizeof(shared_secret), // kw_hlen = lws_genhash_size(jwe->jose.alg->hash_type), - enc_hlen = lws_genhmac_size(jwe->jose.enc_alg->hmac_type), + enc_hlen = (int)lws_genhmac_size(jwe->jose.enc_alg->hmac_type), ekbytes = 32; //jwe->jose.alg->keybits_fixed / 8; struct lws_genec_ctx ecctx; struct lws_jwk *ephem = &jwe->jose.recipient[jwe->recip].jwk_ephemeral; @@ -378,7 +378,7 @@ lws_jwe_encrypt_ecdh_cbc_hs(struct lws_jwe *jwe, char *temp, int *temp_len) { int ss_len, // kw_hlen = lws_genhash_size(jwe->jose.alg->hash_type), - enc_hlen = lws_genhmac_size(jwe->jose.enc_alg->hmac_type); + enc_hlen = (int)lws_genhmac_size(jwe->jose.enc_alg->hmac_type); uint8_t cek[LWS_JWE_LIMIT_KEY_ELEMENT_BYTES]; int ekbytes = jwe->jose.alg->keybits_fixed / 8; int n, ot = *temp_len, ret = -1; @@ -455,7 +455,7 @@ uint8_t shared_secret[LWS_JWE_LIMIT_KEY_ELEMENT_BYTES], derived[LWS_JWE_LIMIT_KEY_ELEMENT_BYTES]; int ekbytes = jwe->jose.enc_alg->keybits_fixed / 8, - enc_hlen = lws_genhmac_size(jwe->jose.enc_alg->hmac_type); + enc_hlen = (int)lws_genhmac_size(jwe->jose.enc_alg->hmac_type); struct lws_genec_ctx ecctx; int n, ret = -1, ss_len = sizeof(shared_secret); diff -Nru libwebsockets-4.0.20/lib/jose/jwe/jwe-rsa-aescbc.c libwebsockets-4.1.6/lib/jose/jwe/jwe-rsa-aescbc.c --- libwebsockets-4.0.20/lib/jose/jwe/jwe-rsa-aescbc.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/jose/jwe/jwe-rsa-aescbc.c 2020-12-01 17:40:26.000000000 +0000 @@ -46,7 +46,8 @@ lws_jwe_encrypt_rsa_aes_cbc_hs(struct lws_jwe *jwe, char *temp, int *temp_len) { - int n, hlen = lws_genhmac_size(jwe->jose.enc_alg->hmac_type), ot = *temp_len; + int n, hlen = (int)lws_genhmac_size(jwe->jose.enc_alg->hmac_type), + ot = *temp_len; char ekey[LWS_GENHASH_LARGEST]; struct lws_genrsa_ctx rsactx; diff -Nru libwebsockets-4.0.20/lib/jose/jwk/jwk.c libwebsockets-4.1.6/lib/jose/jwk/jwk.c --- libwebsockets-4.0.20/lib/jose/jwk/jwk.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/jose/jwk/jwk.c 2020-12-01 17:40:26.000000000 +0000 @@ -595,7 +595,7 @@ case LWS_GENCRYPTO_KTY_OCT: sn = lws_gencrypto_bits_to_bytes(bits); jwk->e[LWS_GENCRYPTO_OCT_KEYEL_K].buf = lws_malloc(sn, "oct"); - jwk->e[LWS_GENCRYPTO_OCT_KEYEL_K].len = sn; + jwk->e[LWS_GENCRYPTO_OCT_KEYEL_K].len = (uint32_t)sn; if (lws_get_random(context, jwk->e[LWS_GENCRYPTO_OCT_KEYEL_K].buf, sn) != sn) { lwsl_err("%s: problem getting random\n", __func__); @@ -646,7 +646,7 @@ lws_jwk_init_jps(&jctx, &jps, jwk, cb, user); - m = (int)(signed char)lejp_parse(&jctx, (uint8_t *)in, len); + m = lejp_parse(&jctx, (uint8_t *)in, (int)len); lejp_destruct(&jctx); if (m < 0) { @@ -789,7 +789,7 @@ lws_strnncpy(p, (const char *)jwk->e[l->idx].buf, jwk->e[l->idx].len, end - p); - m = strlen(p); + m = (int)strlen(p); } else m = lws_jws_base64_enc( (const char *)jwk->e[l->idx].buf, @@ -808,9 +808,9 @@ p += lws_snprintf(p, end - p, (flags & LWSJWKF_EXPORT_NOCRLF) ? "}" : "}\n"); - *len -= p - start; + *len -= lws_ptr_diff(p, start); - return p - start; + return lws_ptr_diff(p, start); } int diff -Nru libwebsockets-4.0.20/lib/jose/jws/jose.c libwebsockets-4.1.6/lib/jose/jws/jose.c --- libwebsockets-4.0.20/lib/jose/jws/jose.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/jose/jws/jose.c 2020-12-01 17:40:26.000000000 +0000 @@ -430,7 +430,7 @@ lejp_construct(&jctx, lws_jws_jose_cb, &args, jws_jose, LWS_ARRAY_SIZE(jws_jose)); - m = (int)(signed char)lejp_parse(&jctx, (uint8_t *)buf, n); + m = lejp_parse(&jctx, (uint8_t *)buf, n); lejp_destruct(&jctx); if (m < 0) { lwsl_notice("%s: parse returned %d\n", __func__, m); @@ -509,7 +509,7 @@ sub = 1; m = lws_b64_encode_string_url((const char *) jose->e[n].buf, jose->e[n].len, - out, end - out); + out, lws_ptr_diff(end, out)); if (m < 0) return -1; out += m; @@ -528,7 +528,7 @@ sub = 1; m = lws_b64_encode_string((const char *) jose->e[n].buf, jose->e[n].len, - out, end - out); + out, lws_ptr_diff(end, out)); if (m < 0) return -1; out += m; @@ -546,7 +546,7 @@ out += lws_snprintf(out, end - out, "%s\"%s\":", sub ? ",\n" : "", jws_jose[n]); sub = 1; - vl = end - out; + vl = lws_ptr_diff(end, out); m = lws_jwk_export(jwk, 0, out, &vl); if (m < 0) { lwsl_notice("%s: failed to export key\n", @@ -598,7 +598,7 @@ if (out > end - 2) return -1; - return out_len - (end - out) - 1; + return lws_ptr_diff(out_len, (end - out)) - 1; bail: return -1; diff -Nru libwebsockets-4.0.20/lib/jose/jws/jws.c libwebsockets-4.1.6/lib/jose/jws/jws.c --- libwebsockets-4.0.20/lib/jose/jws/jws.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/jose/jws/jws.c 2020-12-01 17:40:26.000000000 +0000 @@ -150,7 +150,7 @@ lejp_construct(&jctx, lws_jws_json_cb, &args, jws_json, LWS_ARRAY_SIZE(jws_json)); - m = (int)(signed char)lejp_parse(&jctx, (uint8_t *)buf, len); + m = lejp_parse(&jctx, (uint8_t *)buf, len); lejp_destruct(&jctx); if (m < 0) { lwsl_notice("%s: parse returned %d\n", __func__, m); @@ -200,10 +200,10 @@ memcpy(temp, in, in_len); - map->len[idx] = in_len; + map->len[idx] = (uint32_t)in_len; map->buf[idx] = temp; - *temp_len -= actual_alloc; + *temp_len -= (int)actual_alloc; return 0; } @@ -241,7 +241,7 @@ if ((size_t)*temp_len < actual_alloc) return -1; - map->len[idx] = random_len; + map->len[idx] = (uint32_t)random_len; map->buf[idx] = temp; if (lws_get_random(context, temp, random_len) != random_len) { @@ -249,7 +249,7 @@ return -1; } - *temp_len -= actual_alloc; + *temp_len -= (int)actual_alloc; return 0; } @@ -264,9 +264,9 @@ if ((size_t)*temp_len < actual_alloc) return -1; - map->len[idx] = len; + map->len[idx] = (uint32_t)len; map->buf[idx] = temp; - *temp_len -= actual_alloc; + *temp_len -= (int)actual_alloc; return 0; } @@ -276,7 +276,7 @@ { int n; - n = lws_b64_encode_string_url(in, in_len, out, out_max - 1); + n = lws_b64_encode_string_url(in, (int)in_len, out, (int)out_max - 1); if (n < 0) { lwsl_notice("%s: in len %d too large for %d out buf\n", __func__, (int)in_len, (int)out_max); @@ -391,7 +391,7 @@ lws_jws_encode_section(const char *in, size_t in_len, int first, char **p, char *end) { - int n, len = (end - *p) - 1; + int n, len = lws_ptr_diff(end, (*p)) - 1; char *p_entry = *p; if (len < 3) @@ -406,7 +406,7 @@ *p += n; - return (*p) - p_entry; + return lws_ptr_diff((*p), p_entry); } int @@ -542,7 +542,7 @@ /* SHA256/384/512 HMAC */ - h_len = lws_genhmac_size(jose.alg->hmac_type); + h_len = (int)lws_genhmac_size(jose.alg->hmac_type); /* 6) compute HMAC over payload */ @@ -629,7 +629,7 @@ return -1; } - h_len = lws_genhash_size(jose.alg->hash_type); + h_len = (int)lws_genhash_size(jose.alg->hash_type); if (lws_genecdsa_create(&ecdsactx, context, NULL)) { lwsl_notice("%s: lws_genrsa_public_decrypt_create\n", @@ -696,10 +696,10 @@ struct lws_jws_map map_b64; int n; - if (lws_jws_b64_compact_map(in, len, &map_b64) < 0) + if (lws_jws_b64_compact_map(in, (int)len, &map_b64) < 0) return -1; - n = lws_jws_compact_decode(in, len, map, &map_b64, temp, temp_len); + n = lws_jws_compact_decode(in, (int)len, map, &map_b64, temp, temp_len); if (n > 3 || n < 0) return -1; @@ -727,7 +727,8 @@ struct lws_context *context, char *temp, int *temp_len) { - if (lws_jws_json_parse(jws, (const uint8_t *)in, len, temp, temp_len)) { + if (lws_jws_json_parse(jws, (const uint8_t *)in, + (int)len, temp, temp_len)) { lwsl_err("%s: lws_jws_json_parse failed\n", __func__); return -1; @@ -933,12 +934,303 @@ lws_strnncpy(compact + n, jws->map_b64.buf[LJWS_JOSE], jws->map_b64.len[LJWS_JOSE], len - n); n += strlen(compact + n); + if (n >= len - 1) + return 1; + compact[n++] = '.'; lws_strnncpy(compact + n, jws->map_b64.buf[LJWS_PYLD], jws->map_b64.len[LJWS_PYLD], len - n); n += strlen(compact + n); + if (n >= len - 1) + return 1; + compact[n++] = '.'; lws_strnncpy(compact + n, jws->map_b64.buf[LJWS_SIG], jws->map_b64.len[LJWS_SIG], len - n); n += strlen(compact + n); return n >= len - 1; } + +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) +{ + struct lws_tokenize ts; + struct lws_jose jose; + int otl = tl, r = 1; + struct lws_jws jws; + size_t n; + + memset(&jws, 0, sizeof(jws)); + lws_jose_init(&jose); + + /* + * Decode the b64.b64[.b64] compact serialization + * blocks + */ + + n = lws_jws_compact_decode(com, (int)len, &jws.map, &jws.map_b64, + temp, &tl); + if (n != 3) { + lwsl_err("%s: concat_map failed: %d\n", __func__, (int)n); + goto bail; + } + + temp += otl - tl; + otl = tl; + + /* + * Parse the JOSE header + */ + + if (lws_jws_parse_jose(&jose, jws.map.buf[LJWS_JOSE], + jws.map.len[LJWS_JOSE], temp, &tl) < 0) { + lwsl_err("%s: JOSE parse failed\n", __func__); + goto bail; + } + + /* + * Insist to see an alg in there that we list as acceptable + */ + + lws_tokenize_init(&ts, alg_list, LWS_TOKENIZE_F_COMMA_SEP_LIST | + LWS_TOKENIZE_F_RFC7230_DELIMS); + n = strlen(jose.alg->alg); + + do { + ts.e = lws_tokenize(&ts); + if (ts.e == LWS_TOKZE_TOKEN && ts.token_len == n && + !strncmp(jose.alg->alg, ts.token, ts.token_len)) + break; + } while (ts.e != LWS_TOKZE_ENDED); + + if (ts.e != LWS_TOKZE_TOKEN) { + lwsl_err("%s: JOSE using alg %s (accepted: %s)\n", __func__, + jose.alg->alg, alg_list); + goto bail; + } + + /* we liked the alg... now how about the crypto? */ + + if (lws_jws_sig_confirm(&jws.map_b64, &jws.map, jwk, ctx) < 0) { + lwsl_notice("%s: confirm JWT sig failed\n", + __func__); + goto bail; + } + + /* yeah, it's validated... see about copying it out */ + + if (*out_len < jws.map.len[LJWS_PYLD] + 1) { + /* we don't have enough room */ + r = 2; + goto bail; + } + + memcpy(out, jws.map.buf[LJWS_PYLD], jws.map.len[LJWS_PYLD]); + *out_len = jws.map.len[LJWS_PYLD]; + out[jws.map.len[LJWS_PYLD]] = '\0'; + + r = 0; + +bail: + lws_jws_destroy(&jws); + lws_jose_destroy(&jose); + + return r; +} + +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, ...) +{ + int n, r = 1, otl = tl; + struct lws_jose jose; + struct lws_jws jws; + va_list ap; + char *q; + + lws_jws_init(&jws, jwk, ctx); + lws_jose_init(&jose); + + if (lws_gencrypto_jws_alg_to_definition(alg, &jose.alg)) { + lwsl_err("%s: unknown alg %s\n", __func__, alg); + + goto bail; + } + + /* create JOSE header, also needed for output */ + + if (lws_jws_alloc_element(&jws.map, LJWS_JOSE, temp, &tl, + strlen(alg) + 10, 0)) { + lwsl_err("%s: temp space too small\n", __func__); + return 1; + } + + jws.map.len[LJWS_JOSE] = lws_snprintf((char *)jws.map.buf[LJWS_JOSE], + tl, "{\"alg\":\"%s\"}", alg); + + temp += otl - tl; + otl = tl; + + va_start(ap, format); + n = vsnprintf(NULL, 0, format, ap); + va_end(ap); + if (n + 2 >= tl) + goto bail; + + q = lws_malloc(n + 2, __func__); + if (!q) + goto bail; + + va_start(ap, format); + vsnprintf(q, n + 2, format, ap); + va_end(ap); + + /* add the plaintext from stdin to the map and a b64 version */ + + jws.map.buf[LJWS_PYLD] = q; + jws.map.len[LJWS_PYLD] = n; + + if (lws_jws_encode_b64_element(&jws.map_b64, LJWS_PYLD, temp, &tl, + jws.map.buf[LJWS_PYLD], + jws.map.len[LJWS_PYLD])) + goto bail1; + + temp += otl - tl; + otl = tl; + + /* add the b64 JOSE header to the b64 map */ + + if (lws_jws_encode_b64_element(&jws.map_b64, LJWS_JOSE, temp, &tl, + jws.map.buf[LJWS_JOSE], + jws.map.len[LJWS_JOSE])) + goto bail1; + + temp += otl - tl; + otl = tl; + + /* prepare the space for the b64 signature in the map */ + + if (lws_jws_alloc_element(&jws.map_b64, LJWS_SIG, temp, &tl, + lws_base64_size(LWS_JWE_LIMIT_KEY_ELEMENT_BYTES), + 0)) + goto bail1; + + /* sign the plaintext */ + + n = lws_jws_sign_from_b64(&jose, &jws, + (char *)jws.map_b64.buf[LJWS_SIG], + jws.map_b64.len[LJWS_SIG]); + if (n < 0) + goto bail1; + + /* set the actual b64 signature size */ + jws.map_b64.len[LJWS_SIG] = n; + + /* create the compact JWS representation */ + if (lws_jws_write_compact(&jws, out, *out_len)) + goto bail1; + + *out_len = strlen(out); + + r = 0; + +bail1: + lws_free(q); + +bail: + jws.map.buf[LJWS_PYLD] = NULL; + jws.map.len[LJWS_PYLD] = 0; + lws_jws_destroy(&jws); + lws_jose_destroy(&jose); + + return r; +} + +int +lws_jwt_token_sanity(const char *in, size_t in_len, + const char *iss, const char *aud, + const char *csrf_in, + char *sub, size_t sub_len, unsigned long *expiry_unix_time) +{ + unsigned long now = lws_now_secs(), exp; + const char *cp; + size_t len; + + /* + * It has our issuer? + */ + + if (lws_json_simple_strcmp(in, in_len, "\"iss\":", iss)) { + lwsl_notice("%s: iss mismatch\n", __func__); + return 1; + } + + /* + * ... it is indended for us to consume? (this is set + * to the public base url for this sai instance) + */ + if (lws_json_simple_strcmp(in, in_len, "\"aud\":", aud)) { + lwsl_notice("%s: aud mismatch\n", __func__); + return 1; + } + + /* + * ...it's not too early for it? + */ + cp = lws_json_simple_find(in, in_len, "\"nbf\":", &len); + if (!cp || (unsigned long)atol(cp) > now) { + lwsl_notice("%s: nbf fail\n", __func__); + return 1; + } + + /* + * ... and not too late for it? + */ + cp = lws_json_simple_find(in, in_len, "\"exp\":", &len); + exp = (unsigned long)atol(cp); + if (!cp || (unsigned long)atol(cp) < now) { + lwsl_notice("%s: exp fail %lu vs %lu\n", __func__, + cp ? (unsigned long)atol(cp) : 0, now); + return 1; + } + + /* + * Caller cares about subject? Then we must have it, and it can't be + * empty. + */ + + if (sub) { + cp = lws_json_simple_find(in, in_len, "\"sub\":", &len); + if (!cp || !len) { + lwsl_notice("%s: missing subject\n", __func__); + return 1; + } + lws_strnncpy(sub, cp, len, sub_len); + } + + /* + * If caller has been told a Cross Site Request Forgery (CSRF) nonce, + * require this JWT to express the same CSRF... this makes generated + * links for dangerous privileged auth'd actions expire with the JWT + * that was accessing the site when the links were generated. And it + * leaves an attacker not knowing what links to synthesize unless he + * can read the token or pages generated with it. + * + * Using this is very good for security, but it implies you must refresh + * generated pages still when the auth token is expiring (and the user + * must log in again). + */ + + if (csrf_in && + lws_json_simple_strcmp(in, in_len, "\"csrf\":", csrf_in)) { + lwsl_notice("%s: csrf mismatch\n", __func__); + return 1; + } + + if (expiry_unix_time) + *expiry_unix_time = exp; + + return 0; +} diff -Nru libwebsockets-4.0.20/lib/misc/CMakeLists.txt libwebsockets-4.1.6/lib/misc/CMakeLists.txt --- libwebsockets-4.0.20/lib/misc/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/misc/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,111 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +list(APPEND SOURCES + misc/base64-decode.c + misc/lws-ring.c) + +if (LWS_WITH_FTS) + list(APPEND SOURCES + misc/fts/trie.c + misc/fts/trie-fd.c) +endif() + +if (LWS_WITH_DISKCACHE) + list(APPEND SOURCES + misc/diskcache.c) +endif() + +if (LWS_WITH_STRUCT_JSON) + list(APPEND SOURCES + misc/lws-struct-lejp.c) +endif() + +if (LWS_WITH_STRUCT_SQLITE3) + list(APPEND SOURCES + misc/lws-struct-sqlite.c) +endif() + +if (LWS_WITH_FSMOUNT AND ${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + list(APPEND SOURCES misc/fsmount.c) +endif() + +if (LWS_WITH_DIR) + list(APPEND SOURCES misc/dir.c) +endif() + +if (LWS_WITH_THREADPOOL AND LWS_HAVE_PTHREAD_H) + list(APPEND SOURCES misc/threadpool/threadpool.c) +endif() + +if (LWS_WITH_PEER_LIMITS) + list(APPEND SOURCES + misc/peer-limits.c) +endif() + +if (LWS_WITH_LWSAC) + list(APPEND SOURCES + misc/lwsac/lwsac.c) + if (NOT LWS_PLAT_FREERTOS) + list(APPEND SOURCES + misc/lwsac/cached-file.c) + endif() +endif() + +if (NOT LWS_WITHOUT_BUILTIN_SHA1) + list(APPEND SOURCES + misc/sha-1.c) +endif() + +if (LWS_WITH_LEJP) + list(APPEND SOURCES + misc/lejp.c) +endif() + +if (UNIX) + if (NOT LWS_HAVE_GETIFADDRS) + list(APPEND HDR_PRIVATE misc/getifaddrs.h) + list(APPEND SOURCES misc/getifaddrs.c) + endif() +endif() + +if (NOT WIN32 AND NOT LWS_WITHOUT_DAEMONIZE) + list(APPEND SOURCES + misc/daemonize.c) +endif() + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() diff -Nru libwebsockets-4.0.20/lib/misc/dir.c libwebsockets-4.1.6/lib/misc/dir.c --- libwebsockets-4.0.20/lib/misc/dir.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/misc/dir.c 2020-12-01 17:40:26.000000000 +0000 @@ -34,53 +34,31 @@ #include #include -#if defined(LWS_WITH_LIBUV) && UV_VERSION_MAJOR > 0 - -int -lws_dir(const char *dirpath, void *user, lws_dir_callback_function cb) -{ - struct lws_dir_entry lde; - uv_dirent_t dent; - uv_fs_t req; - int ret = 1, ir; - uv_loop_t loop; - - ir = uv_loop_init(&loop); - if (ir) { - lwsl_err("%s: loop init failed %d\n", __func__, ir); - return 1; - } - - ir = uv_fs_scandir(&loop, &req, dirpath, 0, NULL); - if (ir < 0) { - lwsl_err("Scandir on %s failed, errno %d\n", dirpath, LWS_ERRNO); - ret = 2; - goto bail; - } - - while (uv_fs_scandir_next(&req, &dent) != UV_EOF) { - lde.name = dent.name; - lde.type = (int)dent.type; - if (cb(dirpath, user, &lde)) - goto bail1; - } +#include +#if defined(WIN32) +#include +#define read _read +#define open _open +#define close _close +#define write _write +#define mkdir(x,y) _mkdir(x) +#define rmdir _rmdir +#define unlink _unlink +#define HAVE_STRUCT_TIMESPEC +#if defined(pid_t) +#undef pid_t +#endif +#endif /* win32 */ - ret = 0; +#define COMBO_SIZEOF 512 -bail1: - uv_fs_req_cleanup(&req); -bail: - while (uv_loop_close(&loop)) - ; - - return ret; -} +#if !defined(LWS_PLAT_FREERTOS) +#if defined(WIN32) +#include "../../win32port/dirent/dirent-win32.h" #else - -#if !defined(_WIN32) && !defined(LWS_PLAT_FREERTOS) - #include +#endif static int filter(const struct dirent *ent) { @@ -90,12 +68,62 @@ return 1; } + +#if !defined(WIN32) +static char csep = '/'; +#else +static char csep = '\\'; +#endif + +static void +lws_dir_via_stat(char *combo, size_t l, const char *path, struct lws_dir_entry *lde) +{ + struct stat s; + + lws_strncpy(combo + l, path, COMBO_SIZEOF - l); + + lde->type = LDOT_UNKNOWN; + + if (!stat(combo, &s)) { + switch (s.st_mode & S_IFMT) { + case S_IFBLK: + lde->type = LDOT_BLOCK; + break; + case S_IFCHR: + lde->type = LDOT_CHAR; + break; + case S_IFDIR: + lde->type = LDOT_DIR; + break; + case S_IFIFO: + lde->type = LDOT_FIFO; + break; +#if !defined(WIN32) + case S_IFLNK: + lde->type = LDOT_LINK; + break; +#endif + case S_IFREG: + lde->type = LDOT_FILE; + break; + default: + break; + } + } +} + int lws_dir(const char *dirpath, void *user, lws_dir_callback_function cb) { struct lws_dir_entry lde; struct dirent **namelist; int n, i, ret = 1; + char combo[COMBO_SIZEOF]; + size_t l; + + l = lws_snprintf(combo, COMBO_SIZEOF - 2, "%s", dirpath); + combo[l++] = csep; + combo[l] = '\0'; n = scandir((char *)dirpath, &namelist, filter, alphasort); if (n < 0) { @@ -104,6 +132,7 @@ } for (i = 0; i < n; i++) { + unsigned int type = namelist[i]->d_type; if (strchr(namelist[i]->d_name, '~')) goto skip; lde.name = namelist[i]->d_name; @@ -114,61 +143,33 @@ */ #if defined(__sun) - struct stat s; - stat(namelist[i]->d_name, &s); - switch (s.st_mode) { - case S_IFBLK: - lde.type = LDOT_BLOCK; - break; - case S_IFCHR: - lde.type = LDOT_CHAR; - break; - case S_IFDIR: - lde.type = LDOT_DIR; - break; - case S_IFIFO: - lde.type = LDOT_FIFO; - break; - case S_IFLNK: - lde.type = LDOT_LINK; - break; - case S_IFREG: - lde.type = LDOT_FILE; - break; - default: - lde.type = LDOT_UNKNOWN; - break; - } + lws_dir_via_stat(combo, l, namelist[i]->d_name, &lde); #else - switch (namelist[i]->d_type) { - case DT_BLK: + /* + * XFS on Linux doesn't fill in d_type at all, always zero. + */ + + if (DT_BLK != DT_UNKNOWN && type == DT_BLK) lde.type = LDOT_BLOCK; - break; - case DT_CHR: + else if (DT_CHR != DT_UNKNOWN && type == DT_CHR) lde.type = LDOT_CHAR; - break; - case DT_DIR: + else if (DT_DIR != DT_UNKNOWN && type == DT_DIR) lde.type = LDOT_DIR; - break; - case DT_FIFO: + else if (DT_FIFO != DT_UNKNOWN && type == DT_FIFO) lde.type = LDOT_FIFO; - break; - case DT_LNK: + else if (DT_LNK != DT_UNKNOWN && type == DT_LNK) lde.type = LDOT_LINK; - break; - case DT_REG: + else if (DT_REG != DT_UNKNOWN && type == DT_REG) lde.type = LDOT_FILE; - break; - case DT_SOCK: + else if (DT_SOCK != DT_UNKNOWN && type == DT_SOCK) lde.type = LDOTT_SOCKET; - break; - default: + else { lde.type = LDOT_UNKNOWN; - break; + lws_dir_via_stat(combo, l, namelist[i]->d_name, &lde); } #endif if (cb(dirpath, user, &lde)) { - while (i++ < n) + while (++i < n) free(namelist[i]); goto bail; } @@ -184,7 +185,193 @@ return ret; } +/* + * Check filename against one globby filter + * + * We can support things like "*.rpm" + */ + +static int +lws_dir_glob_check(const char *nm, const char *filt) +{ + while (*nm) { + if (*filt == '*') { + if (!strcmp(nm, filt + 1)) + return 1; + } else { + if (*nm != *filt) + return 0; + filt++; + } + nm++; + } + + return 0; +} + +/* + * We get passed a single filter string, like "*.txt" or "mydir/\*.rpm" or so. + */ + +int +lws_dir_glob_cb(const char *dirpath, void *user, struct lws_dir_entry *lde) +{ + lws_dir_glob_t *filter = (lws_dir_glob_t*)user; + char path[384]; + + if (!strcmp(lde->name, ".") || !strcmp(lde->name, "..")) + return 0; + + if (lde->type == LDOT_DIR) + return 0; + + if (lws_dir_glob_check(lde->name, filter->filter)) { + lws_snprintf(path, sizeof(path), "%s%c%s", dirpath, csep, + lde->name); + filter->cb(filter->user, path); + } + + return 0; +} + +int +lws_dir_rm_rf_cb(const char *dirpath, void *user, struct lws_dir_entry *lde) +{ + char path[384]; + + if (!strcmp(lde->name, ".") || !strcmp(lde->name, "..")) + return 0; + + lws_snprintf(path, sizeof(path), "%s%c%s", dirpath, csep, lde->name); + + if (lde->type == LDOT_DIR) { +#if !defined(WIN32) && !defined(_WIN32) && !defined(__COVERITY__) + char dummy[8]; + /* + * hm... eg, recursive dir symlinks can show up a LDOT_DIR + * here. If it's a symlink, don't recurse into it. + * + * Notice we immediately discard dummy without looking in it. + * There is no way to get into trouble from its lack of NUL + * termination in dummy[]. We just wanted to know if it was + * a symlink at all. + * + * Hide this from Coverity since it flags any use of readlink() + * even if safe. + */ + if (readlink(path, dummy, sizeof(dummy)) < 0) +#endif + lws_dir(path, NULL, lws_dir_rm_rf_cb); + + if (rmdir(path)) + lwsl_warn("%s: rmdir %s failed %d\n", __func__, path, errno); + } else { + if (unlink(path)) { +#if defined(WIN32) + SetFileAttributesA(path, FILE_ATTRIBUTE_NORMAL); + if (unlink(path)) #else -#error "If you want lws_dir on windows, you need libuv" + if (rmdir(path)) #endif + lwsl_warn("%s: unlink %s failed %d (type %d)\n", + __func__, path, errno, lde->type); + } + } + + return 0; +} + + +#endif + +#if defined(LWS_WITH_PLUGINS_API) + +struct lws_plugins_args { + struct lws_plugin **pplugin; + const char *_class; + const char *filter; + each_plugin_cb_t each; + void *each_user; +}; + +static int +lws_plugins_dir_cb(const char *dirpath, void *user, struct lws_dir_entry *lde) +{ + struct lws_plugins_args *pa = (struct lws_plugins_args *)user; + char path[256], base[64], *q = base; + const char *p; + + if (strlen(lde->name) < 7) + return 0; + + /* + * The actual plugin names for protocol plugins look like + * "libprotocol_lws_ssh_base.so" and for event libs + * "libwebsockets-evlib_ev.so"... to recover the base name of + * "lws_ssh_base" and "evlib_ev" we strip from the left to after the + * first _ or -, and then truncate at the first . + */ + + p = lde->name; + while (*p && *p != '_' && *p != '-') + p++; + if (!*p) + return 0; + p++; + while (*p && *p != '.' && lws_ptr_diff(q, base) < (int)sizeof(base) - 1) + *q++ = *p++; + *q = '\0'; + + /* if he's given a filter, only match if base matches it */ + if (pa->filter && strcmp(base, pa->filter)) + return 0; + + lws_snprintf(path, sizeof(path) - 1, "%s/%s", dirpath, lde->name); + lwsl_notice(" %s\n", path); + + return !lws_plat_dlopen(pa->pplugin, path, base, pa->_class, + pa->each, pa->each_user); +} + +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) +{ + struct lws_plugins_args pa; + + pa.pplugin = pplugin; + pa._class = _class; + pa.each = each; + pa.each_user = each_user; + pa.filter = filter; + + while (d && *d) { + lws_dir(*d, &pa, lws_plugins_dir_cb); + d++; + } + + return 0; +} + +int +lws_plugins_destroy(struct lws_plugin **pplugin, each_plugin_cb_t each, + void *each_user) +{ + struct lws_plugin *p = *pplugin, *p1; + + while (p) { + if (each) + each(p, each_user); + lws_plat_destroy_dl(p); + p1 = p->list; + p->list = NULL; + lws_free(p); + p = p1; + } + + *pplugin = NULL; + + return 0; +} #endif diff -Nru libwebsockets-4.0.20/lib/misc/lejp.c libwebsockets-4.1.6/lib/misc/lejp.c --- libwebsockets-4.0.20/lib/misc/lejp.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/misc/lejp.c 2020-12-01 17:40:26.000000000 +0000 @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2020 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -77,6 +77,7 @@ ctx->st[0].b = 0; ctx->sp = 0; ctx->ipos = 0; + ctx->outer_array = 0; ctx->path_match = 0; ctx->path_stride = 0; ctx->path[0] = '\0'; @@ -229,13 +230,15 @@ * unused. */ +static const char esc_char[] = "\"\\/bfnrt"; +static const char esc_tran[] = "\"\\/\b\f\n\r\t"; +static const char tokens[] = "rue alse ull "; + int lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len) { - unsigned char c, n, s, ret = LEJP_REJECT_UNKNOWN; - static const char esc_char[] = "\"\\/bfnrt"; - static const char esc_tran[] = "\"\\/\b\f\n\r\t"; - static const char tokens[] = "rue alse ull "; + unsigned char c, n, s; + int ret = LEJP_REJECT_UNKNOWN; if (!ctx->sp && !ctx->pst[ctx->pst_sp].ppos) ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_START); @@ -263,18 +266,37 @@ switch (s) { case LEJP_IDLE: + if (!ctx->sp && c == '[') { + /* push */ + ctx->outer_array = 1; + ctx->st[ctx->sp].s = LEJP_MP_ARRAY_END; + c = LEJP_MP_VALUE; + ctx->path[ctx->pst[ctx->pst_sp].ppos++] = '['; + ctx->path[ctx->pst[ctx->pst_sp].ppos++] = ']'; + ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0'; + if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_ARRAY_START)) + goto reject_callback; + ctx->i[ctx->ipos++] = 0; + if (ctx->ipos > LWS_ARRAY_SIZE(ctx->i)) { + ret = LEJP_REJECT_MP_DELIM_ISTACK; + goto reject; + } + goto add_stack_level; + } if (c != '{') { ret = LEJP_REJECT_IDLE_NO_BRACE; goto reject; } - if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_OBJECT_START)) { - ret = LEJP_REJECT_CALLBACK; - goto reject; - } + if (ctx->pst[ctx->pst_sp].callback(ctx, + LEJPCB_OBJECT_START)) + goto reject_callback; ctx->st[ctx->sp].s = LEJP_MEMBERS; break; case LEJP_MEMBERS: if (c == '}') { + if (ctx->sp >= 1) + goto pop_level; + ctx->st[ctx->sp].s = LEJP_IDLE; ret = LEJP_REJECT_MEMBERS_NO_CLOSE; goto reject; @@ -300,10 +322,8 @@ if (ctx->st[ctx->sp - 1].s != LEJP_MP_DELIM) { ctx->buf[ctx->npos] = '\0'; if (ctx->pst[ctx->pst_sp].callback(ctx, - LEJPCB_VAL_STR_END) < 0) { - ret = LEJP_REJECT_CALLBACK; - goto reject; - } + LEJPCB_VAL_STR_END) < 0) + goto reject_callback; } /* pop */ ctx->sp--; @@ -346,10 +366,10 @@ ctx->uni |= c - '0'; else if (c >= 'a' && c <= 'f') - ctx->uni = c - 'a' + 10; + ctx->uni |= c - 'a' + 10; else if (c >= 'A' && c <= 'F') - ctx->uni = c - 'A' + 10; + ctx->uni |= c - 'A' + 10; else { ret = LEJP_REJECT_ILLEGAL_HEX; goto reject; @@ -409,10 +429,8 @@ ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0'; lejp_check_path_match(ctx); - if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_PAIR_NAME)) { - ret = LEJP_REJECT_CALLBACK; - goto reject; - } + if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_PAIR_NAME)) + goto reject_callback; break; case LEJP_MP_VALUE: @@ -430,10 +448,9 @@ c = LEJP_MP_STRING; ctx->npos = 0; ctx->buf[0] = '\0'; - if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_VAL_STR_START)) { - ret = LEJP_REJECT_CALLBACK; - goto reject; - } + if (ctx->pst[ctx->pst_sp].callback(ctx, + LEJPCB_VAL_STR_START)) + goto reject_callback; goto add_stack_level; case '{': @@ -441,10 +458,9 @@ ctx->st[ctx->sp].s = LEJP_MP_COMMA_OR_END; c = LEJP_MEMBERS; lejp_check_path_match(ctx); - if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_OBJECT_START)) { - ret = LEJP_REJECT_CALLBACK; - goto reject; - } + if (ctx->pst[ctx->pst_sp].callback(ctx, + LEJPCB_OBJECT_START)) + goto reject_callback; ctx->path_match = 0; goto add_stack_level; @@ -455,10 +471,8 @@ ctx->path[ctx->pst[ctx->pst_sp].ppos++] = '['; ctx->path[ctx->pst[ctx->pst_sp].ppos++] = ']'; ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0'; - if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_ARRAY_START)) { - ret = LEJP_REJECT_CALLBACK; - goto reject; - } + if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_ARRAY_START)) + goto reject_callback; ctx->i[ctx->ipos++] = 0; if (ctx->ipos > LWS_ARRAY_SIZE(ctx->i)) { ret = LEJP_REJECT_MP_DELIM_ISTACK; @@ -479,7 +493,8 @@ } /* drop the path [n] bit */ if (ctx->sp) { - ctx->pst[ctx->pst_sp].ppos = ctx->st[ctx->sp - 1].p; + ctx->pst[ctx->pst_sp].ppos = + ctx->st[ctx->sp - 1].p; ctx->ipos = ctx->st[ctx->sp - 1].i; } ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0'; @@ -490,6 +505,10 @@ * smaller than the matching point */ ctx->path_match = 0; + if (ctx->outer_array && !ctx->sp) { /* ended on ] */ + n = LEJPCB_ARRAY_END; + goto completed; + } goto array_end; case 't': /* true */ @@ -559,15 +578,13 @@ ctx->buf[ctx->npos] = '\0'; if (ctx->f & LEJP_SEEN_POINT) { - if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_VAL_NUM_FLOAT)) { - ret = LEJP_REJECT_CALLBACK; - goto reject; - } + if (ctx->pst[ctx->pst_sp].callback(ctx, + LEJPCB_VAL_NUM_FLOAT)) + goto reject_callback; } else { - if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_VAL_NUM_INT)) { - ret = LEJP_REJECT_CALLBACK; - goto reject; - } + if (ctx->pst[ctx->pst_sp].callback(ctx, + LEJPCB_VAL_NUM_INT)) + goto reject_callback; } /* then this is the post-number character, loop */ @@ -595,25 +612,22 @@ case 3: ctx->buf[0] = '1'; ctx->buf[1] = '\0'; - if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_VAL_TRUE)) { - ret = LEJP_REJECT_CALLBACK; - goto reject; - } + if (ctx->pst[ctx->pst_sp].callback(ctx, + LEJPCB_VAL_TRUE)) + goto reject_callback; break; case 8: ctx->buf[0] = '0'; ctx->buf[1] = '\0'; - if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_VAL_FALSE)) { - ret = LEJP_REJECT_CALLBACK; - goto reject; - } + if (ctx->pst[ctx->pst_sp].callback(ctx, + LEJPCB_VAL_FALSE)) + goto reject_callback; break; case 12: ctx->buf[0] = '\0'; - if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_VAL_NULL)) { - ret = LEJP_REJECT_CALLBACK; - goto reject; - } + if (ctx->pst[ctx->pst_sp].callback(ctx, + LEJPCB_VAL_NULL)) + goto reject_callback; break; } ctx->st[ctx->sp].s = LEJP_MP_COMMA_OR_END; @@ -636,7 +650,7 @@ ctx->pst[ctx->pst_sp].ppos = ctx->st[ctx->sp - 1].p; ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0'; if (ctx->path_match && - ctx->pst[ctx->pst_sp].ppos <= ctx->path_match_len) + ctx->pst[ctx->pst_sp].ppos <= ctx->path_match_len) /* * we shrank the path to be * smaller than the matching point @@ -652,7 +666,7 @@ break; } if (c == ']') { - if (!ctx->sp) { /* JSON can't end on ] */ + if (!ctx->sp) { ret = LEJP_REJECT_MP_C_OR_E_UNDERF; goto reject; } @@ -662,66 +676,68 @@ ret = LEJP_REJECT_MP_C_OR_E_NOTARRAY; goto reject; } + /* drop the path [n] bit */ if (ctx->sp) { - ctx->pst[ctx->pst_sp].ppos = ctx->st[ctx->sp - 1].p; + ctx->pst[ctx->pst_sp].ppos = + ctx->st[ctx->sp - 1].p; ctx->ipos = ctx->st[ctx->sp - 1].i; } ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0'; if (ctx->path_match && - ctx->pst[ctx->pst_sp].ppos <= ctx->path_match_len) + ctx->pst[ctx->pst_sp].ppos <= ctx->path_match_len) /* * we shrank the path to be * smaller than the matching point */ ctx->path_match = 0; + if (ctx->outer_array && !ctx->sp) { /* ended on ] */ + n = LEJPCB_ARRAY_END; + goto completed; + } + /* do LEJP_MP_ARRAY_END processing */ goto redo_character; } - if (c == '}') { - if (!ctx->sp) { - lejp_check_path_match(ctx); - if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_OBJECT_END)) { - ret = LEJP_REJECT_CALLBACK; - goto reject; - } - if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_COMPLETE)) - goto reject; - else - /* done, return unused amount */ - return len; - } - - /* pop */ - - ctx->sp--; - if (ctx->sp) { - ctx->pst[ctx->pst_sp].ppos = - ctx->st[ctx->sp].p; - ctx->ipos = ctx->st[ctx->sp].i; - } - ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0'; - if (ctx->path_match && - ctx->pst[ctx->pst_sp].ppos <= - ctx->path_match_len) - /* - * we shrank the path to be - * smaller than the matching point - */ - ctx->path_match = 0; - + if (c != '}') { + ret = LEJP_REJECT_MP_C_OR_E_NEITHER; + goto reject; + } + if (!ctx->sp) { + n = LEJPCB_OBJECT_END; +completed: lejp_check_path_match(ctx); - if (ctx->pst[ctx->pst_sp].callback(ctx, - LEJPCB_OBJECT_END)) { - ret = LEJP_REJECT_CALLBACK; - goto reject; - } - break; + if (ctx->pst[ctx->pst_sp].callback(ctx, n) || + ctx->pst[ctx->pst_sp].callback(ctx, + LEJPCB_COMPLETE)) + goto reject_callback; + + /* done, return unused amount */ + return len; } - ret = LEJP_REJECT_MP_C_OR_E_NEITHER; - goto reject; + /* pop */ +pop_level: + ctx->sp--; + if (ctx->sp) { + ctx->pst[ctx->pst_sp].ppos = ctx->st[ctx->sp].p; + ctx->ipos = ctx->st[ctx->sp].i; + } + ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0'; + if (ctx->path_match && + ctx->pst[ctx->pst_sp].ppos <= ctx->path_match_len) + /* + * we shrank the path to be + * smaller than the matching point + */ + ctx->path_match = 0; + + lejp_check_path_match(ctx); + if (ctx->pst[ctx->pst_sp].callback(ctx, + LEJPCB_OBJECT_END)) + goto reject_callback; + break; case LEJP_MP_ARRAY_END: array_end: @@ -732,7 +748,8 @@ ctx->i[ctx->ipos - 1]++; ctx->st[ctx->sp].s = LEJP_MP_VALUE; if (ctx->sp) - ctx->pst[ctx->pst_sp].ppos = ctx->st[ctx->sp - 1].p; + ctx->pst[ctx->pst_sp].ppos = + ctx->st[ctx->sp - 1].p; ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0'; break; } @@ -753,10 +770,9 @@ /* assemble the string value into chunks */ ctx->buf[ctx->npos++] = c; if (ctx->npos == sizeof(ctx->buf) - 1) { - if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_VAL_STR_CHUNK)) { - ret = LEJP_REJECT_CALLBACK; - goto reject; - } + if (ctx->pst[ctx->pst_sp].callback(ctx, + LEJPCB_VAL_STR_CHUNK)) + goto reject_callback; ctx->npos = 0; } continue; @@ -798,6 +814,10 @@ return LEJP_CONTINUE; + +reject_callback: + ret = LEJP_REJECT_CALLBACK; + reject: ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_FAILED); return ret; diff -Nru libwebsockets-4.0.20/lib/misc/lws-struct-lejp.c libwebsockets-4.1.6/lib/misc/lws-struct-lejp.c --- libwebsockets-4.0.20/lib/misc/lws-struct-lejp.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/misc/lws-struct-lejp.c 2020-12-01 17:40:26.000000000 +0000 @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2020 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -32,18 +32,62 @@ { lws_struct_args_t *a = (lws_struct_args_t *)ctx->user; const lws_struct_map_t *map = a->map_st[ctx->pst_sp]; - size_t n = a->map_entries_st[ctx->pst_sp]; + size_t n = a->map_entries_st[ctx->pst_sp], imp = 0; lejp_callback cb = map->lejp_cb; + if (reason == LEJPCB_PAIR_NAME && strcmp(ctx->path, "schema")) { + /* + * If not "schema", the schema is implicit rather than + * explicitly given, ie, he just goes ahead and starts using + * member names that imply a particular type. For example, he + * may have an implicit type normally, and a different one for + * exceptions that just starts using "error-message" or whatever + * and we can understand that's the exception type now. + * + * Let's look into each of the maps in the top level array + * and match the first one that mentions the name he gave here, + * and bind to the associated type / create a toplevel object + * of that type. + */ + + while (n--) { + const lws_struct_map_t *child = map->child_map; + int m, child_members = (int)map->child_map_size; + + for (m = 0; m < child_members; m++) { + if (!strcmp(ctx->path, child->colname)) { + /* + * We matched on him... map is pointing + * to the right toplevel type, let's + * just pick up from there as if we + * matched the explicit schema name... + */ + ctx->path_match = 1; + imp = 1; + goto matched; + } + } + map++; + } + lwsl_notice("%s: can't match implicit schema %s\n", + __func__, ctx->path); + + return -1; + } + if (reason != LEJPCB_VAL_STR_END || ctx->path_match != 1) return 0; + /* If "schema", then look for a matching name in the map array */ + while (n--) { if (strcmp(ctx->buf, map->colname)) { map++; continue; } +matched: + a->dest = lwsac_use_zero(&a->ac, map->aux, a->ac_block_size); if (!a->dest) { lwsl_err("%s: OOT\n", __func__); @@ -62,6 +106,12 @@ a->map_st[ctx->pst_sp] = map->child_map; a->map_entries_st[ctx->pst_sp] = map->child_map_size; + // lwsl_notice("%s: child map ofs_clist %d\n", __func__, + // (int)a->map_st[ctx->pst_sp]->ofs_clist); + + if (imp) + return cb(ctx, reason); + return 0; } @@ -104,6 +154,8 @@ } if (reason == LEJPCB_ARRAY_START) { + if (!ctx->path_match) + lwsl_err("%s: ARRAY_START with ctx->path_match 0\n", __func__); map = &args->map_st[ctx->pst_sp][ctx->path_match - 1]; if (map->type == LSMT_LIST) @@ -115,30 +167,47 @@ if (ctx->pst_sp) pmap = &args->map_st[ctx->pst_sp - 1] [ctx->pst[ctx->pst_sp - 1].path_match - 1]; - map = &args->map_st[ctx->pst_sp][ctx->path_match - 1]; - n = args->map_entries_st[ctx->pst_sp]; if (reason == LEJPCB_OBJECT_START) { - if (map->type != LSMT_CHILD_PTR) { + if (!ctx->path_match) { ctx->pst[ctx->pst_sp].user = NULL; return 0; } - pmap = map; - lws_struct_lejp_push(ctx, args, map, NULL); map = &args->map_st[ctx->pst_sp][ctx->path_match - 1]; n = args->map_entries_st[ctx->pst_sp]; + + if (map->type != LSMT_CHILD_PTR && map->type != LSMT_LIST) { + ctx->pst[ctx->pst_sp].user = NULL; + + return 0; + } + pmap = map; + + lws_struct_lejp_push(ctx, args, map, NULL); } - if (reason == LEJPCB_OBJECT_END && pmap && pmap->type == LSMT_CHILD_PTR) - lejp_parser_pop(ctx); + if (reason == LEJPCB_OBJECT_END && pmap) { + if (pmap->type == LSMT_CHILD_PTR) + lejp_parser_pop(ctx); + + if (ctx->pst_sp) + pmap = &args->map_st[ctx->pst_sp - 1] + [ctx->pst[ctx->pst_sp - 1].path_match - 1]; + } + + if (!ctx->path_match) + return 0; + + map = &args->map_st[ctx->pst_sp][ctx->path_match - 1]; + n = args->map_entries_st[ctx->pst_sp]; if (map->type == LSMT_SCHEMA) { while (n--) { - if (strcmp(map->colname, ctx->buf)) { + if (strncmp(map->colname, ctx->buf, ctx->npos)) { map++; continue; } @@ -157,7 +226,9 @@ return 0; } - lwsl_notice("%s: unknown schema\n", __func__); + lwsl_notice("%s: unknown schema %.*s, tried %d\n", __func__, + ctx->npos, ctx->buf, + (int)args->map_entries_st[ctx->pst_sp]); goto cleanup; } @@ -174,6 +245,9 @@ map = &args->map_st[ctx->pst_sp - 1][ctx->path_match - 1]; n = args->map_entries_st[ctx->pst_sp - 1]; + if (!ctx->pst_sp) + return 0; + if (pmap->type != LSMT_LIST && pmap->type != LSMT_CHILD_PTR) return 1; @@ -193,12 +267,13 @@ return 1; } - lwsl_notice("%s: created child object size %d\n", __func__, - (int)pmap->aux); + lwsl_info("%s: created '%s' object size %d\n", __func__, + pmap->colname, (int)pmap->aux); if (pmap->type == LSMT_LIST) { - list = (struct lws_dll2 *)((char *)ctx->pst[ctx->pst_sp].user + - map->ofs_clist); + list = (struct lws_dll2 *) + ((char *)ctx->pst[ctx->pst_sp].user + + pmap->ofs_clist); lws_dll2_add_tail(list, owner); } @@ -395,6 +470,10 @@ int lws_struct_json_init_parse(struct lejp_ctx *ctx, lejp_callback cb, void *user) { + /* + * By default we are looking to match on a toplevel member called + * "schema", against an LSM_SCHEMA + */ if (!cb) cb = lws_struct_schema_only_lejp_cb; lejp_construct(ctx, cb, user, schema, 1); @@ -478,6 +557,10 @@ /* early check if the entry should be elided */ switch (map->type) { + case LSMT_STRING_CHAR_ARRAY: + if (!q) + goto up; + break; case LSMT_STRING_PTR: case LSMT_CHILD_PTR: q = (char *)*(char **)q; @@ -492,6 +575,9 @@ goto up; break; + case LSMT_BLOB_PTR: + goto up; + default: break; } @@ -627,13 +713,15 @@ len--; j = &js->st[++js->sp]; lws_struct_pretty(js, &buf, &len); - budget = lws_snprintf(dbuf, 15, "\"schema\":"); - if (js->flags & LSSERJ_FLAG_PRETTY) - dbuf[budget++] = ' '; - - budget += lws_snprintf(dbuf + budget, - sizeof(dbuf) - budget, - "\"%s\"", map->colname); + if (!(js->flags & LSSERJ_FLAG_OMIT_SCHEMA)) { + budget = lws_snprintf(dbuf, 15, "\"schema\":"); + if (js->flags & LSSERJ_FLAG_PRETTY) + dbuf[budget++] = ' '; + + budget += lws_snprintf(dbuf + budget, + sizeof(dbuf) - budget, + "\"%s\"", map->colname); + } if (js->sp != 1) @@ -645,10 +733,13 @@ j->map_entry = 0; j->obj = js->st[js->sp - 1].obj; j->dllpos = NULL; - /* we're actually at the same level */ - j->subsequent = 1; + if (!(js->flags & LSSERJ_FLAG_OMIT_SCHEMA)) + /* we're actually at the same level */ + j->subsequent = 1; j->idt = 1; break; + default: + break; } switch (map->type) { @@ -671,7 +762,7 @@ * in "used". */ - lws_json_purify((char *)buf, q, len, &used); + lws_json_purify((char *)buf, q, (int)len, &used); m = strlen((const char *)buf); buf += m; len -= m; diff -Nru libwebsockets-4.0.20/lib/misc/lws-struct-sqlite.c libwebsockets-4.1.6/lib/misc/lws-struct-sqlite.c --- libwebsockets-4.0.20/lib/misc/lws-struct-sqlite.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/misc/lws-struct-sqlite.c 2020-12-01 17:40:26.000000000 +0000 @@ -181,9 +181,13 @@ const lws_struct_map_t *schema, lws_dll2_owner_t *o, struct lwsac **ac, int start, int _limit) { - char s[250], where[250]; - lws_struct_args_t a; int limit = _limit < 0 ? -_limit : _limit; + char s[768], results[512], where[250]; + lws_struct_args_t a; + int n, m; + + if (!order) + order = "_lws_idx"; memset(&a, 0, sizeof(a)); a.cb_arg = o; /* lws_dll2_owner tracking query result objects */ @@ -194,17 +198,29 @@ lws_dll2_owner_clear(o); + /* + * Explicitly list the columns instead of use *, so we can skip blobs + */ + + m = 0; + for (n = 0; n < (int)schema->child_map_size; n++) + m += lws_snprintf(&results[m], sizeof(results) - n - 1, + "%s%c", schema->child_map[n].colname, + n + 1 == (int)schema->child_map_size ? ' ' : ','); + where[0] = '\0'; lws_snprintf(where, sizeof(where), " where _lws_idx >= %llu %s", (unsigned long long)start, filter ? filter : ""); - lws_snprintf(s, sizeof(s) - 1, "select * " - "from %s %s order by _lws_idx%s %slimit %d;", - schema->colname, where, order ? order : "", + lws_snprintf(s, sizeof(s) - 1, "select %s " + "from %s %s order by %s %slimit %d;", results, + schema->colname, where, order, _limit < 0 ? "desc " : "", limit); + + if (sqlite3_exec(pdb, s, lws_struct_sq3_deser_cb, &a, NULL) != SQLITE_OK) { - lwsl_err("%s: %s: fail\n", __func__, sqlite3_errmsg(pdb)); + lwsl_err("%s: %s: fail %s\n", __func__, sqlite3_errmsg(pdb), s); lwsac_free(&a.ac); return -1; } @@ -224,7 +240,7 @@ uint32_t idx, void *st) { const lws_struct_map_t *map = schema->child_map; - int n, m, pk = 0, nentries = schema->child_map_size; + int n, m, pk = 0, nentries = schema->child_map_size, nef = 0, did; size_t sql_est = 46 + strlen(schema->colname) + 1; /* "insert into (_lws_idx, ) values (00000001,);" ... * plus the table name */ @@ -233,6 +249,26 @@ char *sql; /* + * Figure out effective number of columns, exluding BLOB. + * + * The first UNSIGNED is a hidden index. Blobs are not handled by + * lws_struct except to create the column in the schema. + */ + + pk = 0; + nef = 0; + for (n = 0; n < nentries; n++) { + if (!pk && map[n].type == LSMT_UNSIGNED) { + pk = 1; + continue; + } + if (map[n].type == LSMT_BLOB_PTR) + continue; + + nef++; + } + + /* * Figure out an estimate for the length of the populated sqlite * command, and then malloc it up */ @@ -273,6 +309,11 @@ sql_est += (p ? lws_sql_purify_len(p) : 0) + 2; break; + case LSMT_BLOB_PTR: + /* we don't deal with blobs actually */ + sql_est -= strlen(map[n].colname) + 2; + break; + default: lwsl_err("%s: unsupported type\n", __func__); assert(0); @@ -292,19 +333,26 @@ * not be specified */ + pk = 0; + did = 0; for (n = 0; n < nentries; n++) { if (!pk && map[n].type == LSMT_UNSIGNED) { pk = 1; continue; } + if (map[n].type == LSMT_BLOB_PTR) + continue; + + did++; m += lws_snprintf(sql + m, sql_est - m, - n == nentries - 1 ? "%s" : "%s, ", + did == nef ? "%s" : "%s, ", map[n].colname); } m += lws_snprintf(sql + m, sql_est - m, ") values(%u, ", idx); pk = 0; + did = 0; for (n = 0; n < nentries; n++) { uint64_t uu64; size_t q; @@ -348,13 +396,18 @@ } sql[m++] = '\''; break; + + case LSMT_BLOB_PTR: + continue; + default: lwsl_err("%s: unsupported type\n", __func__); assert(0); break; } - if (n != nentries - 1) { + did++; + if (did != nef) { if (sql_est - m < 6) return -1; sql[m++] = ','; @@ -365,11 +418,13 @@ lws_snprintf(sql + m, sql_est - m, ");"); n = sqlite3_exec(pdb, sql, NULL, NULL, NULL); - free(sql); if (n != SQLITE_OK) { + lwsl_err("%s\n", sql); + free(sql); lwsl_err("%s: %s: fail\n", __func__, sqlite3_errmsg(pdb)); return -1; } + free(sql); return 0; } @@ -403,7 +458,7 @@ schema->colname); while (map_size--) { - if (map->type > LSMT_STRING_PTR) { + if (map->type > LSMT_STRING_PTR && map->type != LSMT_BLOB_PTR) { map++; continue; } @@ -412,17 +467,23 @@ *p++ = ' '; } subsequent = 1; - if (map->type < LSMT_STRING_CHAR_ARRAY) { - use = ""; - if (map->colname[0] != '_') /* _lws_idx is not primary key */ - use = pri; - p += lws_snprintf(p, end - p, "%s integer%s", - map->colname, use); - if (map->colname[0] != '_') - pri = ""; - } else - p += lws_snprintf(p, end - p, "%s varchar", - map->colname); + if (map->type == LSMT_BLOB_PTR) { + + p += lws_snprintf(p, end - p, "%s blob", map->colname); + + } else { + if (map->type < LSMT_STRING_CHAR_ARRAY) { + use = ""; + if (map->colname[0] != '_') /* _lws_idx is not primary key */ + use = pri; + p += lws_snprintf(p, end - p, "%s integer%s", + map->colname, use); + if (map->colname[0] != '_') + pri = ""; + } else + p += lws_snprintf(p, end - p, "%s varchar", + map->colname); + } map++; } @@ -440,16 +501,17 @@ int lws_struct_sq3_open(struct lws_context *context, const char *sqlite3_path, - sqlite3 **pdb) + char create_if_missing, sqlite3 **pdb) { #if !defined(WIN32) int uid = 0, gid = 0; #endif if (sqlite3_open_v2(sqlite3_path, pdb, - SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, + SQLITE_OPEN_READWRITE | + (create_if_missing ? SQLITE_OPEN_CREATE : 0), NULL) != SQLITE_OK) { - lwsl_err("%s: Unable to open db %s: %s\n", + lwsl_info("%s: Unable to open db %s: %s\n", __func__, sqlite3_path, sqlite3_errmsg(*pdb)); return 1; @@ -458,13 +520,14 @@ #if !defined(WIN32) lws_get_effective_uid_gid(context, &uid, &gid); if (uid) - chown(sqlite3_path, uid, gid); + if (chown(sqlite3_path, uid, gid)) + lwsl_err("%s: failed to chown %s\n", __func__, sqlite3_path); chmod(sqlite3_path, 0600); - lwsl_notice("%s: created %s owned by %u:%u mode 0600\n", __func__, + lwsl_debug("%s: created %s owned by %u:%u mode 0600\n", __func__, sqlite3_path, (unsigned int)uid, (unsigned int)gid); #else - lwsl_notice("%s: created %s\n", __func__, sqlite3_path); + lwsl_debug("%s: created %s\n", __func__, sqlite3_path); #endif sqlite3_extended_result_codes(*pdb, 1); @@ -474,10 +537,19 @@ int lws_struct_sq3_close(sqlite3 **pdb) { + int n; + if (!*pdb) return 0; - sqlite3_close(*pdb); + n = sqlite3_close(*pdb); + if (n != SQLITE_OK) { + /* + * trouble... + */ + lwsl_err("%s: failed to close: %d\n", __func__, n); + return 1; + } *pdb = NULL; return 0; diff -Nru libwebsockets-4.0.20/lib/misc/peer-limits.c libwebsockets-4.1.6/lib/misc/peer-limits.c --- libwebsockets-4.0.20/lib/misc/peer-limits.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/misc/peer-limits.c 2020-12-01 17:40:26.000000000 +0000 @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2020 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -60,42 +60,32 @@ lws_get_or_create_peer(struct lws_vhost *vhost, lws_sockfd_type sockfd) { struct lws_context *context = vhost->context; - socklen_t rlen = 0; - void *q; - uint8_t *q8; struct lws_peer *peer; + lws_sockaddr46 sa46; + socklen_t rlen = 0; uint32_t hash = 0; - int n, af = AF_INET; - struct sockaddr_storage addr; + uint8_t *q8; + void *q; + int n; if (vhost->options & LWS_SERVER_OPTION_UNIX_SOCK) return NULL; -#ifdef LWS_WITH_IPV6 - if (LWS_IPV6_ENABLED(vhost)) { - af = AF_INET6; - } -#endif - rlen = sizeof(addr); - if (getpeername(sockfd, (struct sockaddr*)&addr, &rlen)) + rlen = sizeof(sa46); + if (getpeername(sockfd, (struct sockaddr*)&sa46, &rlen)) /* eg, udp doesn't have to have a peer */ return NULL; #ifdef LWS_WITH_IPV6 - if (af == AF_INET) + if (sa46.sa4.sin_family == AF_INET6) { + q = &sa46.sa6.sin6_addr; + rlen = sizeof(sa46.sa6.sin6_addr); + } else #endif { - struct sockaddr_in *s = (struct sockaddr_in *)&addr; - q = &s->sin_addr; - rlen = sizeof(s->sin_addr); - } -#ifdef LWS_WITH_IPV6 - else { - struct sockaddr_in6 *s = (struct sockaddr_in6 *)&addr; - q = &s->sin6_addr; - rlen = sizeof(s->sin6_addr); + q = &sa46.sa4.sin_addr; + rlen = sizeof(sa46.sa4.sin_addr); } -#endif q8 = q; for (n = 0; n < (int)rlen; n++) @@ -107,9 +97,21 @@ lws_start_foreach_ll(struct lws_peer *, peerx, context->pl_hash_table[hash]) { - if (peerx->af == af && !memcmp(q, peerx->addr, rlen)) { - lws_context_unlock(context); /* === */ - return peerx; + if (peerx->sa46.sa4.sin_family == sa46.sa4.sin_family) { +#if defined(LWS_WITH_IPV6) + if (sa46.sa4.sin_family == AF_INET6 && + !memcmp(q, &peerx->sa46.sa6.sin6_addr, rlen)) + goto hit; +#endif + if (sa46.sa4.sin_family == AF_INET && + !memcmp(q, &peerx->sa46.sa4.sin_addr, rlen)) { +#if defined(LWS_WITH_IPV6) +hit: +#endif + lws_context_unlock(context); /* === */ + + return peerx; + } } } lws_end_foreach_ll(peerx, next); @@ -125,9 +127,8 @@ context->count_peers++; peer->next = context->pl_hash_table[hash]; peer->hash = hash; - peer->af = af; + peer->sa46 = sa46; context->pl_hash_table[hash] = peer; - memcpy(peer->addr, q, rlen); time(&peer->time_created); /* * On creation, the peer has no wsi attached, so is created on the diff -Nru libwebsockets-4.0.20/lib/misc/spawn.c libwebsockets-4.1.6/lib/misc/spawn.c --- libwebsockets-4.0.20/lib/misc/spawn.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/misc/spawn.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,511 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2020 Andy Green - * - * 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. - */ - -#if !defined(_GNU_SOURCE) -#define _GNU_SOURCE -#endif - -#include "private-lib-core.h" -#include - -void -lws_spawn_timeout(struct lws_sorted_usec_list *sul) -{ - struct lws_spawn_piped *lsp = lws_container_of(sul, - struct lws_spawn_piped, sul); - - lwsl_warn("%s: spawn exceeded timeout, killing\n", __func__); - - lws_spawn_piped_kill_child_process(lsp); -} - -static struct lws * -lws_create_basic_wsi(struct lws_context *context, int tsi, - const struct lws_role_ops *ops) -{ - struct lws *new_wsi; - - if (!context->vhost_list) - return NULL; - - if ((unsigned int)context->pt[tsi].fds_count == - context->fd_limit_per_thread - 1) { - lwsl_err("no space for new conn\n"); - return NULL; - } - - new_wsi = lws_zalloc(sizeof(*new_wsi), "new wsi"); - if (new_wsi == NULL) { - lwsl_err("Out of memory for new connection\n"); - return NULL; - } - - new_wsi->tsi = tsi; - new_wsi->context = context; - new_wsi->pending_timeout = NO_PENDING_TIMEOUT; - new_wsi->rxflow_change_to = LWS_RXFLOW_ALLOW; - - /* initialize the instance struct */ - - lws_role_transition(new_wsi, 0, LRS_ESTABLISHED, ops); - - new_wsi->hdr_parsing_completed = 0; - new_wsi->position_in_fds_table = LWS_NO_FDS_POS; - - /* - * these can only be set once the protocol is known - * we set an unestablished connection's protocol pointer - * to the start of the defauly vhost supported list, so it can look - * for matching ones during the handshake - */ - - new_wsi->user_space = NULL; - new_wsi->desc.sockfd = LWS_SOCK_INVALID; - context->count_wsi_allocated++; - - return new_wsi; -} - -void -lws_spawn_piped_destroy(struct lws_spawn_piped **_lsp) -{ - struct lws_spawn_piped *lsp = *_lsp; - int n; - - if (!lsp) - return; - - for (n = 0; n < 3; n++) { - if (lsp->pipe_fds[n][!!(n == 0)] == 0) - lwsl_err("ZERO FD IN CGI CLOSE"); - - if (lsp->pipe_fds[n][!!(n == 0)] >= 0) { - close(lsp->pipe_fds[n][!!(n == 0)]); - lsp->pipe_fds[n][!!(n == 0)] = LWS_SOCK_INVALID; - } - } - - lws_dll2_remove(&lsp->dll); - - lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi, &lsp->sul, - NULL, LWS_SET_TIMER_USEC_CANCEL); - - lws_free_set_NULL((*_lsp)); -} - -int -lws_spawn_reap(struct lws_spawn_piped *lsp) -{ - long hz = sysconf(_SC_CLK_TCK); /* accounting Hz */ - void *opaque = lsp->info.opaque; - lsp_cb_t cb = lsp->info.reap_cb; - struct lws_spawn_piped temp; - struct tms tms; - int n; - - if (lsp->child_pid < 1) - return 0; - - /* check if exited, do not reap yet */ - - memset(&lsp->si, 0, sizeof(lsp->si)); - n = waitid(P_PID, lsp->child_pid, &lsp->si, WEXITED | WNOHANG | WNOWAIT); - if (n < 0) { - lwsl_info("%s: child %d still running\n", __func__, lsp->child_pid); - return 0; - } - - if (!lsp->si.si_code) - return 0; - - /* his process has exited... */ - - if (!lsp->reaped) { - /* mark the earliest time we knew he had gone */ - lsp->reaped = lws_now_usecs(); - - /* - * Switch the timeout to restrict the amount of grace time - * to drain stdwsi - */ - - lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi, - &lsp->sul, lws_spawn_timeout, - 5 * LWS_US_PER_SEC); - } - - /* - * Stage finalizing our reaction to the process going down until the - * stdwsi flushed whatever is in flight and all noticed they were - * closed. For that reason, each stdwsi close must call lws_spawn_reap - * to check if that was the last one and we can proceed with the reap. - */ - - if (!lsp->ungraceful && lsp->pipes_alive) { - lwsl_debug("%s: stdwsi alive, not reaping\n", __func__); - return 0; - } - - /* we reached the reap point, no need for timeout wait */ - - lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi, &lsp->sul, NULL, - LWS_SET_TIMER_USEC_CANCEL); - - /* - * All the stdwsi went down, nothing more is coming... it's over - * Collect the final information and then reap the dead process - */ - - if (times(&tms) != (clock_t) -1) { - /* - * Cpu accounting in us - */ - lsp->accounting[0] = ((uint64_t)tms.tms_cstime * 1000000) / hz; - lsp->accounting[1] = ((uint64_t)tms.tms_cutime * 1000000) / hz; - lsp->accounting[2] = ((uint64_t)tms.tms_stime * 1000000) / hz; - lsp->accounting[3] = ((uint64_t)tms.tms_utime * 1000000) / hz; - } - - temp = *lsp; - waitid(P_PID, lsp->child_pid, &lsp->si, WEXITED | WNOHANG); - lsp->child_pid = -1; - - /* destroy the lsp itself first (it's freed and plsp set NULL */ - - if (lsp->info.plsp) - lws_spawn_piped_destroy(lsp->info.plsp); - - /* then do the parent callback informing it's destroyed */ - - if (cb) - cb(opaque, temp.accounting, &temp.si, - temp.we_killed_him_timeout | - (temp.we_killed_him_spew << 1)); - - return 1; /* was reaped */ -} - -int -lws_spawn_piped_kill_child_process(struct lws_spawn_piped *lsp) -{ - int status, n; - - if (lsp->child_pid <= 0) - return 1; - - lsp->ungraceful = 1; /* don't wait for flushing, just kill it */ - - if (lws_spawn_reap(lsp)) - /* that may have invalidated lsp */ - return 0; - - /* kill the process group */ - n = kill(-lsp->child_pid, SIGTERM); - lwsl_debug("%s: SIGTERM child PID %d says %d (errno %d)\n", __func__, - lsp->child_pid, n, errno); - if (n < 0) { - /* - * hum seen errno=3 when process is listed in ps, - * it seems we don't always retain process grouping - * - * Direct these fallback attempt to the exact child - */ - n = kill(lsp->child_pid, SIGTERM); - if (n < 0) { - n = kill(lsp->child_pid, SIGPIPE); - if (n < 0) { - n = kill(lsp->child_pid, SIGKILL); - if (n < 0) - lwsl_info("%s: SIGKILL PID %d " - "failed errno %d " - "(maybe zombie)\n", __func__, - lsp->child_pid, errno); - } - } - } - - /* He could be unkillable because he's a zombie */ - - n = 1; - while (n > 0) { - n = waitpid(-lsp->child_pid, &status, WNOHANG); - if (n > 0) - lwsl_debug("%s: reaped PID %d\n", __func__, n); - if (n <= 0) { - n = waitpid(lsp->child_pid, &status, WNOHANG); - if (n > 0) - lwsl_debug("%s: reaped PID %d\n", __func__, n); - } - } - - lws_spawn_reap(lsp); - /* that may have invalidated lsp */ - - return 0; -} - -/* - * Deals with spawning a subprocess and executing it securely with stdin/out/err - * diverted into pipes - */ - -struct lws_spawn_piped * -lws_spawn_piped(const struct lws_spawn_piped_info *i) -{ - const struct lws_protocols *pcol = i->vh->context->vhost_list->protocols; - struct lws_context *context = i->vh->context; - struct lws_spawn_piped *lsp; - const char *wd; - int n, m; - - if (i->protocol_name) - pcol = lws_vhost_name_to_protocol(i->vh, i->protocol_name); - if (!pcol) { - lwsl_err("%s: unknown protocol %s\n", __func__, - i->protocol_name ? i->protocol_name : "default"); - - return NULL; - } - - lsp = lws_zalloc(sizeof(*lsp), __func__); - if (!lsp) - return NULL; - - /* wholesale take a copy of info */ - lsp->info = *i; - - /* - * Prepare the stdin / out / err pipes - */ - - for (n = 0; n < 3; n++) { - lsp->pipe_fds[n][0] = -1; - lsp->pipe_fds[n][1] = -1; - } - - /* create pipes for [stdin|stdout] and [stderr] */ - - for (n = 0; n < 3; n++) - if (pipe(lsp->pipe_fds[n]) == -1) - goto bail1; - - /* create wsis for each stdin/out/err fd */ - - for (n = 0; n < 3; n++) { - lsp->stdwsi[n] = lws_create_basic_wsi(i->vh->context, i->tsi, - i->ops ? i->ops : &role_ops_raw_file); - if (!lsp->stdwsi[n]) { - lwsl_err("%s: unable to create lsp stdwsi\n", __func__); - goto bail2; - } - lsp->stdwsi[n]->lsp_channel = n; - lws_vhost_bind_wsi(i->vh, lsp->stdwsi[n]); - lsp->stdwsi[n]->protocol = pcol; - lsp->stdwsi[n]->opaque_user_data = i->opaque; - - lwsl_debug("%s: lsp stdwsi %p: pipe idx %d -> fd %d / %d\n", __func__, - lsp->stdwsi[n], n, lsp->pipe_fds[n][!!(n == 0)], - lsp->pipe_fds[n][!(n == 0)]); - - /* read side is 0, stdin we want the write side, others read */ - - lsp->stdwsi[n]->desc.sockfd = lsp->pipe_fds[n][!!(n == 0)]; - if (fcntl(lsp->pipe_fds[n][!!(n == 0)], F_SETFL, O_NONBLOCK) < 0) { - lwsl_err("%s: setting NONBLOCK failed\n", __func__); - goto bail2; - } - } - - for (n = 0; n < 3; n++) { - if (context->event_loop_ops->sock_accept) - if (context->event_loop_ops->sock_accept(lsp->stdwsi[n])) - goto bail3; - - if (__insert_wsi_socket_into_fds(context, lsp->stdwsi[n])) - goto bail3; - if (i->opt_parent) { - lsp->stdwsi[n]->parent = i->opt_parent; - lsp->stdwsi[n]->sibling_list = i->opt_parent->child_list; - i->opt_parent->child_list = lsp->stdwsi[n]; - } - } - - if (lws_change_pollfd(lsp->stdwsi[LWS_STDIN], LWS_POLLIN, LWS_POLLOUT)) - goto bail3; - if (lws_change_pollfd(lsp->stdwsi[LWS_STDOUT], LWS_POLLOUT, LWS_POLLIN)) - goto bail3; - if (lws_change_pollfd(lsp->stdwsi[LWS_STDERR], LWS_POLLOUT, LWS_POLLIN)) - goto bail3; - - lwsl_debug("%s: fds in %d, out %d, err %d\n", __func__, - lsp->stdwsi[LWS_STDIN]->desc.sockfd, - lsp->stdwsi[LWS_STDOUT]->desc.sockfd, - lsp->stdwsi[LWS_STDERR]->desc.sockfd); - - /* we are ready with the redirection pipes... run the thing */ -#if !defined(LWS_HAVE_VFORK) || !defined(LWS_HAVE_EXECVPE) - lsp->child_pid = fork(); -#else - lsp->child_pid = vfork(); -#endif - if (lsp->child_pid < 0) { - lwsl_err("%s: fork failed, errno %d", __func__, errno); - goto bail3; - } - -#if defined(__linux__) - prctl(PR_SET_PDEATHSIG, SIGTERM); -#endif - - if (lsp->info.disable_ctrlc) - /* stops non-daemonized main processess getting SIGINT - * from TTY */ - setpgrp(); - - if (lsp->child_pid) { - - /* we are the parent process */ - - lwsl_info("%s: lsp %p spawned PID %d\n", __func__, lsp, - lsp->child_pid); - - lws_sul_schedule(context, i->tsi, &lsp->sul, lws_spawn_timeout, - i->timeout_us ? i->timeout_us : - 300 * LWS_US_PER_SEC); - - /* - * close: stdin:r, stdout:w, stderr:w - * hide from other forks: stdin:w, stdout:r, stderr:r - */ - for (n = 0; n < 3; n++) { - lws_plat_apply_FD_CLOEXEC(lsp->pipe_fds[n][!!(n == 0)]); - close(lsp->pipe_fds[n][!(n == 0)]); - } - - lsp->pipes_alive = 3; - lsp->created = lws_now_usecs(); - - if (i->owner) - lws_dll2_add_head(&lsp->dll, i->owner); - - if (i->timeout_us) - lws_sul_schedule(context, i->tsi, &lsp->sul, - lws_spawn_timeout, i->timeout_us); - - return lsp; - } - - /* - * We are the forked process, redirect and kill inherited things. - * - * Because of vfork(), we cannot do anything that changes pages in - * the parent environment. Stuff that changes kernel state for the - * process is OK. Stuff that happens after the execvpe() is OK. - */ - - if (i->chroot_path && chroot(i->chroot_path)) { - lwsl_err("%s: child chroot %s failed, errno %d\n", - __func__, i->chroot_path, errno); - - exit(2); - } - - /* cwd: somewhere we can at least read things and enter it */ - - wd = i->wd; - if (!wd) - wd = "/tmp"; - if (chdir(wd)) - lwsl_notice("%s: Failed to cd to %s\n", __func__, wd); - - for (m = 0; m < 3; m++) { - if (dup2(lsp->pipe_fds[m][!(m == 0)], m) < 0) { - lwsl_err("%s: stdin dup2 failed\n", __func__); - goto bail3; - } - close(lsp->pipe_fds[m][0]); - close(lsp->pipe_fds[m][1]); - } - - // lwsl_notice("%s: child cd %s, exec %s\n", __func__, wd, i->exec_array[0]); - -#if !defined(LWS_HAVE_VFORK) || !defined(LWS_HAVE_EXECVPE) -#if defined(__linux__) - m = 0; - while (i->env_array[m]){ - char *p = strchr(i->env_array[m], '='); - *p++ = '\0'; - setenv(i->env_array[m], p, 1); - m++; - } -#endif - execvp(i->exec_array[0], (char * const *)&i->exec_array[0]); -#else - execvpe(i->exec_array[0], (char * const *)&i->exec_array[0], - &i->env_array[0]); -#endif - - lwsl_err("%s: child exec of %s failed %d\n", __func__, i->exec_array[0], - LWS_ERRNO); - - _exit(1); - -bail3: - - while (--n >= 0) - __remove_wsi_socket_from_fds(lsp->stdwsi[n]); -bail2: - for (n = 0; n < 3; n++) - if (lsp->stdwsi[n]) - __lws_free_wsi(lsp->stdwsi[n]); - -bail1: - for (n = 0; n < 3; n++) { - if (lsp->pipe_fds[n][0] >= 0) - close(lsp->pipe_fds[n][0]); - if (lsp->pipe_fds[n][1] >= 0) - close(lsp->pipe_fds[n][1]); - } - - lws_free(lsp); - - lwsl_err("%s: failed\n", __func__); - - return NULL; -} - -void -lws_spawn_stdwsi_closed(struct lws_spawn_piped *lsp) -{ - assert(lsp); - lsp->pipes_alive--; - lwsl_debug("%s: pipes alive %d\n", __func__, lsp->pipes_alive); - lws_spawn_reap(lsp); -} - -int -lws_spawn_get_stdfd(struct lws *wsi) -{ - return wsi->lsp_channel; -} diff -Nru libwebsockets-4.0.20/lib/misc/threadpool/threadpool.c libwebsockets-4.1.6/lib/misc/threadpool/threadpool.c --- libwebsockets-4.0.20/lib/misc/threadpool/threadpool.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/misc/threadpool/threadpool.c 2020-12-01 17:40:26.000000000 +0000 @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2020 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -26,6 +26,12 @@ #define _GNU_SOURCE #endif +#if defined(WIN32) +#define HAVE_STRUCT_TIMESPEC +#if defined(pid_t) +#undef pid_t +#endif +#endif #include #include "private-lib-core.h" @@ -36,59 +42,61 @@ struct lws_threadpool; struct lws_threadpool_task { - struct lws_threadpool_task *task_queue_next; + struct lws_threadpool_task *task_queue_next; - struct lws_threadpool *tp; - char name[32]; + struct lws_threadpool *tp; + char name[32]; struct lws_threadpool_task_args args; - lws_usec_t created; - lws_usec_t acquired; - lws_usec_t done; - lws_usec_t entered_state; + lws_dll2_t list; + + lws_usec_t created; + lws_usec_t acquired; + lws_usec_t done; + lws_usec_t entered_state; - lws_usec_t acc_running; - lws_usec_t acc_syncing; + lws_usec_t acc_running; + lws_usec_t acc_syncing; - pthread_cond_t wake_idle; + pthread_cond_t wake_idle; enum lws_threadpool_task_status status; - int late_sync_retries; + int late_sync_retries; - char wanted_writeable_cb; - char outlive; + char wanted_writeable_cb; + char outlive; }; struct lws_pool { - struct lws_threadpool *tp; - pthread_t thread; - pthread_mutex_t lock; /* part of task wake_idle */ - struct lws_threadpool_task *task; - lws_usec_t acquired; - int worker_index; + struct lws_threadpool *tp; + pthread_t thread; + pthread_mutex_t lock; /* part of task wake_idle */ + struct lws_threadpool_task *task; + lws_usec_t acquired; + int worker_index; }; struct lws_threadpool { - pthread_mutex_t lock; /* protects all pool lists */ - pthread_cond_t wake_idle; - struct lws_pool *pool_list; + pthread_mutex_t lock; /* protects all pool lists */ + pthread_cond_t wake_idle; + struct lws_pool *pool_list; - struct lws_context *context; - struct lws_threadpool *tp_list; /* context list of threadpools */ + struct lws_context *context; + struct lws_threadpool *tp_list; /* context list of threadpools */ - struct lws_threadpool_task *task_queue_head; - struct lws_threadpool_task *task_done_head; + struct lws_threadpool_task *task_queue_head; + struct lws_threadpool_task *task_done_head; - char name[32]; + char name[32]; - int threads_in_pool; - int queue_depth; - int done_queue_depth; - int max_queue_depth; - int running_tasks; + int threads_in_pool; + int queue_depth; + int done_queue_depth; + int max_queue_depth; + int running_tasks; - unsigned int destroying:1; + unsigned int destroying:1; }; static int @@ -129,10 +137,10 @@ } if (task->acc_running) - runms = task->acc_running; + runms = (int)task->acc_running; if (task->acc_syncing) - syncms = task->acc_syncing; + syncms = (int)task->acc_syncing; if (!task->done) { buf += lws_snprintf(buf, end - buf, @@ -163,7 +171,8 @@ void lws_threadpool_dump(struct lws_threadpool *tp) { -#if defined(_DEBUG) +#if 0 + //defined(_DEBUG) struct lws_threadpool_task **c; char buf[160]; int n, count; @@ -232,17 +241,26 @@ task->status = status; } +static struct lws * +task_to_wsi(struct lws_threadpool_task *task) +{ +#if defined(LWS_WITH_SECURE_STREAMS) + if (task->args.ss) + return task->args.ss->wsi; +#endif + return task->args.wsi; +} + static void lws_threadpool_task_cleanup_destroy(struct lws_threadpool_task *task) { if (task->args.cleanup) - task->args.cleanup(task->args.wsi, task->args.user); + task->args.cleanup(task_to_wsi(task), task->args.user); - if (task->args.wsi) - task->args.wsi->tp_task = NULL; + lws_dll2_remove(&task->list); lwsl_thread("%s: tp %p: cleaned finished task for wsi %p\n", - __func__, task->tp, task->args.wsi); + __func__, task->tp, task_to_wsi(task)); lws_free(task); } @@ -255,25 +273,34 @@ /* remove the task from the done queue */ - c = &tp->task_done_head; + if (tp) { + c = &tp->task_done_head; - while (*c) { - if ((*c) == task) { - t = *c; - *c = t->task_queue_next; - t->task_queue_next = NULL; - tp->done_queue_depth--; + while (*c) { + if ((*c) == task) { + t = *c; + *c = t->task_queue_next; + t->task_queue_next = NULL; + tp->done_queue_depth--; - lwsl_thread("%s: tp %s: reaped task wsi %p\n", __func__, - tp->name, task->args.wsi); + lwsl_thread("%s: tp %s: reaped task wsi %p\n", __func__, + tp->name, task_to_wsi(task)); - break; + break; + } + c = &(*c)->task_queue_next; } - c = &(*c)->task_queue_next; - } - if (!t) - lwsl_err("%s: task %p not in done queue\n", __func__, task); + if (!t) { + lwsl_err("%s: task %p not in done queue\n", __func__, task); + /* + * This shouldn't occur, but in this case not really + * safe to assume there's a task to destroy + */ + return; + } + } else + lwsl_err("%s: task->tp NULL already\n", __func__); /* call the task's cleanup and delete the task itself */ @@ -308,9 +335,10 @@ if (!task) continue; - wsi = task->args.wsi; + wsi = task_to_wsi(task); if (!wsi || wsi->tsi != tsi || - !task->wanted_writeable_cb) + (!task->wanted_writeable_cb && + task->status != LWS_TP_STATUS_SYNCING)) continue; task->wanted_writeable_cb = 0; @@ -331,10 +359,11 @@ while (*c) { task = *c; - wsi = task->args.wsi; + wsi = task_to_wsi(task); if (wsi && wsi->tsi == tsi && - task->wanted_writeable_cb) { + (task->wanted_writeable_cb || + task->status == LWS_TP_STATUS_SYNCING)) { task->wanted_writeable_cb = 0; lws_memory_barrier(); @@ -373,12 +402,12 @@ pthread_mutex_lock(&pool->lock); /* ======================= pool lock */ lwsl_info("%s: %s: task %p (%s): syncing with wsi %p\n", __func__, - pool->tp->name, task, task->name, task->args.wsi); + pool->tp->name, task, task->name, task_to_wsi(task)); temp = task->status; state_transition(task, LWS_TP_STATUS_SYNCING); while (tries--) { - wsi = task->args.wsi; + wsi = task_to_wsi(task); /* * if the wsi is no longer attached to this task, there is @@ -431,7 +460,7 @@ lwsl_err("%s: %s: task %p (%s): SYNC timed out " "(associated wsi %p)\n", __func__, pool->tp->name, task, - task->name, task->args.wsi); + task->name, task_to_wsi(task)); state_transition(task, LWS_TP_STATUS_STOPPING); goto done; @@ -453,6 +482,10 @@ return 0; } +#if !defined(WIN32) +static int dummy; +#endif + static void * lws_threadpool_worker(void *d) { @@ -475,8 +508,8 @@ pthread_cond_wait(&tp->wake_idle, &tp->lock); if (tp->destroying) { - pthread_mutex_unlock(&tp->lock); /* ------ tp unlock */ - continue; + lwsl_notice("%s: bailing\n", __func__); + goto doneski; } c = &tp->task_queue_head; @@ -547,7 +580,7 @@ lws_usec_t then; int n; - if (tp->destroying || !task->args.wsi) { + if (tp->destroying || !task_to_wsi(task)) { lwsl_info("%s: stopping on wsi gone\n", __func__); state_transition(task, LWS_TP_STATUS_STOPPING); } @@ -563,7 +596,7 @@ /* if not destroying the tp, continue */ break; case LWS_TP_RETURN_SYNC: - if (!task->args.wsi) { + if (!task_to_wsi(task)) { lwsl_debug("%s: task that wants to " "outlive lost wsi asked " "to sync: bypassed\n", @@ -623,21 +656,25 @@ /* signal the associated wsi to take a fresh look at * task status */ - if (pool->task->args.wsi) { + if (task_to_wsi(pool->task)) { task->wanted_writeable_cb = 1; lws_cancel_service( - lws_get_context(pool->task->args.wsi)); + lws_get_context(task_to_wsi(pool->task))); } } +doneski: pool->task = NULL; pthread_mutex_unlock(&tp->lock); /* --------------- tp unlock */ } - /* threadpool is being destroyed */ + lwsl_notice("%s: Exiting\n", __func__); - pthread_exit(NULL); + /* threadpool is being destroyed */ +#if !defined(WIN32) + pthread_exit(&dummy); +#endif return NULL; } @@ -724,9 +761,8 @@ c = &task->task_queue_next; } - pthread_mutex_unlock(&tp->lock); /* -------------------- tpool unlock */ - pthread_cond_broadcast(&tp->wake_idle); + pthread_mutex_unlock(&tp->lock); /* -------------------- tpool unlock */ } void @@ -740,8 +776,8 @@ /* remove us from the context list of threadpools */ lws_context_lock(tp->context, __func__); - ptp = &tp->context->tp_list_head; + while (*ptp) { if (*ptp == tp) { *ptp = tp->tp_list; @@ -752,27 +788,32 @@ lws_context_unlock(tp->context); + /* + * Wake up the threadpool guys and tell them to exit + */ pthread_mutex_lock(&tp->lock); /* ======================== tpool lock */ - tp->destroying = 1; pthread_cond_broadcast(&tp->wake_idle); pthread_mutex_unlock(&tp->lock); /* -------------------- tpool unlock */ lws_threadpool_dump(tp); + lwsl_info("%s: waiting for threads to rejoin\n", __func__); +#if defined(WIN32) + Sleep(1000); +#endif + for (n = 0; n < tp->threads_in_pool; n++) { task = tp->pool_list[n].task; - /* he could be sitting waiting for SYNC */ - - if (task != NULL) - pthread_cond_broadcast(&task->wake_idle); - pthread_join(tp->pool_list[n].thread, &retval); pthread_mutex_destroy(&tp->pool_list[n].lock); } lwsl_info("%s: all threadpools exited\n", __func__); +#if defined(WIN32) + Sleep(1000); +#endif task = tp->task_done_head; while (task) { @@ -784,25 +825,21 @@ pthread_mutex_destroy(&tp->lock); + memset(tp, 0xdd, sizeof(*tp)); lws_free(tp); } /* - * we want to stop and destroy the task and related priv. The wsi may no - * longer exist. + * We want to stop and destroy the tasks and related priv. */ int -lws_threadpool_dequeue(struct lws *wsi) +lws_threadpool_dequeue_task(struct lws_threadpool_task *task) { struct lws_threadpool *tp; - struct lws_threadpool_task **c, *task; + struct lws_threadpool_task **c; int n; - task = wsi->tp_task; - if (!task) - return 0; - tp = task->tp; pthread_mutex_lock(&tp->lock); /* ======================== tpool lock */ @@ -810,8 +847,11 @@ /* disconnect from wsi, and wsi from task */ - wsi->tp_task = NULL; + lws_dll2_remove(&task->list); task->args.wsi = NULL; +#if defined(LWS_WITH_SECURE_STREAMS) + task->args.ss = NULL; +#endif goto bail; } @@ -833,7 +873,7 @@ task->done = lws_now_usecs(); lwsl_debug("%s: tp %p: removed queued task wsi %p\n", - __func__, tp, task->args.wsi); + __func__, tp, task_to_wsi(task)); break; } @@ -875,13 +915,16 @@ /* disconnect from wsi, and wsi from task */ - task->args.wsi->tp_task = NULL; + lws_dll2_remove(&task->list); task->args.wsi = NULL; +#if defined(LWS_WITH_SECURE_STREAMS) + task->args.ss = NULL; +#endif pthread_mutex_unlock(&tp->pool_list[n].lock); lwsl_debug("%s: tp %p: request stop running task " - "for wsi %p\n", __func__, tp, task->args.wsi); + "for wsi %p\n", __func__, tp, task_to_wsi(task)); break; } @@ -889,9 +932,12 @@ if (n == tp->threads_in_pool) { /* can't find it */ lwsl_notice("%s: tp %p: no task for wsi %p, decoupling\n", - __func__, tp, task->args.wsi); - task->args.wsi->tp_task = NULL; + __func__, tp, task_to_wsi(task)); + lws_dll2_remove(&task->list); task->args.wsi = NULL; +#if defined(LWS_WITH_SECURE_STREAMS) + task->args.ss = NULL; +#endif } bail: @@ -900,6 +946,21 @@ return 0; } +int +lws_threadpool_dequeue(struct lws *wsi) /* deprecated */ +{ + struct lws_threadpool_task *task; + + if (!wsi->tp_task_owner.count) + return 0; + assert(wsi->tp_task_owner.count != 1); + + task = lws_container_of(wsi->tp_task_owner.head, + struct lws_threadpool_task, list); + + return lws_threadpool_dequeue_task(task); +} + struct lws_threadpool_task * lws_threadpool_enqueue(struct lws_threadpool *tp, const struct lws_threadpool_task_args *args, @@ -911,6 +972,10 @@ if (tp->destroying) return NULL; +#if defined(LWS_WITH_SECURE_STREAMS) + assert(args->ss || args->wsi); +#endif + pthread_mutex_lock(&tp->lock); /* ======================== tpool lock */ /* @@ -957,10 +1022,15 @@ * whatever reason can clean up) */ - args->wsi->tp_task = task; +#if defined(LWS_WITH_SECURE_STREAMS) + if (args->ss) + lws_dll2_add_tail(&task->list, &args->ss->wsi->tp_task_owner); + else +#endif + lws_dll2_add_tail(&task->list, &args->wsi->tp_task_owner); lwsl_thread("%s: tp %s: enqueued task %p (%s) for wsi %p, depth %d\n", - __func__, tp->name, task, task->name, args->wsi, + __func__, tp->name, task, task->name, task_to_wsi(task), tp->queue_depth); /* alert any idle thread there's something new on the task list */ @@ -977,29 +1047,26 @@ /* this should be called from the service thread */ enum lws_threadpool_task_status -lws_threadpool_task_status_wsi(struct lws *wsi, - struct lws_threadpool_task **task, void **user) +lws_threadpool_task_status(struct lws_threadpool_task *task, void **user) { enum lws_threadpool_task_status status; - struct lws_threadpool *tp; + struct lws_threadpool *tp = task->tp; - *task = wsi->tp_task; - if (!*task) - return -1; - - tp = (*task)->tp; - *user = (*task)->args.user; - status = (*task)->status; + if (!tp) + return LWS_TP_STATUS_FINISHED; + + *user = task->args.user; + status = task->status; if (status == LWS_TP_STATUS_FINISHED || status == LWS_TP_STATUS_STOPPED) { char buf[160]; pthread_mutex_lock(&tp->lock); /* ================ tpool lock */ - __lws_threadpool_task_dump(*task, buf, sizeof(buf)); + __lws_threadpool_task_dump(task, buf, sizeof(buf)); lwsl_thread("%s: %s: service thread REAPING: %s\n", __func__, tp->name, buf); - __lws_threadpool_reap(*task); + __lws_threadpool_reap(task); lws_memory_barrier(); pthread_mutex_unlock(&tp->lock); /* ------------ tpool unlock */ } @@ -1007,13 +1074,107 @@ return status; } +enum lws_threadpool_task_status +lws_threadpool_task_status_noreap(struct lws_threadpool_task *task) +{ + return task->status; +} + +enum lws_threadpool_task_status +lws_threadpool_task_status_wsi(struct lws *wsi, + struct lws_threadpool_task **_task, void **user) +{ + struct lws_threadpool_task *task; + + if (!wsi->tp_task_owner.count) { + lwsl_notice("%s: wsi has no task, ~=FINISHED\n", __func__); + return LWS_TP_STATUS_FINISHED; + } + + assert(wsi->tp_task_owner.count == 1); /* see deprecation docs in hdr */ + + task = lws_container_of(wsi->tp_task_owner.head, + struct lws_threadpool_task, list); + + *_task = task; + + return lws_threadpool_task_status(task, user); +} + void lws_threadpool_task_sync(struct lws_threadpool_task *task, int stop) { lwsl_debug("%s\n", __func__); + if (!task) + return; if (stop) state_transition(task, LWS_TP_STATUS_STOPPING); + pthread_mutex_lock(&task->tp->lock); pthread_cond_signal(&task->wake_idle); + pthread_mutex_unlock(&task->tp->lock); +} + +int +lws_threadpool_foreach_task_wsi(struct lws *wsi, void *user, + int (*cb)(struct lws_threadpool_task *task, + void *user)) +{ + struct lws_threadpool_task *task1; + + if (wsi->tp_task_owner.head == NULL) + return 0; + + task1 = lws_container_of(wsi->tp_task_owner.head, + struct lws_threadpool_task, list); + + pthread_mutex_lock(&task1->tp->lock); /* ================ tpool lock */ + + lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, + wsi->tp_task_owner.head) { + struct lws_threadpool_task *task = lws_container_of(d, + struct lws_threadpool_task, list); + + if (cb(task, user)) { + pthread_mutex_unlock(&task1->tp->lock); /* ------------ tpool unlock */ + return 1; + } + + } lws_end_foreach_dll_safe(d, d1); + + pthread_mutex_unlock(&task1->tp->lock); /* ------------ tpool unlock */ + + return 0; +} + +#if defined(LWS_WITH_SECURE_STREAMS) +int +lws_threadpool_foreach_task_ss(struct lws_ss_handle *ss, void *user, + int (*cb)(struct lws_threadpool_task *task, + void *user)) +{ + if (!ss->wsi) + return 0; + + return lws_threadpool_foreach_task_wsi(ss->wsi, user, cb); } +#endif + +struct lws_threadpool_task * +lws_threadpool_get_task_wsi(struct lws *wsi) +{ + if (wsi->tp_task_owner.head == NULL) + return NULL; + + return lws_container_of(wsi->tp_task_owner.head, + struct lws_threadpool_task, list); +} + +#if defined(LWS_WITH_SECURE_STREAMS) +struct lws_threadpool_task * +lws_threadpool_get_task_ss(struct lws_ss_handle *ss) +{ + return lws_threadpool_get_task_wsi(ss->wsi); +} +#endif diff -Nru libwebsockets-4.0.20/lib/plat/freertos/CMakeLists.txt libwebsockets-4.1.6/lib/plat/freertos/CMakeLists.txt --- libwebsockets-4.0.20/lib/plat/freertos/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/freertos/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,60 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(. esp32) + +list(APPEND SOURCES + plat/freertos/freertos-fds.c + plat/freertos/freertos-init.c + plat/freertos/freertos-misc.c + plat/freertos/freertos-pipe.c + plat/freertos/freertos-service.c + plat/freertos/freertos-sockets.c + misc/romfs.c) + +if (LWS_ESP_PLATFORM AND LWS_WITH_DRIVERS) + list(APPEND SOURCES plat/freertos/esp32/drivers/settings-esp32.c) + if (LWS_WITH_NETWORK) + list(APPEND SOURCES plat/freertos/esp32/drivers/netdev/wifi-esp32.c) + endif() +endif() +if (LWS_WITH_FILE_OPS) + list(APPEND SOURCES plat/freertos/freertos-file.c) +endif() +if (LWS_WITH_SYS_ASYNC_DNS OR LWS_WITH_SYS_NTPCLIENT) + list(APPEND SOURCES plat/freertos/freertos-resolv.c) +endif() + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() diff -Nru libwebsockets-4.0.20/lib/plat/freertos/esp32/drivers/gpio-esp32.c libwebsockets-4.1.6/lib/plat/freertos/esp32/drivers/gpio-esp32.c --- libwebsockets-4.0.20/lib/plat/freertos/esp32/drivers/gpio-esp32.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/freertos/esp32/drivers/gpio-esp32.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,96 @@ +/* + * esp32 / esp-idf gpio + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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 + +static void +lws_gpio_esp32_mode(_lws_plat_gpio_t gpio, int flags) +{ + int mode, pup = GPIO_FLOATING; + + switch (flags & (LWSGGPIO_FL_READ | LWSGGPIO_FL_WRITE)) { + default: + lwsl_err("%s: neither read nor write\n", __func__); + return; + case LWSGGPIO_FL_READ: + mode = GPIO_MODE_INPUT; + break; + case LWSGGPIO_FL_WRITE: + mode = GPIO_MODE_OUTPUT; + break; + case LWSGGPIO_FL_READ | LWSGGPIO_FL_WRITE: + mode = GPIO_MODE_INPUT_OUTPUT; + break; + } + + switch (flags & (LWSGGPIO_FL_PULLUP | LWSGGPIO_FL_PULLDOWN)) { + default: + break; + case LWSGGPIO_FL_PULLUP: + pup = GPIO_PULLUP_ONLY; + break; + case LWSGGPIO_FL_PULLDOWN: + pup = GPIO_PULLDOWN_ONLY; + break; + case LWSGGPIO_FL_PULLUP | LWSGGPIO_FL_PULLDOWN: + pup = GPIO_PULLUP_PULLDOWN; + break; + } + + gpio_reset_pin(gpio); + gpio_set_direction(gpio, mode); + gpio_set_pull_mode(gpio, pup); + gpio_set_level(gpio, flags & LWSGGPIO_FL_START_LOW ? 0 : 1); +} + +static int +lws_gpio_esp32_read(_lws_plat_gpio_t gpio) +{ + return gpio_get_level(gpio); +} +static void +lws_gpio_esp32_set(_lws_plat_gpio_t gpio, int val) +{ + gpio_set_level(gpio, val); +} + +static int +lws_gpio_esp32_irq_mode(_lws_plat_gpio_t gpio, lws_gpio_irq_t irq_type, + lws_gpio_irq_cb_t cb, void *arg) +{ + if (gpio_set_intr_type(gpio, irq_type)) + return 1; + + if (cb) + return gpio_isr_handler_add(gpio, cb, arg); + + return gpio_isr_handler_remove(gpio); +} + +const lws_gpio_ops_t lws_gpio_plat = { + .mode = lws_gpio_esp32_mode, + .read = lws_gpio_esp32_read, + .set = lws_gpio_esp32_set, + .irq_mode = lws_gpio_esp32_irq_mode, +}; diff -Nru libwebsockets-4.0.20/lib/plat/freertos/esp32/drivers/lws-plat-gpio.h libwebsockets-4.1.6/lib/plat/freertos/esp32/drivers/lws-plat-gpio.h --- libwebsockets-4.0.20/lib/plat/freertos/esp32/drivers/lws-plat-gpio.h 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/freertos/esp32/drivers/lws-plat-gpio.h 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,25 @@ +/* + * lws generic gpio - esp32 platform wrapper + * + * Written in 2010-2020 by Andy Green + * + * 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. + */ + +extern const lws_gpio_ops_t lws_gpio_plat; diff -Nru libwebsockets-4.0.20/lib/plat/freertos/esp32/drivers/netdev/wifi-esp32.c libwebsockets-4.1.6/lib/plat/freertos/esp32/drivers/netdev/wifi-esp32.c --- libwebsockets-4.0.20/lib/plat/freertos/esp32/drivers/netdev/wifi-esp32.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/freertos/esp32/drivers/netdev/wifi-esp32.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,496 @@ +/* + * libwebsockets - esp32 wifi -> lws_netdev_wifi + * + * Copyright (C) 2010 - 2020 Andy Green + * + * 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. + * + * + * These are the esp platform wifi-specific netdev pieces. Nothing else should + * know any esp-specific apis. + * + * Operations happen via the generic lws_detdev instantiation for the platform + * wifi device, which point in here for operations. We also set up native OS + * event hooks per device for wifi and IP stack events, and post them as lws_smd + * NETWORK events on the if in the "platform private" namespace. We then + * service the events in the lws event loop thread context, which may again + * generate lws_smd NETWORK events in the public namespace depending on what + * happened. + * + * Scan requests go through a sul to make sure we don't get "piling on" from + * scheduled, timed scans. Scan results go through the lws_smd "washing" and + * are actually parsed in lws thread context, where they are converted to lws + * netdev scan results and processed by generic code. + */ + +#include "private-lib-core.h" + +#include "esp_system.h" +#include "esp_spi_flash.h" +#include "esp_wifi.h" +#include +#include + +/* + * lws_netdev_instance_t: + * lws_netdev_instance_wifi_t: + * lws_netdev_instance_wifi_esp32_t + */ + +typedef struct lws_netdev_instance_wifi_esp32 { + lws_netdev_instance_wifi_t wnd; + esp_event_handler_instance_t instance_any_id; + esp_event_handler_instance_t instance_got_ip; + wifi_config_t sta_config; +} lws_netdev_instance_wifi_esp32_t; + +/* +static wifi_config_t config = { + .ap = { + .channel = 6, + .authmode = WIFI_AUTH_OPEN, + .max_connection = 1, + } }; + */ + +/* + * Platform-specific connect / associate + */ + +int +lws_netdev_wifi_connect_plat(lws_netdev_instance_t *nd, const char *ssid, + const char *passphrase, uint8_t *bssid) +{ + lws_netdev_instance_wifi_esp32_t *wnde32 = + (lws_netdev_instance_wifi_esp32_t *)nd; + + wnde32->wnd.inst.ops->up(&wnde32->wnd.inst); + + wnde32->wnd.flags |= LNDIW_MODE_STA; + esp_wifi_set_mode(WIFI_MODE_STA); + +#if 0 + /* we will do our own dhcp */ + tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA); +#endif + + lws_strncpy((char *)wnde32->sta_config.sta.ssid, ssid, + sizeof(wnde32->sta_config.sta.ssid)); + lws_strncpy((char *)wnde32->sta_config.sta.password, passphrase, + sizeof(wnde32->sta_config.sta.password)); + + esp_wifi_set_config(WIFI_IF_STA, &wnde32->sta_config); + esp_wifi_connect(); + + return 0; +} + +/* + * This is called from the SMD / lws thread context, after we heard there were + * scan results on this netdev + */ + +static void +lws_esp32_scan_update(lws_netdev_instance_wifi_t *wnd) +{ +// lws_netdevs_t *netdevs = lws_netdevs_from_ndi(&wnd->inst); + wifi_ap_record_t ap_records[LWS_WIFI_MAX_SCAN_TRACK], *ar; + uint32_t now = lws_now_secs(); + uint16_t count_ap_records; + int n; + + count_ap_records = LWS_ARRAY_SIZE(ap_records); + if (esp_wifi_scan_get_ap_records(&count_ap_records, ap_records)) { + lwsl_err("%s: failed\n", __func__); + return; + } + + if (!count_ap_records) + return; + + if (wnd->state != LWSNDVWIFI_STATE_SCAN) + return; + + /* + * ... let's collect the OS-specific scan results, and convert then to + * lws_netdev sorted by rssi. If we already have it in the scan list, + * keep it and keep a little ringbuffer of its rssi along with an + * averaging. If it's new, add it into the linked-list sorted by rssi. + */ + + ar = &ap_records[0]; + for (n = 0; n < count_ap_records; n++) { + lws_wifi_sta_t *w; + int m; + + m = strlen((const char *)ar->ssid); + if (!m) + goto next; + + /* + * We know this guy from before? + */ + + w = lws_netdev_wifi_scan_find(wnd, (const char *)ar->ssid, + ar->bssid); + if (!w) { + w = lws_zalloc(sizeof(*w) + m + 1, __func__); + if (!w) + goto next; + + w->ssid = (char *)&w[1]; + memcpy(w->ssid, ar->ssid, m + 1); + w->ssid_len = m; + + memcpy(w->bssid, ar->bssid, 6); + + lws_dll2_add_sorted(&w->list, &wnd->scan, + lws_netdev_wifi_rssi_sort_compare); + } + + if (w->rssi_count == LWS_ARRAY_SIZE(w->rssi)) + w->rssi_avg -= w->rssi[w->rssi_next]; + else + w->rssi_count++; + w->rssi[w->rssi_next] = ar->rssi; + w->rssi_avg += w->rssi[w->rssi_next++]; + w->rssi_next = w->rssi_next & (LWS_ARRAY_SIZE(w->rssi) - 1); + + w->ch = ar->primary; + w->authmode = ar->authmode; + w->last_seen = now; + +next: + ar++; + } + + /* + * We can do the rest of it using the generic scan list and credentials + */ + + lws_netdev_wifi_scan_select(wnd); +} + +static wifi_scan_config_t scan_config = { + .ssid = 0, + .bssid = 0, + .channel = 0, + .show_hidden = true +}; + +void +lws_netdev_wifi_scan_plat(lws_netdev_instance_t *nd) +{ + lws_netdev_instance_wifi_t *wnd = (lws_netdev_instance_wifi_t *)nd; + + if (esp_wifi_scan_start(&scan_config, false)) + lwsl_err("%s: %s scan failed\n", __func__, wnd->inst.name); +} + +/* + * Platform-private interface events turn up here after going through SMD and + * passed down by matching network interface name via generic lws_netdev. All + * that messing around gets us from an OS-specific thread with an event to back + * here in lws event loop thread context, with the same event bound to a the + * netdev it belongs to. + */ + +int +lws_netdev_wifi_event_plat(struct lws_netdev_instance *nd, lws_usec_t timestamp, + void *buf, size_t len) +{ + lws_netdev_instance_wifi_t *wnd = (lws_netdev_instance_wifi_t *)nd; + struct lws_context *ctx = netdev_instance_to_ctx(&wnd->inst); + size_t al; + + /* + * netdev-private sync messages? + */ + + if (!lws_json_simple_strcmp(buf, len, "\"type\":", "priv")) { + const char *ev = lws_json_simple_find(buf, len, "\"ev\":", &al); + + if (!ev) + return 0; + + lwsl_notice("%s: smd priv ev %.*s\n", __func__, (int)al, ev); + + switch (atoi(ev)) { + case WIFI_EVENT_STA_START: + wnd->state = LWSNDVWIFI_STATE_INITIAL; + if (!lws_netdev_wifi_redo_last(wnd)) + break; + + /* + * if the "try last successful" one fails, start the + * scan by falling through + */ + + case WIFI_EVENT_STA_DISCONNECTED: + lws_smd_msg_printf(ctx, LWSSMDCL_NETWORK, + "{\"type\":\"linkdown\"," + "\"if\":\"%s\"}", wnd->inst.name); + wnd->state = LWSNDVWIFI_STATE_SCAN; + /* + * We do it via the sul so we don't get timed scans + * on top of each other + */ + lws_sul_schedule(ctx, 0, &wnd->sul_scan, + lws_netdev_wifi_scan, 1); + break; + + case WIFI_EVENT_STA_CONNECTED: + lws_smd_msg_printf(ctx, LWSSMDCL_NETWORK, + "{\"type\":\"linkup\"," + "\"if\":\"%s\"}", wnd->inst.name); + break; + + case WIFI_EVENT_SCAN_DONE: + lws_esp32_scan_update(wnd); + break; + default: + return 0; + } + + return 0; + } + + return 0; +} + +/* + * This is coming from a thread context unrelated to lws... the first order is + * to turn these into lws_smd events synchronized on lws thread, since we want + * to change correspsonding lws netdev object states without locking. + */ + +static void +_event_handler_wifi(void *arg, esp_event_base_t event_base, int32_t event_id, + void *event_data) +{ + lws_netdev_instance_wifi_t *wnd = (lws_netdev_instance_wifi_t *)arg; + struct lws_context *ctx = netdev_instance_to_ctx(&wnd->inst); + + switch (event_id) { + case WIFI_EVENT_STA_START: + case WIFI_EVENT_STA_DISCONNECTED: + case WIFI_EVENT_SCAN_DONE: + case WIFI_EVENT_STA_CONNECTED: + /* + * These are events in the platform's private namespace, + * interpreted only by the lws_smd handler above, ** in the lws + * event thread context **. The point of this is to requeue the + * event in the lws thread context like a bottom-half. + * + * To save on registrations, the context's NETWORK smd + * participant passes messages to lws_netdev, who passes ones + * that have if matching the netdev name to that netdev's + * (*event) handler. + * + * The other handler may emit generic network state SMD events + * for other things to consume. + */ + + lws_smd_msg_printf(ctx, LWSSMDCL_NETWORK, + "{\"type\":\"priv\",\"if\":\"%s\",\"ev\":%d}", + wnd->inst.name, event_id); + break; + default: + return; + } +} + +#if 0 +static int +espip_to_sa46(lws_sockaddr46 *sa46, esp_ip_addr_t *eip) +{ + memset(sa46, 0, sizeof(sa46)); + + switch (eip->type) { + case ESP_IPADDR_TYPE_V4: + sa46->sa4.sin_family = AF_INET; + memcpy(sa46->sa4.sin_addr, &eip->u_addr.ip4.addr, ); + return; + case ESP_IPADDR_TYPE_V6: + } +} +#endif + +/* + * This is coming from a thread context unrelated to lws + */ + +static void +_event_handler_ip(void *arg, esp_event_base_t event_base, int32_t event_id, + void *event_data) +{ + lws_netdev_instance_wifi_t *wnd = (lws_netdev_instance_wifi_t *)arg; + lws_netdevs_t *netdevs = lws_netdevs_from_ndi(&wnd->inst); + struct lws_context *ctx = lws_context_from_netdevs(netdevs); + + if (event_id == IP_EVENT_STA_GOT_IP) { + ip_event_got_ip_t *e = (ip_event_got_ip_t *)event_data; + char ip[16]; +#if 0 + tcpip_adapter_dns_info_t e32ip; + + /* + * Since atm we get this via DHCP, presumably we can get ahold + * of related info set by the router + */ + + if (tcpip_adapter_get_dns_info(TCPIP_ADAPTER_IF_STA, + TCPIP_ADAPTER_DNS_MAIN, + /* also _BACKUP, _FALLBACK */ + &e32ip)) { + lwsl_err("%s: there's no dns server set\n", __func__); + e32ip.ip.u_addr.ipv4 = 0x08080808; + e32ip.ip.type = ESP_IPADDR_TYPE_V4; + } + + netdevs->sa46_dns_resolver. +#endif + + lws_write_numeric_address((void *)&e->ip_info.ip, 4, ip, + sizeof(ip)); + lws_smd_msg_printf(ctx, LWSSMDCL_NETWORK, + "{\"type\":\"ipacq\",\"if\":\"%s\"," + "\"ipv4\":\"%s\"}", wnd->inst.name, ip); + } +} + +/* + * This is the platform (esp-idf) init for any kind of networking to be + * available at all + */ +int +lws_netdev_plat_init(void) +{ + nvs_flash_init(); + esp_netif_init(); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + return 0; +} + +/* + * This is the platform (esp-idf) init for any wifi to be available at all + */ +int +lws_netdev_plat_wifi_init(void) +{ + wifi_init_config_t wic = WIFI_INIT_CONFIG_DEFAULT(); + int n; + + esp_netif_create_default_wifi_sta(); + + n = esp_wifi_init(&wic); + if (n) { + lwsl_err("%s: wifi init fail: %d\n", __func__, n); + return 1; + } + + return 0; +} + + +struct lws_netdev_instance * +lws_netdev_wifi_create_plat(struct lws_context *ctx, + const lws_netdev_ops_t *ops, + const char *name, void *platinfo) +{ + lws_netdev_instance_wifi_esp32_t *wnde32 = lws_zalloc( + sizeof(*wnde32), __func__); + + if (!wnde32) + return NULL; + + wnde32->wnd.inst.type = LWSNDTYP_WIFI; + lws_netdev_instance_create(&wnde32->wnd.inst, ctx, ops, name, platinfo); + + return &wnde32->wnd.inst; +} + +int +lws_netdev_wifi_configure_plat(struct lws_netdev_instance *nd, + lws_netdev_config_t *config) +{ + return 0; +} + +int +lws_netdev_wifi_up_plat(struct lws_netdev_instance *nd) +{ + lws_netdev_instance_wifi_esp32_t *wnde32 = + (lws_netdev_instance_wifi_esp32_t *)nd; + struct lws_context *ctx = netdev_instance_to_ctx(&wnde32->wnd.inst); + + if (wnde32->wnd.flags & LNDIW_UP) + return 0; + + ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, + IP_EVENT_STA_GOT_IP, &_event_handler_ip, nd, + &wnde32->instance_got_ip)); + + ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, + ESP_EVENT_ANY_ID, &_event_handler_wifi, nd, + &wnde32->instance_any_id)); + + esp_wifi_start(); + wnde32->wnd.flags |= LNDIW_UP; + + lws_smd_msg_printf(ctx, LWSSMDCL_NETWORK, + "{\"type\":\"up\",\"if\":\"%s\"}", + wnde32->wnd.inst.name); + + return 0; +} + +int +lws_netdev_wifi_down_plat(struct lws_netdev_instance *nd) +{ + lws_netdev_instance_wifi_esp32_t *wnde32 = + (lws_netdev_instance_wifi_esp32_t *)nd; + struct lws_context *ctx = netdev_instance_to_ctx(&wnde32->wnd.inst); + + if (!(wnde32->wnd.flags & LNDIW_UP)) + return 0; + + lws_smd_msg_printf(ctx, LWSSMDCL_NETWORK, + "{\"type\":\"down\",\"if\":\"%s\"}", + wnde32->wnd.inst.name); + + esp_wifi_stop(); + + esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, + &wnde32->instance_got_ip); + esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, + &wnde32->instance_any_id); + + wnde32->wnd.flags &= ~LNDIW_UP; + + return 0; +} + +void +lws_netdev_wifi_destroy_plat(struct lws_netdev_instance **pnd) +{ + lws_free(*pnd); + *pnd = NULL; +} diff -Nru libwebsockets-4.0.20/lib/plat/freertos/esp32/drivers/pwm-esp32.c libwebsockets-4.1.6/lib/plat/freertos/esp32/drivers/pwm-esp32.c --- libwebsockets-4.0.20/lib/plat/freertos/esp32/drivers/pwm-esp32.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/freertos/esp32/drivers/pwm-esp32.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,80 @@ +/* + * esp32 / esp-idf pwm + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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" +#include "soc/ledc_reg.h" +#include "driver/ledc.h" + +static const ledc_timer_config_t tc = { + .speed_mode = LEDC_HIGH_SPEED_MODE, + .duty_resolution = LEDC_TIMER_13_BIT, + .timer_num = LEDC_TIMER_0, + .freq_hz = 5000, + .clk_cfg = LEDC_AUTO_CLK +}; + +int +lws_pwm_plat_init(const struct lws_pwm_ops *lo) +{ + ledc_channel_config_t lc = { + .duty = 8191, + .intr_type = LEDC_INTR_FADE_END, + .speed_mode = LEDC_HIGH_SPEED_MODE, + .timer_sel = LEDC_TIMER_0, + }; + size_t n; + + ledc_timer_config(&tc); + + for (n = 0; n < lo->count_pwm_map; n++) { + lc.channel = LEDC_CHANNEL_0 + lo->pwm_map[n].index; + lc.gpio_num = lo->pwm_map[n].gpio; + ledc_channel_config(&lc); + ledc_set_duty(LEDC_HIGH_SPEED_MODE, lc.channel, 0); + ledc_update_duty(LEDC_HIGH_SPEED_MODE, lc.channel); + } + + return 0; +} + +void +lws_pwm_plat_intensity(const struct lws_pwm_ops *lo, _lws_plat_gpio_t gpio, + lws_led_intensity_t inten) +{ + size_t n; + + for (n = 0; n < lo->count_pwm_map; n++) { + if (lo->pwm_map[n].gpio == gpio) { + if (!lo->pwm_map[n].active_level) + inten = 65535 - inten; + ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0 + + lo->pwm_map[n].index, inten >> 3); + ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0 + + lo->pwm_map[n].index); + return; + } + } + + lwsl_err("%s: unknown gpio for pwm\n", __func__); +} diff -Nru libwebsockets-4.0.20/lib/plat/freertos/esp32/drivers/settings-esp32.c libwebsockets-4.1.6/lib/plat/freertos/esp32/drivers/settings-esp32.c --- libwebsockets-4.0.20/lib/plat/freertos/esp32/drivers/settings-esp32.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/freertos/esp32/drivers/settings-esp32.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,75 @@ +/* + * esp32 / esp-idf NV settings shim + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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 + +#include + +int +lws_settings_plat_get(lws_settings_instance_t *si, const char *name, + uint8_t *dest, size_t *max_actual) +{ + int n; + + n = nvs_flash_init_partition((const char *)si->opaque_plat); + + lwsl_notice("%s: init partition %d\n", __func__, n); + if (n == ESP_ERR_NOT_FOUND) + return 1; + + if (nvs_open_from_partition((const char *)si->opaque_plat, + "_lws_settings", NVS_READONLY, + (nvs_handle_t *)&si->handle_plat)) + return 1; + + n = nvs_get_blob((nvs_handle_t)si->handle_plat, + name, dest, max_actual); + + nvs_close((nvs_handle_t)si->handle_plat); + + return !!n; +} + +int +lws_settings_plat_set(lws_settings_instance_t *si, const char *name, + const uint8_t *src, size_t len) +{ + int n = nvs_flash_init_partition((const char *)si->opaque_plat); + + lwsl_notice("%s: init partition %d\n", __func__, n); + if (n == ESP_ERR_NOT_FOUND) + return 1; + + if (nvs_open_from_partition((const char *)si->opaque_plat, + "_lws_settings", NVS_READWRITE, + (nvs_handle_t *)&si->handle_plat)) + return 1; + + n = nvs_set_blob((nvs_handle_t)si->handle_plat, name, src, len); + + nvs_commit((nvs_handle_t)si->handle_plat); + nvs_close((nvs_handle_t)si->handle_plat); + + return 0; +} diff -Nru libwebsockets-4.0.20/lib/plat/freertos/esp32/esp32-helpers.c libwebsockets-4.1.6/lib/plat/freertos/esp32/esp32-helpers.c --- libwebsockets-4.0.20/lib/plat/freertos/esp32/esp32-helpers.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/freertos/esp32/esp32-helpers.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,1373 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * 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" - -#include "romfs.h" -#include -#include -#include -#include -#include "soc/ledc_reg.h" -#include "driver/ledc.h" - -struct lws_esp32 lws_esp32 = { - .model = CONFIG_LWS_MODEL_NAME, - .serial = "unknown", -}; - -/* - * Group AP / Station State - */ - -enum lws_gapss { - LWS_GAPSS_INITIAL, /* just started up, init and move to - * LWS_GAPSS_SCAN */ - LWS_GAPSS_SCAN, /* - * Unconnected, scanning: AP known in one of the - * config slots -> configure it, start timeout + - * LWS_GAPSS_STAT, if no AP already up in same - * group with lower MAC, after a random period - * start up our AP (LWS_GAPSS_AP) - */ - LWS_GAPSS_AP, /* - * Trying to be the group AP... periodically do - * a scan LWS_GAPSS_AP_SCAN, faster and then - * slower - */ - LWS_GAPSS_AP_SCAN, /* - * doing a scan while trying to be the group - * AP... if we see a lower MAC being the AP for - * the same group AP, abandon being an AP and - * join that AP as a station - */ - LWS_GAPSS_STAT_GRP_AP, /* - * We have decided to join another group member - * who is being the AP, as its MAC is lower than - * ours. This is a stable state, but we still - * do periodic scans LWS_GAPSS_STAT_GRP_AP_SCAN - * and will always prefer an AP configured in a - * slot. - */ - LWS_GAPSS_STAT_GRP_AP_SCAN, - /* - * We have joined a group member who is doing - * the AP job... we want to check every now and - * then if a configured AP has appeared that we - * should better use instead. Otherwise stay in - * LWS_GAPSS_STAT_GRP_AP - */ - LWS_GAPSS_STAT, /* - * trying to connect to another non-group AP. - * If we don't get an IP within a timeout and - * retries, blacklist it and go back - */ - LWS_GAPSS_STAT_HAPPY, -}; - -static const char *gapss_str[] = { - "LWS_GAPSS_INITIAL", - "LWS_GAPSS_SCAN", - "LWS_GAPSS_AP", - "LWS_GAPSS_AP_SCAN", - "LWS_GAPSS_STAT_GRP_AP", - "LWS_GAPSS_STAT_GRP_AP_SCAN", - "LWS_GAPSS_STAT", - "LWS_GAPSS_STAT_HAPPY", -}; - -static romfs_t lws_esp32_romfs; -static TimerHandle_t leds_timer, scan_timer, debounce_timer, association_timer -#if !defined(CONFIG_LWS_IS_FACTORY_APPLICATION) -, mdns_timer -#endif -; -static enum lws_gapss gapss = LWS_GAPSS_INITIAL; -#if !defined(CONFIG_LWS_IS_FACTORY_APPLICATION) -static mdns_result_t *mdns_results_head; -#endif - -#define GPIO_SW 14 - -struct esp32_file { - const struct inode *i; -}; - -static void lws_gapss_to(enum lws_gapss to) -{ - lwsl_notice("gapss from %s to %s\n", gapss_str[gapss], gapss_str[to]); - gapss = to; -} - -uint32_t lws_esp32_get_reboot_type(void) -{ - uint32_t *p = (uint32_t *)LWS_MAGIC_REBOOT_TYPE_ADS, val = *p; - nvs_handle nvh; - size_t s = 0; - int n = 0; - - ESP_ERROR_CHECK(nvs_open("lws-station", NVS_READWRITE, &nvh)); - if (nvs_get_blob(nvh, "ssl-pub.pem", NULL, &s) == ESP_OK) - n = 1; - if (nvs_get_blob(nvh, "ssl-pri.pem", NULL, &s) == ESP_OK) - n |= 2; - nvs_close(nvh); - - /* - * in the case the SSL certs are not there, don't require - * the button to be down to access all features. - */ - if (n != 3) - val = LWS_MAGIC_REBOOT_TYPE_FORCED_FACTORY_BUTTON; - - return val; -} - -static void render_ip(char *dest, int len, uint8_t *ip) -{ - snprintf(dest, len, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]); -} - -void lws_esp32_restart_guided(uint32_t type) -{ - uint32_t *p_force_factory_magic = (uint32_t *)LWS_MAGIC_REBOOT_TYPE_ADS; - - lwsl_notice("%s: %x\n", __func__, type); - *p_force_factory_magic = type; - - esp_restart(); -} - -/* - * esp-idf goes crazy with zero length str nvs. Use this as a workaround - * to delete the key in that case. - */ - -esp_err_t lws_nvs_set_str(nvs_handle handle, const char* key, const char* value) -{ - if (*value) - return nvs_set_str(handle, key, value); - - return nvs_erase_key(handle, key); -} - -static wifi_scan_config_t scan_config = { - .ssid = 0, - .bssid = 0, - .channel = 0, - .show_hidden = true -}; - -static char scan_ongoing = 0, scan_timer_exists = 0; -static int try_slot = -1; - -static wifi_config_t config = { - .ap = { - .channel = 6, - .authmode = WIFI_AUTH_OPEN, - .max_connection = 1, - } }, sta_config = { - .sta = { - .bssid_set = 0, - } }; - -static void lws_esp32_scan_timer_cb(TimerHandle_t th) -{ - int n; - - lwsl_notice("%s\n", __func__); - scan_ongoing = 0; - n = esp_wifi_scan_start(&scan_config, false); - if (n != ESP_OK) - lwsl_err("scan start failed %d\n", n); -} - -static void lws_esp32_assoc_timer_cb(TimerHandle_t th) -{ - int n; - - xTimerStop(association_timer, 0); - - if (gapss == LWS_GAPSS_STAT_HAPPY) { - lwsl_debug("%s: saw we were happy\n", __func__); - - return; - } - - lwsl_notice("%s: forcing rescan\n", __func__); - - lws_gapss_to(LWS_GAPSS_SCAN); - scan_ongoing = 0; - n = esp_wifi_scan_start(&scan_config, false); - if (n != ESP_OK) - lwsl_err("scan start failed %d\n", n); -} - - -#if !defined(CONFIG_LWS_IS_FACTORY_APPLICATION) - -void __attribute__(( weak )) -lws_group_member_event(int e, void *p) -{ -} - -void __attribute__(( weak )) -lws_get_iframe_size(int *w, int *h) -{ - *w = 320; - *h = 160; -} - -void lws_group_member_event_call(int e, void *p) -{ - lws_group_member_event(e, p); -} - -static int -get_txt_param(const mdns_result_t *mr, const char *param, char *result, int len) -{ - const char *p; - - *result = '\0'; - - p = strstr(mr->txt->key, param); - if (!p) { - *result = '\0'; - return 1; - } - - lws_strncpy(result, mr->txt->value, len); - - return 0; -} - -static void lws_esp32_mdns_timer_cb(TimerHandle_t th) -{ - uint64_t now = lws_now_usecs(); - struct lws_group_member *p, **p1; - const mdns_result_t *r = mdns_results_head; - - while (r) { - char ch = 0, group[16]; - - get_txt_param(r, "group", group, sizeof(group)); - if (strcmp(group, lws_esp32.group)) /* not our group */ { - lwsl_notice("group %s vs %s %s\n", - group, lws_esp32.group, r->txt->value); - continue; - } - - p = lws_esp32.first; - while (p) { - if (strcmp(r->hostname, p->host)) - goto next; - if (memcmp(&r->addr, &p->addr, sizeof(r->addr))) - goto next; - - p->last_seen = now; - break; -next: - p = p->next; - } - if (!p) { /* did not find */ - char temp[8]; - - p = lws_malloc(sizeof(*p), "group"); - if (!p) - continue; - lws_strncpy(p->host, r->hostname, sizeof(p->host)); - - get_txt_param(r, "model", p->model, sizeof(p->model)); - get_txt_param(r, "role", p->role, sizeof(p->role)); - get_txt_param(r, "mac", p->mac, sizeof(p->mac)); - get_txt_param(r, "width", temp, sizeof(temp)); - p->width = atoi(temp); - get_txt_param(r, "height", temp, sizeof(temp)); - p->height = atoi(temp); - - memcpy(&p->addr, &r->addr, sizeof(p->addr)); -// memcpy(&p->addrv6, &r->addrv6, sizeof(p->addrv6)); - p->last_seen = now; - p->flags = 0; - p->next = lws_esp32.first; - lws_esp32.first = p; - lws_esp32.extant_group_members++; - - lws_group_member_event_call(LWS_SYSTEM_GROUP_MEMBER_ADD, p); - } else { - if (memcmp(&p->addr, &r->addr, sizeof(p->addr))) { - memcpy(&p->addr, &r->addr, sizeof(p->addr)); - ch = 1; - } -/* if (memcmp(&p->addrv6, &r->addrv6, sizeof(p->addrv6))) { - memcpy(&p->addrv6, &r->addrv6, sizeof(p->addrv6)); - ch = 1; - } */ - if (ch) - lws_group_member_event_call(LWS_SYSTEM_GROUP_MEMBER_CHANGE, p); - } - } - - mdns_query_results_free(mdns_results_head); - - /* garbage-collect group members not seen for too long */ - p1 = &lws_esp32.first; - while (*p1) { - p = *p1; - if (!(p->flags & LWS_GROUP_FLAG_SELF) && - now - p->last_seen > 60000000) { - lws_esp32.extant_group_members--; - *p1 = p->next; - - lws_group_member_event_call(LWS_SYSTEM_GROUP_MEMBER_REMOVE, p); - lws_free(p); - continue; - } - p1 = &(*p1)->next; - } - - mdns_query_txt(lws_esp32.group, "_lwsgrmem", "_tcp", 0, - &mdns_results_head); - xTimerStart(mdns_timer, 0); -} -#endif - -void __attribute__(( weak )) -lws_esp32_button(int down) -{ -} - -void IRAM_ATTR -gpio_irq(void *arg) -{ - gpio_set_intr_type(GPIO_SW, GPIO_INTR_DISABLE); - xTimerStart(debounce_timer, 0); -} - -static void lws_esp32_debounce_timer_cb(TimerHandle_t th) -{ - if (lws_esp32.button_is_down) - gpio_set_intr_type(GPIO_SW, GPIO_INTR_POSEDGE); - else - gpio_set_intr_type(GPIO_SW, GPIO_INTR_NEGEDGE); - - lws_esp32.button_is_down = gpio_get_level(GPIO_SW); - - lws_esp32_button(lws_esp32.button_is_down); -} - - -static int -start_scan() -{ - /* if no APs configured, no point... */ - - if (!lws_esp32.ssid[0][0] && - !lws_esp32.ssid[1][0] && - !lws_esp32.ssid[2][0] && - !lws_esp32.ssid[3][0]) - return 0; - - if (scan_timer_exists && !scan_ongoing) { - // lwsl_notice("Starting scan timer...\n"); - scan_ongoing = 1; - xTimerStart(scan_timer, 0); - } - - return 0; -} - - - -static void -end_scan() -{ - wifi_ap_record_t ap_records[10]; - uint16_t count_ap_records; - int n, m; - - count_ap_records = LWS_ARRAY_SIZE(ap_records); - if (esp_wifi_scan_get_ap_records(&count_ap_records, ap_records)) { - lwsl_err("%s: failed\n", __func__); - return; - } - - if (!count_ap_records) - goto passthru; - - if (gapss != LWS_GAPSS_SCAN) { - lwsl_info("ignoring scan as gapss %s\n", gapss_str[gapss]); - goto passthru; - } - - /* no point if no APs set up */ - if (!lws_esp32.ssid[0][0] && - !lws_esp32.ssid[1][0] && - !lws_esp32.ssid[2][0] && - !lws_esp32.ssid[3][0]) - goto passthru; - - lwsl_info("checking %d scan records\n", count_ap_records); - - for (n = 0; n < 4; n++) { - - if (!lws_esp32.ssid[(n + try_slot + 1) & 3][0]) - continue; - - lwsl_debug("looking for %s\n", - lws_esp32.ssid[(n + try_slot + 1) & 3]); - - /* this ssid appears in scan results? */ - - for (m = 0; m < count_ap_records; m++) { - // lwsl_notice(" %s\n", ap_records[m].ssid); - if (!strcmp((char *)ap_records[m].ssid, - lws_esp32.ssid[(n + try_slot + 1) & 3])) - goto hit; - } - - continue; - -hit: - m = (n + try_slot + 1) & 3; - try_slot = m; - lwsl_info("Attempting connection with slot %d: %s:\n", m, - lws_esp32.ssid[m]); - /* set the ssid we last tried to connect to */ - lws_strncpy(lws_esp32.active_ssid, lws_esp32.ssid[m], - sizeof(lws_esp32.active_ssid)); - - lws_strncpy((char *)sta_config.sta.ssid, lws_esp32.ssid[m], - sizeof(sta_config.sta.ssid)); - lws_strncpy((char *)sta_config.sta.password, lws_esp32.password[m], - sizeof(sta_config.sta.password)); - - tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, - (const char *)&config.ap.ssid[7]); - lws_gapss_to(LWS_GAPSS_STAT); - xTimerStop(association_timer, 0); - xTimerStart(association_timer, 0); - - esp_wifi_set_config(WIFI_IF_STA, &sta_config); - esp_wifi_connect(); - break; - } - - if (n == 4) - start_scan(); - -passthru: - if (lws_esp32.scan_consumer) - lws_esp32.scan_consumer(count_ap_records, ap_records, - lws_esp32.scan_consumer_arg); - -} - -static void -lws_set_genled(int n) -{ - lws_esp32.genled_t = lws_now_usecs(); - lws_esp32.genled = n; -} - -int -lws_esp32_leds_network_indication(void) -{ - uint64_t us, r; - int n, fadein = 100, speed = 1199, div = 1, base = 0; - - r = lws_now_usecs(); - us = r - lws_esp32.genled_t; - - switch (lws_esp32.genled) { - case LWSESP32_GENLED__INIT: - lws_esp32.genled = LWSESP32_GENLED__LOST_NETWORK; - /* fallthru */ - case LWSESP32_GENLED__LOST_NETWORK: - fadein = us / 10000; /* 100 steps in 1s */ - if (fadein > 100) { - fadein = 100; - lws_esp32.genled = LWSESP32_GENLED__NO_NETWORK; - } - /* fallthru */ - case LWSESP32_GENLED__NO_NETWORK: - break; - case LWSESP32_GENLED__CONN_AP: - base = 4096; - speed = 933; - div = 2; - break; - case LWSESP32_GENLED__GOT_IP: - fadein = us / 10000; /* 100 steps in 1s */ - if (fadein > 100) { - fadein = 100; - lws_esp32.genled = LWSESP32_GENLED__OK; - } - fadein = 100 - fadein; /* we are fading out */ - /* fallthru */ - case LWSESP32_GENLED__OK: - if (lws_esp32.genled == LWSESP32_GENLED__OK) - return 0; - - base = 4096; - speed = 766; - div = 3; - break; - } - - n = base + (lws_esp32_sine_interp(r / speed) / div); - return (n * fadein) / 100; -} - -esp_err_t lws_esp32_event_passthru(void *ctx, system_event_t *event) -{ -#if !defined(CONFIG_LWS_IS_FACTORY_APPLICATION) - struct lws_group_member *mem; - int n; -#endif - nvs_handle nvh; - uint32_t use; - - switch((int)event->event_id) { - case SYSTEM_EVENT_STA_START: - //esp_wifi_connect(); -// break; - /* fallthru */ - case SYSTEM_EVENT_STA_DISCONNECTED: - lwsl_notice("SYSTEM_EVENT_STA_DISCONNECTED\n"); - if (sntp_enabled()) - sntp_stop(); - lws_esp32.conn_ap = 0; - lws_esp32.inet = 0; - lws_esp32.sta_ip[0] = '\0'; - lws_esp32.sta_mask[0] = '\0'; - lws_esp32.sta_gw[0] = '\0'; - lws_gapss_to(LWS_GAPSS_SCAN); - mdns_free(); - lws_set_genled(LWSESP32_GENLED__LOST_NETWORK); - start_scan(); - esp_wifi_connect(); - break; - - case SYSTEM_EVENT_STA_CONNECTED: - lws_esp32.conn_ap = 1; - lws_set_genled(LWSESP32_GENLED__CONN_AP); - break; - - case SYSTEM_EVENT_STA_GOT_IP: - lwsl_notice("SYSTEM_EVENT_STA_GOT_IP\n"); - - lws_esp32.inet = 1; - lws_set_genled(LWSESP32_GENLED__GOT_IP); - - render_ip(lws_esp32.sta_ip, sizeof(lws_esp32.sta_ip) - 1, - (uint8_t *)&event->event_info.got_ip.ip_info.ip); - render_ip(lws_esp32.sta_mask, sizeof(lws_esp32.sta_mask) - 1, - (uint8_t *)&event->event_info.got_ip.ip_info.netmask); - render_ip(lws_esp32.sta_gw, sizeof(lws_esp32.sta_gw) - 1, - (uint8_t *)&event->event_info.got_ip.ip_info.gw); - - if (!nvs_open("lws-station", NVS_READWRITE, &nvh)) { - char slot[8]; - - lws_snprintf(slot, sizeof(slot) - 1, "%duse", try_slot); - use = 0; - nvs_get_u32(nvh, slot, &use); - nvs_set_u32(nvh, slot, use + 1); - nvs_commit(nvh); - nvs_close(nvh); - } - - lws_gapss_to(LWS_GAPSS_STAT_HAPPY); - -#if !defined(CONFIG_LWS_IS_FACTORY_APPLICATION) - n = mdns_init(); - if (!n) { - static mdns_txt_item_t txta[6]; - static char wh[2][6]; - int w, h; - - mdns_hostname_set(lws_esp32.hostname); - mdns_instance_name_set(lws_esp32.group); - - lws_get_iframe_size(&w, &h); - - txta[0].key = "model"; - txta[1].key = "group"; - txta[2].key = "role"; - txta[3].key = "mac"; - txta[4].key = "width"; - txta[5].key = "height"; - - txta[0].value = lws_esp32.model; - txta[1].value = lws_esp32.group; - txta[2].value = lws_esp32.role; - txta[3].value = lws_esp32.mac; - txta[4].value = wh[0]; - txta[5].value = wh[1]; - - lws_snprintf(wh[0], 6, "%d", w); - lws_snprintf(wh[1], 6, "%d", h); - - mdns_service_add(lws_esp32.group, - "_lwsgrmem", "_tcp", 443, txta, - LWS_ARRAY_SIZE(txta)); - - mem = lws_esp32.first; - while (mem) { - if (mem->flags & 1) - break; - mem = mem->next; - } - - if (!mem) { - struct lws_group_member *mem = - lws_malloc(sizeof(*mem), "group"); - if (mem) { - mem->last_seen = ~(uint64_t)0; - strcpy(mem->model, lws_esp32.model); - strcpy(mem->role, lws_esp32.role); - strcpy(mem->host, lws_esp32.hostname); - strcpy(mem->mac, lws_esp32.mac); - mem->flags = LWS_GROUP_FLAG_SELF; - lws_get_iframe_size(&mem->width, - &mem->height); - memcpy(&mem->addr, - &event->event_info.got_ip.ip_info.ip, - sizeof(mem->addr)); - memcpy(&mem->addrv6, - &event->event_info.got_ip6.ip6_info.ip, - sizeof(mem->addrv6)); - mem->next = lws_esp32.first; - lws_esp32.first = mem; - lws_esp32.extant_group_members++; - - lws_group_member_event_call( - LWS_SYSTEM_GROUP_MEMBER_ADD, mem); - } - } else { /* update our IP */ - memcpy(&mem->addr, - &event->event_info.got_ip.ip_info.ip, - sizeof(mem->addr)); - memcpy(&mem->addrv6, - &event->event_info.got_ip6.ip6_info.ip, - sizeof(mem->addrv6)); - lws_group_member_event_call( - LWS_SYSTEM_GROUP_MEMBER_CHANGE, mem); - } - - } else - lwsl_err("unable to init mdns on STA: %d\n", n); - - mdns_query_txt(lws_esp32.group, "_lwsgrmem", "_tcp", 0, - &mdns_results_head); - xTimerStart(mdns_timer, 0); -#endif - - lwsl_notice(" --- Got IP %s\n", lws_esp32.sta_ip); - if (!sntp_enabled()) { - sntp_setoperatingmode(SNTP_OPMODE_POLL); - sntp_setservername(0, "pool.ntp.org"); - sntp_init(); - } - break; - - case SYSTEM_EVENT_SCAN_DONE: - lwsl_notice("SYSTEM_EVENT_SCAN_DONE\n"); - end_scan(); - break; - - default: - break; - } - - return ESP_OK; -} - -#if defined(LWS_WITH_FILE_OPS) -static lws_fop_fd_t IRAM_ATTR -esp32_lws_fops_open(const struct lws_plat_file_ops *fops, const char *filename, - const char *vfs_path, lws_fop_flags_t *flags) -{ - struct esp32_file *f = malloc(sizeof(*f)); - lws_fop_fd_t fop_fd; - size_t len, csum; - - lwsl_notice("%s: %s\n", __func__, filename); - - if (!f) - return NULL; - f->i = romfs_get_info(lws_esp32_romfs, filename, &len, &csum); - if (!f->i) - goto bail; - - fop_fd = malloc(sizeof(*fop_fd)); - if (!fop_fd) - goto bail; - - fop_fd->fops = fops; - fop_fd->filesystem_priv = f; - fop_fd->mod_time = csum; - *flags |= LWS_FOP_FLAG_MOD_TIME_VALID; - fop_fd->flags = *flags; - - fop_fd->len = len; - fop_fd->pos = 0; - - return fop_fd; - -bail: - free(f); - - return NULL; -} - -static int IRAM_ATTR -esp32_lws_fops_close(lws_fop_fd_t *fop_fd) -{ - free((*fop_fd)->filesystem_priv); - free(*fop_fd); - - *fop_fd = NULL; - - return 0; -} -static lws_fileofs_t IRAM_ATTR -esp32_lws_fops_seek_cur(lws_fop_fd_t fop_fd, lws_fileofs_t offset_from_cur_pos) -{ - fop_fd->pos += offset_from_cur_pos; - - if (fop_fd->pos > fop_fd->len) - fop_fd->pos = fop_fd->len; - - return 0; -} - -static int IRAM_ATTR -esp32_lws_fops_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount, uint8_t *buf, - lws_filepos_t len) -{ - struct esp32_file *f = fop_fd->filesystem_priv; -#if 0 - if ((long)buf & 3) { - lwsl_err("misaligned buf\n"); - - return -1; - } -#endif - if (fop_fd->pos >= fop_fd->len) - return 0; - - if (len > fop_fd->len - fop_fd->pos) - len = fop_fd->len - fop_fd->pos; - - spi_flash_read((uint32_t)(char *)f->i + fop_fd->pos, buf, len); - - *amount = len; - fop_fd->pos += len; - - return 0; -} - -static const struct lws_plat_file_ops fops = { - .next = &fops_zip, - .LWS_FOP_OPEN = esp32_lws_fops_open, - .LWS_FOP_CLOSE = esp32_lws_fops_close, - .LWS_FOP_READ = esp32_lws_fops_read, - .LWS_FOP_SEEK_CUR = esp32_lws_fops_seek_cur, -}; -#endif - -int -lws_esp32_wlan_nvs_get(int retry) -{ - nvs_handle nvh; - char lws_esp32_force_ap = 0, slot[12]; - size_t s; - uint8_t mac[6]; - int n; - - esp_efuse_mac_get_default(mac); - mac[5] |= 1; /* match the AP MAC */ - snprintf(lws_esp32.serial, sizeof(lws_esp32.serial) - 1, - "%02X%02X%02X", mac[3], mac[4], mac[5]); - snprintf(lws_esp32.mac, sizeof(lws_esp32.mac) - 1, - "%02X%02X%02X%02X%02X%02X", mac[0], mac[1], mac[2], mac[3], - mac[4], mac[5]); - - ESP_ERROR_CHECK(nvs_open("lws-station", NVS_READWRITE, &nvh)); - - config.sta.ssid[0] = '\0'; - config.sta.password[0] = '\0'; - - for (n = 0; n < 4; n++) { - lws_snprintf(slot, sizeof(slot) - 1, "%dssid", n); - s = sizeof(lws_esp32.ssid[0]) - 1; - lws_esp32.ssid[n][0] = '\0'; - nvs_get_str(nvh, slot, lws_esp32.ssid[n], &s); - - lws_snprintf(slot, sizeof(slot) - 1, "%dpassword", n); - s = sizeof(lws_esp32.password[0]) - 1; - lws_esp32.password[n][0] = '\0'; - nvs_get_str(nvh, slot, lws_esp32.password[n], &s); - } - - s = sizeof(lws_esp32.serial) - 1; - if (nvs_get_str(nvh, "serial", lws_esp32.serial, &s) != ESP_OK) - lws_esp32_force_ap = 1; - else - snprintf((char *)config.ap.ssid, sizeof(config.ap.ssid) - 1, - "config-%s-%s", lws_esp32.model, lws_esp32.serial); - s = sizeof(lws_esp32.opts) - 1; - if (nvs_get_str(nvh, "opts", lws_esp32.opts, &s) != ESP_OK) - lws_esp32_force_ap = 1; - - lws_esp32.access_pw[0] = '\0'; - nvs_get_str(nvh, "access_pw", lws_esp32.access_pw, &s); - - lws_esp32.group[0] = '\0'; - s = sizeof(lws_esp32.group); - nvs_get_str(nvh, "group", lws_esp32.group, &s); - - lws_esp32.role[0] = '\0'; - s = sizeof(lws_esp32.role); - nvs_get_str(nvh, "role", lws_esp32.role, &s); - - /* if group and role defined: group-role */ - if (lws_esp32.group[0] && lws_esp32.role[0]) - lws_snprintf(lws_esp32.hostname, sizeof(lws_esp32.hostname) - 1, - "%s-%s", lws_esp32.group, lws_esp32.role); - else /* otherwise model-serial */ - lws_snprintf(lws_esp32.hostname, sizeof(lws_esp32.hostname) - 1, - "%s-%s", lws_esp32.model, lws_esp32.serial); - - nvs_close(nvh); - - lws_gapss_to(LWS_GAPSS_SCAN); - start_scan(); - - return lws_esp32_force_ap; -} - - -void -lws_esp32_wlan_config(void) -{ - ledc_timer_config_t ledc_timer = { - .bit_num = LEDC_TIMER_13_BIT, - .freq_hz = 5000, - .speed_mode = LEDC_HIGH_SPEED_MODE, - .timer_num = LEDC_TIMER_0 - }; - int n; - - lwsl_debug("%s\n", __func__); - - ledc_timer_config(&ledc_timer); - - lws_set_genled(LWSESP32_GENLED__INIT); - - /* user code needs to provide lws_esp32_leds_timer_cb */ - - leds_timer = xTimerCreate("lws_leds", pdMS_TO_TICKS(25), 1, NULL, - (TimerCallbackFunction_t)lws_esp32_leds_timer_cb); - scan_timer = xTimerCreate("lws_scan", pdMS_TO_TICKS(10000), 0, NULL, - (TimerCallbackFunction_t)lws_esp32_scan_timer_cb); - debounce_timer = xTimerCreate("lws_db", pdMS_TO_TICKS(100), 0, NULL, - (TimerCallbackFunction_t)lws_esp32_debounce_timer_cb); - association_timer = xTimerCreate("lws_assoc", pdMS_TO_TICKS(10000), 0, NULL, - (TimerCallbackFunction_t)lws_esp32_assoc_timer_cb); - -#if !defined(CONFIG_LWS_IS_FACTORY_APPLICATION) - mdns_timer = xTimerCreate("lws_mdns", pdMS_TO_TICKS(5000), 0, NULL, - (TimerCallbackFunction_t)lws_esp32_mdns_timer_cb); -#endif - scan_timer_exists = 1; - xTimerStart(leds_timer, 0); - - *(volatile uint32_t *)PERIPHS_IO_MUX_MTMS_U = FUNC_MTMS_GPIO14; - - gpio_output_set(0, 0, 0, (1 << GPIO_SW)); - - n = gpio_install_isr_service(0); - if (!n) { - gpio_config_t c; - - c.intr_type = GPIO_INTR_NEGEDGE; - c.mode = GPIO_MODE_INPUT; - c.pin_bit_mask = 1 << GPIO_SW; - c.pull_down_en = 0; - c.pull_up_en = 0; - gpio_config(&c); - - if (gpio_isr_handler_add(GPIO_SW, gpio_irq, NULL)) - lwsl_notice("isr handler add for 14 failed\n"); - } else - lwsl_notice("failed to install gpio isr service: %d\n", n); - - lws_esp32_wlan_nvs_get(0); - tcpip_adapter_init(); -} - -void -lws_esp32_wlan_start_ap(void) -{ - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - - ESP_ERROR_CHECK( esp_wifi_init(&cfg)); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM)); - - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_APSTA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_AP, &config) ); - ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &sta_config)); - ESP_ERROR_CHECK( esp_wifi_start()); - - esp_wifi_scan_start(&scan_config, false); - - if (sta_config.sta.ssid[0]) { - tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, - (const char *)&config.ap.ssid[7]); - // esp_wifi_set_auto_connect(1); - ESP_ERROR_CHECK( esp_wifi_connect()); - ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &sta_config)); - ESP_ERROR_CHECK( esp_wifi_connect()); - } -} - -void -lws_esp32_wlan_start_station(void) -{ - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - - ESP_ERROR_CHECK( esp_wifi_init(&cfg)); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM)); - - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA)); - ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &sta_config)); - - ESP_ERROR_CHECK( esp_wifi_start()); - - tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, - (const char *)&config.ap.ssid[7]); - //esp_wifi_set_auto_connect(1); - //ESP_ERROR_CHECK( esp_wifi_connect()); - - lws_esp32_scan_timer_cb(NULL); -} - -const esp_partition_t * -lws_esp_ota_get_boot_partition(void) -{ - const esp_partition_t *part = esp_ota_get_boot_partition(), - *factory_part, *ota; - esp_image_header_t eih, ota_eih; - uint32_t *p_force_factory_magic = (uint32_t *)LWS_MAGIC_REBOOT_TYPE_ADS; - - /* confirm what we are told is the boot part is sane */ - spi_flash_read(part->address , &eih, sizeof(eih)); - factory_part = esp_partition_find_first(ESP_PARTITION_TYPE_APP, - ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL); - ota = esp_partition_find_first(ESP_PARTITION_TYPE_APP, - ESP_PARTITION_SUBTYPE_APP_OTA_0, NULL); - spi_flash_read(ota->address , &ota_eih, sizeof(ota_eih)); - - if (eih.spi_mode == 0xff || - *p_force_factory_magic == LWS_MAGIC_REBOOT_TYPE_FORCED_FACTORY || - *p_force_factory_magic == LWS_MAGIC_REBOOT_TYPE_FORCED_FACTORY_BUTTON - ) { - /* - * we believed we were going to boot OTA, but we fell - * back to FACTORY in the bootloader when we saw it - * had been erased. esp_ota_get_boot_partition() still - * says the OTA partition then even if we are in the - * factory partition right now. - */ - part = factory_part; - } - -#ifdef CONFIG_LWS_IS_FACTORY_APPLICATION - else - if (ota_eih.spi_mode != 0xff && - part->address != factory_part->address) { - uint8_t buf[4096]; - uint32_t n; - /* - * we are a FACTORY image running in an OTA slot... - * it means we were just written and need to copy - * ourselves into the FACTORY slot. - */ - lwsl_notice("Copying FACTORY update into place " - "0x%x len 0x%x\n", factory_part->address, - factory_part->size); - esp_task_wdt_reset(); - if (spi_flash_erase_range(factory_part->address, - factory_part->size)) { - lwsl_err("spi: Failed to erase\n"); - goto retry; - } - - for (n = 0; n < factory_part->size; n += sizeof(buf)) { - esp_task_wdt_reset(); - spi_flash_read(part->address + n , buf, - sizeof(buf)); - if (spi_flash_write(factory_part->address + n, - buf, sizeof(buf))) { - lwsl_err("spi: Failed to write\n"); - goto retry; - } - } - - /* - * We send a message to the bootloader to erase the OTA header, we will come back up in - * factory where the user can reload the OTA image - */ - lwsl_notice(" FACTORY copy successful, rebooting\n"); - lws_esp32_restart_guided(LWS_MAGIC_REBOOT_TYPE_REQ_FACTORY_ERASE_OTA); -retry: - esp_restart(); - } -#endif - - return part; -} - - -void -lws_esp32_set_creation_defaults(struct lws_context_creation_info *info) -{ - const esp_partition_t *part; - - memset(info, 0, sizeof(*info)); - - lws_set_log_level(63, lwsl_emit_syslog); - - part = lws_esp_ota_get_boot_partition(); - (void)part; - - info->vhost_name = "default"; - info->port = 443; - info->fd_limit_per_thread = 16; - info->max_http_header_pool = 5; - info->max_http_header_data = 1024; - info->pt_serv_buf_size = 4096; - info->keepalive_timeout = 30; - info->timeout_secs = 30; - info->simultaneous_ssl_restriction = 2; - info->options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | - LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; -} - -int -lws_esp32_get_image_info(const esp_partition_t *part, struct lws_esp32_image *i, - char *json, int json_len) -{ - esp_image_segment_header_t eis; - esp_image_header_t eih; - uint32_t hdr; - - spi_flash_read(part->address , &eih, sizeof(eih)); - hdr = part->address + sizeof(eih); - - if (eih.magic != ESP_IMAGE_HEADER_MAGIC) { - lwsl_notice("%s: bad image header magic\n", __func__); - return 1; - } - - eis.data_len = 0; - while (eih.segment_count-- && eis.data_len != 0xffffffff) { - spi_flash_read(hdr, &eis, sizeof(eis)); - hdr += sizeof(eis) + eis.data_len; - } - hdr += (~hdr & 15) + 1; - - if (eih.hash_appended) - hdr += 0x20; - -// lwsl_notice("romfs estimated at 0x%x\n", hdr); - - i->romfs = hdr + 0x4; - spi_flash_read(hdr, &i->romfs_len, sizeof(i->romfs_len)); - i->json = i->romfs + i->romfs_len + 4; - spi_flash_read(i->json - 4, &i->json_len, sizeof(i->json_len)); - - if (i->json_len < json_len - 1) - json_len = i->json_len; - spi_flash_read(i->json, json, json_len); - json[json_len] = '\0'; - - return 0; -} - -static int -_rngf(void *context, unsigned char *buf, size_t len) -{ - if (lws_get_random(context, buf, len) == len) - return 0; - - return -1; -} - -int -lws_esp32_selfsigned(struct lws_vhost *vhost) -{ - mbedtls_x509write_cert crt; - char subject[200]; - mbedtls_pk_context mpk; - int buf_size = 4096, n; - uint8_t *buf = malloc(buf_size); /* malloc because given to user code */ - mbedtls_mpi mpi; - nvs_handle nvh; - size_t s; - - lwsl_notice("%s: %s\n", __func__, vhost->name); - - if (!buf) - return -1; - - if (nvs_open("lws-station", NVS_READWRITE, &nvh)) { - lwsl_notice("%s: can't open nvs\n", __func__); - free(buf); - return 1; - } - - n = 0; - if (!nvs_get_blob(nvh, vhost->tls.alloc_cert_path, NULL, &s)) - n |= 1; - if (!nvs_get_blob(nvh, vhost->tls.key_path, NULL, &s)) - n |= 2; - - nvs_close(nvh); - if (n == 3) { - lwsl_notice("%s: certs exist\n", __func__); - free(buf); - return 0; /* certs already exist */ - } - - lwsl_notice("%s: creating selfsigned initial certs\n", __func__); - - mbedtls_x509write_crt_init(&crt); - - mbedtls_pk_init(&mpk); - if (mbedtls_pk_setup(&mpk, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA))) { - lwsl_notice("%s: pk_setup failed\n", __func__); - goto fail; - } - lwsl_notice("%s: generating 2048-bit RSA keypair... " - "this may take a minute or so...\n", __func__); - n = mbedtls_rsa_gen_key(mbedtls_pk_rsa(mpk), _rngf, vhost->context, - 2048, 65537); - if (n) { - lwsl_notice("%s: failed to generate keys\n", __func__); - goto fail1; - } - lwsl_notice("%s: keys done\n", __func__); - - /* subject must be formatted like "C=TW,O=warmcat,CN=myserver" */ - - lws_snprintf(subject, sizeof(subject) - 1, - "C=TW,ST=New Taipei City,L=Taipei,O=warmcat,CN=%s", - lws_esp32.hostname); - - if (mbedtls_x509write_crt_set_subject_name(&crt, subject)) { - lwsl_notice("set SN failed\n"); - goto fail1; - } - mbedtls_x509write_crt_set_subject_key(&crt, &mpk); - if (mbedtls_x509write_crt_set_issuer_name(&crt, subject)) { - lwsl_notice("set IN failed\n"); - goto fail1; - } - mbedtls_x509write_crt_set_issuer_key(&crt, &mpk); - - lws_get_random(vhost->context, &n, sizeof(n)); - lws_snprintf(subject, sizeof(subject), "%d", n); - - mbedtls_mpi_init(&mpi); - mbedtls_mpi_read_string(&mpi, 10, subject); - mbedtls_x509write_crt_set_serial(&crt, &mpi); - mbedtls_mpi_free(&mpi); - - mbedtls_x509write_crt_set_validity(&crt, "20171105235959", - "20491231235959"); - - mbedtls_x509write_crt_set_key_usage(&crt, - MBEDTLS_X509_KU_DIGITAL_SIGNATURE | - MBEDTLS_X509_KU_KEY_ENCIPHERMENT); - - - mbedtls_x509write_crt_set_md_alg(&crt, MBEDTLS_MD_SHA256); - - n = mbedtls_x509write_crt_pem(&crt, buf, buf_size, _rngf, - vhost->context); - if (n < 0) { - lwsl_notice("%s: write crt der failed\n", __func__); - goto fail1; - } - - lws_plat_write_cert(vhost, 0, 0, buf, strlen((const char *)buf)); - - if (mbedtls_pk_write_key_pem(&mpk, buf, buf_size)) { - lwsl_notice("write key pem failed\n"); - goto fail1; - } - - lws_plat_write_cert(vhost, 1, 0, buf, strlen((const char *)buf)); - - mbedtls_pk_free(&mpk); - mbedtls_x509write_crt_free(&crt); - - lwsl_notice("%s: cert creation complete\n", __func__); - - return n; - -fail1: - mbedtls_pk_free(&mpk); -fail: - mbedtls_x509write_crt_free(&crt); - free(buf); - - nvs_close(nvh); - - return -1; -} - -void -lws_esp32_update_acme_info(void) -{ - int n; - - n = lws_plat_read_file("acme-email", lws_esp32.le_email, - sizeof(lws_esp32.le_email) - 1); - if (n >= 0) - lws_esp32.le_email[n] = '\0'; - - n = lws_plat_read_file("acme-cn", lws_esp32.le_dns, - sizeof(lws_esp32.le_dns) - 1); - if (n >= 0) - lws_esp32.le_dns[n] = '\0'; -} - -struct lws_context * -lws_esp32_init(struct lws_context_creation_info *info, struct lws_vhost **pvh) -{ - const esp_partition_t *part = lws_esp_ota_get_boot_partition(); - struct lws_context *context; - struct lws_esp32_image i; - struct lws_vhost *vhost; - struct lws wsi; - char buf[512]; - - context = lws_create_context(info); - if (context == NULL) { - lwsl_err("Failed to create context\n"); - return NULL; - } - - lws_esp32_get_image_info(part, &i, buf, sizeof(buf) - 1); - - lws_esp32_romfs = (romfs_t)i.romfs; - if (!romfs_mount_check(lws_esp32_romfs)) { - lwsl_err("mount error on ROMFS at %p 0x%x\n", lws_esp32_romfs, - i.romfs); - return NULL; - } - - lwsl_notice("ROMFS length %uKiB\n", i.romfs_len >> 10); - - puts(buf); - - /* set the lws vfs to use our romfs */ -#if defined(LWS_WITH_FILE_OPS) - lws_set_fops(context, &fops); -#endif - - info->options |= LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX | - LWS_SERVER_OPTION_IGNORE_MISSING_CERT; - - vhost = lws_create_vhost(context, info); - if (!vhost) { - lwsl_err("Failed to create vhost\n"); - return NULL; - } - - lws_esp32_update_acme_info(); - - lws_esp32_selfsigned(vhost); - wsi.context = vhost->context; - wsi.vhost = vhost; - - lws_tls_server_certs_load(vhost, &wsi, info->ssl_cert_filepath, - info->ssl_private_key_filepath, NULL, 0, NULL, 0); - - lws_init_vhost_client_ssl(info, vhost); - - if (pvh) - *pvh = vhost; - - if (lws_protocol_init(context)) - return NULL; - - return context; -} - -static const uint16_t sineq16[] = { - 0x0000, 0x0191, 0x031e, 0x04a4, 0x061e, 0x0789, 0x08e2, 0x0a24, - 0x0b4e, 0x0c5c, 0x0d4b, 0x0e1a, 0x0ec6, 0x0f4d, 0x0faf, 0x0fea, -}; - -static uint16_t sine_lu(int n) -{ - switch ((n >> 4) & 3) { - case 1: - return 4096 + sineq16[n & 15]; - case 2: - return 4096 + sineq16[15 - (n & 15)]; - case 3: - return 4096 - sineq16[n & 15]; - default: - return 4096 - sineq16[15 - (n & 15)]; - } -} - -/* useful for sine led fade patterns */ - -uint16_t lws_esp32_sine_interp(int n) -{ - /* - * 2: quadrant - * 4: table entry in quadrant - * 4: interp (LSB) - * - * total 10 bits / 1024 steps per cycle - * - * + 0: 0 - * + 256: 4096 - * + 512: 8192 - * + 768: 4096 - * +1023: 0 - */ - - return (sine_lu(n >> 4) * (15 - (n & 15)) + - sine_lu((n >> 4) + 1) * (n & 15)) / 15; -} diff -Nru libwebsockets-4.0.20/lib/plat/freertos/freertos-file.c libwebsockets-4.1.6/lib/plat/freertos/freertos-file.c --- libwebsockets-4.0.20/lib/plat/freertos/freertos-file.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/freertos/freertos-file.c 2020-12-01 17:40:26.000000000 +0000 @@ -135,7 +135,7 @@ q = string; n = 0; - while (n < sizeof(buf) - 1 && q != p) + while ((size_t)n < sizeof(buf) - 1 && q != p) buf[n++] = *q++; buf[n] = '\0'; diff -Nru libwebsockets-4.0.20/lib/plat/freertos/freertos-init.c libwebsockets-4.1.6/lib/plat/freertos/freertos-init.c --- libwebsockets-4.0.20/lib/plat/freertos/freertos-init.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/freertos/freertos-init.c 2020-12-01 17:40:26.000000000 +0000 @@ -33,7 +33,7 @@ void lws_plat_context_early_destroy(struct lws_context *context) { -#if defined(LWS_AMAZON_RTOS) +#if defined(LWS_AMAZON_RTOS) && defined(LWS_WITH_MBEDTLS) mbedtls_ctr_drbg_free(&context->mcdc); mbedtls_entropy_free(&context->mec); #endif @@ -73,7 +73,7 @@ lws_plat_init(struct lws_context *context, const struct lws_context_creation_info *info) { -#if defined(LWS_AMAZON_RTOS) +#if defined(LWS_AMAZON_RTOS) && defined(LWS_WITH_MBEDTLS) int n; /* initialize platform random through mbedtls */ @@ -111,5 +111,9 @@ context->set = lws_h2_defaults_esp32; #endif +#if defined(LWS_ESP_PLATFORM) + gpio_install_isr_service(0); +#endif + return 0; } diff -Nru libwebsockets-4.0.20/lib/plat/freertos/freertos-misc.c libwebsockets-4.1.6/lib/plat/freertos/freertos-misc.c --- libwebsockets-4.0.20/lib/plat/freertos/freertos-misc.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/freertos/freertos-misc.c 2020-12-01 17:40:26.000000000 +0000 @@ -24,6 +24,18 @@ #include "private-lib-core.h" +/* + * Normally you don't want this, use lws_sul instead inside the event loop. + * But sometimes for drivers it makes sense, so there's an internal-only + * crossplatform api for it. + */ + +void +lws_msleep(unsigned int ms) +{ + vTaskDelay(portTICK_PERIOD_MS > ms ? 1 : ms / portTICK_PERIOD_MS); +} + lws_usec_t lws_now_usecs(void) { @@ -43,7 +55,7 @@ uint8_t *p = (uint8_t *)&r; int b = 4; - if (len < b) + if (len < (size_t)b) b = len; len -= b; @@ -54,6 +66,7 @@ return pb - (uint8_t *)buf; #else +#if defined(LWS_WITH_MBEDTLS) int n; n = mbedtls_ctr_drbg_random(&context->mcdc, buf, len); @@ -63,7 +76,7 @@ /* failed */ lwsl_err("%s: mbedtls_ctr_drbg_random returned 0x%x\n", __func__, n); - +#endif return 0; #endif } diff -Nru libwebsockets-4.0.20/lib/plat/freertos/freertos-pipe.c libwebsockets-4.1.6/lib/plat/freertos/freertos-pipe.c --- libwebsockets-4.0.20/lib/plat/freertos/freertos-pipe.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/freertos/freertos-pipe.c 2020-12-01 17:40:26.000000000 +0000 @@ -27,14 +27,18 @@ int lws_plat_pipe_create(struct lws *wsi) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; - struct sockaddr_in *si = &wsi->context->frt_pipe_si; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; + struct sockaddr_in *si = &wsi->a.context->frt_pipe_si; lws_sockfd_type *fd = pt->dummy_pipe_fds; + socklen_t sl; /* * 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. + * + * 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); @@ -53,11 +57,26 @@ si->sin_family = AF_INET; 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) 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; bail: @@ -69,8 +88,8 @@ int lws_plat_pipe_signal(struct lws *wsi) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; - struct sockaddr_in *si = &wsi->context->frt_pipe_si; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; + struct sockaddr_in *si = &wsi->a.context->frt_pipe_si; lws_sockfd_type *fd = pt->dummy_pipe_fds; uint8_t u = 0; int n; @@ -95,7 +114,7 @@ void lws_plat_pipe_close(struct lws *wsi) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; lws_sockfd_type *fd = pt->dummy_pipe_fds; if (fd[0] && fd[0] != -1) diff -Nru libwebsockets-4.0.20/lib/plat/freertos/freertos-resolv.c libwebsockets-4.1.6/lib/plat/freertos/freertos-resolv.c --- libwebsockets-4.0.20/lib/plat/freertos/freertos-resolv.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/freertos/freertos-resolv.c 2020-12-01 17:40:26.000000000 +0000 @@ -24,6 +24,7 @@ #include "private-lib-core.h" +#if defined(LWS_WITH_SYS_ASYNC_DNS) lws_async_dns_server_check_t lws_plat_asyncdns_init(struct lws_context *context, lws_sockaddr46 *sa46) { @@ -40,3 +41,14 @@ return s; } +#endif + +int +lws_plat_ntpclient_config(struct lws_context *context) +{ + lws_system_blob_heap_append(lws_system_get_blob(context, + LWS_SYSBLOB_TYPE_NTP_SERVER, 0), + (const uint8_t *)"pool.ntp.org", 12); + + return 0; +} diff -Nru libwebsockets-4.0.20/lib/plat/freertos/freertos-service.c libwebsockets-4.1.6/lib/plat/freertos/freertos-service.c --- libwebsockets-4.0.20/lib/plat/freertos/freertos-service.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/freertos/freertos-service.c 2020-12-01 17:40:26.000000000 +0000 @@ -46,7 +46,7 @@ /* stay dead once we are dead */ - if (!context || !context->vhost_list) + if (!context) return 1; pt = &context->pt[tsi]; @@ -57,19 +57,19 @@ if (m > context->time_last_state_dump) { context->time_last_state_dump = m; -#if defined(LWS_AMAZON_RTOS) - n = xPortGetFreeHeapSize(); -#else +#if defined(LWS_ESP_PLATFORM) n = esp_get_free_heap_size(); +#else + n = xPortGetFreeHeapSize(); #endif if ((unsigned int)n != context->last_free_heap) { if ((unsigned int)n > context->last_free_heap) - lwsl_notice(" heap :%ld (+%ld)\n", + lwsl_debug(" heap :%ld (+%ld)\n", (unsigned long)n, (unsigned long)(n - context->last_free_heap)); else - lwsl_notice(" heap :%ld (-%ld)\n", + lwsl_debug(" heap :%ld (-%ld)\n", (unsigned long)n, (unsigned long)( context->last_free_heap - @@ -86,15 +86,14 @@ timeout_ms = 2000000000; timeout_us = ((lws_usec_t)timeout_ms) * LWS_US_PER_MS; - if (!pt->service_tid_detected) { - struct lws *_lws = pt->fake_wsi; + if (!pt->service_tid_detected && context->vhost_list) { + lws_fakewsi_def_plwsa(pt); - if (!_lws) - return 1; - _lws->context = context; + lws_fakewsi_prep_plwsa_ctx(context); pt->service_tid = context->vhost_list->protocols[0].callback( - _lws, LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0); + (struct lws *)plwsa, LWS_CALLBACK_GET_THREAD_ID, + NULL, NULL, 0); pt->service_tid_detected = 1; } @@ -110,7 +109,9 @@ lws_pt_lock(pt, __func__); /* don't stay in poll wait longer than next hr timeout */ - us = __lws_sul_service_ripe(&pt->pt_sul_owner, lws_now_usecs()); + us = __lws_sul_service_ripe(pt->pt_sul_owner, + LWS_COUNT_PT_SUL_OWNERS, + lws_now_usecs()); if (us && us < timeout_us) timeout_us = us; @@ -177,10 +178,11 @@ m |= !!pt->ws.rx_draining_ext_list; #endif +#if defined(LWS_WITH_TLS) if (pt->context->tls_ops && pt->context->tls_ops->fake_POLLIN_for_buffered) m |= pt->context->tls_ops->fake_POLLIN_for_buffered(pt); - +#endif if (!m && !n) return 0; } else diff -Nru libwebsockets-4.0.20/lib/plat/freertos/freertos-sockets.c libwebsockets-4.1.6/lib/plat/freertos/freertos-sockets.c --- libwebsockets-4.0.20/lib/plat/freertos/freertos-sockets.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/freertos/freertos-sockets.c 2020-12-01 17:40:26.000000000 +0000 @@ -23,6 +23,14 @@ */ #include "private-lib-core.h" +#include +#if defined(LWS_WITH_MBEDTLS) +#if defined(LWS_HAVE_MBEDTLS_NET_SOCKETS) +#include "mbedtls/net_sockets.h" +#else +#include "mbedtls/net.h" +#endif +#endif int lws_send_pipe_choked(struct lws *wsi) @@ -259,3 +267,56 @@ return -1; } + +#if defined(LWS_WITH_MBEDTLS) +int +lws_plat_mbedtls_net_send(void *ctx, const uint8_t *buf, size_t len) +{ + int fd = ((mbedtls_net_context *) ctx)->fd; + int ret; + + if (fd < 0) + return MBEDTLS_ERR_NET_INVALID_CONTEXT; + + ret = write(fd, buf, len); + if (ret >= 0) + return ret; + + if (errno == EAGAIN || errno == EWOULDBLOCK) + return MBEDTLS_ERR_SSL_WANT_WRITE; + + if (errno == EPIPE || errno == ECONNRESET) + return MBEDTLS_ERR_NET_CONN_RESET; + + if( errno == EINTR ) + return MBEDTLS_ERR_SSL_WANT_WRITE; + + return MBEDTLS_ERR_NET_SEND_FAILED; +} + +int +lws_plat_mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len) +{ + int fd = ((mbedtls_net_context *) ctx)->fd; + int ret; + + if (fd < 0) + return MBEDTLS_ERR_NET_INVALID_CONTEXT; + + ret = (int)read(fd, buf, len); + if (ret >= 0) + return ret; + + if (errno == EAGAIN || errno == EWOULDBLOCK) + return MBEDTLS_ERR_SSL_WANT_READ; + + if (errno == EPIPE || errno == ECONNRESET) + return MBEDTLS_ERR_NET_CONN_RESET; + + if (errno == EINTR || !errno) + return MBEDTLS_ERR_SSL_WANT_READ; + + return MBEDTLS_ERR_NET_RECV_FAILED; +} +#endif + diff -Nru libwebsockets-4.0.20/lib/plat/freertos/private-lib-plat-freertos.h libwebsockets-4.1.6/lib/plat/freertos/private-lib-plat-freertos.h --- libwebsockets-4.0.20/lib/plat/freertos/private-lib-plat-freertos.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/freertos/private-lib-plat-freertos.h 2020-12-01 17:40:26.000000000 +0000 @@ -24,7 +24,9 @@ * Included from lib/private-lib-core.h if LWS_PLAT_FREERTOS */ +#if !defined(LWS_ESP_PLATFORM) #define SOMAXCONN 3 +#endif #if defined(LWS_AMAZON_RTOS) int @@ -43,7 +45,6 @@ #ifndef __cplusplus #include #endif - #include #include #if defined(LWS_AMAZON_RTOS) const char * @@ -59,6 +60,7 @@ #endif #include "timers.h" #include + #include #else #include "freertos/timers.h" #include @@ -68,8 +70,15 @@ #if defined(LWS_WITH_ESP32) #include "lwip/apps/sntp.h" +#include #endif +typedef SemaphoreHandle_t lws_mutex_t; +#define lws_mutex_init(x) x = xSemaphoreCreateMutex() +#define lws_mutex_destroy(x) vSemaphoreDelete(x) +#define lws_mutex_lock(x) xSemaphoreTake(x, portMAX_DELAY) +#define lws_mutex_unlock(x) xSemaphoreGive(x) + #include #if defined(LWS_BUILTIN_GETIFADDRS) @@ -110,3 +119,14 @@ #define delete_from_fd(A,B) A->lws_lookup[B - lws_plat_socket_offset()] = 0 +#define LWS_PLAT_TIMER_TYPE TimerHandle_t +#define LWS_PLAT_TIMER_CB(name, var) void name(TimerHandle_t var) +#define LWS_PLAT_TIMER_CB_GET_OPAQUE(x) pvTimerGetTimerID(x) +#define LWS_PLAT_TIMER_CREATE(name, interval, repeat, opaque, cb) \ + xTimerCreate(name, pdMS_TO_TICKS(interval) ? pdMS_TO_TICKS(interval) : 1, \ + repeat ? pdTRUE : 0, opaque, cb) +#define LWS_PLAT_TIMER_DELETE(ptr) xTimerDelete(ptr, 0) +#define LWS_PLAT_TIMER_START(ptr) xTimerStart(ptr, 0) +#define LWS_PLAT_TIMER_STOP(ptr) xTimerStop(ptr, 0) + + diff -Nru libwebsockets-4.0.20/lib/plat/optee/CMakeLists.txt libwebsockets-4.1.6/lib/plat/optee/CMakeLists.txt --- libwebsockets-4.0.20/lib/plat/optee/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/optee/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,49 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +list(APPEND SOURCES + plat/optee/lws-plat-optee.c +) +if (LWS_WITH_NETWORK) + list(APPEND SOURCES + plat/optee/network.c + ) +endif() + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --sysroot ../../../../lib/libutils/isoc/include -I../../../../lib/libutils/isoc/include -I../../../../lib/libutils/ext/include" ) + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() diff -Nru libwebsockets-4.0.20/lib/plat/optee/lws-plat-optee.c libwebsockets-4.1.6/lib/plat/optee/lws-plat-optee.c --- libwebsockets-4.0.20/lib/plat/optee/lws-plat-optee.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/optee/lws-plat-optee.c 2020-12-01 17:40:26.000000000 +0000 @@ -235,3 +235,27 @@ { return 4096; } + +int +lws_plat_ntpclient_config(struct lws_context *context) +{ +#if 0 + char *ntpsrv = getenv("LWS_NTP_SERVER"); + + if (ntpsrv && strlen(ntpsrv) < 64) { + lws_system_blob_heap_append(lws_system_get_blob(context, + LWS_SYSBLOB_TYPE_NTP_SERVER, 0), + (const uint8_t *)ntpsrv, + strlen(ntpsrv)); + return 1; + } +#endif + return 0; +} + +void +lws_msleep(unsigned int ms) +{ +} + + diff -Nru libwebsockets-4.0.20/lib/plat/optee/network.c libwebsockets-4.1.6/lib/plat/optee/network.c --- libwebsockets-4.0.20/lib/plat/optee/network.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/optee/network.c 2020-12-01 17:40:26.000000000 +0000 @@ -24,6 +24,13 @@ #include "private-lib-core.h" +#if defined(LWS_WITH_MBEDTLS) +#if defined(LWS_HAVE_MBEDTLS_NET_SOCKETS) +#include "mbedtls/net_sockets.h" +#else +#include "mbedtls/net.h" +#endif +#endif int lws_plat_pipe_create(struct lws *wsi) @@ -89,7 +96,7 @@ /* stay dead once we are dead */ - if (!context || !context->vhost_list) + if (!context) return 1; pt = &context->pt[tsi]; @@ -99,7 +106,7 @@ else timeout_ms = 2000000000; - if (!pt->service_tid_detected) { + if (!pt->service_tid_detected && context->vhost_list) { struct lws _lws; memset(&_lws, 0, sizeof(_lws)); @@ -121,7 +128,9 @@ lws_pt_lock(pt, __func__); /* don't stay in poll wait longer than next hr timeout */ - us = __lws_sul_service_ripe(&pt->pt_sul_owner, lws_now_usecs()); + us = __lws_sul_service_ripe(pt->pt_sul_owner, + LWS_COUNT_PT_SUL_OWNERS, + lws_now_usecs()); if (us && us < timeout_us) timeout_us = us; @@ -247,4 +256,55 @@ return 1; } +#if defined(LWS_WITH_MBEDTLS) +int +lws_plat_mbedtls_net_send(void *ctx, const uint8_t *buf, size_t len) +{ + int fd = ((mbedtls_net_context *) ctx)->fd; + int ret; + + if (fd < 0) + return MBEDTLS_ERR_NET_INVALID_CONTEXT; + + ret = write(fd, buf, len); + if (ret >= 0) + return ret; + + if (errno == EAGAIN || errno == EWOULDBLOCK) + return MBEDTLS_ERR_SSL_WANT_WRITE; + + if (errno == EPIPE || errno == ECONNRESET) + return MBEDTLS_ERR_NET_CONN_RESET; + + if( errno == EINTR ) + return MBEDTLS_ERR_SSL_WANT_WRITE; + + return MBEDTLS_ERR_NET_SEND_FAILED; +} +int +lws_plat_mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len) +{ + int fd = ((mbedtls_net_context *) ctx)->fd; + int ret; + + if (fd < 0) + return MBEDTLS_ERR_NET_INVALID_CONTEXT; + + ret = (int)read(fd, buf, len); + if (ret >= 0) + return ret; + + if (errno == EAGAIN || errno == EWOULDBLOCK) + return MBEDTLS_ERR_SSL_WANT_READ; + + if (errno == EPIPE || errno == ECONNRESET) + return MBEDTLS_ERR_NET_CONN_RESET; + + if (errno == EINTR) + return MBEDTLS_ERR_SSL_WANT_READ; + + return MBEDTLS_ERR_NET_RECV_FAILED; +} + +#endif diff -Nru libwebsockets-4.0.20/lib/plat/unix/CMakeLists.txt libwebsockets-4.1.6/lib/plat/unix/CMakeLists.txt --- libwebsockets-4.0.20/lib/plat/unix/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/unix/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,109 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +execute_process( COMMAND grep -c illumos /lib/ld.so.1 + OUTPUT_VARIABLE ILLUMOS ERROR_QUIET ) +# Chomp the \n at end of output. +string(REGEX REPLACE "[\n]+" "" ILLUMOS "${ILLUMOS}") + +if (NOT ${ILLUMOS} MATCHES "0") + set(ILLUMOS 1) +endif() + +set(LWS_PLAT_UNIX 1) +list(APPEND SOURCES + plat/unix/unix-caps.c + plat/unix/unix-misc.c + plat/unix/unix-init.c +) +if (LWS_WITH_FILE_OPS) + list(APPEND SOURCES plat/unix/unix-file.c) +endif() +if (LWS_WITH_NETWORK) + list(APPEND SOURCES + plat/unix/unix-pipe.c + plat/unix/unix-service.c + plat/unix/unix-sockets.c + plat/unix/unix-fds.c + ) + if (LWS_WITH_SYS_ASYNC_DNS) + if (LWS_PLAT_ANDROID) + list(APPEND SOURCES plat/unix/android/android-resolv.c) + else() + list(APPEND SOURCES plat/unix/unix-resolv.c) + endif() + endif() +endif() + +if (LWS_WITH_PLUGINS_API) + list(APPEND SOURCES plat/unix/unix-plugins.c) +endif() + +if (LWS_WITH_SPAWN) + list(APPEND SOURCES plat/unix/unix-spawn.c) +endif() + +if (HAIKU) + set(CMAKE_REQUIRED_LIBRARIES network) + list(APPEND LIB_LIST_AT_END network) +endif() + +IF (CMAKE_SYSTEM_NAME STREQUAL Linux) + CHECK_FUNCTION_EXISTS(eventfd_read LWS_HAVE_EVENTFD) +endif() + +list(APPEND LIB_LIST_AT_END m) + +if (ILLUMOS) + list(APPEND LIB_LIST_AT_END socket) +endif() + +if (LWS_HAVE_LIBCAP) + list(APPEND LIB_LIST_AT_END cap) +endif() + +if (${CMAKE_SYSTEM_NAME} MATCHES "QNX") + list(APPEND LIB_LIST_AT_END socket) +endif() + +list(APPEND LIB_LIST_AT_END dl) + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() +set(LWS_PLAT_UNIX ${LWS_PLAT_UNIX} PARENT_SCOPE) +set(ILLUMOS ${ILLUMOS} PARENT_SCOPE) +set(LIB_LIST_AT_END ${LIB_LIST_AT_END} PARENT_SCOPE) +set(LWS_PLAT_UNIX ${LWS_PLAT_UNIX} PARENT_SCOPE) diff -Nru libwebsockets-4.0.20/lib/plat/unix/private-lib-plat-unix.h libwebsockets-4.1.6/lib/plat/unix/private-lib-plat-unix.h --- libwebsockets-4.0.20/lib/plat/unix/private-lib-plat-unix.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/unix/private-lib-plat-unix.h 2020-12-01 17:40:26.000000000 +0000 @@ -75,6 +75,15 @@ #endif #endif +#if defined(LWS_HAVE_PTHREAD_H) +#include +typedef pthread_mutex_t lws_mutex_t; +#define lws_mutex_init(x) pthread_mutex_init(&(x), NULL) +#define lws_mutex_destroy(x) pthread_mutex_destroy(&(x)) +#define lws_mutex_lock(x) pthread_mutex_lock(&(x)) +#define lws_mutex_unlock(x) pthread_mutex_unlock(&(x)) +#endif + #if defined(__sun) && defined(__GNUC__) #include @@ -166,6 +175,7 @@ #endif #define compatible_close(x) close(x) +#define compatible_file_close(fd) close(fd) #define lws_plat_socket_offset() (0) /* @@ -173,6 +183,8 @@ * but happily have something equivalent in the SO_NOSIGPIPE flag. */ #ifdef __APPLE__ +/* iOS SDK 12+ seems to define it, undef it for compatibility both ways */ +#undef MSG_NOSIGNAL #define MSG_NOSIGNAL SO_NOSIGPIPE #endif diff -Nru libwebsockets-4.0.20/lib/plat/unix/unix-caps.c libwebsockets-4.1.6/lib/plat/unix/unix-caps.c --- libwebsockets-4.0.20/lib/plat/unix/unix-caps.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/unix/unix-caps.c 2020-12-01 17:40:26.000000000 +0000 @@ -172,7 +172,9 @@ context->count_caps); #endif - initgroups(p->pw_name, context->gid); + if (initgroups(p->pw_name, context->gid)) + return 1; + if (setuid(context->uid)) { lwsl_err("%s: setuid: %s failed\n", __func__, strerror(LWS_ERRNO)); diff -Nru libwebsockets-4.0.20/lib/plat/unix/unix-fds.c libwebsockets-4.1.6/lib/plat/unix/unix-fds.c --- libwebsockets-4.0.20/lib/plat/unix/unix-fds.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/unix/unix-fds.c 2020-12-01 17:40:26.000000000 +0000 @@ -49,11 +49,85 @@ return NULL; } +#if defined(_DEBUG) +int +sanity_assert_no_wsi_traces(const struct lws_context *context, struct lws *wsi) +{ + struct lws **p, **done; + + if (!context->max_fds_unrelated_to_ulimit) + /* can't tell */ + return 0; + + /* slow fds handling */ + + p = context->lws_lookup; + done = &p[context->max_fds]; + + /* confirm the wsi doesn't already exist */ + + while (p != done && *p != wsi) + p++; + + if (p == done) + return 0; + + assert(0); /* this wsi is still mentioned inside lws */ + + return 1; +} + +int +sanity_assert_no_sockfd_traces(const struct lws_context *context, + lws_sockfd_type sfd) +{ +#if LWS_MAX_SMP > 1 + /* + * We can't really do this test... another thread can accept and + * reuse the closed fd + */ + return 0; +#else + struct lws **p, **done; + + if (sfd == LWS_SOCK_INVALID) + return 0; + + if (!context->max_fds_unrelated_to_ulimit && + context->lws_lookup[sfd - lws_plat_socket_offset()]) { + assert(0); /* the fd is still in use */ + return 1; + } + + /* slow fds handling */ + + p = context->lws_lookup; + done = &p[context->max_fds]; + + /* confirm the sfd not already in use */ + + while (p != done && (!*p || (*p)->desc.sockfd != sfd)) + p++; + + if (p == done) + return 0; + + assert(0); /* this fd is still in the tables */ + + return 1; +#endif +} +#endif + + int insert_wsi(const struct lws_context *context, struct lws *wsi) { struct lws **p, **done; + if (sanity_assert_no_wsi_traces(context, wsi)) + return 0; + if (!context->max_fds_unrelated_to_ulimit) { assert(context->lws_lookup[wsi->desc.sockfd - lws_plat_socket_offset()] == 0); @@ -69,28 +143,12 @@ p = context->lws_lookup; done = &p[context->max_fds]; -#if defined(_DEBUG) - - /* confirm it doesn't already exist */ - - while (p != done && *p != wsi) - p++; - - assert(p == done); - p = context->lws_lookup; - - /* confirm fd doesn't already exist */ + /* confirm fd isn't already in use by a wsi */ - while (p != done && (!*p || (*p)->desc.sockfd != wsi->desc.sockfd)) - p++; + if (sanity_assert_no_sockfd_traces(context, wsi->desc.sockfd)) + return 0; - if (p != done) { - lwsl_err("%s: wsi %p already says it has fd %d\n", - __func__, *p, wsi->desc.sockfd); - assert(0); - } p = context->lws_lookup; -#endif /* find an empty slot */ @@ -107,6 +165,8 @@ return 0; } + + void delete_from_fd(const struct lws_context *context, int fd) { @@ -130,7 +190,7 @@ p++; if (p == done) - lwsl_err("%s: fd %d not found\n", __func__, fd); + lwsl_debug("%s: fd %d not found\n", __func__, fd); else *p = NULL; @@ -148,6 +208,30 @@ } void +delete_from_fdwsi(const struct lws_context *context, struct lws *wsi) +{ + + struct lws **p, **done; + + if (!context->max_fds_unrelated_to_ulimit) + return; + + + /* slow fds handling */ + + p = context->lws_lookup; + done = &p[context->max_fds]; + + /* find the match */ + + while (p != done && (!*p || (*p) != wsi)) + p++; + + if (p != done) + *p = NULL; +} + +void lws_plat_insert_socket_into_fds(struct lws_context *context, struct lws *wsi) { struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; diff -Nru libwebsockets-4.0.20/lib/plat/unix/unix-init.c libwebsockets-4.1.6/lib/plat/unix/unix-init.c --- libwebsockets-4.0.20/lib/plat/unix/unix-init.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/unix/unix-init.c 2020-12-01 17:40:26.000000000 +0000 @@ -75,7 +75,23 @@ lws_context_unlock(context); #endif - __lws_sul_insert(&pt->pt_sul_owner, &pt->sul_plat, 30 * LWS_US_PER_SEC); + __lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], + &pt->sul_plat, 30 * LWS_US_PER_SEC); +} +#endif + +#if defined(LWS_WITH_PLUGINS) +static int +protocol_plugin_cb(struct lws_plugin *pin, void *each_user) +{ + struct lws_context *context = (struct lws_context *)each_user; + const lws_plugin_protocol_t *plpr = + (const lws_plugin_protocol_t *)pin->hdr; + + context->plugin_protocol_count += plpr->count_protocols; + context->plugin_extension_count += plpr->count_extensions; + + return 0; } #endif @@ -126,14 +142,16 @@ #endif context->fd_random = fd; if (context->fd_random < 0) { - lwsl_err("Unable to open random device %s %d\n", - SYSTEM_RANDOM_FILEPATH, context->fd_random); + lwsl_err("Unable to open random device %s %d, errno %d\n", + SYSTEM_RANDOM_FILEPATH, context->fd_random, errno); return 1; } #if defined(LWS_WITH_PLUGINS) if (info->plugin_dirs) - lws_plat_plugins_init(context, info->plugin_dirs); + lws_plugins_init(&context->plugin_list, info->plugin_dirs, + "lws_protocol_plugin", NULL, + protocol_plugin_cb, context); #endif @@ -141,8 +159,8 @@ /* we only need to do this on pt[0] */ context->pt[0].sul_plat.cb = lws_sul_plat_unix; - __lws_sul_insert(&context->pt[0].pt_sul_owner, &context->pt[0].sul_plat, - 30 * LWS_US_PER_SEC); + __lws_sul_insert_us(&context->pt[0].pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], + &context->pt[0].sul_plat, 30 * LWS_US_PER_SEC); #endif return 0; @@ -166,9 +184,9 @@ void lws_plat_context_late_destroy(struct lws_context *context) { -#ifdef LWS_WITH_PLUGINS +#if defined(LWS_WITH_PLUGINS) if (context->plugin_list) - lws_plat_plugins_destroy(context); + lws_plugins_destroy(&context->plugin_list, NULL, NULL); #endif #if defined(LWS_WITH_NETWORK) if (context->lws_lookup) diff -Nru libwebsockets-4.0.20/lib/plat/unix/unix-misc.c libwebsockets-4.1.6/lib/plat/unix/unix-misc.c --- libwebsockets-4.0.20/lib/plat/unix/unix-misc.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/unix/unix-misc.c 2020-12-01 17:40:26.000000000 +0000 @@ -27,6 +27,18 @@ #endif #include "private-lib-core.h" +/* + * Normally you don't want this, use lws_sul instead inside the event loop. + * But sometimes for drivers it makes sense, so there's an internal-only + * crossplatform api for it. + */ + +void +lws_msleep(unsigned int ms) +{ + usleep(ms * LWS_US_PER_MS); +} + lws_usec_t lws_now_usecs(void) { @@ -89,7 +101,8 @@ n = write(fd, buf, len); - fsync(fd); + if (fsync(fd)) + return 1; if (lseek(fd, 0, SEEK_SET) < 0) return 1; diff -Nru libwebsockets-4.0.20/lib/plat/unix/unix-pipe.c libwebsockets-4.1.6/lib/plat/unix/unix-pipe.c --- libwebsockets-4.0.20/lib/plat/unix/unix-pipe.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/unix/unix-pipe.c 2020-12-01 17:40:26.000000000 +0000 @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2020 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -27,15 +27,17 @@ #endif #include "private-lib-core.h" - int lws_plat_pipe_create(struct lws *wsi) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; + #if defined(LWS_HAVE_EVENTFD) - pt->dummy_pipe_fds[0] = eventfd(0, EFD_CLOEXEC|EFD_NONBLOCK); + pt->dummy_pipe_fds[0] = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); pt->dummy_pipe_fds[1] = -1; - return pt->dummy_pipe_fds[0]<0?-1:0; + + return pt->dummy_pipe_fds[0] < 0 ? -1 : 0; + #elif defined(LWS_HAVE_PIPE2) return pipe2(pt->dummy_pipe_fds, O_NONBLOCK); #else @@ -46,9 +48,10 @@ int lws_plat_pipe_signal(struct lws *wsi) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; #if defined(LWS_HAVE_EVENTFD) eventfd_t value = 1; + return eventfd_write(pt->dummy_pipe_fds[0], value); #else char buf = 0; @@ -63,7 +66,7 @@ void lws_plat_pipe_close(struct lws *wsi) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; if (pt->dummy_pipe_fds[0] && pt->dummy_pipe_fds[0] != -1) close(pt->dummy_pipe_fds[0]); diff -Nru libwebsockets-4.0.20/lib/plat/unix/unix-plugins.c libwebsockets-4.1.6/lib/plat/unix/unix-plugins.c --- libwebsockets-4.0.20/lib/plat/unix/unix-plugins.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/unix/unix-plugins.c 2020-12-01 17:40:26.000000000 +0000 @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2020 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -29,154 +29,77 @@ #include #include - -#ifdef LWS_WITH_PLUGINS #include -#endif -#include -static int filter(const struct dirent *ent) +const lws_plugin_header_t * +lws_plat_dlopen(struct lws_plugin **pplugin, const char *libpath, + const char *sofilename, const char *_class, + each_plugin_cb_t each, void *each_user) { - if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) - return 0; - - return 1; -} - -int -lws_plat_plugins_init(struct lws_context * context, const char * const *d) -{ - struct lws_plugin_capability lcaps; - struct lws_plugin *plugin; - lws_plugin_init_func initfunc; - struct dirent **namelist; - int n, i, m, ret = 0; - char path[256]; + const lws_plugin_header_t *hdr; + struct lws_plugin *pin; + char sym[96]; void *l; + int m; -#if defined(LWS_WITH_PLUGINS) && (UV_VERSION_MAJOR > 0) - if (lws_check_opt(context->options, LWS_SERVER_OPTION_LIBUV)) - return lws_uv_plugins_init(context, d); -#endif + if (strlen(sofilename) < 6) + /* [lib]...[.so] */ + return NULL; + + l = dlopen(libpath, RTLD_NOW); + if (!l) { + lwsl_err("%s: Error loading DSO: %s\n", __func__, dlerror()); - lwsl_notice(" Plugins:\n"); + return NULL; + } - while (d && *d) { - n = scandir(*d, &namelist, filter, alphasort); - if (n < 0) { - lwsl_err("Scandir on %s failed\n", *d); - return 1; - } - - for (i = 0; i < n; i++) { - if (strlen(namelist[i]->d_name) < 7) - goto inval; - - lwsl_notice(" %s\n", namelist[i]->d_name); - - lws_snprintf(path, sizeof(path) - 1, "%s/%s", *d, - namelist[i]->d_name); - l = dlopen(path, RTLD_NOW); - if (!l) { - lwsl_err("Error loading DSO: %s\n", dlerror()); - while (i++ < n) - free(namelist[i]); - goto bail; - } - /* we could open it, can we get his init function? */ - m = lws_snprintf(path, sizeof(path) - 1, "init_%s", - namelist[i]->d_name + 3 /* snip lib... */); - path[m - 3] = '\0'; /* snip the .so */ - initfunc = dlsym(l, path); - if (!initfunc) { - lwsl_err("%s: Failed to get init '%s' on %s: %s\n", - __func__, path, namelist[i]->d_name, dlerror()); - goto skip; - } - lcaps.api_magic = LWS_PLUGIN_API_MAGIC; - m = initfunc(context, &lcaps); - if (m) { - lwsl_err("Initializing %s failed %d\n", - namelist[i]->d_name, m); - goto skip; - } - - plugin = lws_malloc(sizeof(*plugin), "plugin"); - if (!plugin) { - dlclose(l); - lwsl_err("OOM\n"); - goto bail; - } - plugin->list = context->plugin_list; - context->plugin_list = plugin; - lws_strncpy(plugin->name, namelist[i]->d_name, - sizeof(plugin->name)); - plugin->l = l; - plugin->caps = lcaps; - context->plugin_protocol_count += lcaps.count_protocols; - context->plugin_extension_count += lcaps.count_extensions; - - free(namelist[i]); - continue; - - skip: - dlclose(l); - inval: - free(namelist[i]); - } - free(namelist); - d++; + /* we could open it... can we get his export struct? */ + m = lws_snprintf(sym, sizeof(sym) - 1, "%s", sofilename); + if (m < 4) + goto bail; + if (!strcmp(&sym[m - 3], ".so")) + sym[m - 3] = '\0'; /* snip the .so */ + + hdr = (const lws_plugin_header_t *)dlsym(l, sym); + if (!hdr) { + lwsl_err("%s: Failed to get export '%s' from %s: %s\n", + __func__, sym, libpath, dlerror()); + goto bail; } - return 0; + if (hdr->api_magic != LWS_PLUGIN_API_MAGIC) { + lwsl_err("%s: plugin %s has outdated api %d (vs %d)\n", + __func__, libpath, hdr->api_magic, + LWS_PLUGIN_API_MAGIC); + goto bail; + } -bail: - free(namelist); + if (strcmp(hdr->_class, _class)) + goto bail; - return ret; -} + pin = lws_malloc(sizeof(*pin), __func__); + if (!pin) + goto bail; -int -lws_plat_plugins_destroy(struct lws_context * context) -{ - struct lws_plugin *plugin = context->plugin_list, *p; - lws_plugin_destroy_func func; - char path[256]; - int m; + pin->list = *pplugin; + *pplugin = pin; -#if defined(LWS_WITH_PLUGINS) && (UV_VERSION_MAJOR > 0) - if (lws_check_opt(context->options, LWS_SERVER_OPTION_LIBUV)) - return lws_uv_plugins_destroy(context); -#endif + pin->u.l = l; + pin->hdr = hdr; - if (!plugin) - return 0; + if (each) + each(pin, each_user); - lwsl_notice("%s\n", __func__); + return hdr; - while (plugin) { - p = plugin; - m = lws_snprintf(path, sizeof(path) - 1, "destroy_%s", - plugin->name + 3); - path[m - 3] = '\0'; - func = dlsym(plugin->l, path); - if (!func) { - lwsl_err("Failed to get destroy on %s: %s", - plugin->name, dlerror()); - goto next; - } - m = func(context); - if (m) - lwsl_err("Initializing %s failed %d\n", - plugin->name, m); -next: - dlclose(p->l); - plugin = p->list; - p->list = NULL; - free(p); - } +bail: + dlclose(l); - context->plugin_list = NULL; + return NULL; +} - return 0; +int +lws_plat_destroy_dl(struct lws_plugin *p) +{ + return dlclose(p->u.l); } diff -Nru libwebsockets-4.0.20/lib/plat/unix/unix-resolv.c libwebsockets-4.1.6/lib/plat/unix/unix-resolv.c --- libwebsockets-4.0.20/lib/plat/unix/unix-resolv.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/unix/unix-resolv.c 2020-12-01 17:40:26.000000000 +0000 @@ -28,10 +28,12 @@ lws_plat_asyncdns_init(struct lws_context *context, lws_sockaddr46 *sa46) { lws_async_dns_server_check_t s = LADNS_CONF_SERVER_CHANGED; - char resolv[512], ads[48]; lws_sockaddr46 sa46t; lws_tokenize_t ts; int fd, n, ns = 0; + char ads[48], *r; + + r = (char *)context->pt[0].serv_buf; /* grab the first chunk of /etc/resolv.conf */ @@ -39,17 +41,17 @@ if (fd < 0) return LADNS_CONF_SERVER_UNKNOWN; - n = read(fd, resolv, sizeof(resolv) - 1); + n = read(fd, r, context->pt_serv_buf_size - 1); close(fd); if (n < 0) return LADNS_CONF_SERVER_UNKNOWN; - resolv[n] = '\0'; - lws_tokenize_init(&ts, resolv, LWS_TOKENIZE_F_DOT_NONTERM | - LWS_TOKENIZE_F_NO_FLOATS | - LWS_TOKENIZE_F_NO_INTEGERS | - LWS_TOKENIZE_F_MINUS_NONTERM | - LWS_TOKENIZE_F_HASH_COMMENT); + r[n] = '\0'; + lws_tokenize_init(&ts, r, LWS_TOKENIZE_F_DOT_NONTERM | + LWS_TOKENIZE_F_NO_FLOATS | + LWS_TOKENIZE_F_NO_INTEGERS | + LWS_TOKENIZE_F_MINUS_NONTERM | + LWS_TOKENIZE_F_HASH_COMMENT); do { ts.e = lws_tokenize(&ts); if (ts.e != LWS_TOKZE_TOKEN) { @@ -86,3 +88,24 @@ return LADNS_CONF_SERVER_UNKNOWN; } + +/* + * Platform-specific ntpclient server configuration + */ + +int +lws_plat_ntpclient_config(struct lws_context *context) +{ +#if defined(LWS_HAVE_GETENV) + char *ntpsrv = getenv("LWS_NTP_SERVER"); + + if (ntpsrv && strlen(ntpsrv) < 64) { + lws_system_blob_direct_set(lws_system_get_blob(context, + LWS_SYSBLOB_TYPE_NTP_SERVER, 0), + (const uint8_t *)ntpsrv, + strlen(ntpsrv)); + return 1; + } +#endif + return 0; +} diff -Nru libwebsockets-4.0.20/lib/plat/unix/unix-service.c libwebsockets-4.1.6/lib/plat/unix/unix-service.c --- libwebsockets-4.0.20/lib/plat/unix/unix-service.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/unix/unix-service.c 2020-12-01 17:40:26.000000000 +0000 @@ -71,14 +71,14 @@ volatile struct lws_context_per_thread *vpt; struct lws_context_per_thread *pt; lws_usec_t timeout_us, us; - int n = -1; + int n; #if (defined(LWS_ROLE_WS) && !defined(LWS_WITHOUT_EXTENSIONS)) || defined(LWS_WITH_TLS) int m; #endif /* stay dead once we are dead */ - if (!context || !context->vhost_list) + if (!context) return 1; pt = &context->pt[tsi]; @@ -96,14 +96,14 @@ if (context->event_loop_ops->run_pt) context->event_loop_ops->run_pt(context, tsi); - if (!pt->service_tid_detected) { - struct lws _lws; + if (!pt->service_tid_detected && context->vhost_list) { + lws_fakewsi_def_plwsa(pt); - memset(&_lws, 0, sizeof(_lws)); - _lws.context = context; + lws_fakewsi_prep_plwsa_ctx(context); pt->service_tid = context->vhost_list->protocols[0].callback( - &_lws, LWS_CALLBACK_GET_THREAD_ID, + (struct lws *)plwsa, + LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0); pt->service_tid_detected = 1; } @@ -113,7 +113,7 @@ /* * service ripe scheduled events, and limit wait to next expected one */ - us = __lws_sul_service_ripe(&pt->pt_sul_owner, us); + us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS, us); if (us && us < timeout_us) timeout_us = us; diff -Nru libwebsockets-4.0.20/lib/plat/unix/unix-sockets.c libwebsockets-4.1.6/lib/plat/unix/unix-sockets.c --- libwebsockets-4.0.20/lib/plat/unix/unix-sockets.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/unix/unix-sockets.c 2020-12-01 17:40:26.000000000 +0000 @@ -38,7 +38,13 @@ #include #include - +#if defined(LWS_WITH_MBEDTLS) +#if defined(LWS_HAVE_MBEDTLS_NET_SOCKETS) +#include "mbedtls/net_sockets.h" +#else +#include "mbedtls/net.h" +#endif +#endif int lws_send_pipe_choked(struct lws *wsi) @@ -197,9 +203,13 @@ struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr; #endif - getifaddrs(&ifr); + if (getifaddrs(&ifr)) { + lwsl_err("%s: unable to getifaddrs: errno %d\n", __func__, errno); + + return LWS_ITOSA_USABLE; + } for (ifc = ifr; ifc != NULL && rc; ifc = ifc->ifa_next) { - if (!ifc->ifa_addr) + if (!ifc->ifa_addr || !ifc->ifa_name) continue; lwsl_debug(" interface %s vs %s (fam %d) ipv6 %d\n", @@ -399,7 +409,6 @@ uint8_t *gateway_ip) { #if defined(__linux__) - struct sockaddr_in *addr; struct sockaddr_in sin; struct rtentry route; struct ifreq ifr; @@ -430,17 +439,12 @@ lws_plat_if_up(ifname, fd, 1); - addr = (struct sockaddr_in *)&route.rt_gateway; - addr->sin_family = AF_INET; - addr->sin_addr.s_addr = htonl(*(uint32_t *)gateway_ip); - - addr = (struct sockaddr_in *)&route.rt_dst; - addr->sin_family = AF_INET; - addr->sin_addr.s_addr = 0; - - addr = (struct sockaddr_in *)&route.rt_genmask; - addr->sin_family = AF_INET; - addr->sin_addr.s_addr = 0; + sin.sin_addr.s_addr = htonl(*(uint32_t *)gateway_ip); + memcpy(&route.rt_gateway, &sin, sizeof(struct sockaddr)); + + sin.sin_addr.s_addr = 0; + memcpy(&route.rt_dst, &sin, sizeof(struct sockaddr)); + memcpy(&route.rt_genmask, &sin, sizeof(struct sockaddr)); route.rt_flags = RTF_UP | RTF_GATEWAY; route.rt_metric = 100; @@ -459,3 +463,55 @@ return -1; #endif } + +#if defined(LWS_WITH_MBEDTLS) +int +lws_plat_mbedtls_net_send(void *ctx, const uint8_t *buf, size_t len) +{ + int fd = ((mbedtls_net_context *) ctx)->fd; + int ret; + + if (fd < 0) + return MBEDTLS_ERR_NET_INVALID_CONTEXT; + + ret = write(fd, buf, len); + if (ret >= 0) + return ret; + + if (errno == EAGAIN || errno == EWOULDBLOCK) + return MBEDTLS_ERR_SSL_WANT_WRITE; + + if (errno == EPIPE || errno == ECONNRESET) + return MBEDTLS_ERR_NET_CONN_RESET; + + if( errno == EINTR ) + return MBEDTLS_ERR_SSL_WANT_WRITE; + + return MBEDTLS_ERR_NET_SEND_FAILED; +} + +int +lws_plat_mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len) +{ + int fd = ((mbedtls_net_context *) ctx)->fd; + int ret; + + if (fd < 0) + return MBEDTLS_ERR_NET_INVALID_CONTEXT; + + ret = (int)read(fd, buf, len); + if (ret >= 0) + return ret; + + if (errno == EAGAIN || errno == EWOULDBLOCK) + return MBEDTLS_ERR_SSL_WANT_READ; + + if (errno == EPIPE || errno == ECONNRESET) + return MBEDTLS_ERR_NET_CONN_RESET; + + if (errno == EINTR) + return MBEDTLS_ERR_SSL_WANT_READ; + + return MBEDTLS_ERR_NET_RECV_FAILED; +} +#endif diff -Nru libwebsockets-4.0.20/lib/plat/unix/unix-spawn.c libwebsockets-4.1.6/lib/plat/unix/unix-spawn.c --- libwebsockets-4.0.20/lib/plat/unix/unix-spawn.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/unix/unix-spawn.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,593 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2020 Andy Green + * + * 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. + */ + +#if !defined(_GNU_SOURCE) +#define _GNU_SOURCE +#endif + +#include "private-lib-core.h" +#include + +void +lws_spawn_timeout(struct lws_sorted_usec_list *sul) +{ + struct lws_spawn_piped *lsp = lws_container_of(sul, + struct lws_spawn_piped, sul); + + lwsl_warn("%s: spawn exceeded timeout, killing\n", __func__); + + lws_spawn_piped_kill_child_process(lsp); +} + +void +lws_spawn_sul_reap(struct lws_sorted_usec_list *sul) +{ + struct lws_spawn_piped *lsp = lws_container_of(sul, + struct lws_spawn_piped, sul_reap); + + lwsl_notice("%s: reaping spawn after last stdpipe, tries left %d\n", + __func__, lsp->reap_retry_budget); + if (!lws_spawn_reap(lsp) && !lsp->pipes_alive) { + if (--lsp->reap_retry_budget) { + lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi, + &lsp->sul_reap, lws_spawn_sul_reap, + 250 * LWS_US_PER_MS); + } else { + lwsl_err("%s: Unable to reap lsp %p, killing\n", + __func__, lsp); + lsp->reap_retry_budget = 20; + lws_spawn_piped_kill_child_process(lsp); + } + } +} + +static struct lws * +lws_create_basic_wsi(struct lws_context *context, int tsi, + const struct lws_role_ops *ops) +{ + size_t s = sizeof(struct lws); + struct lws *new_wsi; + + if (!context->vhost_list) + return NULL; + + if ((unsigned int)context->pt[tsi].fds_count == + context->fd_limit_per_thread - 1) { + lwsl_err("no space for new conn\n"); + return NULL; + } + +#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) { + lwsl_err("Out of memory for new connection\n"); + 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->a.context = context; + new_wsi->pending_timeout = NO_PENDING_TIMEOUT; + new_wsi->rxflow_change_to = LWS_RXFLOW_ALLOW; + + /* initialize the instance struct */ + + lws_role_transition(new_wsi, 0, LRS_ESTABLISHED, ops); + + new_wsi->hdr_parsing_completed = 0; + new_wsi->position_in_fds_table = LWS_NO_FDS_POS; + + /* + * these can only be set once the protocol is known + * we set an unestablished connection's protocol pointer + * to the start of the defauly vhost supported list, so it can look + * for matching ones during the handshake + */ + + new_wsi->user_space = NULL; + new_wsi->desc.sockfd = LWS_SOCK_INVALID; + context->count_wsi_allocated++; + + return new_wsi; +} + +void +lws_spawn_piped_destroy(struct lws_spawn_piped **_lsp) +{ + struct lws_spawn_piped *lsp = *_lsp; + int n; + + if (!lsp) + return; + + lws_dll2_remove(&lsp->dll); + + lws_sul_cancel(&lsp->sul); + lws_sul_cancel(&lsp->sul_reap); + + for (n = 0; n < 3; n++) { +#if 0 + if (lsp->pipe_fds[n][!!(n == 0)] == 0) + lwsl_err("ZERO FD IN CGI CLOSE"); + + if (lsp->pipe_fds[n][!!(n == 0)] >= 0) { + close(lsp->pipe_fds[n][!!(n == 0)]); + lsp->pipe_fds[n][!!(n == 0)] = LWS_SOCK_INVALID; + } +#endif + if (lsp->stdwsi[n]) { + lws_set_timeout(lsp->stdwsi[n], 1, LWS_TO_KILL_ASYNC); + lsp->stdwsi[n] = NULL; + } + } + + lws_free_set_NULL((*_lsp)); +} + +int +lws_spawn_reap(struct lws_spawn_piped *lsp) +{ + long hz = sysconf(_SC_CLK_TCK); /* accounting Hz */ + void *opaque = lsp->info.opaque; + lsp_cb_t cb = lsp->info.reap_cb; + struct lws_spawn_piped temp; + struct tms tms; + int n; + + if (lsp->child_pid < 1) + return 0; + + /* check if exited, do not reap yet */ + + memset(&lsp->si, 0, sizeof(lsp->si)); + n = waitid(P_PID, lsp->child_pid, &lsp->si, WEXITED | WNOHANG | WNOWAIT); + if (n < 0) { + lwsl_info("%s: child %d still running\n", __func__, lsp->child_pid); + return 0; + } + + if (!lsp->si.si_code) + return 0; + + /* his process has exited... */ + + if (!lsp->reaped) { + /* mark the earliest time we knew he had gone */ + lsp->reaped = lws_now_usecs(); + + /* + * Switch the timeout to restrict the amount of grace time + * to drain stdwsi + */ + + lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi, + &lsp->sul, lws_spawn_timeout, + 5 * LWS_US_PER_SEC); + } + + /* + * Stage finalizing our reaction to the process going down until the + * stdwsi flushed whatever is in flight and all noticed they were + * closed. For that reason, each stdwsi close must call lws_spawn_reap + * to check if that was the last one and we can proceed with the reap. + */ + + if (!lsp->ungraceful && lsp->pipes_alive) { + lwsl_info("%s: %d stdwsi alive, not reaping\n", __func__, + lsp->pipes_alive); + return 0; + } + + /* we reached the reap point, no need for timeout wait */ + + lws_sul_cancel(&lsp->sul); + + /* + * All the stdwsi went down, nothing more is coming... it's over + * Collect the final information and then reap the dead process + */ + + if (times(&tms) != (clock_t) -1) { + /* + * Cpu accounting in us + */ + lsp->accounting[0] = ((uint64_t)tms.tms_cstime * 1000000) / hz; + lsp->accounting[1] = ((uint64_t)tms.tms_cutime * 1000000) / hz; + lsp->accounting[2] = ((uint64_t)tms.tms_stime * 1000000) / hz; + lsp->accounting[3] = ((uint64_t)tms.tms_utime * 1000000) / hz; + } + + temp = *lsp; + n = waitid(P_PID, lsp->child_pid, &temp.si, WEXITED | WNOHANG); + temp.si.si_status &= 0xff; /* we use b8 + for flags */ + lwsl_info("%s: waitd says %d, process exit %d\n", + __func__, n, temp.si.si_status); + + lsp->child_pid = -1; + + /* destroy the lsp itself first (it's freed and plsp set NULL */ + + if (lsp->info.plsp) + lws_spawn_piped_destroy(lsp->info.plsp); + + /* then do the parent callback informing it's destroyed */ + + if (cb) + cb(opaque, temp.accounting, &temp.si, + temp.we_killed_him_timeout | + (temp.we_killed_him_spew << 1)); + + return 1; /* was reaped */ +} + +int +lws_spawn_piped_kill_child_process(struct lws_spawn_piped *lsp) +{ + int status, n; + + if (lsp->child_pid <= 0) + return 1; + + lsp->ungraceful = 1; /* don't wait for flushing, just kill it */ + + if (lws_spawn_reap(lsp)) + /* that may have invalidated lsp */ + return 0; + + /* kill the process group */ + n = kill(-lsp->child_pid, SIGTERM); + lwsl_debug("%s: SIGTERM child PID %d says %d (errno %d)\n", __func__, + lsp->child_pid, n, errno); + if (n < 0) { + /* + * hum seen errno=3 when process is listed in ps, + * it seems we don't always retain process grouping + * + * Direct these fallback attempt to the exact child + */ + n = kill(lsp->child_pid, SIGTERM); + if (n < 0) { + n = kill(lsp->child_pid, SIGPIPE); + if (n < 0) { + n = kill(lsp->child_pid, SIGKILL); + if (n < 0) + lwsl_info("%s: SIGKILL PID %d " + "failed errno %d " + "(maybe zombie)\n", __func__, + lsp->child_pid, errno); + } + } + } + + /* He could be unkillable because he's a zombie */ + + n = 1; + while (n > 0) { + n = waitpid(-lsp->child_pid, &status, WNOHANG); + if (n > 0) + lwsl_debug("%s: reaped PID %d\n", __func__, n); + if (n <= 0) { + n = waitpid(lsp->child_pid, &status, WNOHANG); + if (n > 0) + lwsl_debug("%s: reaped PID %d\n", __func__, n); + } + } + + lws_spawn_reap(lsp); + /* that may have invalidated lsp */ + + return 0; +} + +/* + * Deals with spawning a subprocess and executing it securely with stdin/out/err + * diverted into pipes + */ + +struct lws_spawn_piped * +lws_spawn_piped(const struct lws_spawn_piped_info *i) +{ + const struct lws_protocols *pcol = i->vh->context->vhost_list->protocols; + struct lws_context *context = i->vh->context; + struct lws_spawn_piped *lsp; + const char *wd; + int n, m; + + if (i->protocol_name) + pcol = lws_vhost_name_to_protocol(i->vh, i->protocol_name); + if (!pcol) { + lwsl_err("%s: unknown protocol %s\n", __func__, + i->protocol_name ? i->protocol_name : "default"); + + return NULL; + } + + lsp = lws_zalloc(sizeof(*lsp), __func__); + if (!lsp) + return NULL; + + /* wholesale take a copy of info */ + lsp->info = *i; + lsp->reap_retry_budget = 20; + + /* + * Prepare the stdin / out / err pipes + */ + + for (n = 0; n < 3; n++) { + lsp->pipe_fds[n][0] = -1; + lsp->pipe_fds[n][1] = -1; + } + + /* create pipes for [stdin|stdout] and [stderr] */ + + for (n = 0; n < 3; n++) { + if (pipe(lsp->pipe_fds[n]) == -1) + goto bail1; + lws_plat_apply_FD_CLOEXEC(lsp->pipe_fds[n][n == 0]); + } + + /* + * At this point, we have 6 pipe fds open on lws side and no wsis + * bound to them + */ + + /* create wsis for each stdin/out/err fd */ + + for (n = 0; n < 3; n++) { + lsp->stdwsi[n] = lws_create_basic_wsi(i->vh->context, i->tsi, + i->ops ? i->ops : &role_ops_raw_file); + if (!lsp->stdwsi[n]) { + lwsl_err("%s: unable to create lsp stdwsi\n", __func__); + goto bail2; + } + lsp->stdwsi[n]->lsp_channel = n; + lws_vhost_bind_wsi(i->vh, lsp->stdwsi[n]); + lsp->stdwsi[n]->a.protocol = pcol; + lsp->stdwsi[n]->a.opaque_user_data = i->opaque; + + lwsl_debug("%s: lsp stdwsi %p: pipe idx %d -> fd %d / %d\n", __func__, + lsp->stdwsi[n], n, lsp->pipe_fds[n][n == 0], + lsp->pipe_fds[n][n != 0]); + + /* read side is 0, stdin we want the write side, others read */ + + lsp->stdwsi[n]->desc.sockfd = lsp->pipe_fds[n][n == 0]; + if (fcntl(lsp->pipe_fds[n][n == 0], F_SETFL, O_NONBLOCK) < 0) { + lwsl_err("%s: setting NONBLOCK failed\n", __func__); + goto bail2; + } + + /* + * We have bound 3 x pipe fds to wsis, wr side of stdin and rd + * side of stdout / stderr... those are marked CLOEXEC so they + * won't go through the fork + * + * rd side of stdin and wr side of stdout / stderr are open but + * not bound to anything on lws side. + */ + } + + /* + * Stitch the wsi fd into the poll wait + */ + + for (n = 0; n < 3; n++) { + if (context->event_loop_ops->sock_accept) + if (context->event_loop_ops->sock_accept(lsp->stdwsi[n])) + goto bail3; + + if (__insert_wsi_socket_into_fds(context, lsp->stdwsi[n])) + goto bail3; + if (i->opt_parent) { + lsp->stdwsi[n]->parent = i->opt_parent; + lsp->stdwsi[n]->sibling_list = i->opt_parent->child_list; + i->opt_parent->child_list = lsp->stdwsi[n]; + } + } + + if (lws_change_pollfd(lsp->stdwsi[LWS_STDIN], LWS_POLLIN, LWS_POLLOUT)) + goto bail3; + if (lws_change_pollfd(lsp->stdwsi[LWS_STDOUT], LWS_POLLOUT, LWS_POLLIN)) + goto bail3; + if (lws_change_pollfd(lsp->stdwsi[LWS_STDERR], LWS_POLLOUT, LWS_POLLIN)) + goto bail3; + + lwsl_info("%s: fds in %d, out %d, err %d\n", __func__, + lsp->stdwsi[LWS_STDIN]->desc.sockfd, + lsp->stdwsi[LWS_STDOUT]->desc.sockfd, + lsp->stdwsi[LWS_STDERR]->desc.sockfd); + + /* we are ready with the redirection pipes... do the (v)fork */ +#if !defined(LWS_HAVE_VFORK) || !defined(LWS_HAVE_EXECVPE) + lsp->child_pid = fork(); +#else + lsp->child_pid = vfork(); +#endif + if (lsp->child_pid < 0) { + lwsl_err("%s: fork failed, errno %d", __func__, errno); + goto bail3; + } + +#if defined(__linux__) + if (!lsp->child_pid) + prctl(PR_SET_PDEATHSIG, SIGTERM); +#endif + + if (lsp->info.disable_ctrlc) + /* stops non-daemonized main processess getting SIGINT + * from TTY */ +#if defined(__FreeBSD__) + setpgid(0, 0); +#else + setpgrp(); +#endif + + if (lsp->child_pid) { + + /* + * We are the parent process. We can close our copy of the + * "other" side of the pipe fds, ie, rd for stdin and wr for + * stdout / stderr. + */ + for (n = 0; n < 3; n++) + /* these guys didn't have any wsi footprint */ + close(lsp->pipe_fds[n][n != 0]); + + lsp->pipes_alive = 3; + lsp->created = lws_now_usecs(); + + lwsl_info("%s: lsp %p spawned PID %d\n", __func__, lsp, + lsp->child_pid); + + lws_sul_schedule(context, i->tsi, &lsp->sul, lws_spawn_timeout, + i->timeout_us ? i->timeout_us : + 300 * LWS_US_PER_SEC); + + if (i->owner) + lws_dll2_add_head(&lsp->dll, i->owner); + + if (i->timeout_us) + lws_sul_schedule(context, i->tsi, &lsp->sul, + lws_spawn_timeout, i->timeout_us); + + return lsp; + } + + /* + * We are the forked process, redirect and kill inherited things. + * + * Because of vfork(), we cannot do anything that changes pages in + * the parent environment. Stuff that changes kernel state for the + * process is OK. Stuff that happens after the execvpe() is OK. + */ + + if (i->chroot_path && chroot(i->chroot_path)) { + lwsl_err("%s: child chroot %s failed, errno %d\n", + __func__, i->chroot_path, errno); + + exit(2); + } + + /* cwd: somewhere we can at least read things and enter it */ + + wd = i->wd; + if (!wd) + wd = "/tmp"; + if (chdir(wd)) + lwsl_notice("%s: Failed to cd to %s\n", __func__, wd); + + /* + * Bind the child's stdin / out / err to its side of our pipes + */ + + for (m = 0; m < 3; m++) { + if (dup2(lsp->pipe_fds[m][m != 0], m) < 0) { + lwsl_err("%s: stdin dup2 failed\n", __func__); + goto bail3; + } + /* + * CLOEXEC on the lws-side of the pipe fds should have already + * dealt with closing those for the child perspective. + * + * Now it has done the dup, the child should close its original + * copies of its side of the pipes. + */ + + close(lsp->pipe_fds[m][m != 0]); + } + +#if !defined(LWS_HAVE_VFORK) || !defined(LWS_HAVE_EXECVPE) +#if defined(__linux__) || defined(__APPLE__) + m = 0; + while (i->env_array[m]){ + char *p = strchr(i->env_array[m], '='); + *p++ = '\0'; + setenv(i->env_array[m], p, 1); + m++; + } +#endif + execvp(i->exec_array[0], (char * const *)&i->exec_array[0]); +#else + execvpe(i->exec_array[0], (char * const *)&i->exec_array[0], + &i->env_array[0]); +#endif + + lwsl_err("%s: child exec of %s failed %d\n", __func__, i->exec_array[0], + LWS_ERRNO); + + _exit(1); + +bail3: + + while (--n >= 0) + __remove_wsi_socket_from_fds(lsp->stdwsi[n]); +bail2: + for (n = 0; n < 3; n++) + if (lsp->stdwsi[n]) + __lws_free_wsi(lsp->stdwsi[n]); + +bail1: + for (n = 0; n < 3; n++) { + if (lsp->pipe_fds[n][0] >= 0) + close(lsp->pipe_fds[n][0]); + if (lsp->pipe_fds[n][1] >= 0) + close(lsp->pipe_fds[n][1]); + } + + lws_free(lsp); + + lwsl_err("%s: failed\n", __func__); + + return NULL; +} + +void +lws_spawn_stdwsi_closed(struct lws_spawn_piped *lsp, struct lws *wsi) +{ + int n; + + assert(lsp); + lsp->pipes_alive--; + lwsl_debug("%s: pipes alive %d\n", __func__, lsp->pipes_alive); + if (!lsp->pipes_alive) + lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi, + &lsp->sul_reap, lws_spawn_sul_reap, 1); + + for (n = 0; n < 3; n++) + if (lsp->stdwsi[n] == wsi) + lsp->stdwsi[n] = NULL; +} + +int +lws_spawn_get_stdfd(struct lws *wsi) +{ + return wsi->lsp_channel; +} diff -Nru libwebsockets-4.0.20/lib/plat/windows/CMakeLists.txt libwebsockets-4.1.6/lib/plat/windows/CMakeLists.txt --- libwebsockets-4.0.20/lib/plat/windows/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/windows/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,103 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +list(APPEND SOURCES + plat/windows/windows-fds.c + plat/windows/windows-file.c + plat/windows/windows-init.c + plat/windows/windows-misc.c + plat/windows/windows-pipe.c + plat/windows/windows-plugins.c + plat/windows/windows-service.c + plat/windows/windows-sockets.c + ) +if (LWS_WITH_SYS_ASYNC_DNS) + list(APPEND SOURCES plat/windows/windows-resolv.c) +endif() + +if (LWS_WITH_SPAWN) + list(APPEND SOURCES plat/windows/windows-spawn.c) +endif() + +if (LWS_WITH_ZLIB AND LWS_WITH_BUNDLED_ZLIB) + set(WIN32_ZLIB_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../../win32port/zlib") + set(ZLIB_SRCS + ${WIN32_ZLIB_PATH}/adler32.c + ${WIN32_ZLIB_PATH}/compress.c + ${WIN32_ZLIB_PATH}/crc32.c + ${WIN32_ZLIB_PATH}/deflate.c + ${WIN32_ZLIB_PATH}/gzlib.c + ${WIN32_ZLIB_PATH}/gzread.c + ${WIN32_ZLIB_PATH}/gzwrite.c + ${WIN32_ZLIB_PATH}/infback.c + ${WIN32_ZLIB_PATH}/inffast.c + ${WIN32_ZLIB_PATH}/inflate.c + ${WIN32_ZLIB_PATH}/inftrees.c + ${WIN32_ZLIB_PATH}/trees.c + ${WIN32_ZLIB_PATH}/uncompr.c + ${WIN32_ZLIB_PATH}/zutil.c) + add_library(zlib_internal STATIC ${ZLIB_SRCS}) + set(ZLIB_INCLUDE_DIRS ${WIN32_ZLIB_PATH}) + set(ZLIB_LIBRARIES "") + set(ZLIB_FOUND 1) + # Make sure zlib_internal is compiled before the libs. + foreach (lib ${LWS_LIBRARIES}) + add_dependencies(${lib} zlib_internal) + endforeach() +endif() + +# Add helper files for Windows + +# (from ./lib perspective) +set(WIN32_HELPERS_PATH ../win32port/win32helpers) + +# from our perspective in ./lib/plat/windows +include_directories(../../${WIN32_HELPERS_PATH}) + +list(APPEND SOURCES + ${WIN32_HELPERS_PATH}/gettimeofday.c +) + +list(APPEND HDR_PRIVATE + ${WIN32_HELPERS_PATH}/gettimeofday.h +) + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() +set(WIN32_HELPERS_PATH ${WIN32_HELPERS_PATH} PARENT_SCOPE) +set(HDR_PRIVATE ${HDR_PRIVATE} PARENT_SCOPE) +set(ZLIB_FOUND ${ZLIB_FOUND} PARENT_SCOPE) +set(LIB_LIST_AT_END ${LIB_LIST_AT_END} PARENT_SCOPE) diff -Nru libwebsockets-4.0.20/lib/plat/windows/private-lib-plat-windows.h libwebsockets-4.1.6/lib/plat/windows/private-lib-plat-windows.h --- libwebsockets-4.0.20/lib/plat/windows/private-lib-plat-windows.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/windows/private-lib-plat-windows.h 2020-12-01 17:40:26.000000000 +0000 @@ -51,6 +51,7 @@ #define SHUT_WR SD_SEND #define compatible_close(fd) closesocket(fd) + #define compatible_file_close(fd) CloseHandle(fd) #define lws_set_blocking_send(wsi) wsi->sock_send_blocking = 1 #include @@ -63,6 +64,18 @@ #include #include +#if defined(LWS_WITH_UNIX_SOCK) +#include +#endif + +#if defined(LWS_HAVE_PTHREAD_H) +#define lws_mutex_t pthread_mutex_t +#define lws_mutex_init(x) pthread_mutex_init(&(x), NULL) +#define lws_mutex_destroy(x) pthread_mutex_destroy(&(x)) +#define lws_mutex_lock(x) pthread_mutex_lock(&(x)) +#define lws_mutex_unlock(x) pthread_mutex_unlock(&(x)) +#endif + #if !defined(LWS_HAVE_ATOLL) #if defined(LWS_HAVE__ATOI64) #define atoll _atoi64 diff -Nru libwebsockets-4.0.20/lib/plat/windows/windows-fds.c libwebsockets-4.1.6/lib/plat/windows/windows-fds.c --- libwebsockets-4.0.20/lib/plat/windows/windows-fds.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/windows/windows-fds.c 2020-12-01 17:40:26.000000000 +0000 @@ -73,7 +73,7 @@ return 0; } - lwsl_err("Failed to find fd %d requested for " + lwsl_debug("Failed to find fd %d requested for " "delete in hashtable\n", fd); return 1; } diff -Nru libwebsockets-4.0.20/lib/plat/windows/windows-init.c libwebsockets-4.1.6/lib/plat/windows/windows-init.c --- libwebsockets-4.0.20/lib/plat/windows/windows-init.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/windows/windows-init.c 2020-12-01 17:40:26.000000000 +0000 @@ -55,6 +55,21 @@ return 1; } +#if defined(LWS_WITH_PLUGINS) +static int +protocol_plugin_cb(struct lws_plugin *pin, void *each_user) +{ + struct lws_context *context = (struct lws_context *)each_user; + const lws_plugin_protocol_t *plpr = + (const lws_plugin_protocol_t *)pin->hdr; + + context->plugin_protocol_count += plpr->count_protocols; + context->plugin_extension_count += plpr->count_extensions; + + return 0; +} +#endif + int lws_plat_init(struct lws_context *context, const struct lws_context_creation_info *info) @@ -72,8 +87,10 @@ } while (n--) { + int m; 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); pt++; @@ -81,9 +98,11 @@ context->fd_random = 0; -#ifdef LWS_WITH_PLUGINS +#if defined(LWS_WITH_PLUGINS) if (info->plugin_dirs) - lws_plat_plugins_init(context, info->plugin_dirs); + lws_plat_plugins_init(&context->plugin_list, info->plugin_dirs, + "lws_protocol_plugin", + protocol_plugin_cb, context); #endif return 0; @@ -96,7 +115,9 @@ int n = context->count_threads; while (n--) { - WSACloseEvent(pt->events); + int m; + for (m = 0; m < WSA_MAXIMUM_WAIT_EVENTS; m++) + WSACloseEvent(pt->events[m]); DeleteCriticalSection(&pt->interrupt_lock); pt++; } @@ -107,6 +128,11 @@ { int n; +#ifdef LWS_WITH_PLUGINS + if (context->plugin_list) + lws_plugins_destroy(&context->plugin_list); +#endif + for (n = 0; n < FD_HASHTABLE_MODULUS; n++) { if (context->fd_hashtable[n].wsi) lws_free(context->fd_hashtable[n].wsi); diff -Nru libwebsockets-4.0.20/lib/plat/windows/windows-misc.c libwebsockets-4.1.6/lib/plat/windows/windows-misc.c --- libwebsockets-4.0.20/lib/plat/windows/windows-misc.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/windows/windows-misc.c 2020-12-01 17:40:26.000000000 +0000 @@ -27,6 +27,17 @@ #endif #include "private-lib-core.h" +/* + * Normally you don't want this, use lws_sul instead inside the event loop. + * But sometimes for drivers it makes sense, so there's an internal-only + * crossplatform api for it. + */ + +void +lws_msleep(unsigned int ms) +{ + Sleep(ms); +} lws_usec_t lws_now_usecs(void) diff -Nru libwebsockets-4.0.20/lib/plat/windows/windows-pipe.c libwebsockets-4.1.6/lib/plat/windows/windows-pipe.c --- libwebsockets-4.0.20/lib/plat/windows/windows-pipe.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/windows/windows-pipe.c 2020-12-01 17:40:26.000000000 +0000 @@ -36,12 +36,17 @@ int lws_plat_pipe_signal(struct lws *wsi) { - struct lws_context_per_thread *pt = &wsi->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); - pt->interrupt_requested = 1; + WSASetEvent(pt->events[0]); /* trigger the cancel event */ LeaveCriticalSection(&pt->interrupt_lock); - WSASetEvent(pt->events); /* trigger the cancel event */ return 0; } diff -Nru libwebsockets-4.0.20/lib/plat/windows/windows-plugins.c libwebsockets-4.1.6/lib/plat/windows/windows-plugins.c --- libwebsockets-4.0.20/lib/plat/windows/windows-plugins.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/windows/windows-plugins.c 2020-12-01 17:40:26.000000000 +0000 @@ -27,12 +27,119 @@ #endif #include "private-lib-core.h" +/* + * ie, if the plugins api needed at all + */ + +#if defined(LWS_WITH_PLUGINS_API) && (UV_VERSION_MAJOR > 0) + +const lws_plugin_header_t * +lws_plat_dlopen(struct lws_plugin **pplugin, const char *libpath, + const char *sofilename, const char *_class, + each_plugin_cb_t each, void *each_user) +{ + const lws_plugin_header_t *hdr; + struct lws_plugin *pin; + char sym[96], *dot; + uv_lib_t lib; + void *v; + int m; + + lib.errmsg = NULL; + lib.handle = NULL; + + if (uv_dlopen(libpath, &lib)) { + uv_dlerror(&lib); + lwsl_err("Error loading DSO: %s\n", lib.errmsg); + uv_dlclose(&lib); + return NULL; + } + + /* we could open it... can we get his export struct? */ + m = lws_snprintf(sym, sizeof(sym) - 1, "%s", sofilename); + if (m < 4) + goto bail; + dot = strchr(sym, '.'); + if (dot) + *dot = '\0'; /* snip the .so or .lib or what-have-you*/ + + if (uv_dlsym(&lib, sym, &v)) { + uv_dlerror(&lib); + lwsl_err("%s: Failed to get '%s' on %s: %s\n", + __func__, path, dent.name, lib.errmsg); + goto bail; + } + + hdr = (const lws_plugin_header_t *)v; + if (hdr->api_magic != LWS_PLUGIN_API_MAGIC) { + lwsl_err("%s: plugin %s has outdated api %d (vs %d)\n", + __func__, libpath, hdr->api_magic, + LWS_PLUGIN_API_MAGIC); + goto bail; + } + + if (strcmp(hdr->_class, _class)) + goto bail; + + pin = lws_malloc(sizeof(*pin), __func__); + if (!pin) + goto bail; + + pin->list = *pplugin; + *pplugin = pin; + + pin->u.lib = lib; + pin->hdr = hdr; + + if (each) + each(pin, each_user); + + return hdr; + +bail: + uv_dlclose(&lib); + + return NULL; +} + +int +lws_plat_destroy_dl(struct lws_plugin *p) +{ + return uv_dlclose(&p->u.lib); +} + +#endif + +/* + * Specifically for protocol plugins support + */ + +#if defined(LWS_WITH_PLUGINS) && (UV_VERSION_MAJOR > 0) + +static int +protocol_plugin_cb(struct lws_plugin *pin, void *each_user) +{ + struct lws_context *context = (struct lws_context *)each_user; + const lws_plugin_protocol_t *plpr = + (const lws_plugin_protocol_t *)pin->hdr; + + context->plugin_protocol_count += plpr->count_protocols; + context->plugin_extension_count += plpr->count_extensions; + + return 0; +} +#endif + int -lws_plat_plugins_init(struct lws_context * context, const char * const *d) +lws_plat_plugins_init(struct lws_context *context, const char * const *d) { #if defined(LWS_WITH_PLUGINS) && (UV_VERSION_MAJOR > 0) - if (lws_check_opt(context->options, LWS_SERVER_OPTION_LIBUV)) - return lws_uv_plugins_init(context, d); + if (info->plugin_dirs) { + uv_loop_init(&context->uv.loop); + lws_plugins_init(&context->plugin_list, info->plugin_dirs, + "lws_protocol_plugin", NULL, + protocol_plugin_cb, context); + } #endif return 0; @@ -42,8 +149,12 @@ lws_plat_plugins_destroy(struct lws_context * context) { #if defined(LWS_WITH_PLUGINS) && (UV_VERSION_MAJOR > 0) - if (lws_check_opt(context->options, LWS_SERVER_OPTION_LIBUV)) - return lws_uv_plugins_destroy(context); + if (lws_check_opt(context->options, LWS_SERVER_OPTION_LIBUV) && + context->plugin_list) { + lws_plugins_destroy(&context->plugin_list, NULL, NULL); + while (uv_loop_close(&context->uv.loop)) + ; + } #endif return 0; diff -Nru libwebsockets-4.0.20/lib/plat/windows/windows-resolv.c libwebsockets-4.1.6/lib/plat/windows/windows-resolv.c --- libwebsockets-4.0.20/lib/plat/windows/windows-resolv.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/windows/windows-resolv.c 2020-12-01 17:40:26.000000000 +0000 @@ -1,16 +1,4 @@ /* - * Adapted from tadns 1.1, from http://adns.sourceforge.net/ - * Original license --> - * - * Copyright (c) 2004-2005 Sergey Lyubka - * - * "THE BEER-WARE LICENSE" (Revision 42): - * Sergey Lyubka wrote this file. As long as you retain this notice you - * can do whatever you want with this stuff. If we meet some day, and you think - * this stuff is worth it, you can buy me a beer in return. - * - * Integrated into lws, largely rewritten and relicensed (as allowed above) - * * libwebsockets - small server side websockets and web server implementation * * Copyright (C) 2010 - 2019 Andy Green @@ -35,39 +23,44 @@ */ #include "private-lib-core.h" +#include lws_async_dns_server_check_t lws_plat_asyncdns_init(struct lws_context *context, lws_sockaddr46 *sa46) { - char subkey[512], value[128], *key = - "SYSTEM\\ControlSet001\\Services\\Tcpip\\Parameters\\Interfaces"; - HKEY hKey, hSub; - LONG err; - int i, n; + unsigned long ul; + FIXED_INFO fi; + int n; + + ul = sizeof(fi); + if (GetNetworkParams(&fi, &ul) != NO_ERROR) { + lwsl_err("%s: can't get dns servers\n", __func__); - if ((err = RegOpenKey(HKEY_LOCAL_MACHINE, key, &hKey)) != ERROR_SUCCESS) { - lwsl_err("%s: cannot open reg key %s: %d\n", __func__, key, err); - - return 1; + return LADNS_CONF_SERVER_UNKNOWN; } - for (i = 0; RegEnumKey(hKey, i, subkey, sizeof(subkey)) == ERROR_SUCCESS; i++) { - DWORD type, len = sizeof(value); + lwsl_info("%s: trying %s\n", __func__, + fi.DnsServerList.IpAddress.String); + n = lws_sa46_parse_numeric_address( + fi.DnsServerList.IpAddress.String, sa46); - if (RegOpenKey(hKey, subkey, &hSub) == ERROR_SUCCESS && - (RegQueryValueEx(hSub, "NameServer", 0, - &type, value, &len) == ERROR_SUCCESS || - RegQueryValueEx(hSub, "DhcpNameServer", 0, - &type, value, &len) == ERROR_SUCCESS)) { - n = lws_sa46_parse_numeric_address(value, sa46); - RegCloseKey(hSub); - RegCloseKey(hKey); - return n == 0 ? LADNS_CONF_SERVER_CHANGED : - LADNS_CONF_SERVER_UNKNOWN; - } - } - RegCloseKey(hKey); - - return LADNS_CONF_SERVER_UNKNOWN; + return n == 0 ? LADNS_CONF_SERVER_CHANGED : + LADNS_CONF_SERVER_UNKNOWN; } +int +lws_plat_ntpclient_config(struct lws_context *context) +{ +#if defined(LWS_HAVE_GETENV) + char *ntpsrv = getenv("LWS_NTP_SERVER"); + + if (ntpsrv && strlen(ntpsrv) < 64) { + lws_system_blob_heap_append(lws_system_get_blob(context, + LWS_SYSBLOB_TYPE_NTP_SERVER, 0), + (const uint8_t *)ntpsrv, + strlen(ntpsrv)); + return 1; + } +#endif + return 0; +} diff -Nru libwebsockets-4.0.20/lib/plat/windows/windows-service.c libwebsockets-4.1.6/lib/plat/windows/windows-service.c --- libwebsockets-4.0.20/lib/plat/windows/windows-service.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/windows/windows-service.c 2020-12-01 17:40:26.000000000 +0000 @@ -32,9 +32,9 @@ _lws_plat_service_forced_tsi(struct lws_context *context, int tsi) { struct lws_context_per_thread *pt = &context->pt[tsi]; - int m, n; + int m, n, r; - lws_service_flag_pending(context, tsi); + r = lws_service_flag_pending(context, tsi); /* any socket with events to service? */ for (n = 0; n < (int)pt->fds_count; n++) { @@ -51,9 +51,10 @@ lws_service_do_ripe_rxflow(pt); - return 0; + return r; } +extern void lws_client_conn_wait_timeout(lws_sorted_usec_list_t *sul); int _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) @@ -66,23 +67,21 @@ unsigned int i; DWORD ev; int n; - unsigned int eIdx; - int interrupt_requested; /* stay dead once we are dead */ - if (context == NULL || !context->vhost_list) + if (context == NULL) return 1; pt = &context->pt[tsi]; - if (!pt->service_tid_detected) { - struct lws _lws; + if (!pt->service_tid_detected && context->vhost_list) { + lws_fakewsi_def_plwsa(pt); - memset(&_lws, 0, sizeof(_lws)); - _lws.context = context; + lws_fakewsi_prep_plwsa_ctx(context); pt->service_tid = context->vhost_list-> - protocols[0].callback(&_lws, LWS_CALLBACK_GET_THREAD_ID, + protocols[0].callback((struct lws *)plwsa, + LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0); pt->service_tid_detected = 1; } @@ -125,100 +124,193 @@ } /* - * is there anybody with pending stuff that needs service forcing? - */ - if (!lws_service_adjust_timeout(context, 1, tsi)) - _lws_plat_service_forced_tsi(context, tsi); - - /* - * service pending callbakcs and get maximum wait time + * service pending callbacks and get maximum wait time */ { lws_usec_t us; lws_pt_lock(pt, __func__); /* don't stay in poll wait longer than next hr timeout */ - us = __lws_sul_service_ripe(&pt->pt_sul_owner, lws_now_usecs()); + us = __lws_sul_service_ripe(pt->pt_sul_owner, + LWS_COUNT_PT_SUL_OWNERS, + lws_now_usecs()); if (us && us < timeout_us) timeout_us = us; lws_pt_unlock(pt); } + if (_lws_plat_service_forced_tsi(context, tsi)) + timeout_us = 0; + + /* + * is there anybody with pending stuff that needs service forcing? + */ + + if (!lws_service_adjust_timeout(context, 1, tsi)) + 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++) - 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; + + 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); - interrupt_requested = pt->interrupt_requested; - pt->interrupt_requested = 0; + WSAResetEvent(pt->events[0]); LeaveCriticalSection(&pt->interrupt_lock); - if (interrupt_requested) { - lws_broadcast(pt, LWS_CALLBACK_EVENT_WAIT_CANCELLED, - NULL, 0); - return 0; - } + lws_broadcast(pt, LWS_CALLBACK_EVENT_WAIT_CANCELLED, NULL, 0); + + return 0; + } + + /* + * Otherwise at least fds[ev - 1] has something to do... + */ #if defined(LWS_WITH_TLS) - if (pt->context->tls_ops && - pt->context->tls_ops->fake_POLLIN_for_buffered) - pt->context->tls_ops->fake_POLLIN_for_buffered(pt); + if (pt->context->tls_ops && + pt->context->tls_ops->fake_POLLIN_for_buffered) + pt->context->tls_ops->fake_POLLIN_for_buffered(pt); #endif - for (eIdx = 0; eIdx < pt->fds_count; ++eIdx) { - unsigned int err; + /* + * POLLOUT for any fds that can + */ - if (WSAEnumNetworkEvents(pt->fds[eIdx].fd, pt->events, - &networkevents) == SOCKET_ERROR) { - lwsl_err("WSAEnumNetworkEvents() failed " - "with error %d\n", LWS_ERRNO); - return -1; + 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; + + /* handle fds[ev - 1] */ - if (!networkevents.lNetworkEvents) - networkevents.lNetworkEvents = LWS_POLLOUT; + if (WSAEnumNetworkEvents(pt->fds[ev - 1].fd, pt->events[ev], + &networkevents) == SOCKET_ERROR) { + lwsl_err("WSAEnumNetworkEvents() failed " + "with error %d\n", LWS_ERRNO); + return -1; + } - pfd = &pt->fds[eIdx]; - pfd->revents = (short)networkevents.lNetworkEvents; + pfd = &pt->fds[ev - 1]; + pfd->revents = (short)networkevents.lNetworkEvents; - err = networkevents.iErrorCode[FD_CONNECT_BIT]; + if (!pfd->write_blocked && pfd->revents & FD_WRITE) + pfd->write_blocked = 0; - if ((networkevents.lNetworkEvents & FD_CONNECT) && - err && err != LWS_EALREADY && - err != LWS_EINPROGRESS && err != LWS_EWOULDBLOCK && - err != WSAEINVAL) { + 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)); + pfd->revents &= ~LWS_POLLOUT; + if (err && err != LWS_EALREADY && + err != LWS_EINPROGRESS && + err != LWS_EWOULDBLOCK && + err != WSAEINVAL) { lwsl_debug("Unable to connect errno=%d\n", err); - pfd->revents |= LWS_POLLHUP; - } - if (pfd->revents & LWS_POLLOUT) { - wsi = wsi_from_fd(context, pfd->fd); - if (wsi) - wsi->sock_send_blocking = 0; - } - /* if something closed, retry this slot */ - if (pfd->revents & LWS_POLLHUP) - --eIdx; + /* + * the connection has definitively failed... but + * do we have more DNS entries to try? + */ + 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); + return 0; + } else + pfd->revents |= LWS_POLLHUP; + } else + if (wsi_from_fd(context, pfd->fd)) { + if (wsi_from_fd(context, pfd->fd)->udp) + pfd->revents |= LWS_POLLHUP; + else + lws_client_connect_3_connect( + wsi_from_fd(context, pfd->fd), + NULL, NULL, + LWS_CONNECT_COMPLETION_GOOD, + NULL); + } + } - if (pfd->revents) { - recv(pfd->fd, NULL, 0, 0); - lws_service_fd_tsi(context, pfd, tsi); - } + if (pfd->revents & LWS_POLLOUT) { + wsi = wsi_from_fd(context, pfd->fd); + if (wsi) + wsi->sock_send_blocking = 0; } - return 0; - } + if (pfd->revents) { + /* + * On windows is somehow necessary to "acknowledge" the + * POLLIN event, otherwise we never receive another one + * on the TCP connection. But it breaks UDP, so only + * do it on non-UDP. + */ + wsi = wsi_from_fd(context, pfd->fd); + if (wsi && !wsi->udp) + recv(pfd->fd, NULL, 0, 0); - // if (ev == WSA_WAIT_TIMEOUT) { } - // if (ev == WSA_WAIT_FAILED) - // return 0; + lws_service_fd_tsi(context, pfd, tsi); + } + } return 0; } diff -Nru libwebsockets-4.0.20/lib/plat/windows/windows-sockets.c libwebsockets-4.1.6/lib/plat/windows/windows-sockets.c --- libwebsockets-4.0.20/lib/plat/windows/windows-sockets.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/windows/windows-sockets.c 2020-12-01 17:40:26.000000000 +0000 @@ -27,6 +27,13 @@ #endif #include "private-lib-core.h" +#if defined(LWS_WITH_MBEDTLS) +#if defined(LWS_HAVE_MBEDTLS_NET_SOCKETS) +#include "mbedtls/net_sockets.h" +#else +#include "mbedtls/net.h" +#endif +#endif int lws_send_pipe_choked(struct lws *wsi) @@ -173,15 +180,15 @@ lws_plat_insert_socket_into_fds(struct lws_context *context, struct lws *wsi) { struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; - int n = LWS_POLLIN | LWS_POLLHUP | FD_CONNECT; if (wsi->udp) { lwsl_info("%s: UDP\n", __func__); - n = LWS_POLLIN; + pt->fds[pt->fds_count].events |= LWS_POLLIN; } 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 @@ -212,24 +219,26 @@ } 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]; - long e = LWS_POLLHUP | FD_CONNECT; + long e = LWS_POLLHUP | FD_CONNECT | FD_ACCEPT | FD_CLOSE | FD_WRITE; - if ((pfd->events & LWS_POLLIN)) - e |= LWS_POLLIN; + /* + * 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 ((pfd->events & LWS_POLLOUT)) - e |= LWS_POLLOUT; + if (pfd->events & LWS_POLLIN) + e |= FD_READ; - if (WSAEventSelect(wsi->desc.sockfd, pt->events, e) != SOCKET_ERROR) - return 0; - - 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 * @@ -381,3 +390,49 @@ return -1; } +#if defined(LWS_WITH_MBEDTLS) +int +lws_plat_mbedtls_net_send(void *ctx, const uint8_t *buf, size_t len) +{ + int fd = ((mbedtls_net_context *) ctx)->fd; + int ret; + + if (fd < 0) + return MBEDTLS_ERR_NET_INVALID_CONTEXT; + + ret = write(fd, buf, len); + if (ret >= 0) + return ret; + + if (errno == EAGAIN || errno == EWOULDBLOCK) + return MBEDTLS_ERR_SSL_WANT_WRITE; + + if (WSAGetLastError() == WSAECONNRESET ) + return( MBEDTLS_ERR_NET_CONN_RESET ); + + return MBEDTLS_ERR_NET_SEND_FAILED; +} + +int +lws_plat_mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len) +{ + int fd = ((mbedtls_net_context *) ctx)->fd; + int ret; + + if (fd < 0) + return MBEDTLS_ERR_NET_INVALID_CONTEXT; + + ret = (int)read(fd, buf, len); + if (ret >= 0) + return ret; + + if (errno == EAGAIN || errno == EWOULDBLOCK) + return MBEDTLS_ERR_SSL_WANT_READ; + + if (WSAGetLastError() == WSAECONNRESET) + return MBEDTLS_ERR_NET_CONN_RESET; + + return MBEDTLS_ERR_NET_RECV_FAILED; +} +#endif + diff -Nru libwebsockets-4.0.20/lib/plat/windows/windows-spawn.c libwebsockets-4.1.6/lib/plat/windows/windows-spawn.c --- libwebsockets-4.0.20/lib/plat/windows/windows-spawn.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/plat/windows/windows-spawn.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,581 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2020 Andy Green + * + * 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" + +#include +#include +#include + +void +lws_spawn_timeout(struct lws_sorted_usec_list *sul) +{ + struct lws_spawn_piped *lsp = lws_container_of(sul, + struct lws_spawn_piped, sul); + + lwsl_warn("%s: spawn exceeded timeout, killing\n", __func__); + + lws_spawn_piped_kill_child_process(lsp); +} + +void +lws_spawn_sul_reap(struct lws_sorted_usec_list *sul) +{ + struct lws_spawn_piped *lsp = lws_container_of(sul, + struct lws_spawn_piped, sul_reap); + + lwsl_notice("%s: reaping spawn after last stdpipe, tries left %d\n", + __func__, lsp->reap_retry_budget); + if (!lws_spawn_reap(lsp) && !lsp->pipes_alive) { + if (--lsp->reap_retry_budget) { + lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi, + &lsp->sul_reap, lws_spawn_sul_reap, + 250 * LWS_US_PER_MS); + } else { + lwsl_err("%s: Unable to reap lsp %p, killing\n", + __func__, lsp); + lsp->reap_retry_budget = 20; + lws_spawn_piped_kill_child_process(lsp); + } + } +} + +static struct lws * +lws_create_basic_wsi(struct lws_context *context, int tsi, + const struct lws_role_ops *ops) +{ + struct lws *new_wsi; + size_t s = sizeof(*new_wsi); + + if (!context->vhost_list) + return NULL; + + if ((unsigned int)context->pt[tsi].fds_count == + context->fd_limit_per_thread - 1) { + lwsl_err("no space for new conn\n"); + return NULL; + } + +#if defined(LWS_WITH_EVENT_LIBS) + s += vhost->context->event_loop_ops->evlib_size_wsi; +#endif + + new_wsi = lws_zalloc(s, "new wsi"); + if (new_wsi == NULL) { + lwsl_err("Out of memory for new connection\n"); + 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->a.context = context; + new_wsi->pending_timeout = NO_PENDING_TIMEOUT; + new_wsi->rxflow_change_to = LWS_RXFLOW_ALLOW; + + /* initialize the instance struct */ + + lws_role_transition(new_wsi, 0, LRS_ESTABLISHED, ops); + + new_wsi->hdr_parsing_completed = 0; + new_wsi->position_in_fds_table = LWS_NO_FDS_POS; + + /* + * these can only be set once the protocol is known + * we set an unestablished connection's protocol pointer + * to the start of the defauly vhost supported list, so it can look + * for matching ones during the handshake + */ + + new_wsi->user_space = NULL; + new_wsi->desc.sockfd = LWS_SOCK_INVALID; + context->count_wsi_allocated++; + + return new_wsi; +} + +void +lws_spawn_piped_destroy(struct lws_spawn_piped **_lsp) +{ + struct lws_spawn_piped *lsp = *_lsp; + struct lws *wsi; + int n; + + if (!lsp) + return; + + for (n = 0; n < 3; n++) { + if (lsp->pipe_fds[n][!!(n == 0)]) { + CloseHandle(lsp->pipe_fds[n][n == 0]); + lsp->pipe_fds[n][n == 0] = NULL; + } + + for (n = 0; n < 3; n++) { + if (lsp->stdwsi[n]) { + lwsl_notice("%s: closing stdwsi %d\n", __func__, n); + wsi = lsp->stdwsi[n]; + lsp->stdwsi[n]->desc.filefd = NULL; + lsp->stdwsi[n] = NULL; + lws_set_timeout(wsi, 1, LWS_TO_KILL_SYNC); + } + } + } + + lws_dll2_remove(&lsp->dll); + + lws_sul_cancel(&lsp->sul); + lws_sul_cancel(&lsp->sul_reap); + lws_sul_cancel(&lsp->sul_poll); + + lwsl_warn("%s: deleting lsp\n", __func__); + + lws_free_set_NULL((*_lsp)); +} + +int +lws_spawn_reap(struct lws_spawn_piped *lsp) +{ + + void *opaque = lsp->info.opaque; + lsp_cb_t cb = lsp->info.reap_cb; + struct _lws_siginfo_t lsi; + lws_usec_t acct[4]; + DWORD ex; + + if (!lsp->child_pid) + return 0; + + if (!GetExitCodeProcess(lsp->child_pid, &ex)) { + lwsl_notice("%s: GetExitCodeProcess failed\n", __func__); + return 0; + } + + /* nonzero = success */ + + if (ex == STILL_ACTIVE) { + lwsl_notice("%s: still active\n", __func__); + return 0; + } + + /* mark the earliest time we knew he had gone */ + if (!lsp->reaped) { + lsp->reaped = lws_now_usecs(); + + /* + * Switch the timeout to restrict the amount of grace time + * to drain stdwsi + */ + + lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi, + &lsp->sul, lws_spawn_timeout, + 5 * LWS_US_PER_SEC); + } + + /* + * Stage finalizing our reaction to the process going down until the + * stdwsi flushed whatever is in flight and all noticed they were + * closed. For that reason, each stdwsi close must call lws_spawn_reap + * to check if that was the last one and we can proceed with the reap. + */ + + if (!lsp->ungraceful && lsp->pipes_alive) { + lwsl_notice("%s: stdwsi alive, not reaping\n", __func__); + return 0; + } + + /* we reached the reap point, no need for timeout wait */ + + lws_sul_cancel(&lsp->sul); + + /* + * All the stdwsi went down, nothing more is coming... it's over + * Collect the final information and then reap the dead process + */ + + lsi.retcode = 0x10000 | (int)ex; + lwsl_notice("%s: process exit 0x%x\n", __func__, lsi.retcode); + lsp->child_pid = NULL; + + /* destroy the lsp itself first (it's freed and plsp set NULL */ + + if (lsp->info.plsp) + lws_spawn_piped_destroy(lsp->info.plsp); + + /* then do the parent callback informing it's destroyed */ + + memset(acct, 0, sizeof(acct)); + if (cb) + cb(opaque, acct, &lsi, 0); + + lwsl_notice("%s: completed reap\n", __func__); + + return 1; /* was reaped */ +} + +int +lws_spawn_piped_kill_child_process(struct lws_spawn_piped *lsp) +{ + if (!lsp->child_pid) + return 1; + + lsp->ungraceful = 1; /* don't wait for flushing, just kill it */ + + if (lws_spawn_reap(lsp)) + /* that may have invalidated lsp */ + return 0; + + lwsl_warn("%s: calling TerminateProcess on child pid\n", __func__); + TerminateProcess(lsp->child_pid, 252); + lws_spawn_reap(lsp); + + /* that may have invalidated lsp */ + + return 0; +} + +static void +windows_pipe_poll_hack(lws_sorted_usec_list_t *sul) +{ + struct lws_spawn_piped *lsp = lws_container_of(sul, + struct lws_spawn_piped, sul_poll); + struct lws *wsi, *wsi1; + DWORD br; + char c; + + /* + * Do it first, we know lsp exists and if it's destroyed inbetweentimes, + * it will already have cancelled this + */ + + lws_sul_schedule(lsp->context, 0, &lsp->sul_poll, + windows_pipe_poll_hack, 50 * LWS_US_PER_MS); + + wsi = lsp->stdwsi[LWS_STDOUT]; + wsi1 = lsp->stdwsi[LWS_STDERR]; + if (wsi && lsp->pipe_fds[LWS_STDOUT][0] != NULL) { + if (!PeekNamedPipe(lsp->pipe_fds[LWS_STDOUT][0], &c, 1, &br, + NULL, NULL)) { + + lwsl_notice("%s: stdout pipe errored\n", __func__); + CloseHandle(lsp->stdwsi[LWS_STDOUT]->desc.filefd); + lsp->pipe_fds[LWS_STDOUT][0] = NULL; + lsp->stdwsi[LWS_STDOUT]->desc.filefd = NULL; + lsp->stdwsi[LWS_STDOUT] = NULL; + lws_set_timeout(wsi, 1, LWS_TO_KILL_SYNC); + + if (lsp->stdwsi[LWS_STDIN]) { + lwsl_notice("%s: closing stdin from stdout close\n", + __func__); + CloseHandle(lsp->stdwsi[LWS_STDIN]->desc.filefd); + wsi = lsp->stdwsi[LWS_STDIN]; + lsp->stdwsi[LWS_STDIN]->desc.filefd = NULL; + lsp->stdwsi[LWS_STDIN] = NULL; + lsp->pipe_fds[LWS_STDIN][1] = NULL; + lws_set_timeout(wsi, 1, LWS_TO_KILL_SYNC); + } + + /* + * lsp may be destroyed by here... if we wanted to + * handle a still-extant stderr we'll get it next time + */ + + return; + } else + if (br) + wsi->a.protocol->callback(wsi, + LWS_CALLBACK_RAW_RX_FILE, + NULL, NULL, 0); + } + + /* + * lsp may have been destroyed above + */ + + if (wsi1 && lsp->pipe_fds[LWS_STDERR][0]) { + if (!PeekNamedPipe(lsp->pipe_fds[LWS_STDERR][0], &c, 1, &br, + NULL, NULL)) { + + lwsl_notice("%s: stderr pipe errored\n", __func__); + CloseHandle(wsi1->desc.filefd); + /* + * Assume is stderr still extant on entry, lsp can't + * have been destroyed by stdout/stdin processing + */ + lsp->stdwsi[LWS_STDERR]->desc.filefd = NULL; + lsp->stdwsi[LWS_STDERR] = NULL; + lsp->pipe_fds[LWS_STDERR][0] = NULL; + lws_set_timeout(wsi1, 1, LWS_TO_KILL_SYNC); + /* + * lsp may have been destroyed above + */ + } else + if (br) + wsi1->a.protocol->callback(wsi1, + LWS_CALLBACK_RAW_RX_FILE, + NULL, NULL, 0); + } +} + + + +/* + * Deals with spawning a subprocess and executing it securely with stdin/out/err + * diverted into pipes + */ + +struct lws_spawn_piped * +lws_spawn_piped(const struct lws_spawn_piped_info *i) +{ + const struct lws_protocols *pcol = i->vh->context->vhost_list->protocols; + struct lws_context *context = i->vh->context; + struct lws_spawn_piped *lsp; + PROCESS_INFORMATION pi; + SECURITY_ATTRIBUTES sa; + char cli[300], *p; + STARTUPINFO si; + int n; + + if (i->protocol_name) + pcol = lws_vhost_name_to_protocol(i->vh, i->protocol_name); + if (!pcol) { + lwsl_err("%s: unknown protocol %s\n", __func__, + i->protocol_name ? i->protocol_name : "default"); + + return NULL; + } + + lsp = lws_zalloc(sizeof(*lsp), __func__); + if (!lsp) { + lwsl_err("%s: OOM\n", __func__); + return NULL; + } + + /* wholesale take a copy of info */ + lsp->info = *i; + lsp->context = context; + lsp->reap_retry_budget = 20; + + /* + * Prepare the stdin / out / err pipes + */ + + for (n = 0; n < 3; n++) { + lsp->pipe_fds[n][0] = NULL; + lsp->pipe_fds[n][1] = NULL; + } + + /* create pipes for [stdin|stdout] and [stderr] */ + + memset(&sa, 0, sizeof(sa)); + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.bInheritHandle = TRUE; /* inherit the pipes */ + sa.lpSecurityDescriptor = NULL; + + for (n = 0; n < 3; n++) { + DWORD waitmode = PIPE_NOWAIT; + + if (!CreatePipe(&lsp->pipe_fds[n][0], &lsp->pipe_fds[n][1], + &sa, 0)) { + lwsl_err("%s: CreatePipe() failed\n", __func__); + goto bail1; + } + + SetNamedPipeHandleState(lsp->pipe_fds[1][0], &waitmode, NULL, NULL); + SetNamedPipeHandleState(lsp->pipe_fds[2][0], &waitmode, NULL, NULL); + + /* don't inherit the pipe side that belongs to the parent */ + + if (!SetHandleInformation(&lsp->pipe_fds[n][!n], + HANDLE_FLAG_INHERIT, 0)) { + lwsl_err("%s: SetHandleInformation() failed\n", __func__); + //goto bail1; + } + } + + /* create wsis for each stdin/out/err fd */ + + for (n = 0; n < 3; n++) { + lsp->stdwsi[n] = lws_create_basic_wsi(i->vh->context, i->tsi, + i->ops ? i->ops : &role_ops_raw_file); + if (!lsp->stdwsi[n]) { + lwsl_err("%s: unable to create lsp stdwsi\n", __func__); + goto bail2; + } + lsp->stdwsi[n]->lsp_channel = n; + lws_vhost_bind_wsi(i->vh, lsp->stdwsi[n]); + lsp->stdwsi[n]->a.protocol = pcol; + lsp->stdwsi[n]->a.opaque_user_data = i->opaque; + + lsp->stdwsi[n]->desc.filefd = lsp->pipe_fds[n][!n]; + lsp->stdwsi[n]->file_desc = 1; + + lwsl_debug("%s: lsp stdwsi %p: pipe idx %d -> fd %d / %d\n", + __func__, lsp->stdwsi[n], n, + lsp->pipe_fds[n][!!(n == 0)], + lsp->pipe_fds[n][!(n == 0)]); + +#if 0 + + /* read side is 0, stdin we want the write side, others read */ + + lsp->stdwsi[n]->desc.filefd = lsp->pipe_fds[n][!!(n == 0)]; + if (fcntl(lsp->pipe_fds[n][!!(n == 0)], F_SETFL, O_NONBLOCK) < 0) { + lwsl_err("%s: setting NONBLOCK failed\n", __func__); + goto bail2; + } +#endif + } + + for (n = 0; n < 3; n++) + if (i->opt_parent) { + lsp->stdwsi[n]->parent = i->opt_parent; + lsp->stdwsi[n]->sibling_list = i->opt_parent->child_list; + i->opt_parent->child_list = lsp->stdwsi[n]; + } + + lwsl_notice("%s: pipe handles in %p, out %p, err %p\n", __func__, + lsp->stdwsi[LWS_STDIN]->desc.sockfd, + lsp->stdwsi[LWS_STDOUT]->desc.sockfd, + lsp->stdwsi[LWS_STDERR]->desc.sockfd); + + /* + * Windows nonblocking pipe handling is a mess that is unable + * to interoperate with WSA-based wait as far as I can tell. + * + * Let's set up a sul to poll the pipes and synthesize the + * protocol callbacks if anything coming. + */ + lws_sul_schedule(context, 0, &lsp->sul_poll, windows_pipe_poll_hack, + 50 * LWS_US_PER_MS); + + + /* + * Windows wants a single string commandline + */ + p = cli; + n = 0; + while (i->exec_array[n]) { + lws_strncpy(p, i->exec_array[n], + sizeof(cli) - lws_ptr_diff(p, cli)); + if (sizeof(cli) - lws_ptr_diff(p, cli) < 4) + break; + p += strlen(p); + *p++ = ' '; + *p = '\0'; + n++; + } + + puts(cli); + + memset(&pi, 0, sizeof(pi)); + memset(&si, 0, sizeof(si)); + + si.cb = sizeof(STARTUPINFO); + si.hStdInput = lsp->pipe_fds[LWS_STDIN][0]; + si.hStdOutput = lsp->pipe_fds[LWS_STDOUT][1]; + si.hStdError = lsp->pipe_fds[LWS_STDERR][1]; + si.dwFlags = STARTF_USESTDHANDLES | CREATE_NO_WINDOW; + si.wShowWindow = TRUE; + + if (!CreateProcess(NULL, cli, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { + lwsl_err("%s: CreateProcess failed 0x%x\n", __func__, + (unsigned long)GetLastError()); + goto bail3; + } + + lsp->child_pid = pi.hProcess; + + lwsl_notice("%s: lsp %p spawned PID %d\n", __func__, lsp, lsp->child_pid); + + lws_sul_schedule(context, i->tsi, &lsp->sul, lws_spawn_timeout, + i->timeout_us ? i->timeout_us : 300 * LWS_US_PER_SEC); + + /* + * close: stdin:r, stdout:w, stderr:w + */ + for (n = 0; n < 3; n++) + CloseHandle(lsp->pipe_fds[n][n != 0]); + + lsp->pipes_alive = 3; + lsp->created = lws_now_usecs(); + + if (i->owner) + lws_dll2_add_head(&lsp->dll, i->owner); + + if (i->timeout_us) + lws_sul_schedule(context, i->tsi, &lsp->sul, + lws_spawn_timeout, i->timeout_us); + + return lsp; + +bail3: + + lws_sul_cancel(&lsp->sul_poll); + + while (--n >= 0) + __remove_wsi_socket_from_fds(lsp->stdwsi[n]); +bail2: + for (n = 0; n < 3; n++) + if (lsp->stdwsi[n]) + __lws_free_wsi(lsp->stdwsi[n]); + +bail1: + for (n = 0; n < 3; n++) { + if (lsp->pipe_fds[n][0] >= 0) + CloseHandle(lsp->pipe_fds[n][0]); + if (lsp->pipe_fds[n][1] >= 0) + CloseHandle(lsp->pipe_fds[n][1]); + } + + lws_free(lsp); + + lwsl_err("%s: failed\n", __func__); + + return NULL; +} + +void +lws_spawn_stdwsi_closed(struct lws_spawn_piped *lsp, struct lws *wsi) +{ + int n; + + assert(lsp); + lsp->pipes_alive--; + lwsl_debug("%s: pipes alive %d\n", __func__, lsp->pipes_alive); + if (!lsp->pipes_alive) + lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi, + &lsp->sul_reap, lws_spawn_sul_reap, 1); + + for (n = 0; n < 3; n++) + if (lsp->stdwsi[n] == wsi) + lsp->stdwsi[n] = NULL; +} + +int +lws_spawn_get_stdfd(struct lws *wsi) +{ + return wsi->lsp_channel; +} diff -Nru libwebsockets-4.0.20/lib/roles/cgi/cgi-server.c libwebsockets-4.1.6/lib/roles/cgi/cgi-server.c --- libwebsockets-4.0.20/lib/roles/cgi/cgi-server.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/cgi/cgi-server.c 2020-12-01 17:40:26.000000000 +0000 @@ -68,12 +68,49 @@ return out - start; } +static void +lws_cgi_grace(lws_sorted_usec_list_t *sul) +{ + struct lws_cgi *cgi = lws_container_of(sul, struct lws_cgi, sul_grace); + + /* act on the reap cb from earlier */ + + lwsl_info("%s: wsi %p\n", __func__, cgi->wsi); + + if (!cgi->wsi->http.cgi->post_in_expected) + cgi->wsi->http.cgi->cgi_transaction_over = 1; + + lws_callback_on_writable(cgi->wsi); +} + + +static void +lws_cgi_reap_cb(void *opaque, lws_usec_t *accounting, siginfo_t *si, + int we_killed_him) +{ + struct lws *wsi = (struct lws *)opaque; + + /* + * The cgi has come to an end, by itself or with a signal... + */ + + lwsl_info("%s: wsi %p post_in_expected %d\n", __func__, wsi, + (int)wsi->http.cgi->post_in_expected); + + /* + * Grace period to handle the incoming stdout + */ + + lws_sul_schedule(wsi->a.context, wsi->tsi, &wsi->http.cgi->sul_grace, + lws_cgi_grace, 1 * LWS_US_PER_SEC); +} + int lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len, int timeout_secs, const struct lws_protocol_vhost_options *mp_cgienv) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; struct lws_spawn_piped_info info; char *env_array[30], cgi_path[500], e[1024], *p = e, *end = p + sizeof(e) - 1, tok[256], *t, *sum, *sumend; @@ -354,9 +391,11 @@ info.opt_parent = wsi; info.timeout_us = 5 * 60 * LWS_US_PER_SEC; info.tsi = wsi->tsi; - info.vh = wsi->vhost; + info.vh = wsi->a.vhost; info.ops = &role_ops_cgi; info.plsp = &wsi->http.cgi->lsp; + info.opaque = wsi; + info.reap_cb = lws_cgi_reap_cb; /* * Actually having made the env, as a cgi we don't need the ah @@ -375,10 +414,10 @@ /* we are the parent process */ - wsi->context->count_cgi_spawned++; + wsi->a.context->count_cgi_spawned++; /* inform cgi owner of the child PID */ - n = user_callback_handle_rxflow(wsi->protocol->callback, wsi, + n = user_callback_handle_rxflow(wsi->a.protocol->callback, wsi, LWS_CALLBACK_CGI_PROCESS_ATTACH, wsi->user_space, NULL, cgi->lsp->child_pid); (void)n; @@ -386,6 +425,7 @@ return 0; bail: + lws_sul_cancel(&wsi->http.cgi->sul_grace); lws_free_set_NULL(wsi->http.cgi); lwsl_err("%s: failed\n", __func__); @@ -561,7 +601,7 @@ cmd = LWS_WRITE_HTTP_HEADERS_CONTINUATION; if (wsi->http.cgi->headers_dumped + n != - wsi->http.cgi->headers_pos) { + wsi->http.cgi->headers_pos) { lwsl_notice("adding no fin flag\n"); cmd |= LWS_WRITE_NO_FIN; } @@ -578,14 +618,23 @@ wsi->http.cgi->headers_pos) { wsi->hdr_state = LHCS_PAYLOAD; lws_free_set_NULL(wsi->http.cgi->headers_buf); - lwsl_debug("freed cgi headers\n"); + lwsl_debug("%s: freed cgi headers\n", __func__); + + if (wsi->http.cgi->post_in_expected) { + lwsl_info("%s: post data still expected, " + "asking for writeable\n", + __func__); + lws_callback_on_writable(wsi); + } + } else { wsi->reason_bf |= LWS_CB_REASON_AUX_BF__CGI_HEADERS; lws_callback_on_writable(wsi); } - /* writeability becomes uncertain now we wrote + /* + * writeability becomes uncertain now we wrote * something, we must return to the event loop */ return 0; @@ -821,7 +870,7 @@ if (!wsi->mux_substream && m) { uint8_t term[LWS_PRE + 6]; - lwsl_notice("%s: sent trailer\n", __func__); + lwsl_info("%s: sent trailer\n", __func__); memcpy(term + LWS_PRE, (uint8_t *)"0\x0d\x0a\x0d\x0a", 5); if (lws_write(wsi, term + LWS_PRE, 5, @@ -867,7 +916,7 @@ if (pid != -1) { m = wsi->http.cgi->being_closed; - n = user_callback_handle_rxflow(wsi->protocol->callback, wsi, + n = user_callback_handle_rxflow(wsi->a.protocol->callback, wsi, LWS_CALLBACK_CGI_TERMINATED, wsi->user_space, (void *)&args, pid); @@ -962,7 +1011,7 @@ cgi = *pcgi; pcgi = &(*pcgi)->cgi_list; - if (cgi->lsp->child_pid <= 0) + if (!cgi || !cgi->lsp || cgi->lsp->child_pid <= 0) continue; /* we deferred killing him after reaping his PID */ @@ -1026,7 +1075,7 @@ void lws_cgi_remove_and_kill(struct lws *wsi) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; struct lws_cgi **pcgi = &pt->http.cgi_list; /* remove us from the cgi list */ @@ -1040,7 +1089,7 @@ pcgi = &(*pcgi)->cgi_list; } if (wsi->http.cgi->headers_buf) { - lwsl_debug("close: freed cgi headers\n"); + lwsl_debug("%s: close: freed cgi headers\n", __func__); lws_free_set_NULL(wsi->http.cgi->headers_buf); } /* we have a cgi going, we must kill it */ diff -Nru libwebsockets-4.0.20/lib/roles/cgi/CMakeLists.txt libwebsockets-4.1.6/lib/roles/cgi/CMakeLists.txt --- libwebsockets-4.0.20/lib/roles/cgi/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/cgi/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,42 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +list(APPEND SOURCES + roles/cgi/cgi-server.c + roles/cgi/ops-cgi.c) + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() diff -Nru libwebsockets-4.0.20/lib/roles/cgi/ops-cgi.c libwebsockets-4.1.6/lib/roles/cgi/ops-cgi.c --- libwebsockets-4.0.20/lib/roles/cgi/ops-cgi.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/cgi/ops-cgi.c 2020-12-01 17:40:26.000000000 +0000 @@ -46,6 +46,27 @@ return LWS_HPI_RET_WSI_ALREADY_DIED; } + if (!wsi->parent) { + lwsl_debug("%s: stdwsi content with parent\n", + __func__); + + return LWS_HPI_RET_HANDLED; + } + + if (!wsi->parent->http.cgi) { + lwsl_notice("%s: stdwsi content with deleted cgi object\n", + __func__); + + return LWS_HPI_RET_HANDLED; + } + + if (!wsi->parent->http.cgi->lsp) { + lwsl_notice("%s: stdwsi content with reaped lsp\n", + __func__); + + return LWS_HPI_RET_HANDLED; + } + args.ch = wsi->lsp_channel; args.stdwsi = &wsi->parent->http.cgi->lsp->stdwsi[0]; args.hdr_state = wsi->hdr_state; @@ -53,7 +74,7 @@ lwsl_debug("CGI LWS_STDOUT %p wsistate 0x%x\n", wsi->parent, wsi->wsistate); - if (user_callback_handle_rxflow(wsi->parent->protocol->callback, + if (user_callback_handle_rxflow(wsi->parent->a.protocol->callback, wsi->parent, LWS_CALLBACK_CGI, wsi->parent->user_space, (void *)&args, 0)) @@ -92,8 +113,8 @@ lws_cgi_kill_terminated(pt); - __lws_sul_insert(&pt->pt_sul_owner, &pt->sul_cgi, - 3 * LWS_US_PER_SEC); + __lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], + &pt->sul_cgi, 3 * LWS_US_PER_SEC); } static int @@ -105,14 +126,23 @@ pt->sul_cgi.cb = lws_cgi_sul_cb; - __lws_sul_insert(&pt->pt_sul_owner, &pt->sul_cgi, - 3 * LWS_US_PER_SEC); + __lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], + &pt->sul_cgi, 3 * LWS_US_PER_SEC); } else lws_dll2_remove(&pt->sul_cgi.list); return 0; } +static int +rops_close_role_cgi(struct lws_context_per_thread *pt, struct lws *wsi) +{ + if (wsi->parent && wsi->parent->http.cgi && wsi->parent->http.cgi->lsp) + lws_spawn_stdwsi_closed(wsi->parent->http.cgi->lsp, wsi); + + return 0; +} + const struct lws_role_ops role_ops_cgi = { /* role name */ "cgi", @@ -131,7 +161,7 @@ /* encapsulation_parent */ NULL, /* alpn_negotiated */ NULL, /* close_via_role_protocol */ NULL, - /* close_role */ NULL, + /* close_role */ rops_close_role_cgi, /* close_kill_connection */ NULL, /* destroy_role */ rops_destroy_role_cgi, /* adoption_bind */ NULL, diff -Nru libwebsockets-4.0.20/lib/roles/cgi/private-lib-roles-cgi.h libwebsockets-4.1.6/lib/roles/cgi/private-lib-roles-cgi.h --- libwebsockets-4.0.20/lib/roles/cgi/private-lib-roles-cgi.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/cgi/private-lib-roles-cgi.h 2020-12-01 17:40:26.000000000 +0000 @@ -55,7 +55,8 @@ struct lws_cgi { struct lws_cgi *cgi_list; - struct lws_spawn_piped *lsp; + struct lws_spawn_piped *lsp; + lws_sorted_usec_list_t sul_grace; struct lws *wsi; /* owner */ unsigned char *headers_buf; diff -Nru libwebsockets-4.0.20/lib/roles/CMakeLists.txt libwebsockets-4.1.6/lib/roles/CMakeLists.txt --- libwebsockets-4.0.20/lib/roles/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,90 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +if (LWS_ROLE_MQTT) + add_subdir_include_directories(mqtt) +endif() + +if (LWS_ROLE_DBUS AND NOT LWS_PLAT_FREERTOS) + add_subdir_include_directories(dbus) +endif() + +if (LWS_ROLE_H1 OR LWS_ROLE_H2) + add_subdir_include_directories(http) +endif() + +if (LWS_ROLE_H1) + add_subdir_include_directories(h1) +endif() + +if (LWS_ROLE_H2) + add_subdir_include_directories(h2) +endif() + +if (LWS_ROLE_WS) + add_subdir_include_directories(ws) +endif() + +if (LWS_ROLE_RAW) + add_subdir_include_directories(raw-skt) +endif() + +if (LWS_ROLE_RAW_FILE) + add_subdir_include_directories(raw-file) +endif() + +if (LWS_WITH_CGI) + add_subdir_include_directories(cgi) +endif() + +if (LWS_ROLE_RAW_PROXY) + add_subdir_include_directories(raw-proxy) +endif() + +if (NOT LWS_WITHOUT_SERVER OR LWS_WITH_SECURE_STREAMS_PROCESS_API) + add_subdir_include_directories(listen) +endif() + +if (NOT LWS_WITHOUT_CLIENT) + list(APPEND SOURCES + roles/http/client/client-http.c + roles/http/client/client-handshake.c) +endif() + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() +set(LWS_DEPS_LIB_PATHS ${LWS_DEPS_LIB_PATHS} PARENT_SCOPE) + diff -Nru libwebsockets-4.0.20/lib/roles/dbus/CMakeLists.txt libwebsockets-4.1.6/lib/roles/dbus/CMakeLists.txt --- libwebsockets-4.0.20/lib/roles/dbus/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/dbus/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,65 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +list(APPEND SOURCES + roles/dbus/dbus.c) + +if (NOT LWS_DBUS_LIB) + set(LWS_DBUS_LIB "dbus-1") +endif() + +find_package(PkgConfig QUIET) +pkg_check_modules(PC_DBUS1 dbus-1 QUIET) +list(APPEND LWS_DBUS_INCLUDE1 ${PC_DBUS1_INCLUDE_DIRS}) +list(APPEND LWS_DBUS_LIB ${PC_DBUS1_LIBRARIES}) +list(APPEND LWS_DEPS_LIB_PATHS ${PC_DBUS1_LIBRARY_DIRS}) + +set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES};${LWS_DBUS_INCLUDE1}) + +CHECK_C_SOURCE_COMPILES("#include +int main(void) { + return 0; +}" LWS_DBUS_CHECK_OK) + +message("dbus include dir 1: ${LWS_DBUS_INCLUDE1}") +include_directories("${LWS_DBUS_INCLUDE1}") +list(APPEND LIB_LIST ${LWS_DBUS_LIB}) + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() +set(LWS_DBUS_CHECK_OK ${LWS_DBUS_CHECK_OK} PARENT_SCOPE) +set(LWS_DEPS_LIB_PATHS ${LWS_DEPS_LIB_PATHS} PARENT_SCOPE) + diff -Nru libwebsockets-4.0.20/lib/roles/dbus/dbus.c libwebsockets-4.1.6/lib/roles/dbus/dbus.c --- libwebsockets-4.0.20/lib/roles/dbus/dbus.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/dbus/dbus.c 2020-12-01 17:40:26.000000000 +0000 @@ -48,6 +48,7 @@ static struct lws * __lws_shadow_wsi(struct lws_dbus_ctx *ctx, DBusWatch *w, int fd, int create_ok) { + size_t s = sizeof(struct lws); struct lws *wsi; if (fd < 0 || fd >= (int)ctx->vh->context->fd_limit_per_thread) { @@ -68,18 +69,26 @@ if (!create_ok) return NULL; - wsi = lws_zalloc(sizeof(*wsi), "shadow wsi"); +#if defined(LWS_WITH_EVENT_LIBS) + s += ctx->vh->context->event_loop_ops->evlib_size_wsi; +#endif + + wsi = lws_zalloc(s, "shadow wsi"); if (wsi == NULL) { lwsl_err("Out of mem\n"); return NULL; } +#if defined(LWS_WITH_EVENT_LIBS) + wsi->evlib_wsi = (uint8_t *)wsi + sizeof(*wsi); +#endif + lwsl_info("%s: creating shadow wsi\n", __func__); - wsi->context = ctx->vh->context; + wsi->a.context = ctx->vh->context; wsi->desc.sockfd = fd; lws_role_transition(wsi, 0, LRS_ESTABLISHED, &role_ops_dbus); - wsi->protocol = ctx->vh->protocols; + wsi->a.protocol = ctx->vh->protocols; wsi->tsi = ctx->tsi; wsi->shadow = 1; wsi->opaque_parent_data = ctx; @@ -491,7 +500,7 @@ } } lws_end_foreach_dll_safe(rdt, nx); - __lws_sul_insert(&pt->pt_sul_owner, &pt->dbus.sul, + lws_sul_schedule(pt->context, pt->tid, &pt->dbus.sul, lws_dbus_sul_cb, 3 * LWS_US_PER_SEC); } @@ -501,13 +510,10 @@ struct lws_context_per_thread *pt, int destroy) { if (!destroy) { - - pt->dbus.sul.cb = lws_dbus_sul_cb; - - __lws_sul_insert(&pt->pt_sul_owner, &pt->dbus.sul, + lws_sul_schedule(context, pt->tid, &pt->dbus.sul, lws_dbus_sul_cb, 3 * LWS_US_PER_SEC); } else - lws_dll2_remove(&pt->dbus.sul.list); + lws_sul_cancel(&pt->dbus.sul); return 0; } diff -Nru libwebsockets-4.0.20/lib/roles/h1/CMakeLists.txt libwebsockets-4.1.6/lib/roles/h1/CMakeLists.txt --- libwebsockets-4.0.20/lib/roles/h1/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/h1/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,41 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +list(APPEND SOURCES + roles/h1/ops-h1.c) + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() diff -Nru libwebsockets-4.0.20/lib/roles/h1/ops-h1.c libwebsockets-4.1.6/lib/roles/h1/ops-h1.c --- libwebsockets-4.0.20/lib/roles/h1/ops-h1.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/h1/ops-h1.c 2020-12-01 17:40:26.000000000 +0000 @@ -150,7 +150,7 @@ /* returns how much used */ n = user_callback_handle_rxflow( - wsi->protocol->callback, + wsi->a.protocol->callback, wsi, LWS_CALLBACK_CGI_STDIN_DATA, wsi->user_space, (void *)&args, 0); @@ -159,7 +159,7 @@ } else { #endif if (lwsi_state(wsi) != LRS_DISCARD_BODY) { - n = wsi->protocol->callback(wsi, + n = wsi->a.protocol->callback(wsi, LWS_CALLBACK_HTTP_BODY, wsi->user_space, buf, (size_t)body_chunk_len); if (n) @@ -174,7 +174,7 @@ if (wsi->http.rx_content_remain) { lws_set_timeout(wsi, PENDING_TIMEOUT_HTTP_CONTENT, - wsi->context->timeout_secs); + wsi->a.context->timeout_secs); break; } /* he sent all the content in time */ @@ -186,7 +186,7 @@ */ if (wsi->http.cgi) lws_set_timeout(wsi, PENDING_TIMEOUT_CGI, - wsi->context->timeout_secs); + wsi->a.context->timeout_secs); else #endif lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0); @@ -203,14 +203,14 @@ */ if (lws_http_transaction_completed(wsi)) - return -1; + goto bail; break; } #endif lwsl_info("HTTP_BODY_COMPLETION: %p (%s)\n", - wsi, wsi->protocol->name); + wsi, wsi->a.protocol->name); - n = wsi->protocol->callback(wsi, + n = wsi->a.protocol->callback(wsi, LWS_CALLBACK_HTTP_BODY_COMPLETION, wsi->user_space, NULL, 0); if (n) @@ -301,7 +301,7 @@ static int lws_h1_server_socket_service(struct lws *wsi, struct lws_pollfd *pollfd) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; struct lws_tokens ebuf; int n, buffered; @@ -507,7 +507,7 @@ } #endif - n = user_callback_handle_rxflow(wsi->protocol->callback, wsi, + n = user_callback_handle_rxflow(wsi->a.protocol->callback, wsi, LWS_CALLBACK_HTTP_WRITEABLE, wsi->user_space, NULL, 0); if (n < 0) { @@ -643,7 +643,8 @@ return n; if (lwsi_state(wsi) != LRS_SSL_INIT) if (lws_server_socket_service_ssl(wsi, - LWS_SOCK_INVALID)) + LWS_SOCK_INVALID, + !!(pollfd->revents & LWS_POLLIN))) return LWS_HPI_RET_PLEASE_CLOSE_ME; return LWS_HPI_RET_HANDLED; @@ -669,12 +670,12 @@ if (lws_change_pollfd(wsi, LWS_POLLIN, 0)) return LWS_HPI_RET_PLEASE_CLOSE_ME; - //lwsl_notice("calling back %s\n", wsi->protocol->name); + //lwsl_notice("calling back %s\n", wsi->a.protocol->name); /* let user code know, he'll usually ask for writeable * callback and drain / re-enable it there */ - if (user_callback_handle_rxflow(wsi->protocol->callback, wsi, + if (user_callback_handle_rxflow(wsi->a.protocol->callback, wsi, LWS_CALLBACK_RECEIVE_CLIENT_HTTP, wsi->user_space, NULL, 0)) { lwsl_info("RECEIVE_CLIENT_HTTP closed it\n"); @@ -752,7 +753,7 @@ #endif lwsi_set_state(wsi, LRS_WAITING_SERVER_REPLY); lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE, - wsi->context->timeout_secs); + wsi->a.context->timeout_secs); } } #endif @@ -856,7 +857,7 @@ static int rops_destroy_role_h1(struct lws *wsi) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; struct allocated_headers *ah; /* we may not have an ah, but may be on the waiting list... */ @@ -906,25 +907,43 @@ return 1; } - lws_role_transition(wsi, LWSIFR_SERVER, (type & LWS_ADOPT_ALLOW_SSL) ? - LRS_SSL_INIT : LRS_HEADERS, &role_ops_h1); +#if defined(LWS_WITH_SERVER) && defined(LWS_WITH_SECURE_STREAMS) + if (wsi->a.vhost->ss_handle && + wsi->a.vhost->ss_handle->policy->protocol == LWSSSP_RAW) { + lws_role_transition(wsi, LWSIFR_SERVER, (type & LWS_ADOPT_ALLOW_SSL) ? + LRS_SSL_INIT : LRS_ESTABLISHED, &role_ops_raw_skt); + return 1; + } +#endif + + /* If Non-TLS and HTTP2 prior knowledge is enabled, skip to clear text HTTP2 */ + +#if defined(LWS_WITH_HTTP2) + if ((!(type & LWS_ADOPT_ALLOW_SSL)) && (wsi->a.vhost->options & LWS_SERVER_OPTION_H2_PRIOR_KNOWLEDGE)) { + lwsl_info("http/2 prior knowledge\n"); + lws_role_call_alpn_negotiated(wsi, "h2"); + } + else +#endif + lws_role_transition(wsi, LWSIFR_SERVER, (type & LWS_ADOPT_ALLOW_SSL) ? + LRS_SSL_INIT : LRS_HEADERS, &role_ops_h1); /* - * We have to bind to h1 as a default even when we're actually going to + * Otherwise, we have to bind to h1 as a default even when we're actually going to * replace it as an h2 bind later. So don't take this seriously if the * default is disabled (ws upgrade caees properly about it) */ - if (!vh_prot_name && wsi->vhost->default_protocol_index < - wsi->vhost->count_protocols) - wsi->protocol = &wsi->vhost->protocols[ - wsi->vhost->default_protocol_index]; + if (!vh_prot_name && wsi->a.vhost->default_protocol_index < + wsi->a.vhost->count_protocols) + wsi->a.protocol = &wsi->a.vhost->protocols[ + wsi->a.vhost->default_protocol_index]; else - wsi->protocol = &wsi->vhost->protocols[0]; + wsi->a.protocol = &wsi->a.vhost->protocols[0]; /* the transport is accepted... give him time to negotiate */ lws_set_timeout(wsi, PENDING_TIMEOUT_ESTABLISH_WITH_SERVER, - wsi->context->timeout_secs); + wsi->a.context->timeout_secs); return 1; /* bound */ } @@ -1002,12 +1021,13 @@ #if defined(LWS_ROLE_WS) if (lws_create_client_ws_object(i, wsi)) goto fail_wsi; + + goto bind_h1; #else lwsl_err("%s: ws role not configured\n", __func__); goto fail_wsi; #endif - goto bind_h1; } /* if a recognized http method, bind to it */ @@ -1107,7 +1127,7 @@ wsi->http.proxy_clientside = 0; - if (user_callback_handle_rxflow(wsi->protocol->callback, wsi, + if (user_callback_handle_rxflow(wsi->a.protocol->callback, wsi, LWS_CALLBACK_COMPLETED_CLIENT_HTTP, wsi->user_space, NULL, 0)) return 0; @@ -1129,8 +1149,8 @@ pt->sul_ah_lifecheck.cb = lws_sul_http_ah_lifecheck; - __lws_sul_insert(&pt->pt_sul_owner, &pt->sul_ah_lifecheck, - 30 * LWS_US_PER_SEC); + __lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], + &pt->sul_ah_lifecheck, 30 * LWS_US_PER_SEC); } else lws_dll2_remove(&pt->sul_ah_lifecheck.list); #endif diff -Nru libwebsockets-4.0.20/lib/roles/h2/CMakeLists.txt libwebsockets-4.1.6/lib/roles/h2/CMakeLists.txt --- libwebsockets-4.0.20/lib/roles/h2/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/h2/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,44 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +list(APPEND SOURCES + roles/h2/http2.c + roles/h2/hpack.c + roles/h2/ops-h2.c) + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() + diff -Nru libwebsockets-4.0.20/lib/roles/h2/hpack.c libwebsockets-4.1.6/lib/roles/h2/hpack.c --- libwebsockets-4.0.20/lib/roles/h2/hpack.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/h2/hpack.c 2020-12-01 17:40:26.000000000 +0000 @@ -283,7 +283,7 @@ ah->data[ah->pos++] = c; ah->frags[ah->nfrag].len++; - return (int)ah->pos >= wsi->context->max_http_header_data; + return (int)ah->pos >= wsi->a.context->max_http_header_data; } static int lws_frag_end(struct lws *wsi) @@ -333,9 +333,11 @@ strcpy(s, "(too big to show)"); else s[len] = '\0'; +#if defined(_DEBUG) p = lws_token_to_string(hdr); lwsl_header(" hdr tok %d (%s) = '%s' (len %d)\n", hdr, p ? (char *)p : (char *)"null", s, len); +#endif } /* @@ -403,7 +405,7 @@ } index -= (int)LWS_ARRAY_SIZE(static_token); - index = (dyn->pos - 1 - index) % dyn->num_entries; + index = lws_safe_modulo(dyn->pos - 1 - index, dyn->num_entries); if (index < 0) index += dyn->num_entries; @@ -441,7 +443,7 @@ dyn->virtual_payload_usage, dyn->virtual_payload_max); for (n = 0; n < dyn->used_entries; n++) { - m = (dyn->pos - 1 - n) % dyn->num_entries; + m = lws_safe_modulo(dyn->pos - 1 - n, dyn->num_entries); if (m < 0) m += dyn->num_entries; if (dyn->entries[m].lws_hdr_idx != LWS_HPACK_IGNORE_ENTRY) @@ -506,7 +508,7 @@ } lws_h2_dynamic_table_dump(wsi); - new_index = (dyn->pos) % dyn->num_entries; + new_index = lws_safe_modulo(dyn->pos, dyn->num_entries); if (dyn->num_entries && dyn->used_entries == dyn->num_entries) { if (dyn->virtual_payload_usage < dyn->virtual_payload_max) lwsl_err("Dropping header content before limit!\n"); @@ -524,7 +526,8 @@ dyn->used_entries && dyn->virtual_payload_usage + hdr_len + len > dyn->virtual_payload_max + 1024) { - int n = (dyn->pos - dyn->used_entries) % dyn->num_entries; + int n = lws_safe_modulo(dyn->pos - dyn->used_entries, + dyn->num_entries); if (n < 0) n += dyn->num_entries; lws_dynamic_free(dyn, n); @@ -559,7 +562,7 @@ lws_hdr_index, hdr_len, dyn->entries[new_index].value ? dyn->entries[new_index].value : "null", len); - dyn->pos = (dyn->pos + 1) % dyn->num_entries; + dyn->pos = lws_safe_modulo(dyn->pos + 1, dyn->num_entries); lws_h2_dynamic_table_dump(wsi); @@ -597,27 +600,27 @@ dyn = &nwsi->h2.h2n->hpack_dyn_table; lwsl_info("%s: from %d to %d, lim %u\n", __func__, (int)dyn->num_entries, size, - (unsigned int)nwsi->vhost->h2.set.s[H2SET_HEADER_TABLE_SIZE]); + (unsigned int)nwsi->a.vhost->h2.set.s[H2SET_HEADER_TABLE_SIZE]); if (!size) { size = dyn->num_entries * 8; lws_hpack_destroy_dynamic_header(wsi); } - if (size > (int)nwsi->vhost->h2.set.s[H2SET_HEADER_TABLE_SIZE]) { + if (size > (int)nwsi->a.vhost->h2.set.s[H2SET_HEADER_TABLE_SIZE]) { lwsl_info("rejecting hpack dyn size %u vs %u\n", size, - (unsigned int)nwsi->vhost->h2.set.s[H2SET_HEADER_TABLE_SIZE]); + (unsigned int)nwsi->a.vhost->h2.set.s[H2SET_HEADER_TABLE_SIZE]); // this seems necessary to work with some browsers - if (nwsi->vhost->h2.set.s[H2SET_HEADER_TABLE_SIZE] == 65536 && + if (nwsi->a.vhost->h2.set.s[H2SET_HEADER_TABLE_SIZE] == 65536 && size == 65537) { /* h2spec */ lws_h2_goaway(nwsi, H2_ERR_COMPRESSION_ERROR, "Asked for header table bigger than we told"); goto bail; } - size = nwsi->vhost->h2.set.s[H2SET_HEADER_TABLE_SIZE]; + size = nwsi->a.vhost->h2.set.s[H2SET_HEADER_TABLE_SIZE]; } dyn->virtual_payload_max = size; @@ -641,7 +644,7 @@ while (dyn->virtual_payload_usage && dyn->used_entries && dyn->virtual_payload_usage > dyn->virtual_payload_max) { - n = (dyn->pos - dyn->used_entries) % dyn->num_entries; + n = lws_safe_modulo(dyn->pos - dyn->used_entries, dyn->num_entries); if (n < 0) n += dyn->num_entries; lws_dynamic_free(dyn, n); @@ -666,7 +669,7 @@ dyn->num_entries = size; dyn->used_entries = min; if (size) - dyn->pos = min % size; + dyn->pos = lws_safe_modulo(min, size); else dyn->pos = 0; @@ -754,47 +757,48 @@ return 0; } -#if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { 0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif -#if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif -#if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { - 0x03,0x00,0x80,0x0f,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x03,0x00,0x80,0x0f,0x00,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { - 0x07,0x00,0x00,0x3e,0x00,0x00,0x00,0x80,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00, + 0x07,0x00,0x00,0x3e,0x00,0x00,0x00,0x80,0x03,0x09,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif -#if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { - 0x03,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00, + 0x03,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) +#if defined(LWS_HTTP_HEADERS_ALL) || ( defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2)) static uint8_t lws_header_implies_psuedoheader_map[] = { - 0x07,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x00,0x0e,0x04,0x00,0x00,0x00,0x00,0x00, + 0x07,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x00,0x0e,0x24,0x00,0x00,0x00,0x00,0x00, }; #endif + static int lws_hpack_handle_pseudo_rules(struct lws *nwsi, struct lws *wsi, int m) { @@ -1250,8 +1254,6 @@ } } - n = 8; - /* we have the header */ if (!h2n->value) { h2n->value = 1; @@ -1276,6 +1278,13 @@ /* header length is determined by known index */ m = lws_token_from_index(wsi, h2n->hdr_idx, NULL, NULL, &h2n->hpack_hdr_len); + if (m < 0) + /* + * The peer may only send known 6-bit indexes, + * there's still the possibility it sends an unset + * dynamic index that we can't succeed to look up + */ + return 1; goto add_it; /* NEW literal hdr with value */ case HPKT_LITERAL_HDR_VALUE_INCR: @@ -1391,8 +1400,15 @@ { int len; - lwsl_header("%s: %p %s:%s (len %d)\n", __func__, *p, name, value, - length); +#if defined(_DEBUG) + /* value does not have to be NUL-terminated... %.*s not available on + * all platforms */ + lws_strnncpy((char *)*p, (const char *)value, length, + lws_ptr_diff(end, (*p))); + + lwsl_header("%s: %p %s:%s (len %d)\n", __func__, *p, name, + (const char *)*p, length); +#endif len = (int)strlen((char *)name); if (len) diff -Nru libwebsockets-4.0.20/lib/roles/h2/http2.c libwebsockets-4.1.6/lib/roles/h2/http2.c --- libwebsockets-4.0.20/lib/roles/h2/http2.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/h2/http2.c 2020-12-01 17:40:26.000000000 +0000 @@ -133,7 +133,7 @@ void lws_h2_init(struct lws *wsi) { - wsi->h2.h2n->our_set = wsi->vhost->h2.set; + wsi->h2.h2n->our_set = wsi->a.vhost->h2.set; wsi->h2.h2n->peer_set = lws_h2_defaults; } @@ -261,12 +261,17 @@ lwsi_set_state(wsi, LRS_ESTABLISHED); lwsi_set_role(wsi, lwsi_role(parent_wsi)); - wsi->protocol = &vh->protocols[0]; + wsi->a.protocol = &vh->protocols[0]; if (lws_ensure_user_space(wsi)) goto bail1; #if defined(LWS_WITH_SERVER_STATUS) - wsi->vhost->conn_stats.h2_subs++; + wsi->a.vhost->conn_stats.h2_subs++; +#endif + +#if defined(LWS_WITH_SERVER) && defined(LWS_WITH_SECURE_STREAMS) + if (lws_adopt_ss_server_accept(wsi)) + goto bail1; #endif /* get the ball rolling */ @@ -344,7 +349,7 @@ lws_callback_on_writable(wsi); #if defined(LWS_WITH_SERVER_STATUS) - wsi->vhost->conn_stats.h2_subs++; + wsi->a.vhost->conn_stats.h2_subs++; #endif return wsi; @@ -356,7 +361,7 @@ if (wsi->user_space) lws_free_set_NULL(wsi->user_space); - wsi->protocol->callback(wsi, LWS_CALLBACK_WSI_DESTROY, NULL, NULL, 0); + wsi->a.protocol->callback(wsi, LWS_CALLBACK_WSI_DESTROY, NULL, NULL, 0); lws_free(wsi); return NULL; @@ -540,7 +545,7 @@ break; case H2SET_MAX_FRAME_SIZE: - if (b < wsi->vhost->h2.set.s[H2SET_MAX_FRAME_SIZE]) { + if (b < wsi->a.vhost->h2.set.s[H2SET_MAX_FRAME_SIZE]) { lws_h2_goaway(nwsi, H2_ERR_PROTOCOL_ERROR, "Frame size < initial"); return 1; @@ -765,11 +770,16 @@ #endif if (lws_is_ssl(lws_get_network_wsi(wsi))) break; + + if (wsi->a.vhost->options & + LWS_SERVER_OPTION_H2_PRIOR_KNOWLEDGE) + break; + /* * we need to treat the headers from the upgrade as the * first job. So these need to get shifted to sid 1. */ - h2n->swsi = lws_wsi_server_new(wsi->vhost, wsi, 1); + h2n->swsi = lws_wsi_server_new(wsi->a.vhost, wsi, 1); if (!h2n->swsi) goto bail; @@ -789,7 +799,7 @@ lwsl_info("servicing initial http request\n"); #if defined(LWS_WITH_SERVER_STATUS) - wsi->vhost->conn_stats.h2_trans++; + wsi->a.vhost->conn_stats.h2_trans++; #endif #if defined(LWS_WITH_SERVER) if (lws_http_action(h2n->swsi)) @@ -862,7 +872,7 @@ if (cwsi) { lwsl_debug("%s: closing cwsi %p %s %s (wsi %p)\n", __func__, cwsi, cwsi->role_ops->name, - cwsi->protocol->name, wsi); + cwsi->a.protocol->name, wsi); lws_close_free_wsi(cwsi, 0, "reset stream"); } break; @@ -930,8 +940,8 @@ if (!wsi->immortal_substream_count) lws_set_timeout(wsi, PENDING_TIMEOUT_HTTP_KEEPALIVE_IDLE, - wsi->vhost->keepalive_timeout ? - wsi->vhost->keepalive_timeout : 31); + wsi->a.vhost->keepalive_timeout ? + wsi->a.vhost->keepalive_timeout : 31); if (h2n->sid) h2n->swsi = lws_wsi_mux_from_id(wsi, h2n->sid); @@ -943,8 +953,16 @@ if (h2n->we_told_goaway && h2n->sid > h2n->highest_sid) h2n->type = LWS_H2_FRAME_TYPE_COUNT; /* ie, IGNORE */ - if (h2n->type == LWS_H2_FRAME_TYPE_COUNT) - return 0; + if (h2n->type >= LWS_H2_FRAME_TYPE_COUNT) { + lwsl_info("%s: ignoring unknown frame type %d (len %d)\n", __func__, h2n->type, (unsigned int)h2n->length); + /* we MUST ignore frames we don't understand */ + h2n->type = LWS_H2_FRAME_TYPE_COUNT; + } + + /* + * Even if we have decided to logically ignore this frame, we must + * consume the correct "frame length" amount of data to retain sync + */ if (h2n->length > h2n->our_set.s[H2SET_MAX_FRAME_SIZE]) { /* @@ -993,7 +1011,7 @@ } } - if (h2n->swsi && h2n->sid && + if (h2n->swsi && h2n->sid && h2n->type != LWS_H2_FRAME_TYPE_COUNT && !(http2_rx_validity[h2n->swsi->h2.h2_state] & (1 << h2n->type))) { lwsl_info("%s: wsi %p, State: %s, ILLEGAL cmdrx %d (OK 0x%x)\n", __func__, h2n->swsi, @@ -1010,7 +1028,8 @@ return 0; } - if (h2n->cont_exp && (h2n->cont_exp_sid != h2n->sid || + if (h2n->cont_exp && h2n->type != LWS_H2_FRAME_TYPE_COUNT && + (h2n->cont_exp_sid != h2n->sid || h2n->type != LWS_H2_FRAME_TYPE_CONTINUATION)) { lwsl_info("%s: expected cont on sid %u (got %d on sid %u)\n", __func__, (unsigned int)h2n->cont_exp_sid, h2n->type, @@ -1106,7 +1125,7 @@ } if (!(h2n->flags & LWS_H2_FLAG_SETTINGS_ACK)) { - if ((!h2n->length) || h2n->length % 6) { + if (h2n->length % 6) { lws_h2_goaway(wsi, H2_ERR_FRAME_SIZE_ERROR, "Settings length error"); break; @@ -1218,7 +1237,7 @@ * of a new stream */ - h2n->swsi = lws_wsi_server_new(wsi->vhost, wsi, + h2n->swsi = lws_wsi_server_new(wsi->a.vhost, wsi, h2n->sid); if (!h2n->swsi) { lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR, @@ -1264,7 +1283,7 @@ assert(w->mux.sibling_list != w); } lws_end_foreach_ll(w, mux.sibling_list); - if (lws_check_opt(h2n->swsi->vhost->options, + if (lws_check_opt(h2n->swsi->a.vhost->options, LWS_SERVER_OPTION_VH_H2_HALF_CLOSED_LONG_POLL)) { /* @@ -1312,6 +1331,10 @@ lwsl_info("LWS_H2_FRAME_TYPE_WINDOW_UPDATE\n"); break; case LWS_H2_FRAME_TYPE_COUNT: + if (h2n->length == 0) + lws_h2_parse_end_of_frame(wsi); + else + lwsl_debug("%s: going on to deal with unknown frame remaining len %d\n", __func__, (unsigned int)h2n->length); break; default: lwsl_info("%s: ILLEGAL FRAME TYPE %d\n", __func__, h2n->type); @@ -1396,7 +1419,7 @@ * we need to treat the headers from the upgrade as the * first job. So these need to get shifted to sid 1. */ - h2n->swsi = lws_wsi_server_new(wsi->vhost, wsi, 1); + h2n->swsi = lws_wsi_server_new(wsi->a.vhost, wsi, 1); if (!h2n->swsi) return 1; h2n->sid = 1; @@ -1419,15 +1442,15 @@ h2n->swsi->flags = wsi->flags; #endif - h2n->swsi->protocol = wsi->protocol; + h2n->swsi->a.protocol = wsi->a.protocol; if (h2n->swsi->user_space && !h2n->swsi->user_space_externally_allocated) lws_free(h2n->swsi->user_space); h2n->swsi->user_space = wsi->user_space; h2n->swsi->user_space_externally_allocated = wsi->user_space_externally_allocated; - h2n->swsi->opaque_user_data = wsi->opaque_user_data; - wsi->opaque_user_data = NULL; + h2n->swsi->a.opaque_user_data = wsi->a.opaque_user_data; + wsi->a.opaque_user_data = NULL; h2n->swsi->txc.manual_initial_tx_credit = wsi->txc.manual_initial_tx_credit; @@ -1532,9 +1555,12 @@ #endif if (lws_hdr_extant(h2n->swsi, WSI_TOKEN_HTTP_CONTENT_LENGTH)) { - h2n->swsi->http.rx_content_length = atoll( - lws_hdr_simple_ptr(h2n->swsi, - WSI_TOKEN_HTTP_CONTENT_LENGTH)); + const char *simp = lws_hdr_simple_ptr(h2n->swsi, + WSI_TOKEN_HTTP_CONTENT_LENGTH); + + if (!simp) /* coverity */ + return 1; + h2n->swsi->http.rx_content_length = atoll(simp); h2n->swsi->http.rx_content_remain = h2n->swsi->http.rx_content_length; lwsl_info("setting rx_content_length %lld\n", @@ -1617,6 +1643,7 @@ n = lws_hdr_total_length(h2n->swsi, WSI_TOKEN_TE); if (n != 8 || + !lws_hdr_simple_ptr(h2n->swsi, WSI_TOKEN_TE) || strncmp(lws_hdr_simple_ptr(h2n->swsi, WSI_TOKEN_TE), "trailers", n)) { lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR, @@ -1630,7 +1657,7 @@ #endif #if defined(LWS_WITH_SERVER_STATUS) - wsi->vhost->conn_stats.h2_trans++; + wsi->a.vhost->conn_stats.h2_trans++; #endif p = lws_hdr_simple_ptr(h2n->swsi, WSI_TOKEN_HTTP_COLON_METHOD); /* @@ -1638,7 +1665,7 @@ * index, so that it looks the same as h1 in the ah */ for (n = 0; n < (int)LWS_ARRAY_SIZE(method_names); n++) - if (!strcasecmp(p, method_names[n])) { + if (p && !strcasecmp(p, method_names[n])) { h2n->swsi->http.ah->frag_index[method_index[n]] = h2n->swsi->http.ah->frag_index[ WSI_TOKEN_HTTP_COLON_PATH]; @@ -1748,7 +1775,7 @@ break; /* ignore */ } - if (eff_wsi->vhost->options & + if (eff_wsi->a.vhost->options & LWS_SERVER_OPTION_H2_JUST_FIX_WINDOW_UPDATE_OVERFLOW && (uint64_t)eff_wsi->txc.tx_cr + (uint64_t)h2n->hpack_e_dep > (uint64_t)0x7fffffff) @@ -1856,7 +1883,7 @@ c = *in++; - // lwsl_notice("%s: 0x%x\n", __func__, c); + lwsl_debug("%s: 0x%x, count %u, len %u (type %d)\n", __func__, c, (unsigned int)h2n->count, (unsigned int)h2n->length, h2n->type); switch (lwsi_state(wsi)) { case LRS_H2_AWAIT_PREFACE: @@ -1886,6 +1913,7 @@ case LRS_H2_WAITING_TO_SEND_HEADERS: case LRS_ESTABLISHED: case LRS_H2_AWAIT_SETTINGS: + if (h2n->frame_state != LWS_H2_FRAME_HEADER_LENGTH) goto try_frame_start; @@ -1894,6 +1922,12 @@ */ h2n->count++; + if (h2n->type == LWS_H2_FRAME_TYPE_COUNT) { /* IGNORING FRAME */ + lwsl_debug("%s: consuming for ignored %u %u\n", __func__, (unsigned int)h2n->count, (unsigned int)h2n->length); + goto frame_end; + } + + if (h2n->flags & LWS_H2_FLAG_PADDED && !h2n->pad_length) { /* @@ -2006,8 +2040,8 @@ if (!wsi->immortal_substream_count) lws_set_timeout(wsi, PENDING_TIMEOUT_HTTP_KEEPALIVE_IDLE, - wsi->vhost->keepalive_timeout ? - wsi->vhost->keepalive_timeout : 31); + wsi->a.vhost->keepalive_timeout ? + wsi->a.vhost->keepalive_timeout : 31); if (!h2n->swsi) break; @@ -2030,6 +2064,10 @@ h2n->swsi->http.rx_content_remain < inlen + 1 && /* last */ h2n->inside < h2n->length) { + lwsl_warn("%s: rem %d, inlen %d\n", + __func__, + (int)h2n->swsi->http.rx_content_remain, + (int)inlen + 1); /* unread data in frame */ lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR, @@ -2050,7 +2088,7 @@ } #if defined(LWS_WITH_CLIENT) if (h2n->swsi->client_mux_substream) { - if (!h2n->swsi->protocol) { + if (!h2n->swsi->a.protocol) { lwsl_err("%s: swsi %p doesn't have protocol\n", __func__, h2n->swsi); m = 1; @@ -2061,7 +2099,7 @@ __func__, h2n->swsi->mux.my_sid); m = user_callback_handle_rxflow( - h2n->swsi->protocol->callback, + h2n->swsi->a.protocol->callback, h2n->swsi, LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ, h2n->swsi->user_space, @@ -2091,7 +2129,7 @@ if (m) { struct lws_context_per_thread *pt; - pt = &wsi->context->pt[(int)wsi->tsi]; + pt = &wsi->a.context->pt[(int)wsi->tsi]; lwsl_debug("%s: added %p to rxflow list\n", __func__, wsi); lws_dll2_add_head( @@ -2218,6 +2256,8 @@ break; case LWS_H2_FRAME_TYPE_COUNT: /* IGNORING FRAME */ + lwsl_debug("%s: consuming for ignored %u %u\n", __func__, (unsigned int)h2n->count, (unsigned int)h2n->length); + h2n->count++; break; default: @@ -2229,13 +2269,13 @@ frame_end: if (h2n->count > h2n->length) { - lwsl_notice("%s: count > length %u %u\n", + lwsl_notice("%s: count > length %u %u (type %d)\n", __func__, (unsigned int)h2n->count, - (unsigned int)h2n->length); - goto fail; - } - if (h2n->count != h2n->length) - break; + (unsigned int)h2n->length, h2n->type); + + } else + if (h2n->count != h2n->length) + break; /* * end of frame just happened @@ -2279,12 +2319,16 @@ } } - if (h2n->frame_state == LWS_H2_FRAME_HEADER_LENGTH) - if (lws_h2_parse_frame_header(wsi)) - goto fail; + if (h2n->frame_state == LWS_H2_FRAME_HEADER_LENGTH && + lws_h2_parse_frame_header(wsi)) + goto fail; break; default: + if (h2n->type == LWS_H2_FRAME_TYPE_COUNT) { /* IGNORING FRAME */ + lwsl_debug("%s: consuming for ignored %u %u\n", __func__, (unsigned int)h2n->count, (unsigned int)h2n->length); + h2n->count++; + } break; } } @@ -2315,10 +2359,10 @@ int lws_h2_client_handshake(struct lws *wsi) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; uint8_t *buf, *start, *p, *p1, *end; char *meth = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_METHOD), - *uri = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_URI); + *uri = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_URI), *simp; struct lws *nwsi = lws_get_network_wsi(wsi); int n, m; /* @@ -2344,11 +2388,12 @@ wsi->mux.my_sid = nwsi->h2.h2n->highest_sid_opened = sid; lwsl_info("%s: wsi %p: assigning SID %d at header send\n", __func__, wsi, sid); + lwsl_info("%s: CLIENT_WAITING_TO_SEND_HEADERS: pollout (sid %d)\n", __func__, wsi->mux.my_sid); p = start = buf = pt->serv_buf + LWS_PRE; - end = start + (wsi->context->pt_serv_buf_size / 2) - LWS_PRE - 1; + end = start + (wsi->a.context->pt_serv_buf_size / 2) - LWS_PRE - 1; /* it's time for us to send our client stream headers */ @@ -2367,27 +2412,25 @@ &p, end)) goto fail_length; - if (lws_add_http_header_by_token(wsi, + n = lws_hdr_total_length(wsi, _WSI_TOKEN_CLIENT_URI); + if (n && lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_COLON_PATH, - (unsigned char *)uri, - lws_hdr_total_length(wsi, _WSI_TOKEN_CLIENT_URI), - &p, end)) + (unsigned char *)uri, n, &p, end)) goto fail_length; - if (lws_add_http_header_by_token(wsi, + n = lws_hdr_total_length(wsi, _WSI_TOKEN_CLIENT_ORIGIN); + simp = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN); + if (n && simp && lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_COLON_AUTHORITY, - (unsigned char *)lws_hdr_simple_ptr(wsi, - _WSI_TOKEN_CLIENT_ORIGIN), - lws_hdr_total_length(wsi, _WSI_TOKEN_CLIENT_ORIGIN), - &p, end)) + (unsigned char *)simp, n, &p, end)) goto fail_length; - if (!wsi->client_h2_alpn && + n = lws_hdr_total_length(wsi, _WSI_TOKEN_CLIENT_HOST); + simp = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_HOST); + + if (!wsi->client_h2_alpn && n && simp && lws_add_http_header_by_token(wsi, WSI_TOKEN_HOST, - (unsigned char *)lws_hdr_simple_ptr(wsi, - _WSI_TOKEN_CLIENT_HOST), - lws_hdr_total_length(wsi, _WSI_TOKEN_CLIENT_HOST), - &p, end)) + (unsigned char *)simp, n, &p, end)) goto fail_length; if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_USER_AGENT, @@ -2412,7 +2455,7 @@ /* give userland a chance to append, eg, cookies */ - if (wsi->protocol->callback(wsi, + if (wsi->a.protocol->callback(wsi, LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER, wsi->user_space, &p, (end - p) - 12)) goto fail_length; @@ -2473,7 +2516,7 @@ } #endif -#if defined(LWS_ROLE_WS) +#if defined(LWS_ROLE_WS) && defined(LWS_WITH_SERVER) int lws_h2_ws_handshake(struct lws *wsi) { @@ -2505,11 +2548,50 @@ * - one came in, and ... */ if (lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL) && /* - it is not an empty string */ - wsi->protocol->name && wsi->protocol->name[0]) { + wsi->a.protocol->name && wsi->a.protocol->name[0]) { + +#if defined(LWS_WITH_SECURE_STREAMS) && defined(LWS_WITH_SERVER) + + /* + * This is the h2 version of server-ws.c understanding that it + * did the ws upgrade on a ss server object, therefore it needs + * to pass back to the peer the policy ws-protocol name, not + * the generic ss-ws.c protocol name + */ + + if (wsi->a.vhost && wsi->a.vhost->ss_handle && + wsi->a.vhost->ss_handle->policy->u.http.u.ws.subprotocol) { + lws_ss_handle_t *h = + (lws_ss_handle_t *)wsi->a.opaque_user_data; + + lwsl_notice("%s: Server SS %p .wsi %p switching to ws protocol\n", + __func__, h, h->wsi); + + wsi->a.protocol = &protocol_secstream_ws; + + /* + * inform the SS user code that this has done a one-way + * upgrade to some other protocol... it will likely + * want to treat subsequent payloads differently + */ + + lws_ss_event_helper(h, LWSSSCS_SERVER_UPGRADE); + + lws_mux_mark_immortal(wsi); + if (lws_add_http_header_by_token(wsi, WSI_TOKEN_PROTOCOL, - (unsigned char *)wsi->protocol->name, - (int)strlen(wsi->protocol->name), &p, end)) - return -1; + (unsigned char *)wsi->a.vhost->ss_handle->policy-> + u.http.u.ws.subprotocol, + (int)strlen(wsi->a.vhost->ss_handle->policy-> + u.http.u.ws.subprotocol), &p, end)) + return -1; + } else +#endif + + if (lws_add_http_header_by_token(wsi, WSI_TOKEN_PROTOCOL, + (unsigned char *)wsi->a.protocol->name, + (int)strlen(wsi->a.protocol->name), &p, end)) + return -1; } } @@ -2538,7 +2620,7 @@ hit = lws_find_mount(wsi, uri_ptr, n); if (hit && hit->cgienv && - wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP_PMO, wsi->user_space, + wsi->a.protocol->callback(wsi, LWS_CALLBACK_HTTP_PMO, wsi->user_space, (void *)hit->cgienv, 0)) return 1; diff -Nru libwebsockets-4.0.20/lib/roles/h2/ops-h2.c libwebsockets-4.1.6/lib/roles/h2/ops-h2.c --- libwebsockets-4.0.20/lib/roles/h2/ops-h2.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/h2/ops-h2.c 2020-12-01 17:40:26.000000000 +0000 @@ -203,7 +203,7 @@ ebuf.token = pt->serv_buf; ebuf.len = lws_ssl_capable_read(wsi, ebuf.token, - wsi->context->pt_serv_buf_size); + wsi->a.context->pt_serv_buf_size); switch (ebuf.len) { case 0: lwsl_info("%s: zero length read\n", __func__); @@ -248,7 +248,7 @@ * callback and drain / re-enable it there */ if (user_callback_handle_rxflow( - wsi->protocol->callback, + wsi->a.protocol->callback, wsi, LWS_CALLBACK_RECEIVE_CLIENT_HTTP, wsi->user_space, NULL, 0)) { lwsl_info("RECEIVE_CLIENT_HTTP closed it\n"); @@ -403,8 +403,8 @@ )) { //assert(0); lwsl_notice("%s: binning wsistate 0x%x %d: %s\n", __func__, - (unsigned int)wsi->wsistate, *wp, wsi->protocol ? - wsi->protocol->name : "no protocol"); + (unsigned int)wsi->wsistate, *wp, wsi->a.protocol ? + wsi->a.protocol->name : "no protocol"); return 0; } @@ -488,6 +488,7 @@ return (int)olen; } +#if defined(LWS_WITH_SERVER) static int rops_check_upgrades_h2(struct lws *wsi) { @@ -501,7 +502,7 @@ * SETTINGS saying that we support it though. */ p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_METHOD); - if (!wsi->vhost->h2.set.s[H2SET_ENABLE_CONNECT_PROTOCOL] || + if (!wsi->a.vhost->h2.set.s[H2SET_ENABLE_CONNECT_PROTOCOL] || !wsi->mux_substream || !p || strcmp(p, "CONNECT")) return LWS_UPG_RET_CONTINUE; @@ -510,7 +511,7 @@ return LWS_UPG_RET_CONTINUE; #if defined(LWS_WITH_SERVER_STATUS) - wsi->vhost->conn_stats.ws_upg++; + wsi->a.vhost->conn_stats.ws_upg++; #endif lwsl_info("Upgrade h2 to ws\n"); lws_mux_mark_immortal(wsi); @@ -526,6 +527,7 @@ return LWS_UPG_RET_CONTINUE; #endif } +#endif static int rops_init_vhost_h2(struct lws_vhost *vh, @@ -558,8 +560,8 @@ pt->sul_ah_lifecheck.cb = lws_sul_http_ah_lifecheck; - __lws_sul_insert(&pt->pt_sul_owner, &pt->sul_ah_lifecheck, - 30 * LWS_US_PER_SEC); + __lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], + &pt->sul_ah_lifecheck, 30 * LWS_US_PER_SEC); } else lws_dll2_remove(&pt->sul_ah_lifecheck.list); #endif @@ -607,7 +609,7 @@ static int rops_destroy_role_h2(struct lws *wsi) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; struct allocated_headers *ah; /* we may not have an ah, but may be on the waiting list... */ @@ -650,7 +652,7 @@ wsi->http.proxy_clientside = 0; - if (user_callback_handle_rxflow(wsi->protocol->callback, + if (user_callback_handle_rxflow(wsi->a.protocol->callback, wsi, LWS_CALLBACK_COMPLETED_CLIENT_HTTP, wsi->user_space, NULL, 0)) @@ -766,12 +768,22 @@ p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_METHOD); if (p && !strcmp(p, "POST")) { - const struct lws_http_mount *hit = - lws_find_mount(wsi, - lws_hdr_simple_ptr(wsi, - WSI_TOKEN_HTTP_COLON_PATH), - lws_hdr_total_length(wsi, - WSI_TOKEN_HTTP_COLON_PATH)); + const struct lws_http_mount *hit; + + if (!lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COLON_PATH) || + !lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_PATH)) + /* + * There must be a path. Actually this is checked at + * http2.c along with the other required header + * presence before we can get here. + * + * But Coverity insists to see us check it. + */ + return 1; + + hit = lws_find_mount(wsi, + lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_PATH), + lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COLON_PATH)); lwsl_debug("%s: %s: hit %p: %s\n", __func__, lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_PATH), @@ -783,7 +795,7 @@ if (hit->protocol) name = hit->protocol; - pp = lws_vhost_name_to_protocol(wsi->vhost, name); + pp = lws_vhost_name_to_protocol(wsi->a.vhost, name); if (!pp) { lwsl_info("Unable to find protocol '%s'\n", name); return 1; @@ -794,7 +806,7 @@ } lwsl_info("%s: setting LRS_BODY from 0x%x (%s)\n", __func__, - (int)wsi->wsistate, wsi->protocol->name); + (int)wsi->wsistate, wsi->a.protocol->name); lwsi_set_state(wsi, LRS_BODY); } @@ -1153,7 +1165,7 @@ wsi->upgraded_to_http2 = 1; #if defined(LWS_WITH_SERVER_STATUS) - wsi->vhost->conn_stats.h2_alpn++; + wsi->a.vhost->conn_stats.h2_alpn++; #endif /* adopt the header info */ @@ -1225,7 +1237,11 @@ const struct lws_role_ops role_ops_h2 = { /* role name */ "h2", /* alpn id */ "h2", +#if defined(LWS_WITH_SERVER) /* check_upgrades */ rops_check_upgrades_h2, +#else + NULL, +#endif /* pt_init_destroy */ rops_pt_init_destroy_h2, /* init_vhost */ rops_init_vhost_h2, /* destroy_vhost */ NULL, diff -Nru libwebsockets-4.0.20/lib/roles/http/client/client-handshake.c libwebsockets-4.1.6/lib/roles/http/client/client-handshake.c --- libwebsockets-4.0.20/lib/roles/http/client/client-handshake.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/http/client/client-handshake.c 2020-12-01 17:40:26.000000000 +0000 @@ -62,7 +62,7 @@ ssize_t plen) { #if defined(LWS_CLIENT_HTTP_PROXYING) - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; #endif const char *meth; struct lws_pollfd pfd; @@ -87,7 +87,7 @@ /* we are connected to server, or proxy */ /* http proxy */ - if (wsi->vhost->http.http_proxy_port) { + if (wsi->a.vhost->http.http_proxy_port) { const char *cpa; cpa = lws_wsi_client_stash_item(wsi, CIS_ADDRESS, @@ -104,10 +104,10 @@ cpa, wsi->ocport); #if defined(LWS_WITH_HTTP_BASIC_AUTH) - if (wsi->vhost->proxy_basic_auth_token[0]) + 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->vhost->proxy_basic_auth_token); + wsi->a.vhost->proxy_basic_auth_token); #endif plen += lws_snprintf((char *)pt->serv_buf + plen, 5, "\x0d\x0a"); @@ -119,13 +119,13 @@ */ if (wsi->stash) wsi->stash->cis[CIS_ADDRESS] = - wsi->vhost->http.http_proxy_address; + wsi->a.vhost->http.http_proxy_address; else if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS, - wsi->vhost->http.http_proxy_address)) + wsi->a.vhost->http.http_proxy_address)) goto failed; - wsi->c_port = wsi->vhost->http.http_proxy_port; + wsi->c_port = wsi->a.vhost->http.http_proxy_port; n = send(wsi->desc.sockfd, (char *)pt->serv_buf, (int)plen, MSG_NOSIGNAL); @@ -136,7 +136,7 @@ } lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_PROXY_RESPONSE, - wsi->context->timeout_secs); + wsi->a.context->timeout_secs); lwsi_set_state(wsi, LRS_WAITING_PROXY_REPLY); @@ -145,6 +145,10 @@ #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)) { @@ -192,49 +196,59 @@ } 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->protocol->name, rawish, wsi->vhost->name, lwsi_state(wsi)); + wsi->a.protocol->name, rawish, wsi->a.vhost->name, + lwsi_state(wsi)); /* we are making our own connection */ - if (!rawish) - lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE); - else { - /* for a method = "RAW" connection, this makes us - * established */ - + 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)) { - - + /* we have connected if we got here */ - /* we can retry this... just cook the SSL BIO the first time */ + if (lwsi_state(wsi) == LRS_WAITING_CONNECT && + (wsi->tls.use_ssl & LCCSCF_USE_SSL)) { + int result; - switch (lws_client_create_tls(wsi, &cce, 1)) { - case 0: - break; - case 1: - return wsi; - default: - goto failed; - } + /* + * 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: st 0x%x\n", - __func__, wsi, lwsi_state(wsi)); + lwsl_notice("%s: wsi %p: tls established st 0x%x\n", + __func__, wsi, lwsi_state(wsi)); - if (lwsi_state(wsi) == LRS_WAITING_CONNECT) - lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE2); - lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND, - wsi->context->timeout_secs); + 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); - return wsi; - } + goto provoke_service; + } #endif /* clear his established timeout */ @@ -243,7 +257,7 @@ m = wsi->role_ops->adoption_cb[0]; if (m) { n = user_callback_handle_rxflow( - wsi->protocol->callback, wsi, + wsi->a.protocol->callback, wsi, m, wsi->user_space, NULL, 0); if (n < 0) { lwsl_info("LWS_CALLBACK_RAW_PROXY_CLI_ADOPT failed\n"); @@ -269,7 +283,7 @@ * provoke service to issue the CONNECT directly. */ lws_set_timeout(wsi, PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE, - AWAITING_TIMEOUT); + wsi->a.context->timeout_secs); assert(lws_socket_is_valid(wsi->desc.sockfd)); @@ -278,7 +292,7 @@ pfd.revents = LWS_POLLOUT; lwsl_info("%s: going to service fd\n", __func__); - n = lws_service_fd(wsi->context, &pfd); + n = lws_service_fd(wsi->a.context, &pfd); if (n < 0) { cce = "first service failed"; goto failed; @@ -304,9 +318,11 @@ * 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->context->timeout_secs); + wsi->a.context->timeout_secs); assert(lws_socket_is_valid(wsi->desc.sockfd)); @@ -314,7 +330,7 @@ pfd.events = LWS_POLLIN; pfd.revents = LWS_POLLIN; - n = lws_service_fd(wsi->context, &pfd); + n = lws_service_fd(wsi->a.context, &pfd); if (n < 0) { cce = "first service failed"; goto failed; @@ -333,6 +349,20 @@ 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) @@ -341,18 +371,22 @@ struct sockaddr_un sau; #endif #ifdef LWS_WITH_IPV6 - char ipv6only = lws_check_opt(wsi->vhost->options, + 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; - const char *cce = "", *iface; 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 @@ -365,16 +399,7 @@ if (!lws_dll2_is_detached(&wsi->dll2_cli_txn_queue)) return wsi; -#if 0 - if (!ads && !result) { - cce = "dns resolution failed"; - if (!wsi->oom4) - goto oom4; - else - goto failed; - } -#endif -#if !defined(WIN32) + /* * We can check using getsockopt if our connect actually completed. * Posix connect() allows nonblocking to redo the connect to @@ -384,22 +409,36 @@ 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, -#if defined(WIN32) - (char *) -#endif &e, &sl)) { if (!e) { - lwsl_info("%s: getsockopt check: conn OK\n", - __func__); + lwsl_debug("%s: getsockopt check: conn OK errno %d\n", + __func__, errno); goto conn_good; } @@ -407,12 +446,12 @@ 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; } -#endif #if defined(LWS_WITH_UNIX_SOCK) if (ads && *ads == '+') { @@ -435,7 +474,11 @@ #if defined(LWS_WITH_SYS_ASYNC_DNS) if (n == LADNS_RET_FAILED) { lwsl_notice("%s: adns failed %s\n", __func__, ads); - goto oom4; + /* + * Caller that is giving us LADNS_RET_FAILED will deal + * with cleanup + */ + return NULL; } #endif @@ -448,13 +491,13 @@ #if defined(LWS_WITH_DETAILED_LATENCY) if (lwsi_state(wsi) == LRS_WAITING_DNS && - wsi->context->detailed_latency_cb) { + 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->context, &wsi->detlat); + lws_det_lat_cb(wsi->a.context, &wsi->detlat); wsi->detlat.earliest_write_req_pre_write = lws_now_usecs(); } #endif @@ -465,9 +508,8 @@ * * Priority 1: connect to http proxy */ - if (wsi->vhost->http.http_proxy_port) { - ads = wsi->vhost->http.http_proxy_address; - port = wsi->vhost->http.http_proxy_port; + if (wsi->a.vhost->http.http_proxy_port) { + port = wsi->a.vhost->http.http_proxy_port; #else if (0) { #endif @@ -476,15 +518,15 @@ /* Priority 2: Connect to SOCK5 Proxy */ - } else if (wsi->vhost->socks_proxy_port) { + } 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->vhost->socks_proxy_address; - port = wsi->vhost->socks_proxy_port; + ads = wsi->a.vhost->socks_proxy_address; + port = wsi->a.vhost->socks_proxy_port; #endif } @@ -529,7 +571,8 @@ 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, ni); + lwsl_info("%s: %s ipv4->ipv6 %s\n", __func__, + ads ? ads : "(null)", ni); break; } #endif @@ -542,7 +585,7 @@ 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, ni); + lwsl_info("%s: %s ipv4 %s\n", __func__, ads ? ads : "(null)", ni); break; case AF_INET6: #if defined(LWS_WITH_IPV6) @@ -559,7 +602,7 @@ 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, 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 @@ -574,8 +617,8 @@ if (!lws_socket_is_valid(wsi->desc.sockfd)) { - if (wsi->context->event_loop_ops->check_client_connect_ok && - wsi->context->event_loop_ops->check_client_connect_ok(wsi)) { + 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; } @@ -593,7 +636,7 @@ goto try_next_result; } - if (lws_plat_set_socket_options(wsi->vhost, wsi->desc.sockfd, + if (lws_plat_set_socket_options(wsi->a.vhost, wsi->desc.sockfd, #if defined(LWS_WITH_UNIX_SOCK) wsi->unix_skt)) { #else @@ -606,35 +649,42 @@ lwsl_debug("%s: %p: WAITING_CONNECT\n", __func__, wsi); lwsi_set_state(wsi, LRS_WAITING_CONNECT); - if (wsi->context->event_loop_ops->sock_accept) - if (wsi->context->event_loop_ops->sock_accept(wsi)) + if (wsi->a.context->event_loop_ops->sock_accept) + if (wsi->a.context->event_loop_ops->sock_accept(wsi)) goto try_next_result_closesock; - if (__insert_wsi_socket_into_fds(wsi->context, wsi)) + lws_pt_lock(pt, __func__); + if (__insert_wsi_socket_into_fds(wsi->a.context, wsi)) { + lws_pt_unlock(pt); goto try_next_result_closesock; - - if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) - goto try_next_result_fds; + } + 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. */ - wsi->oom4 = 1; - if (!wsi->protocol) - wsi->protocol = &wsi->vhost->protocols[0]; + + 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->context->timeout_secs); + 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->vhost, wsi->desc.sockfd, 0, + m = lws_socket_bind(wsi->a.vhost, wsi->desc.sockfd, 0, iface, wsi->ipv6); if (m < 0) goto try_next_result_fds; @@ -645,9 +695,9 @@ if (wsi->unix_skt) { psa = (const struct sockaddr *)&sau; if (sau.sun_path[0]) - n = sizeof(uint16_t) + strlen(sau.sun_path); + n = (int)(sizeof(uint16_t) + strlen(sau.sun_path)); else - n = sizeof(uint16_t) + strlen(&sau.sun_path[1]) + 1; + n = (int)(sizeof(uint16_t) + strlen(&sau.sun_path[1]) + 1); } else #endif @@ -663,13 +713,16 @@ 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 != LWS_EALREADY && + if (errno_copy && errno_copy != LWS_EALREADY && errno_copy != LWS_EINPROGRESS && errno_copy != LWS_EWOULDBLOCK #ifdef _WIN32 @@ -694,29 +747,41 @@ #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->context->detailed_latency_cb) { + 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->context, &wsi->detlat); + lws_det_lat_cb(wsi->a.context, &wsi->detlat); wsi->detlat.earliest_write_req = wsi->detlat.earliest_write_req_pre_write = lws_now_usecs(); @@ -725,18 +790,25 @@ lws_addrinfo_clean(wsi); - if (wsi->protocol) - wsi->protocol->callback(wsi, LWS_CALLBACK_WSI_CREATE, + 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: - if (lwsi_role_client(wsi) && wsi->protocol /* && lwsi_state_est(wsi) */) + /* + * 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; /* @@ -747,25 +819,37 @@ * so nobody else should have had a chance to queue on us. */ { - struct lws_vhost *vhost = wsi->vhost; + 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: - wsi->oom4 = 0; __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) @@ -831,6 +915,13 @@ 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; @@ -838,7 +929,7 @@ lwsl_notice("%s: ACTIVE_CONNS_MUXED\n", __func__); if (lwsi_role_h2(wsi)) { - if (wsi->protocol->callback(wsi, + if (wsi->a.protocol->callback(wsi, LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP, wsi->user_space, NULL, 0)) goto failed1; @@ -850,6 +941,14 @@ 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); } @@ -889,12 +988,12 @@ !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->vhost); + 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->vhost->dll_cli_active_conns_owner); - lws_vhost_unlock(wsi->vhost); + &wsi->a.vhost->dll_cli_active_conns_owner); + lws_vhost_unlock(wsi->a.vhost); } /* @@ -905,6 +1004,14 @@ 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; @@ -916,7 +1023,7 @@ /* * start off allowing ipv6 on connection if vhost allows it */ - wsi->ipv6 = LWS_IPV6_ENABLED(wsi->vhost); + wsi->ipv6 = LWS_IPV6_ENABLED(wsi->a.vhost); #ifdef LWS_WITH_IPV6 if (wsi->stash) iface = wsi->stash->cis[CIS_IFACE]; @@ -932,13 +1039,13 @@ #if defined(LWS_WITH_DETAILED_LATENCY) if (lwsi_state(wsi) == LRS_WAITING_DNS && - wsi->context->detailed_latency_cb) { + 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->context, &wsi->detlat); + lws_det_lat_cb(wsi->a.context, &wsi->detlat); wsi->detlat.earliest_write_req_pre_write = lws_now_usecs(); } #endif @@ -950,9 +1057,9 @@ * * Priority 1: connect to http proxy */ - if (wsi->vhost->http.http_proxy_port) { - ads = wsi->vhost->http.http_proxy_address; - port = wsi->vhost->http.http_proxy_port; + 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 @@ -961,10 +1068,10 @@ /* Priority 2: Connect to SOCK5 Proxy */ - } else if (wsi->vhost->socks_proxy_port) { + } else if (wsi->a.vhost->socks_proxy_port) { lwsl_client("Sending SOCKS Greeting\n"); - ads = wsi->vhost->socks_proxy_address; - port = wsi->vhost->socks_proxy_port; + ads = wsi->a.vhost->socks_proxy_address; + port = wsi->a.vhost->socks_proxy_port; #endif } else { @@ -995,7 +1102,7 @@ lwsi_set_state(wsi, LRS_WAITING_DNS); /* this is either FAILED, CONTINUING, or already called connect_4 */ - n = lws_async_dns_query(wsi->context, wsi->tsi, ads, LWS_ADNS_RECORD_A, + 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; @@ -1099,7 +1206,8 @@ */ for (n = 0; n < (int)LWS_ARRAY_SIZE(hnames2); n++) - if (lws_hdr_total_length(wsi, 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); @@ -1148,8 +1256,8 @@ if (wsi->role_ops && wsi->role_ops->close_kill_connection) wsi->role_ops->close_kill_connection(wsi, 1); - if (wsi->context->event_loop_ops->close_handle_manually) - wsi->context->event_loop_ops->close_handle_manually(wsi); + 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); @@ -1166,8 +1274,8 @@ } #endif - if (wsi->protocol && wsi->role_ops && wsi->protocol_bind_balance) { - wsi->protocol->callback(wsi, + 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); @@ -1177,9 +1285,9 @@ wsi->desc.sockfd = LWS_SOCK_INVALID; lws_role_transition(wsi, LWSIFR_CLIENT, LRS_UNCONNECTED, &role_ops_h1); -// wsi->protocol = NULL; - if (wsi->protocol) - lws_bind_protocol(wsi, wsi->protocol, "client_reset"); +// 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; @@ -1380,8 +1488,8 @@ break; } - if (r->wsi->protocol_bind_balance && - user_callback_handle_rxflow(r->wsi->protocol->callback, + 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; @@ -1414,7 +1522,7 @@ if (!stash) return wsi; - wsi->opaque_user_data = wsi->stash->opaque_user_data; + 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"))) @@ -1432,18 +1540,18 @@ } #if defined(LWS_WITH_SOCKS5) - if (!wsi->vhost->socks_proxy_port) + if (!wsi->a.vhost->socks_proxy_port) lws_free_set_NULL(wsi->stash); #endif no_ah: - wsi->context->count_wsi_allocated++; + wsi->a.context->count_wsi_allocated++; return lws_client_connect_2_dnsreq(wsi); bail1: #if defined(LWS_WITH_SOCKS5) - if (!wsi->vhost->socks_proxy_port) + if (!wsi->a.vhost->socks_proxy_port) lws_free_set_NULL(wsi->stash); #endif diff -Nru libwebsockets-4.0.20/lib/roles/http/client/client-http.c libwebsockets-4.1.6/lib/roles/http/client/client-http.c --- libwebsockets-4.0.20/lib/roles/http/client/client-http.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/http/client/client-http.c 2020-12-01 17:40:26.000000000 +0000 @@ -28,34 +28,38 @@ int lws_client_create_tls(struct lws *wsi, const char **pcce, int do_c1) { - int n; /* 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 -1; + return CCTLS_RETURN_ERROR; } +#if defined(LWS_WITH_TLS) if (!wsi->transaction_from_pipeline_queue && - lws_tls_restrict_borrow(wsi->context)) { + lws_tls_restrict_borrow(wsi->a.context)) { *pcce = "tls restriction limit"; - return -1; + return CCTLS_RETURN_ERROR; } +#endif } if (!do_c1) return 0; - n = lws_ssl_client_connect1(wsi); + 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 1; /* caller should return 0 */ + return CCTLS_RETURN_RETRY; /* caller should return 0 */ if (n < 0) { - *pcce = "lws_ssl_client_connect1 failed"; - return -1; + *pcce = (const char *)wsi->a.context->pt[(int)wsi->tsi].serv_buf; + return CCTLS_RETURN_ERROR; } } else wsi->tls.ssl = NULL; @@ -76,12 +80,12 @@ /* send the H2 preface to legitimize the connection */ if (lws_h2_issue_preface(wsi)) { *pcce = "error sending h2 preface"; - return -1; + return CCTLS_RETURN_ERROR; } } #endif - return 0; /* OK */ + return CCTLS_RETURN_DONE; /* OK */ } #endif @@ -95,7 +99,7 @@ int lws_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd) { - struct lws_context *context = wsi->context; + struct lws_context *context = wsi->a.context; struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; char *p = (char *)&pt->serv_buf[0]; #if defined(LWS_WITH_TLS) @@ -193,7 +197,7 @@ lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0); - /* fallthru */ + /* fallthrough */ #endif @@ -231,8 +235,13 @@ cce = ebuf; goto bail3; } - } else + } else { wsi->tls.ssl = NULL; + if(wsi->flags & LCCSCF_H2_PRIOR_KNOWLEDGE) { + lwsl_info("h2 prior knowledge\n"); + lws_role_call_alpn_negotiated(wsi, "h2"); + } + } #endif #if defined(LWS_WITH_DETAILED_LATENCY) if (context->detailed_latency_cb) { @@ -241,20 +250,24 @@ lws_now_usecs() - wsi->detlat.earliest_write_req_pre_write; wsi->detlat.latencies[LAT_DUR_USERCB] = 0; - lws_det_lat_cb(wsi->context, &wsi->detlat); + lws_det_lat_cb(wsi->a.context, &wsi->detlat); } #endif #if defined (LWS_WITH_HTTP2) if (wsi->client_h2_alpn) { /* - * We connected to the server and set up tls, and - * negotiated "h2". + * We connected to the server and set up tls and + * negotiated "h2" or connected as clear text + * with http/2 prior knowledge. * * 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); + if (wsi->tls.use_ssl & LCCSCF_USE_SSL) { + lws_tls_server_conn_alpn(wsi); + } #endif /* send the H2 preface to legitimize the connection */ @@ -343,7 +356,7 @@ } lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE, - wsi->context->timeout_secs); + wsi->a.context->timeout_secs); lws_callback_on_writable(wsi); @@ -439,8 +452,13 @@ buffered, __func__)) return -1; - eb.token += m; - eb.len -= m; + + /* + * coverity: uncomment if extended + * + * eb.token += m; + * eb.len -= m; + */ if (n) { assert(wsi->http.ah->parser_state == @@ -467,9 +485,12 @@ return lws_client_interpret_server_handshake(wsi); bail3: - lwsl_info("closing conn at LWS_CONNMODE...SERVER_REPLY\n"); + lwsl_info("%s: closing conn at LWS_CONNMODE...SERVER_REPLY, wsi %p, state 0x%x\n", + __func__, wsi, lwsi_state(wsi)); if (cce) lwsl_info("reason: %s\n", cce); + else + cce = "unknown"; lws_inform_client_conn_fail(wsi, (void *)cce, strlen(cce)); lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "cbail3"); @@ -487,11 +508,12 @@ int LWS_WARN_UNUSED_RESULT lws_http_transaction_completed_client(struct lws *wsi) { + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; int n; - lwsl_info("%s: wsi: %p (%s)\n", __func__, wsi, wsi->protocol->name); + lwsl_info("%s: wsi: %p (%s)\n", __func__, wsi, wsi->a.protocol->name); - if (user_callback_handle_rxflow(wsi->protocol->callback, wsi, + if (user_callback_handle_rxflow(wsi->a.protocol->callback, wsi, LWS_CALLBACK_COMPLETED_CLIENT_HTTP, wsi->user_space, NULL, 0)) { lwsl_debug("%s: Completed call returned nonzero (role 0x%lx)\n", @@ -505,7 +527,9 @@ * For h1, wsi may pass some assets on to a queued child and be * destroyed during this. */ - n = _lws_generic_transaction_completed_active_conn(&wsi); + lws_pt_lock(pt, __func__); + n = _lws_generic_transaction_completed_active_conn(&wsi, 1); + lws_pt_unlock(pt); if (wsi->http.ah) { if (wsi->client_mux_substream) @@ -536,7 +560,7 @@ wsi->http.ah->unk_pos = 0; lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE, - wsi->context->timeout_secs); + wsi->a.context->timeout_secs); /* If we're (re)starting on headers, need other implied init */ wsi->http.ah->ues = URIES_IDLE; @@ -574,7 +598,7 @@ const char *prot, *ads = NULL, *path, *cce = NULL; struct allocated_headers *ah, *ah1; struct lws *nwsi = lws_get_network_wsi(wsi); - char *p = NULL, *q; + char *p = NULL, *q, *simp; char new_path[300]; lws_free_set_NULL(wsi->stash); @@ -672,6 +696,15 @@ goto bail3; } + /* let's let the user code know, if he cares */ + + if (wsi->a.protocol->callback(wsi, + LWS_CALLBACK_CLIENT_HTTP_REDIRECT, + wsi->user_space, p, n)) { + cce = "HS: user code rejected redirect"; + goto bail3; + } + /* * Some redirect codes imply we have to change the method * used for the subsequent transaction, commonly POST -> @@ -773,72 +806,119 @@ return 0; } - if (!wsi->do_ws) { - - /* if h1 KA is allowed, enable the queued pipeline guys */ + /* if h1 KA is allowed, enable the queued pipeline guys */ - if (!wsi->client_h2_alpn && !wsi->client_mux_substream) { - /* ie, coming to this for the first time */ - if (wsi->http.conn_type == HTTP_CONNECTION_KEEP_ALIVE) - wsi->keepalive_active = 1; - else { - /* - * Ugh... now the main http connection has seen - * both sides, we learn the server doesn't - * support keepalive. - * - * That means any guys queued on us are going - * to have to be restarted from connect2 with - * their own connections. - */ + if (!wsi->client_h2_alpn && !wsi->client_mux_substream) { + /* ie, coming to this for the first time */ + if (wsi->http.conn_type == HTTP_CONNECTION_KEEP_ALIVE) + wsi->keepalive_active = 1; + else { + /* + * Ugh... now the main http connection has seen + * both sides, we learn the server doesn't + * support keepalive. + * + * That means any guys queued on us are going + * to have to be restarted from connect2 with + * their own connections. + */ - /* - * stick around telling any new guys they can't - * pipeline to this server - */ - wsi->keepalive_rejected = 1; + /* + * stick around telling any new guys they can't + * pipeline to this server + */ + wsi->keepalive_rejected = 1; - lws_vhost_lock(wsi->vhost); - lws_start_foreach_dll_safe(struct lws_dll2 *, - d, d1, - wsi->dll2_cli_txn_queue_owner.head) { - struct lws *ww = lws_container_of(d, - struct lws, - dll2_cli_txn_queue); - - /* remove him from our queue */ - lws_dll2_remove(&ww->dll2_cli_txn_queue); - /* give up on pipelining */ - ww->client_pipeline = 0; - - /* go back to "trying to connect" state */ - lws_role_transition(ww, LWSIFR_CLIENT, - LRS_UNCONNECTED, + lws_vhost_lock(wsi->a.vhost); + lws_start_foreach_dll_safe(struct lws_dll2 *, + d, d1, + wsi->dll2_cli_txn_queue_owner.head) { + struct lws *ww = lws_container_of(d, + struct lws, + dll2_cli_txn_queue); + + /* remove him from our queue */ + lws_dll2_remove(&ww->dll2_cli_txn_queue); + /* give up on pipelining */ + ww->client_pipeline = 0; + + /* go back to "trying to connect" state */ + lws_role_transition(ww, LWSIFR_CLIENT, + LRS_UNCONNECTED, #if defined(LWS_ROLE_H1) - &role_ops_h1); + &role_ops_h1); #else #if defined (LWS_ROLE_H2) - &role_ops_h2); + &role_ops_h2); #else - &role_ops_raw); + &role_ops_raw); #endif #endif - ww->user_space = NULL; - } lws_end_foreach_dll_safe(d, d1); - lws_vhost_unlock(wsi->vhost); - } + ww->user_space = NULL; + } lws_end_foreach_dll_safe(d, d1); + lws_vhost_unlock(wsi->a.vhost); } + } #ifdef LWS_WITH_HTTP_PROXY - wsi->http.perform_rewrite = 0; - if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE)) { - if (!strncmp(lws_hdr_simple_ptr(wsi, - WSI_TOKEN_HTTP_CONTENT_TYPE), - "text/html", 9)) - wsi->http.perform_rewrite = 0; - } + wsi->http.perform_rewrite = 0; + if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE)) { + if (!strncmp(lws_hdr_simple_ptr(wsi, + WSI_TOKEN_HTTP_CONTENT_TYPE), + "text/html", 9)) + wsi->http.perform_rewrite = 0; + } #endif + /* he may choose to send us stuff in chunked transfer-coding */ + wsi->chunked = 0; + wsi->chunk_remaining = 0; /* ie, next thing is chunk size */ + if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_TRANSFER_ENCODING)) { + simp = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_TRANSFER_ENCODING); + + /* cannot be NULL, since it has nonzero length... coverity */ + if (!simp) + goto bail2; + wsi->chunked = !strcmp(simp, "chunked"); + /* first thing is hex, after payload there is crlf */ + wsi->chunk_parser = ELCP_HEX; + } + + wsi->http.content_length_given = 0; + if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH)) { + simp = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH); + + /* cannot be NULL, since it has nonzero length... coverity */ + if (!simp) + goto bail2; + + wsi->http.rx_content_length = atoll(simp); + lwsl_info("%s: incoming content length %llu\n", + __func__, (unsigned long long) + wsi->http.rx_content_length); + wsi->http.rx_content_remain = + wsi->http.rx_content_length; + wsi->http.content_length_given = 1; + } else { /* can't do 1.1 without a content length or chunked */ + if (!wsi->chunked) + wsi->http.conn_type = HTTP_CONNECTION_CLOSE; + lwsl_debug("%s: no content length\n", __func__); + } + + if (wsi->do_ws) { + /* + * Give one last opportunity to ws protocols to inspect server reply + * before the ws upgrade code discard it. ie: download reply body in case + * of any other response code than 101. + */ + if (wsi->a.protocol->callback(wsi, + LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP, + wsi->user_space, NULL, 0)) { + + cce = "HS: disallowed by client filter"; + goto bail2; + } + } else { /* allocate the per-connection user memory (if any) */ if (lws_ensure_user_space(wsi)) { lwsl_err("Problem allocating wsi user mem\n"); @@ -846,34 +926,6 @@ goto bail2; } - /* he may choose to send us stuff in chunked transfer-coding */ - wsi->chunked = 0; - wsi->chunk_remaining = 0; /* ie, next thing is chunk size */ - if (lws_hdr_total_length(wsi, - WSI_TOKEN_HTTP_TRANSFER_ENCODING)) { - wsi->chunked = !strcmp(lws_hdr_simple_ptr(wsi, - WSI_TOKEN_HTTP_TRANSFER_ENCODING), - "chunked"); - /* first thing is hex, after payload there is crlf */ - wsi->chunk_parser = ELCP_HEX; - } - - wsi->http.content_length_given = 0; - if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH)) { - wsi->http.rx_content_length = - atoll(lws_hdr_simple_ptr(wsi, - WSI_TOKEN_HTTP_CONTENT_LENGTH)); - lwsl_info("%s: incoming content length %llu\n", - __func__, (unsigned long long) - wsi->http.rx_content_length); - wsi->http.rx_content_remain = - wsi->http.rx_content_length; - wsi->http.content_length_given = 1; - } else { /* can't do 1.1 without a content length or chunked */ - if (!wsi->chunked) - wsi->http.conn_type = HTTP_CONNECTION_CLOSE; - lwsl_debug("%s: no content length\n", __func__); - } /* * we seem to be good to go, give client last chance to check @@ -881,7 +933,7 @@ */ ah1 = wsi->http.ah; wsi->http.ah = ah; - if (wsi->protocol->callback(wsi, + if (wsi->a.protocol->callback(wsi, LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH, wsi->user_space, NULL, 0)) { wsi->http.ah = ah1; @@ -895,7 +947,7 @@ wsi->rxflow_change_to = LWS_RXFLOW_ALLOW; /* call him back to inform him he is up */ - if (wsi->protocol->callback(wsi, + if (wsi->a.protocol->callback(wsi, LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP, wsi->user_space, NULL, 0)) { wsi->http.ah = ah1; @@ -949,7 +1001,7 @@ close_reason = LWS_CLOSE_STATUS_NOSTATUS; bail2: - if (wsi->protocol) { + if (wsi->a.protocol) { n = 0; if (cce) n = (int)strlen(cce); @@ -958,8 +1010,8 @@ } lwsl_info("closing connection (prot %s) " - "due to bail2 connection error: %s\n", wsi->protocol ? - wsi->protocol->name : "unknown", cce); + "due to bail2 connection error: %s\n", wsi->a.protocol ? + wsi->a.protocol->name : "unknown", cce); /* closing will free up his parsing allocations */ lws_close_free_wsi(wsi, close_reason, "c hs interp"); @@ -978,7 +1030,10 @@ char buf[10], arg[48]; int n; - lws_get_random(wsi->context, (uint8_t *)buf, sizeof(buf)); + if (lws_get_random(wsi->a.context, (uint8_t *)buf, sizeof(buf)) != + sizeof(buf)) + return NULL; + lws_b64_encode_string(buf, sizeof(buf), wsi->http.multipart_boundary, sizeof(wsi->http.multipart_boundary)); @@ -1008,7 +1063,7 @@ assert(wsi->http.multipart); if (!name) { - *p += lws_snprintf((char *)(*p), lws_ptr_diff(end, p), + *p += lws_snprintf((char *)(*p), lws_ptr_diff(end, *p), "\xd\xa--%s--\xd\xa", wsi->http.multipart_boundary); @@ -1016,22 +1071,22 @@ } if (wsi->client_subsequent_mime_part) - *p += lws_snprintf((char *)(*p), lws_ptr_diff(end, p), "\xd\xa"); + *p += lws_snprintf((char *)(*p), lws_ptr_diff(end, *p), "\xd\xa"); wsi->client_subsequent_mime_part = 1; - *p += lws_snprintf((char *)(*p), lws_ptr_diff(end, p), "--%s\xd\xa" + *p += lws_snprintf((char *)(*p), lws_ptr_diff(end, *p), "--%s\xd\xa" "Content-Disposition: form-data; " "name=\"%s\"", wsi->http.multipart_boundary, name); if (filename) - *p += lws_snprintf((char *)(*p), lws_ptr_diff(end, p), + *p += lws_snprintf((char *)(*p), lws_ptr_diff(end, *p), "; filename=\"%s\"", filename); if (content_type) - *p += lws_snprintf((char *)(*p), lws_ptr_diff(end, p), "\xd\xa" + *p += lws_snprintf((char *)(*p), lws_ptr_diff(end, *p), "\xd\xa" "Content-Type: %s", content_type); - *p += lws_snprintf((char *)(*p), lws_ptr_diff(end, p), "\xd\xa\xd\xa"); + *p += lws_snprintf((char *)(*p), lws_ptr_diff(end, *p), "\xd\xa\xd\xa"); return *p == end; } @@ -1058,7 +1113,7 @@ if (pp) { const struct lws_protocols *pr; - pr = lws_vhost_name_to_protocol(wsi->vhost, pp); + pr = lws_vhost_name_to_protocol(wsi->a.vhost, pp); if (!pr) { lwsl_err("protocol %s not enabled on vhost\n", @@ -1069,7 +1124,7 @@ lws_bind_protocol(wsi, pr, __func__); } - if ((wsi->protocol->callback)(wsi, LWS_CALLBACK_RAW_ADOPT, + if ((wsi->a.protocol->callback)(wsi, LWS_CALLBACK_RAW_ADOPT, wsi->user_space, NULL, 0)) return NULL; @@ -1103,7 +1158,7 @@ lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_HOST)); if (lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN)) { - if (lws_check_opt(wsi->context->options, + if (lws_check_opt(wsi->a.context->options, LWS_SERVER_OPTION_JUST_USE_RAW_ORIGIN)) p += lws_snprintf(p, 128, "Origin: %s\x0d\x0a", lws_hdr_simple_ptr(wsi, @@ -1156,10 +1211,10 @@ /* give userland a chance to append, eg, cookies */ - if (wsi->protocol->callback(wsi, + if (wsi->a.protocol->callback(wsi, LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER, wsi->user_space, &p, - (pkt + wsi->context->pt_serv_buf_size) - p - 12)) + (pkt + wsi->a.context->pt_serv_buf_size) - p - 12)) return NULL; if (wsi->flags & LCCSCF_HTTP_X_WWW_FORM_URLENCODED) { @@ -1207,7 +1262,7 @@ int lws_http_client_read(struct lws *wsi, char **buf, int *len) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; struct lws_tokens eb; int buffered, n, consumed = 0; @@ -1387,13 +1442,16 @@ !!wsi->protocol_bind_balance #endif ) { - if (user_callback_handle_rxflow(wsi->protocol->callback, + int q; + + q = user_callback_handle_rxflow(wsi->a.protocol->callback, wsi, LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ, - wsi->user_space, *buf, n)) { - lwsl_info("%s: RECEIVE_CLIENT_HTTP_READ returned -1\n", - __func__); + wsi->user_space, *buf, n); + if (q) { + lwsl_info("%s: RECEIVE_CLIENT_HTTP_READ returned %d\n", + __func__, q); - return -1; + return q; } } else lwsl_notice("%s: swallowed read (%d)\n", __func__, n); diff -Nru libwebsockets-4.0.20/lib/roles/http/CMakeLists.txt libwebsockets-4.1.6/lib/roles/http/CMakeLists.txt --- libwebsockets-4.0.20/lib/roles/http/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/http/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,90 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(. ./compression) + +list(APPEND SOURCES + roles/http/header.c + roles/http/parsers.c) + +if (NOT LWS_WITHOUT_SERVER) + list(APPEND SOURCES + roles/http/server/server.c + roles/http/server/lws-spa.c) +endif() + +if (LWS_WITH_HTTP_PROXY AND LWS_WITH_HUBBUB) + list(APPEND SOURCES + roles/http/server/rewrite.c) +endif() + +if (LWS_WITH_ACCESS_LOG) + list(APPEND SOURCES + roles/http/server/access-log.c) +endif() + +if (LWS_WITH_HTTP_STREAM_COMPRESSION) + list(APPEND SOURCES + roles/http/compression/stream.c + roles/http/compression/deflate/deflate.c) + + if (LWS_WITH_HTTP_BROTLI) + list(APPEND SOURCES + roles/http/compression/brotli/brotli.c) + list(APPEND LIB_LIST brotlienc brotlidec brotlidec) + endif() +endif() + +if (LWS_WITH_LEJP_CONF AND LWS_WITH_NETWORK AND NOT LWS_PLAT_OPTEE) + list(APPEND SOURCES + roles/http/server/lejp-conf.c + ) +endif() + +if (LWS_WITH_RANGES) + list(APPEND SOURCES + roles/http/server/ranges.c) +endif() + +if (LWS_WITH_ZIP_FOPS) + if (LWS_WITH_ZLIB) + list(APPEND SOURCES + roles/http/server/fops-zip.c) + else() + message(FATAL_ERROR "Pre-zipped file support (LWS_WITH_ZIP_FOPS) requires ZLIB (LWS_WITH_ZLIB)") + endif() +endif() + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() \ No newline at end of file diff -Nru libwebsockets-4.0.20/lib/roles/http/header.c libwebsockets-4.1.6/lib/roles/http/header.c --- libwebsockets-4.0.20/lib/roles/http/header.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/http/header.c 2020-12-01 17:40:26.000000000 +0000 @@ -157,7 +157,8 @@ if (lws_add_http_header_status(wsi, code, p, end)) return 1; - if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE, + if (content_type && + lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE, (unsigned char *)content_type, (int)strlen(content_type), p, end)) return 1; @@ -326,7 +327,7 @@ return 1; } - headers = wsi->vhost->headers; + headers = wsi->a.vhost->headers; while (headers) { if (lws_add_http_header_by_name(wsi, (const unsigned char *)headers->name, @@ -337,7 +338,7 @@ headers = headers->next; } - if (wsi->vhost->options & + if (wsi->a.vhost->options & LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE) { headers = &pvo_hsbph[LWS_ARRAY_SIZE(pvo_hsbph) - 1]; while (headers) { @@ -351,16 +352,16 @@ } } - if (wsi->context->server_string && + if (wsi->a.context->server_string && !(_code & LWSAHH_FLAG_NO_SERVER_NAME)) { - assert(wsi->context->server_string_len > 0); + assert(wsi->a.context->server_string_len > 0); if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_SERVER, - (unsigned char *)wsi->context->server_string, - wsi->context->server_string_len, p, end)) + (unsigned char *)wsi->a.context->server_string, + wsi->a.context->server_string_len, p, end)) return 1; } - if (wsi->vhost->options & LWS_SERVER_OPTION_STS) + if (wsi->a.vhost->options & LWS_SERVER_OPTION_STS) if (lws_add_http_header_by_name(wsi, (unsigned char *) "Strict-Transport-Security:", (unsigned char *)"max-age=15768000 ; " @@ -389,19 +390,19 @@ int n = 0, m = 0, len; char slen[20]; - if (!wsi->vhost) { + if (!wsi->a.vhost) { lwsl_err("%s: wsi not bound to vhost\n", __func__); return 1; } #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) if (!wsi->handling_404 && - wsi->vhost->http.error_document_404 && + wsi->a.vhost->http.error_document_404 && code == HTTP_STATUS_NOT_FOUND) /* we should do a redirect, and do the 404 there */ if (lws_http_redirect(wsi, HTTP_STATUS_FOUND, - (uint8_t *)wsi->vhost->http.error_document_404, - (int)strlen(wsi->vhost->http.error_document_404), + (uint8_t *)wsi->a.vhost->http.error_document_404, + (int)strlen(wsi->a.vhost->http.error_document_404), &p, end) > 0) return 0; #endif @@ -570,9 +571,9 @@ const unsigned char *c; if (!ah->in_use || !ah->wsi || !ah->assigned || - (ah->wsi->vhost && + (ah->wsi->a.vhost && (now - ah->assigned) < - ah->wsi->vhost->timeout_secs_ah_idle + 360)) { + ah->wsi->a.vhost->timeout_secs_ah_idle + 360)) { ah = ah->next; continue; } diff -Nru libwebsockets-4.0.20/lib/roles/http/lextable.h libwebsockets-4.1.6/lib/roles/http/lextable.h --- libwebsockets-4.0.20/lib/roles/http/lextable.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/http/lextable.h 2020-12-01 17:40:26.000000000 +0000 @@ -1,4 +1,4 @@ -#if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) /* 0: 0: get */ /* 1: 1: post */ /* 2: 3: host: */ @@ -522,7 +522,7 @@ /* total size 662 bytes */ #endif -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) /* 0: 0: get */ /* 1: 1: post */ /* 2: 2: options */ @@ -1290,7 +1290,7 @@ /* total size 968 bytes */ #endif -#if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) /* 0: 0: get */ /* 1: 1: post */ /* 2: 3: host: */ @@ -2134,7 +2134,7 @@ /* total size 1088 bytes */ #endif -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) /* 0: 0: get */ /* 1: 1: post */ /* 2: 2: options */ @@ -2998,7 +2998,7 @@ /* total size 1088 bytes */ #endif -#if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) /* 0: 0: get */ /* 1: 1: post */ /* 2: 3: host: */ @@ -3912,7 +3912,7 @@ /* total size 1177 bytes */ #endif -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) /* 0: 0: get */ /* 1: 1: post */ /* 2: 2: options */ @@ -4833,7 +4833,7 @@ /* total size 1177 bytes */ #endif -#if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) /* 0: 0: get */ /* 1: 1: post */ /* 2: 3: host: */ @@ -5757,7 +5757,7 @@ /* total size 1177 bytes */ #endif -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) +#if defined(LWS_HTTP_HEADERS_ALL) || (defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2)) /* 0: 0: get */ /* 1: 1: post */ /* 2: 2: options */ @@ -6690,42 +6690,42 @@ /* -#if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { 0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif -#if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif -#if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { 0x03,0x00,0x80,0x0f,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { 0x07,0x00,0x00,0x3e,0x00,0x00,0x00,0x80,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif -#if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { 0x03,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) +#if defined(LWS_HTTP_HEADERS_ALL) || (defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2)) static uint8_t lws_header_implies_psuedoheader_map[] = { 0x07,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x00,0x0e,0x04,0x00,0x00,0x00,0x00,0x00, }; diff -Nru libwebsockets-4.0.20/lib/roles/http/lextable-strings.h libwebsockets-4.1.6/lib/roles/http/lextable-strings.h --- libwebsockets-4.0.20/lib/roles/http/lextable-strings.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/http/lextable-strings.h 2020-12-01 17:40:26.000000000 +0000 @@ -3,19 +3,19 @@ static const char * const set[] = { "get ", "post ", -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) "options ", #endif "host:", "connection:", "upgrade:", "origin:", -#if defined(LWS_ROLE_WS) +#if defined(LWS_ROLE_WS) || defined(LWS_HTTP_HEADERS_ALL) "sec-websocket-draft:", #endif "\x0d\x0a", -#if defined(LWS_ROLE_WS) +#if defined(LWS_ROLE_WS) || defined(LWS_HTTP_HEADERS_ALL) "sec-websocket-extensions:", "sec-websocket-key1:", "sec-websocket-key2:", @@ -25,12 +25,12 @@ "sec-websocket-nonce:", #endif "http/1.1 ", -#if defined(LWS_ROLE_H2) +#if defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) "http2-settings:", #endif "accept:", -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) "access-control-request-headers:", #endif "if-modified-since:", @@ -45,26 +45,26 @@ "content-type:", "date:", "range:", -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) "referer:", #endif -#if defined(LWS_ROLE_WS) +#if defined(LWS_ROLE_WS) || defined(LWS_HTTP_HEADERS_ALL) "sec-websocket-key:", "sec-websocket-version:", "sec-websocket-origin:", #endif -#if defined(LWS_ROLE_H2) +#if defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) ":authority", ":method", ":path", ":scheme", ":status", #endif -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) "accept-charset:", #endif "accept-ranges:", -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) "access-control-allow-origin:", #endif "age:", @@ -84,7 +84,7 @@ "last-modified:", "link:", "location:", -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) "max-forwards:", "proxy-authenticate:", "proxy-authorization:", @@ -93,17 +93,17 @@ "retry-after:", "server:", "set-cookie:", -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) "strict-transport-security:", #endif "transfer-encoding:", -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) "user-agent:", "vary:", "via:", "www-authenticate:", #endif -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) "patch", "put", "delete", @@ -111,7 +111,7 @@ "uri-args", /* fake header used for uri-only storage */ -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) "proxy ", "x-real-ip:", #endif @@ -120,11 +120,11 @@ "x-forwarded-for:", "connect ", "head ", -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) "te:", /* http/2 wants it to reject it */ "replay-nonce:", /* ACME */ #endif -#if defined(LWS_ROLE_H2) +#if defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) ":protocol", /* defined in mcmanus-httpbis-h2-ws-02 */ #endif diff -Nru libwebsockets-4.0.20/lib/roles/http/minilex.c libwebsockets-4.1.6/lib/roles/http/minilex.c --- libwebsockets-4.0.20/lib/roles/http/minilex.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/http/minilex.c 2020-12-01 17:40:26.000000000 +0000 @@ -138,7 +138,7 @@ static unsigned char lws_header_implies_psuedoheader_map[] = { 0x07, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00 /* <-64 */, - 0x0e /* <- 72 */, 0x04 /* <- 80 */, 0, 0, 0, 0 + 0x0e /* <- 72 */, 0x24 /* <- 80 */, 0, 0, 0, 0 }; /* @@ -249,10 +249,16 @@ memset(rset, 0, sizeof(rset)); - printf("#if %cdefined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && " - "%cdefined(LWS_ROLE_WS) && " - "%cdefined(LWS_ROLE_H2)\n", version & 1 ? ' ' : '!', - version & 2 ? ' ' : '!', version & 4 ? ' ' : '!'); + if (version == 7) + printf("#if defined(LWS_HTTP_HEADERS_ALL) || (%cdefined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && " + "%cdefined(LWS_ROLE_WS) && " + "%cdefined(LWS_ROLE_H2))\n", version & 1 ? ' ' : '!', + version & 2 ? ' ' : '!', version & 4 ? ' ' : '!'); + else + printf("#if !defined(LWS_HTTP_HEADERS_ALL) && %cdefined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && " + "%cdefined(LWS_ROLE_WS) && " + "%cdefined(LWS_ROLE_H2)\n", version & 1 ? ' ' : '!', + version & 2 ? ' ' : '!', version & 4 ? ' ' : '!'); /* * let's create version's view of the set of strings @@ -467,7 +473,13 @@ for (n = 0; n < 8; n++) { - printf("#if %cdefined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && " + if (n == 7) + printf("#if defined(LWS_HTTP_HEADERS_ALL) || (%cdefined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && " + "%cdefined(LWS_ROLE_WS) && " + "%cdefined(LWS_ROLE_H2))\n", n & 1 ? ' ' : '!', + n & 2 ? ' ' : '!', n & 4 ? ' ' : '!'); + else + printf("#if !defined(LWS_HTTP_HEADERS_ALL) && %cdefined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && " "%cdefined(LWS_ROLE_WS) && " "%cdefined(LWS_ROLE_H2)\n", n & 1 ? ' ' : '!', n & 2 ? ' ' : '!', n & 4 ? ' ' : '!'); diff -Nru libwebsockets-4.0.20/lib/roles/http/parsers.c libwebsockets-4.1.6/lib/roles/http/parsers.c --- libwebsockets-4.0.20/lib/roles/http/parsers.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/http/parsers.c 2020-12-01 17:40:26.000000000 +0000 @@ -124,7 +124,7 @@ /* while we hold the ah, keep a timeout on the wsi */ __lws_set_timeout(wsi, PENDING_TIMEOUT_HOLDING_AH, - wsi->vhost->timeout_secs_ah_idle); + wsi->a.vhost->timeout_secs_ah_idle); time(&ah->assigned); @@ -133,7 +133,7 @@ autoservice) { lwsl_debug("%s: service on readbuf ah\n", __func__); - pt = &wsi->context->pt[(int)wsi->tsi]; + pt = &wsi->a.context->pt[(int)wsi->tsi]; /* * Unlike a normal connect, we have the headers already * (or the first part of them anyway) @@ -141,14 +141,14 @@ pfd = &pt->fds[wsi->position_in_fds_table]; pfd->revents |= LWS_POLLIN; lwsl_err("%s: calling service\n", __func__); - lws_service_fd_tsi(wsi->context, pfd, wsi->tsi); + lws_service_fd_tsi(wsi->a.context, pfd, wsi->tsi); } } void lws_header_table_reset(struct lws *wsi, int autoservice) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; lws_pt_lock(pt, __func__); @@ -160,7 +160,7 @@ static void _lws_header_ensure_we_are_on_waiting_list(struct lws *wsi) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; struct lws_pollargs pa; struct lws **pwsi = &pt->http.ah_wait_list; @@ -183,7 +183,7 @@ static int __lws_remove_from_ah_waiting_list(struct lws *wsi) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; struct lws **pwsi =&pt->http.ah_wait_list; while (*pwsi) { @@ -206,7 +206,7 @@ int LWS_WARN_UNUSED_RESULT lws_header_table_attach(struct lws *wsi, int autoservice) { - struct lws_context *context = wsi->context; + struct lws_context *context = wsi->a.context; struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; struct lws_pollargs pa; int n; @@ -308,7 +308,7 @@ int __lws_header_table_detach(struct lws *wsi, int autoservice) { - struct lws_context *context = wsi->context; + struct lws_context *context = wsi->a.context; struct allocated_headers *ah = wsi->http.ah; struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; struct lws_pollargs pa; @@ -451,7 +451,7 @@ int lws_header_table_detach(struct lws *wsi, int autoservice) { - struct lws_context *context = wsi->context; + struct lws_context *context = wsi->a.context; struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; int n; @@ -659,10 +659,10 @@ return -1; if (wsi->http.ah->pos < - (unsigned int)wsi->context->max_http_header_data) + (unsigned int)wsi->a.context->max_http_header_data) return 0; - if ((int)wsi->http.ah->pos >= wsi->context->max_http_header_data - 1) { + if ((int)wsi->http.ah->pos >= wsi->a.context->max_http_header_data - 1) { lwsl_err("Ran out of header data space\n"); return 1; } @@ -673,7 +673,7 @@ */ lwsl_err("%s: pos %ld, limit %ld\n", __func__, (unsigned long)wsi->http.ah->pos, - (unsigned long)wsi->context->max_http_header_data); + (unsigned long)wsi->a.context->max_http_header_data); assert(0); return 1; @@ -961,7 +961,7 @@ lws_parse(struct lws *wsi, unsigned char *buf, int *len) { struct allocated_headers *ah = wsi->http.ah; - struct lws_context *context = wsi->context; + struct lws_context *context = wsi->a.context; unsigned int n, m; unsigned char c; int r, pos; @@ -1065,12 +1065,18 @@ check_eol: /* bail at EOL */ if (ah->parser_state != WSI_TOKEN_CHALLENGE && - c == '\x0d') { + (c == '\x0d' || c == '\x0a')) { if (ah->ues != URIES_IDLE) goto forbid; + if (c == '\x0a') { + /* broken peer */ + ah->parser_state = WSI_TOKEN_NAME_PART; + ah->unk_pos = ah->lextable_pos = 0; + } else + ah->parser_state = WSI_TOKEN_SKIPPING_SAW_CR; + c = '\0'; - ah->parser_state = WSI_TOKEN_SKIPPING_SAW_CR; lwsl_parser("*\n"); } @@ -1095,6 +1101,10 @@ (unsigned long)lwsi_role(wsi), ah->lextable_pos); + if (!ah->unk_pos && c == '\x0a') + /* broken peer */ + goto set_parsing_complete; + if (c >= 'A' && c <= 'Z') c += 'a' - 'A'; /* @@ -1105,6 +1115,7 @@ if (!wsi->mux_substream && !ah->unk_pos) { ah->unk_pos = ah->pos; + #if defined(LWS_WITH_CUSTOM_HEADERS) /* * Prepare new unknown header linked-list entry @@ -1271,7 +1282,7 @@ * Are we set up to transition to another role * in these cases? */ - if (lws_check_opt(wsi->vhost->options, + if (lws_check_opt(wsi->a.vhost->options, LWS_SERVER_OPTION_FALLBACK_TO_APPLY_LISTEN_ACCEPT_CONFIG)) { lwsl_notice("%s: http fail fallback\n", __func__); @@ -1283,6 +1294,9 @@ goto forbid; } if (ah->lextable_pos < 0) { + /* + * It's not a header that lws knows about... + */ #if defined(LWS_WITH_CUSTOM_HEADERS) if (!wsi->mux_substream) goto unknown_hdr; @@ -1309,11 +1323,21 @@ return LPR_FAIL; } + if (!wsi->mux_substream) { + /* + * Whether we are collecting unknown names or not, + * if we matched an internal header we can dispense + * with the header name part we were keeping + */ + ah->pos = ah->unk_pos; + ah->unk_pos = 0; + } + +#if defined(LWS_ROLE_WS) /* * WSORIGIN is protocol equiv to ORIGIN, * JWebSocket likes to send it, map to ORIGIN */ -#if defined(LWS_ROLE_WS) if (n == WSI_TOKEN_SWORIGIN) n = WSI_TOKEN_ORIGIN; #endif @@ -1328,7 +1352,7 @@ ah->parser_state]; else ah->current_token_limit = - wsi->context->max_http_header_data; + wsi->a.context->max_http_header_data; if (ah->parser_state == WSI_TOKEN_CHALLENGE) goto set_parsing_complete; @@ -1377,6 +1401,12 @@ case WSI_TOKEN_SKIPPING: lwsl_parser("WSI_TOKEN_SKIPPING '%c'\n", c); + if (c == '\x0a') { + /* broken peer */ + ah->parser_state = WSI_TOKEN_NAME_PART; + ah->unk_pos = ah->lextable_pos = 0; + } + if (c == '\x0d') ah->parser_state = WSI_TOKEN_SKIPPING_SAW_CR; break; @@ -1408,9 +1438,9 @@ if (lws_hdr_total_length(wsi, WSI_TOKEN_UPGRADE)) { #if defined(LWS_ROLE_WS) - if (lws_hdr_total_length(wsi, WSI_TOKEN_VERSION)) - wsi->rx_frame_type = /* temp for ws version index */ - atoi(lws_hdr_simple_ptr(wsi, WSI_TOKEN_VERSION)); + const char *pv = lws_hdr_simple_ptr(wsi, WSI_TOKEN_VERSION); + if (pv) + wsi->rx_frame_type = atoi(pv); lwsl_parser("v%02d hdrs done\n", wsi->rx_frame_type); #endif @@ -1429,3 +1459,158 @@ return LPR_FORBIDDEN; } +int +lws_http_cookie_get(struct lws *wsi, const char *name, char *buf, + size_t *max_len) +{ + int n, bl = (int)strlen(name); + size_t max = *max_len; + char *p, *bo = buf; + + n = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COOKIE); + lwsl_notice("%s: cookie hdr len %d\n", __func__, n); + if (n < bl + 1) + return 1; + + p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COOKIE); + if (!p) + return 1; + + lwsl_hexdump_notice(p, n); + + p += bl; + n -= bl; + while (n-- > bl) { + if (*p == '=' && !memcmp(p - bl, name, bl)) { + p++; + while (*p != ';' && n-- && max) { + *buf++ = *p++; + max--; + } + if (!max) + return 2; + + *buf = '\0'; + *max_len = lws_ptr_diff(buf, bo); + + return 0; + } + p++; + } + + return 1; +} + +#if defined(LWS_WITH_JOSE) + +#define MAX_JWT_SIZE 1024 + +int +lws_jwt_get_http_cookie_validate_jwt(struct lws *wsi, + struct lws_jwt_sign_set_cookie *i, + char *out, size_t *out_len) +{ + char temp[MAX_JWT_SIZE * 2]; + size_t cml = *out_len; + const char *cp; + + /* first use out to hold the encoded JWT */ + + if (lws_http_cookie_get(wsi, i->cookie_name, out, out_len)) { + lwsl_notice("%s: cookie %s not provided\n", __func__, + i->cookie_name); + return 1; + } + + /* decode the JWT into temp */ + + if (lws_jwt_signed_validate(wsi->a.context, i->jwk, i->alg, out, + *out_len, temp, sizeof(temp), out, &cml)) { + lwsl_notice("%s: jwt validation failed\n", __func__); + return 1; + } + + /* + * Copy out the decoded JWT payload into out, overwriting the + * original encoded JWT taken from the cookie (that has long ago been + * translated into allocated buffers in the JOSE object) + */ + + if (lws_jwt_token_sanity(out, cml, i->iss, i->aud, i->csrf_in, + i->sub, sizeof(i->sub), + &i->expiry_unix_time)) { + lwsl_notice("%s: jwt sanity failed\n", __func__); + return 1; + } + + /* + * If he's interested in his private JSON part, point him to that in + * the args struct (it's pointing to the data in out + */ + + cp = lws_json_simple_find(out, cml, "\"ext\":", &i->extra_json_len); + if (cp) + i->extra_json = cp; + + if (cp) + lwsl_hexdump_notice(cp, i->extra_json_len); + else + lwsl_notice("%s: no ext JWT payload\n", __func__); + + return 0; +} + +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) +{ + char plain[MAX_JWT_SIZE + 1], temp[MAX_JWT_SIZE * 2], csrf[17]; + size_t pl = sizeof(plain); + unsigned long long ull; + int n; + + /* + * Create a 16-char random csrf token with the same lifetime as the JWT + */ + + lws_hex_random(wsi->a.context, csrf, sizeof(csrf)); + ull = lws_now_secs(); + if (lws_jwt_sign_compact(wsi->a.context, i->jwk, i->alg, plain, &pl, + temp, sizeof(temp), + "{\"iss\":\"%s\",\"aud\":\"%s\"," + "\"iat\":%llu,\"nbf\":%llu,\"exp\":%llu," + "\"csrf\":\"%s\",\"sub\":\"%s\"%s%s%s}", + i->iss, i->aud, ull, ull - 60, + ull + i->expiry_unix_time, + csrf, i->sub, + i->extra_json ? ",\"ext\":{" : "", + i->extra_json ? i->extra_json : "", + i->extra_json ? "}" : "")) { + lwsl_err("%s: failed to create JWT\n", __func__); + + return 1; + } + + /* + * There's no point the browser holding on to a JWT beyond the JWT's + * expiry time, so set it to be the same. + */ + + n = lws_snprintf(temp, sizeof(temp), "__Host-%s=%s;" + "HttpOnly;" + "Secure;" + "SameSite=strict;" + "Path=/;" + "Max-Age=%lu", + i->cookie_name, plain, i->expiry_unix_time); + + if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_SET_COOKIE, + (uint8_t *)temp, n, p, end)) { + lwsl_err("%s: failed to add JWT cookie header\n", __func__); + return 1; + } + + return 0; +} +#endif diff -Nru libwebsockets-4.0.20/lib/roles/http/private-lib-roles-http.h libwebsockets-4.1.6/lib/roles/http/private-lib-roles-http.h --- libwebsockets-4.0.20/lib/roles/http/private-lib-roles-http.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/http/private-lib-roles-http.h 2020-12-01 17:40:26.000000000 +0000 @@ -327,5 +327,11 @@ uint8_t * lws_http_multipart_headers(struct lws *wsi, uint8_t *p); +enum { + CCTLS_RETURN_ERROR = -1, + CCTLS_RETURN_DONE = 0, + CCTLS_RETURN_RETRY = 1, +}; + int lws_client_create_tls(struct lws *wsi, const char **pcce, int do_c1); diff -Nru libwebsockets-4.0.20/lib/roles/http/server/access-log.c libwebsockets-4.1.6/lib/roles/http/server/access-log.c --- libwebsockets-4.0.20/lib/roles/http/server/access-log.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/http/server/access-log.c 2020-12-01 17:40:26.000000000 +0000 @@ -50,11 +50,11 @@ int l = 256, m; struct tm *tmp; - if (!wsi->vhost) + if (!wsi->a.vhost) return; /* only worry about preparing it if we store it */ - if (wsi->vhost->log_fd == (int)LWS_INVALID_FILE) + if (wsi->a.vhost->log_fd == (int)LWS_INVALID_FILE) return; if (wsi->access_log_pending) @@ -70,10 +70,13 @@ else strcpy(da, "01/Jan/1970:00:00:00 +0000"); +#if defined(LWS_ROLE_H2) if (wsi->mux_substream) me = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_METHOD); else +#endif me = method_names[meth]; + if (!me) me = "(null)"; @@ -138,10 +141,10 @@ *p1 = wsi->http.access_log.referrer; int l; - if (!wsi->vhost) + if (!wsi->a.vhost) return 0; - if (wsi->vhost->log_fd == (int)LWS_INVALID_FILE) + if (wsi->a.vhost->log_fd == (int)LWS_INVALID_FILE) return 0; if (!wsi->access_log_pending) @@ -173,7 +176,7 @@ ass[sizeof(ass) - 1] = '\0'; - if (write(wsi->vhost->log_fd, ass, l) != l) + if (write(wsi->a.vhost->log_fd, ass, l) != l) lwsl_err("Failed to write log\n"); if (wsi->http.access_log.header_log) { diff -Nru libwebsockets-4.0.20/lib/roles/http/server/fops-zip.c libwebsockets-4.1.6/lib/roles/http/server/fops-zip.c --- libwebsockets-4.0.20/lib/roles/http/server/fops-zip.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/http/server/fops-zip.c 2020-12-01 17:40:26.000000000 +0000 @@ -144,6 +144,9 @@ LWS_FZ_ERR_SEEK_COMPRESSED, }; +#define eff_size(_priv) (_priv->hdr.method == ZIP_COMPRESSION_METHOD_STORE ? \ + _priv->hdr.uncomp_size : _priv->hdr.comp_size) + static uint16_t get_u16(void *p) { @@ -341,7 +344,7 @@ priv->zip_fop_fd = fops->LWS_FOP_OPEN(fops, rp, NULL, &local_flags); if (!priv->zip_fop_fd) { - lwsl_err("unable to open zip %s\n", rp); + lwsl_err("%s: unable to open zip %s\n", __func__, rp); goto bail1; } @@ -526,11 +529,8 @@ spin: if (!priv->inflate.avail_in) { rlen = sizeof(priv->rbuf); - if (rlen > priv->hdr.comp_size - - (cur - priv->content_start)) - rlen = priv->hdr.comp_size - - (priv->hdr.comp_size - - priv->content_start); + if (rlen > eff_size(priv) - (cur - priv->content_start)) + rlen = eff_size(priv) - (cur - priv->content_start); if (priv->zip_fop_fd->fops->LWS_FOP_READ( priv->zip_fop_fd, &ramount, priv->rbuf, @@ -632,14 +632,15 @@ lwsl_info("%s: store\n", __func__); - if (len > priv->hdr.uncomp_size - (cur - priv->content_start)) - len = priv->hdr.comp_size - (priv->hdr.comp_size - - priv->content_start); + if (len > eff_size(priv) - cur) + len = eff_size(priv) - cur; if (priv->zip_fop_fd->fops->LWS_FOP_READ(priv->zip_fop_fd, amount, buf, len)) return LWS_FZ_ERR_READ_CONTENT; + fd->pos += *amount; + return 0; } diff -Nru libwebsockets-4.0.20/lib/roles/http/server/lejp-conf.c libwebsockets-4.1.6/lib/roles/http/server/lejp-conf.c --- libwebsockets-4.0.20/lib/roles/http/server/lejp-conf.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/http/server/lejp-conf.c 2020-12-01 17:40:26.000000000 +0000 @@ -40,13 +40,14 @@ "global.init-ssl", "global.server-string", "global.plugin-dir", - "global.ws-pingpong-secs", + "global.ws-pingpong-secs", /* deprecated */ "global.timeout-secs", "global.reject-service-keywords[].*", "global.reject-service-keywords[]", "global.default-alpn", "global.ip-limit-ah", "global.ip-limit-wsi", + "global.rlimit-nofile", }; enum lejp_global_paths { @@ -65,6 +66,7 @@ LWJPGP_DEFAULT_ALPN, LWJPGP_IP_LIMIT_AH, LWJPGP_IP_LIMIT_WSI, + LWJPGP_FD_LIMIT_PT, }; static const char * const paths_vhosts[] = { @@ -326,18 +328,20 @@ a->plugin_dirs[a->count_plugin_dirs++] = a->p; break; - case LWJPGP_PINGPONG_SECS: - a->info->ws_ping_pong_interval = atoi(ctx->buf); + case LWJPGP_PINGPONG_SECS: /* deprecated */ return 0; case LWJPGP_TIMEOUT_SECS: a->info->timeout_secs = atoi(ctx->buf); return 0; +#if defined(LWS_WITH_TLS) case LWJPGP_DEFAULT_ALPN: a->info->alpn = a->p; break; +#endif +#if defined(LWS_WITH_PEER_LIMITS) case LWJPGP_IP_LIMIT_AH: a->info->ip_limit_ah = atoi(ctx->buf); return 0; @@ -345,6 +349,11 @@ case LWJPGP_IP_LIMIT_WSI: a->info->ip_limit_wsi = atoi(ctx->buf); return 0; +#endif + + case LWJPGP_FD_LIMIT_PT: + a->info->rlimit_nofile = atoi(ctx->buf); + return 0; default: return 0; @@ -397,7 +406,6 @@ #if defined(LWS_WITH_SERVER) ss = a->info->server_string; #endif - i[2] = a->info->ws_ping_pong_interval; i[3] = a->info->timeout_secs; memset(a->info, 0, sizeof(*a->info)); @@ -407,13 +415,15 @@ #if defined(LWS_WITH_SERVER) a->info->server_string = ss; #endif - a->info->ws_ping_pong_interval = i[2]; a->info->timeout_secs = i[3]; a->info->protocols = a->protocols; a->info->pprotocols = a->pprotocols; +#if defined(LWS_ROLE_WS) a->info->extensions = a->extensions; +#endif #if defined(LWS_WITH_TLS) +#if defined(LWS_WITH_CLIENT) a->info->client_ssl_cipher_list = "ECDHE-ECDSA-AES256-GCM-SHA384:" "ECDHE-RSA-AES256-GCM-SHA384:" "DHE-RSA-AES256-GCM-SHA384:" @@ -428,6 +438,7 @@ "!AES256-GCM-SHA384:" "!AES256-SHA256"; #endif +#if defined(LWS_WITH_SERVER) a->info->ssl_cipher_list = "ECDHE-ECDSA-AES256-GCM-SHA384:" "ECDHE-RSA-AES256-GCM-SHA384:" "DHE-RSA-AES256-GCM-SHA384:" @@ -441,6 +452,8 @@ "!DHE-RSA-AES256-SHA256:" "!AES256-GCM-SHA384:" "!AES256-SHA256"; +#endif +#endif a->info->keepalive_timeout = 5; } @@ -526,7 +539,7 @@ vhost->default_protocol_index = 255; } -#if defined(LWS_WITH_TLS) +#if defined(LWS_WITH_TLS) && defined(LWS_WITH_CLIENT) if (a->enable_client_ssl) { const char *cert_filepath = a->info->client_ssl_cert_filepath; @@ -629,6 +642,7 @@ else a->info->options &= ~(LWS_SERVER_OPTION_STS); return 0; +#if defined(LWS_WITH_TLS) case LEJPVP_HOST_SSL_KEY: a->info->ssl_private_key_filepath = a->p; break; @@ -638,6 +652,7 @@ case LEJPVP_HOST_SSL_CA: a->info->ssl_ca_filepath = a->p; break; +#endif case LEJPVP_ACCESS_LOG: a->info->log_filepath = a->p; break; @@ -682,23 +697,25 @@ a->info->keepalive_timeout = atoi(ctx->buf); return 0; #if defined(LWS_WITH_TLS) +#if defined(LWS_WITH_CLIENT) case LEJPVP_CLIENT_CIPHERS: a->info->client_ssl_cipher_list = a->p; break; + case LEJPVP_CLIENT_TLS13_CIPHERS: + a->info->client_tls_1_3_plus_cipher_list = a->p; + break; #endif + case LEJPVP_CIPHERS: a->info->ssl_cipher_list = a->p; break; case LEJPVP_TLS13_CIPHERS: a->info->tls1_3_plus_cipher_list = a->p; break; - case LEJPVP_CLIENT_TLS13_CIPHERS: - a->info->client_tls_1_3_plus_cipher_list = a->p; - break; - case LEJPVP_ECDH_CURVE: a->info->ecdh_curve = a->p; break; +#endif case LEJPVP_PMO: case LEJPVP_CGI_ENV: mp_cgienv = lwsws_align(a); @@ -768,7 +785,7 @@ case LEJPVP_ENABLE_CLIENT_SSL: a->enable_client_ssl = arg_to_bool(ctx->buf); return 0; -#if defined(LWS_WITH_TLS) +#if defined(LWS_WITH_TLS) && defined(LWS_WITH_CLIENT) case LEJPVP_CLIENT_SSL_KEY: a->info->client_ssl_private_key_filepath = a->p; break; @@ -816,6 +833,7 @@ a->info->error_document_404 = a->p; break; +#if defined(LWS_WITH_TLS) case LEJPVP_SSL_OPTION_SET: a->info->ssl_options_set |= atol(ctx->buf); return 0; @@ -823,16 +841,19 @@ a->info->ssl_options_clear |= atol(ctx->buf); return 0; +#if defined(LWS_WITH_CLIENT) case LEJPVP_SSL_CLIENT_OPTION_SET: a->info->ssl_client_options_set |= atol(ctx->buf); return 0; case LEJPVP_SSL_CLIENT_OPTION_CLEAR: a->info->ssl_client_options_clear |= atol(ctx->buf); return 0; +#endif case LEJPVP_ALPN: a->info->alpn = a->p; break; +#endif case LEJPVP_LISTEN_ACCEPT_ROLE: a->info->listen_accept_role = a->p; @@ -924,7 +945,7 @@ if (!n) break; - m = (int)(signed char)lejp_parse(&ctx, buf, n); + m = lejp_parse(&ctx, buf, n); } while (m == LEJP_CONTINUE); close(fd); @@ -969,7 +990,9 @@ { struct lws_dir_args da; struct jpargs a; +#if defined(LWS_WITH_PLUGINS) const char * const *old = info->plugin_dirs; +#endif char dd[128]; memset(&a, 0, sizeof(a)); @@ -980,16 +1003,20 @@ a.valid = 0; lwsws_align(&a); +#if defined(LWS_WITH_PLUGINS) info->plugin_dirs = (void *)a.p; +#endif a.plugin_dirs = (void *)a.p; /* writeable version */ a.p += MAX_PLUGIN_DIRS * sizeof(void *); +#if defined(LWS_WITH_PLUGINS) /* copy any default paths */ while (old && *old) { a.plugin_dirs[a.count_plugin_dirs++] = *old; old++; } +#endif lws_snprintf(dd, sizeof(dd) - 1, "%s/conf", d); if (lwsws_get_config(&a, dd, paths_global, @@ -1031,7 +1058,9 @@ a.context = context; a.protocols = info->protocols; a.pprotocols = info->pprotocols; +#if defined(LWS_ROLE_WS) a.extensions = info->extensions; +#endif lws_snprintf(dd, sizeof(dd) - 1, "%s/conf", d); if (lwsws_get_config(&a, dd, paths_vhosts, diff -Nru libwebsockets-4.0.20/lib/roles/http/server/lws-spa.c libwebsockets-4.1.6/lib/roles/http/server/lws-spa.c --- libwebsockets-4.0.20/lib/roles/http/server/lws-spa.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/http/server/lws-spa.c 2020-12-01 17:40:26.000000000 +0000 @@ -145,7 +145,7 @@ s->mime_boundary[m++] = *p++; s->mime_boundary[m] = '\0'; - lwsl_notice("boundary '%s'\n", s->mime_boundary); + // lwsl_notice("boundary '%s'\n", s->mime_boundary); } } } @@ -598,7 +598,7 @@ goto bail5; } - lwsl_notice("%s: Created SPA %p\n", __func__, spa); + // lwsl_notice("%s: Created SPA %p\n", __func__, spa); return spa; diff -Nru libwebsockets-4.0.20/lib/roles/http/server/server.c libwebsockets-4.1.6/lib/roles/http/server/server.c --- libwebsockets-4.0.20/lib/roles/http/server/server.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/http/server/server.c 2020-12-01 17:40:26.000000000 +0000 @@ -52,6 +52,7 @@ _lws_vhost_init_server(const struct lws_context_creation_info *info, struct lws_vhost *vhost) { + struct lws_context_per_thread *pt; int n, opt = 1, limit = 1; lws_sockfd_type sockfd; struct lws_vhost *vh; @@ -271,10 +272,21 @@ goto deal; } - wsi = lws_zalloc(sizeof(struct lws), "listen wsi"); - if (wsi == NULL) { - lwsl_err("Out of mem\n"); - goto bail; + { + size_t s = sizeof(struct lws); + +#if defined(LWS_WITH_EVENT_LIBS) + s += vhost->context->event_loop_ops->evlib_size_wsi; +#endif + + wsi = lws_zalloc(s, "listen wsi"); + if (wsi == NULL) { + lwsl_err("Out of mem\n"); + goto bail; + } +#if defined(LWS_WITH_EVENT_LIBS) + wsi->evlib_wsi = (uint8_t *)wsi + sizeof(*wsi); +#endif } #ifdef LWS_WITH_UNIX_SOCK @@ -287,24 +299,29 @@ lwsl_debug("%s: lws_socket_bind says %d\n", __func__, is); } - wsi->context = vhost->context; + wsi->a.context = vhost->context; wsi->desc.sockfd = sockfd; lws_role_transition(wsi, 0, LRS_UNCONNECTED, &role_ops_listen); - wsi->protocol = vhost->protocols; + wsi->a.protocol = vhost->protocols; wsi->tsi = m; lws_vhost_bind_wsi(vhost, wsi); wsi->listener = 1; - if (wsi->context->event_loop_ops->init_vhost_listen_wsi) - wsi->context->event_loop_ops->init_vhost_listen_wsi(wsi); + if (wsi->a.context->event_loop_ops->init_vhost_listen_wsi) + wsi->a.context->event_loop_ops->init_vhost_listen_wsi(wsi); + + pt = &vhost->context->pt[m]; + lws_pt_lock(pt, __func__); if (__insert_wsi_socket_into_fds(vhost->context, wsi)) { lwsl_notice("inserting wsi socket into fds failed\n"); + lws_pt_unlock(pt); goto bail; } vhost->context->count_wsi_allocated++; vhost->lserv_wsi = wsi; + lws_pt_unlock(pt); n = listen(wsi->desc.sockfd, LWS_SOMAXCONN); if (n < 0) { @@ -514,12 +531,12 @@ int n; wsi->handling_404 = 0; - if (!wsi->vhost) + if (!wsi->a.vhost) return -1; #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) - if (wsi->vhost->http.error_document_404 && - !strcmp(uri, wsi->vhost->http.error_document_404)) + if (wsi->a.vhost->http.error_document_404 && + !strcmp(uri, wsi->a.vhost->http.error_document_404)) wsi->handling_404 = 1; #endif @@ -531,12 +548,12 @@ do { spin++; - fops = lws_vfs_select_fops(wsi->context->fops, path, &vpath); + fops = lws_vfs_select_fops(wsi->a.context->fops, path, &vpath); if (wsi->http.fop_fd) lws_vfs_file_close(&wsi->http.fop_fd); - wsi->http.fop_fd = fops->LWS_FOP_OPEN(wsi->context->fops, + wsi->http.fop_fd = fops->LWS_FOP_OPEN(wsi->a.context->fops, path, vpath, &fflags); if (!wsi->http.fop_fd) { lwsl_info("%s: Unable to open '%s': errno %d\n", @@ -712,15 +729,15 @@ wsi->sending_chunked = 1; wsi->protocol_interpret_idx = (char)( - lws_vhost_name_to_protocol(wsi->vhost, + lws_vhost_name_to_protocol(wsi->a.vhost, pvo->value) - &lws_get_vhost(wsi)->protocols[0]); lwsl_debug("want %s interpreted by %s (pcol is %s)\n", path, - wsi->vhost->protocols[ + wsi->a.vhost->protocols[ (int)wsi->protocol_interpret_idx].name, - wsi->protocol->name); - if (lws_bind_protocol(wsi, &wsi->vhost->protocols[ + wsi->a.protocol->name); + if (lws_bind_protocol(wsi, &wsi->a.vhost->protocols[ (int)wsi->protocol_interpret_idx], __func__)) return -1; @@ -741,7 +758,7 @@ if (m->protocol) { const struct lws_protocols *pp = lws_vhost_name_to_protocol( - wsi->vhost, m->protocol); + wsi->a.vhost, m->protocol); if (lws_bind_protocol(wsi, pp, __func__)) return -1; @@ -775,7 +792,7 @@ const struct lws_http_mount *hm, *hit = NULL; int best = 0; - hm = wsi->vhost->http.mount_list; + hm = wsi->a.vhost->http.mount_list; while (hm) { if (uri_len >= hm->mountpoint_len && !strncmp(uri_ptr, hm->mountpoint, hm->mountpoint_len) && @@ -857,7 +874,7 @@ int lws_unauthorised_basic_auth(struct lws *wsi) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; unsigned char *start = pt->serv_buf + LWS_PRE, *p = start, *end = p + 2048; char buf[64]; @@ -1031,7 +1048,7 @@ return LCBA_FAILED_AUTH; case LWSAUTHM_BASIC_AUTH_CALLBACK: - bar = wsi->protocol->callback(wsi, + bar = wsi->a.protocol->callback(wsi, LWS_CALLBACK_VERIFY_BASIC_AUTHORIZATION, wsi->user_space, plain, m); if (!bar) @@ -1220,7 +1237,7 @@ if (i.host) lws_snprintf(host, sizeof(host), "%s:%u", i.host, - wsi->vhost->listen_port); + wsi->a.vhost->listen_port); else lws_snprintf(host, sizeof(host), "%s:%d", i.address, i.port); @@ -1318,7 +1335,7 @@ (hit->origin_protocol != LWSMPRO_CGI && hit->origin_protocol != LWSMPRO_CALLBACK)) { unsigned char *start = pt->serv_buf + LWS_PRE, *p = start, - *end = p + wsi->context->pt_serv_buf_size - + *end = p + wsi->a.context->pt_serv_buf_size - LWS_PRE - 512; *h = 1; @@ -1374,7 +1391,7 @@ int lws_http_action(struct lws *wsi) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; int uri_len = 0, meth, m, http_version_len, ha; const struct lws_http_mount *hit = NULL; enum http_version request_version; @@ -1382,8 +1399,11 @@ enum http_conn_type conn_type; char content_length_str[32]; char http_version_str[12]; - char *uri_ptr = NULL, *s; char http_conn_str[25]; + char *uri_ptr = NULL; +#if defined(LWS_WITH_FILE_OPS) + char *s; +#endif unsigned int n; meth = lws_http_get_uri_and_method(wsi, &uri_ptr, &uri_len); @@ -1476,7 +1496,7 @@ wsi->http.conn_type = conn_type; } - n = wsi->protocol->callback(wsi, LWS_CALLBACK_FILTER_HTTP_CONNECTION, + n = wsi->a.protocol->callback(wsi, LWS_CALLBACK_FILTER_HTTP_CONNECTION, wsi->user_space, uri_ptr, uri_len); if (n) { lwsl_info("LWS_CALLBACK_HTTP closing\n"); @@ -1489,7 +1509,7 @@ */ if (!wsi->mux_stream_immortal) lws_set_timeout(wsi, PENDING_TIMEOUT_HTTP_CONTENT, - wsi->context->timeout_secs); + wsi->a.context->timeout_secs); #ifdef LWS_WITH_TLS if (wsi->tls.redirect_to_https) { /* @@ -1498,12 +1518,15 @@ * URI from the host: header and ignore the path part */ unsigned char *start = pt->serv_buf + LWS_PRE, *p = start, - *end = p + wsi->context->pt_serv_buf_size - LWS_PRE; + *end = p + wsi->a.context->pt_serv_buf_size - LWS_PRE; n = lws_hdr_total_length(wsi, WSI_TOKEN_HOST); if (!n || n > 128) goto bail_nuke_ah; + if (!lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST)) + goto bail_nuke_ah; + p += lws_snprintf((char *)p, lws_ptr_diff(end, p), "https://"); memcpy(p, lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST), n); p += n; @@ -1533,19 +1556,21 @@ lwsl_info("no hit\n"); - if (lws_bind_protocol(wsi, &wsi->vhost->protocols[0], + if (lws_bind_protocol(wsi, &wsi->a.vhost->protocols[0], "no mount hit")) return 1; lwsi_set_state(wsi, LRS_DOING_TRANSACTION); - m = wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP, + m = wsi->a.protocol->callback(wsi, LWS_CALLBACK_HTTP, wsi->user_space, uri_ptr, uri_len); goto after; } +#if defined(LWS_WITH_FILE_OPS) s = uri_ptr + hit->mountpoint_len; +#endif n = lws_http_redirect_hit(pt, wsi, hit, uri_ptr, uri_len, &ha); if (ha) return n; @@ -1599,7 +1624,7 @@ if (hit->protocol) name = hit->protocol; - pp = lws_vhost_name_to_protocol(wsi->vhost, name); + pp = lws_vhost_name_to_protocol(wsi->a.vhost, name); if (!pp) { lwsl_err("Unable to find plugin '%s'\n", hit->origin); @@ -1618,7 +1643,7 @@ args.final = 0; /* used to signal callback dealt with it */ args.chunked = 0; - n = wsi->protocol->callback(wsi, + n = wsi->a.protocol->callback(wsi, LWS_CALLBACK_CHECK_ACCESS_RIGHTS, wsi->user_space, &args, 0); if (n) { @@ -1629,13 +1654,13 @@ if (args.final) /* callback completely handled it well */ return 0; - if (hit->cgienv && wsi->protocol->callback(wsi, + if (hit->cgienv && wsi->a.protocol->callback(wsi, LWS_CALLBACK_HTTP_PMO, wsi->user_space, (void *)hit->cgienv, 0)) return 1; if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI)) { - m = wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP, + m = wsi->a.protocol->callback(wsi, LWS_CALLBACK_HTTP, wsi->user_space, uri_ptr + hit->mountpoint_len, uri_len - hit->mountpoint_len); @@ -1669,19 +1694,21 @@ } #endif +#if defined(LWS_WITH_FILE_OPS) n = uri_len - lws_ptr_diff(s, uri_ptr); if (s[0] == '\0' || (n == 1 && s[n - 1] == '/')) s = (char *)hit->def; if (!s) s = "index.html"; +#endif wsi->cache_secs = hit->cache_max_age; wsi->cache_reuse = hit->cache_reusable; wsi->cache_revalidate = hit->cache_revalidate; wsi->cache_intermediaries = hit->cache_intermediaries; - m = 1; #if defined(LWS_WITH_FILE_OPS) + m = 1; if (hit->origin_protocol == LWSMPRO_FILE) m = lws_http_serve(wsi, s, hit->origin, hit); @@ -1694,7 +1721,11 @@ if (hit->protocol) { const struct lws_protocols *pp = lws_vhost_name_to_protocol( - wsi->vhost, hit->protocol); + wsi->a.vhost, hit->protocol); + + /* coverity */ + if (!pp) + return 1; lwsi_set_state(wsi, LRS_DOING_TRANSACTION); @@ -1706,7 +1737,7 @@ uri_ptr + hit->mountpoint_len, uri_len - hit->mountpoint_len); } else - m = wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP, + m = wsi->a.protocol->callback(wsi, LWS_CALLBACK_HTTP, wsi->user_space, uri_ptr, uri_len); } @@ -1750,10 +1781,10 @@ * status code and result body if any, and to do the transaction * complete processing. */ - if (wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP_BODY, + if (wsi->a.protocol->callback(wsi, LWS_CALLBACK_HTTP_BODY, wsi->user_space, NULL, 0)) return 1; - if (wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP_BODY_COMPLETION, + if (wsi->a.protocol->callback(wsi, LWS_CALLBACK_HTTP_BODY_COMPLETION, wsi->user_space, NULL, 0)) return 1; @@ -1841,10 +1872,10 @@ if (lws_tokenize(&ts) != LWS_TOKZE_TOKEN) goto bad_format; - if (strncmp(ts.token, wsi->vhost->name, ts.token_len)) { + if (strncmp(ts.token, wsi->a.vhost->name, ts.token_len)) { buf[(ts.token - buf) + ts.token_len] = '\0'; lwsl_info("%s: '%s' in host hdr but vhost name %s\n", - __func__, ts.token, wsi->vhost->name); + __func__, ts.token, wsi->a.vhost->name); return 1; } @@ -1858,9 +1889,9 @@ if (e != LWS_TOKZE_ENDED) goto bad_format; - if (wsi->vhost->listen_port != port) { + if (wsi->a.vhost->listen_port != port) { lwsl_info("%s: host port %d mismatches vhost port %d\n", - __func__, port, wsi->vhost->listen_port); + __func__, port, wsi->a.vhost->listen_port); return 1; } @@ -1880,17 +1911,17 @@ { const struct lws_role_ops *role = &role_ops_raw_skt; const struct lws_protocols *p1, *protocol = - &wsi->vhost->protocols[wsi->vhost->raw_protocol_index]; + &wsi->a.vhost->protocols[wsi->a.vhost->raw_protocol_index]; char ipbuf[64]; int n; - if (wsi->vhost->listen_accept_role && - lws_role_by_name(wsi->vhost->listen_accept_role)) - role = lws_role_by_name(wsi->vhost->listen_accept_role); - - if (wsi->vhost->listen_accept_protocol) { - p1 = lws_vhost_name_to_protocol(wsi->vhost, - wsi->vhost->listen_accept_protocol); + if (wsi->a.vhost->listen_accept_role && + lws_role_by_name(wsi->a.vhost->listen_accept_role)) + role = lws_role_by_name(wsi->a.vhost->listen_accept_role); + + if (wsi->a.vhost->listen_accept_protocol) { + p1 = lws_vhost_name_to_protocol(wsi->a.vhost, + wsi->a.vhost->listen_accept_protocol); if (p1) protocol = p1; } @@ -1912,16 +1943,17 @@ #endif lwsl_notice("%s: vh %s, peer: %s, role %s, " - "protocol %s, cb %d, ah %p\n", __func__, wsi->vhost->name, - ipbuf, role->name, protocol->name, n, wsi->http.ah); + "protocol %s, cb %d, ah %p\n", __func__, wsi->a.vhost->name, + ipbuf, role ? role->name : "null", protocol->name, n, + wsi->http.ah); - if ((wsi->protocol->callback)(wsi, n, wsi->user_space, NULL, 0)) + if ((wsi->a.protocol->callback)(wsi, n, wsi->user_space, NULL, 0)) return 1; n = LWS_CALLBACK_RAW_RX; if (wsi->role_ops->rx_cb[lwsi_role_server(wsi)]) n = wsi->role_ops->rx_cb[lwsi_role_server(wsi)]; - if (wsi->protocol->callback(wsi, n, wsi->user_space, obuf, olen)) + if (wsi->a.protocol->callback(wsi, n, wsi->user_space, obuf, olen)) return 1; return 0; @@ -1993,6 +2025,10 @@ goto bail_nuke_ah; } + /* coverity... */ + if (!wsi->http.ah) + goto bail_nuke_ah; + if (wsi->http.ah->parser_state != WSI_PARSING_COMPLETE) continue; @@ -2000,10 +2036,10 @@ /* select vhost */ - if (wsi->vhost->listen_port && + if (wsi->a.vhost->listen_port && lws_hdr_total_length(wsi, WSI_TOKEN_HOST)) { struct lws_vhost *vhost = lws_select_vhost( - context, wsi->vhost->listen_port, + context, wsi->a.vhost->listen_port, lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST)); if (vhost) @@ -2013,11 +2049,11 @@ if (!lwsi_role_h2(wsi) || !lwsi_role_server(wsi)) { #if defined(LWS_WITH_SERVER_STATUS) - wsi->vhost->conn_stats.h1_trans++; + wsi->a.vhost->conn_stats.h1_trans++; #endif if (!wsi->conn_stat_done) { #if defined(LWS_WITH_SERVER_STATUS) - wsi->vhost->conn_stats.h1_conn++; + wsi->a.vhost->conn_stats.h1_conn++; #endif wsi->conn_stat_done = 1; } @@ -2025,9 +2061,9 @@ /* check for unwelcome guests */ #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) - if (wsi->context->reject_service_keywords) { + if (wsi->a.context->reject_service_keywords) { const struct lws_protocol_vhost_options *rej = - wsi->context->reject_service_keywords; + wsi->a.context->reject_service_keywords; char ua[384], *msg = NULL; if (lws_hdr_copy(wsi, ua, sizeof(ua) - 1, @@ -2058,7 +2094,7 @@ /* wsi close will do the log */ #endif #if defined(LWS_WITH_SERVER_STATUS) - wsi->vhost->conn_stats.rejected++; + wsi->a.vhost->conn_stats.rejected++; #endif /* * We don't want anything from @@ -2100,7 +2136,6 @@ if (lws_hdr_total_length(wsi, WSI_TOKEN_CONNECT)) { lwsl_info("Changing to RAW mode\n"); - m = 0; goto raw_transition; } @@ -2122,7 +2157,7 @@ goto bail_nuke_ah; } - n = user_callback_handle_rxflow(wsi->protocol->callback, + n = user_callback_handle_rxflow(wsi->a.protocol->callback, wsi, LWS_CALLBACK_HTTP_CONFIRM_UPGRADE, wsi->user_space, (char *)up, 0); @@ -2144,7 +2179,7 @@ /* callback said 0, it was allowed */ - if (wsi->vhost->options & + if (wsi->a.vhost->options & LWS_SERVER_OPTION_VHOST_UPG_STRICT_HOST_CHECK && lws_confirm_host_header(wsi)) goto bail_nuke_ah; @@ -2152,7 +2187,7 @@ if (!strcasecmp(up, "websocket")) { #if defined(LWS_ROLE_WS) #if defined(LWS_WITH_SERVER_STATUS) - wsi->vhost->conn_stats.ws_upg++; + wsi->a.vhost->conn_stats.ws_upg++; #endif lwsl_info("Upgrade to ws\n"); goto upgrade_ws; @@ -2161,7 +2196,7 @@ #if defined(LWS_WITH_HTTP2) if (!strcasecmp(up, "h2c")) { #if defined(LWS_WITH_SERVER_STATUS) - wsi->vhost->conn_stats.h2_upg++; + wsi->a.vhost->conn_stats.h2_upg++; #endif lwsl_info("Upgrade to h2c\n"); goto upgrade_h2c; @@ -2334,7 +2369,7 @@ peer[0] = '\0'; #endif peer[sizeof(peer) - 1] = '\0'; - lwsl_notice("%s: (from %s) ignoring, ah parsing incomplete\n", + lwsl_info("%s: (from %s) ignoring, ah parsing incomplete\n", __func__, peer); return 0; } @@ -2345,6 +2380,7 @@ wsi->http.cgi_transaction_complete = 1; lws_cgi_remove_and_kill(wsi); lws_spawn_piped_destroy(&wsi->http.cgi->lsp); + lws_sul_cancel(&wsi->http.cgi->sul_grace); lws_free_set_NULL(wsi->http.cgi); wsi->http.cgi_transaction_complete = 0; @@ -2363,7 +2399,7 @@ return 1; } - if (lws_bind_protocol(wsi, &wsi->vhost->protocols[0], __func__)) + if (lws_bind_protocol(wsi, &wsi->a.vhost->protocols[0], __func__)) return 1; /* @@ -2389,9 +2425,9 @@ #endif n = NO_PENDING_TIMEOUT; - if (wsi->vhost->keepalive_timeout) + if (wsi->a.vhost->keepalive_timeout) n = PENDING_TIMEOUT_HTTP_KEEPALIVE_IDLE; - lws_set_timeout(wsi, n, wsi->vhost->keepalive_timeout); + lws_set_timeout(wsi, n, wsi->a.vhost->keepalive_timeout); /* * We already know we are on http1.1 / keepalive and the next thing @@ -2418,10 +2454,10 @@ * SSL is scarce, drop this connection without waiting */ - if (wsi->vhost->tls.use_ssl && - wsi->context->simultaneous_ssl_restriction && - wsi->context->simultaneous_ssl == - wsi->context->simultaneous_ssl_restriction) { + if (wsi->a.vhost->tls.use_ssl && + wsi->a.context->simultaneous_ssl_restriction && + wsi->a.context->simultaneous_ssl == + wsi->a.context->simultaneous_ssl_restriction) { lwsl_info("%s: simultaneous_ssl_restriction\n", __func__); return 1; @@ -2438,7 +2474,7 @@ * open. */ lws_set_timeout(wsi, PENDING_TIMEOUT_HOLDING_AH, - wsi->vhost->keepalive_timeout); + wsi->a.vhost->keepalive_timeout); } /* If we're (re)starting on headers, need other implied init */ if (wsi->http.ah) @@ -2491,9 +2527,9 @@ * If wsi->http.fop_fd is already set, the caller already opened it */ if (!wsi->http.fop_fd) { - fops = lws_vfs_select_fops(wsi->context->fops, file, &vpath); + fops = lws_vfs_select_fops(wsi->a.context->fops, file, &vpath); fflags |= lws_vfs_prepare_flags(wsi); - wsi->http.fop_fd = fops->LWS_FOP_OPEN(wsi->context->fops, + wsi->http.fop_fd = fops->LWS_FOP_OPEN(wsi->a.context->fops, file, vpath, &fflags); if (!wsi->http.fop_fd) { lwsl_info("%s: Unable to open: '%s': errno %d\n", @@ -2763,7 +2799,7 @@ int lws_serve_http_file_fragment(struct lws *wsi) { - struct lws_context *context = wsi->context; + struct lws_context *context = wsi->a.context; struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; struct lws_process_html_args args; lws_filepos_t amount, poss; @@ -2860,9 +2896,9 @@ * If there is a hint about how much we will do well to send at * one time, restrict ourselves to only trying to send that. */ - if (wsi->protocol->tx_packet_size && - poss > wsi->protocol->tx_packet_size) - poss = wsi->protocol->tx_packet_size; + if (wsi->a.protocol->tx_packet_size && + poss > wsi->a.protocol->tx_packet_size) + poss = wsi->a.protocol->tx_packet_size; if (wsi->role_ops->tx_credit) { lws_filepos_t txc = @@ -2925,7 +2961,7 @@ wsi->http.filelen; args.chunked = wsi->sending_chunked; if (user_callback_handle_rxflow( - wsi->vhost->protocols[ + wsi->a.vhost->protocols[ (int)wsi->protocol_interpret_idx].callback, wsi, LWS_CALLBACK_PROCESS_HTML, wsi->user_space, &args, 0) < 0) @@ -2997,8 +3033,8 @@ lwsl_debug("file completed\n"); - if (wsi->protocol->callback && - user_callback_handle_rxflow(wsi->protocol->callback, + if (wsi->a.protocol->callback && + user_callback_handle_rxflow(wsi->a.protocol->callback, wsi, LWS_CALLBACK_HTTP_FILE_COMPLETION, wsi->user_space, NULL, 0) < 0) { /* @@ -3052,8 +3088,10 @@ return; #if !defined(LWS_PLAT_FREERTOS) /* find canonical hostname */ - gethostname((char *)context->canonical_hostname, - sizeof(context->canonical_hostname) - 1); + if (gethostname((char *)context->canonical_hostname, + sizeof(context->canonical_hostname) - 1)) + lws_strncpy((char *)context->canonical_hostname, "unknown", + sizeof(context->canonical_hostname)); lwsl_info(" canonical_hostname = %s\n", context->canonical_hostname); #else diff -Nru libwebsockets-4.0.20/lib/roles/listen/CMakeLists.txt libwebsockets-4.1.6/lib/roles/listen/CMakeLists.txt --- libwebsockets-4.0.20/lib/roles/listen/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/listen/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,42 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +list(APPEND SOURCES + roles/listen/ops-listen.c) + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() + diff -Nru libwebsockets-4.0.20/lib/roles/listen/ops-listen.c libwebsockets-4.1.6/lib/roles/listen/ops-listen.c --- libwebsockets-4.0.20/lib/roles/listen/ops-listen.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/listen/ops-listen.c 2020-12-01 17:40:26.000000000 +0000 @@ -28,17 +28,15 @@ rops_handle_POLLIN_listen(struct lws_context_per_thread *pt, struct lws *wsi, struct lws_pollfd *pollfd) { - struct lws_context *context = wsi->context; - lws_sockfd_type accept_fd = LWS_SOCK_INVALID; + struct lws_context *context = wsi->a.context; + struct lws_filter_network_conn_args filt; lws_sock_file_fd_type fd; - struct sockaddr_storage cli_addr; - socklen_t clilen; - memset(&cli_addr, 0, sizeof(cli_addr)); + memset(&filt, 0, sizeof(filt)); /* if our vhost is going down, ignore it */ - if (wsi->vhost->being_destroyed) + if (wsi->a.vhost->being_destroyed) return LWS_HPI_RET_HANDLED; /* pollin means a client has connected to us then @@ -61,7 +59,7 @@ * another vhost may also have had POLLIN on his * listener this round and used it up already */ - if (wsi->vhost->tls.use_ssl && + if (wsi->a.vhost->tls.use_ssl && context->simultaneous_ssl_restriction && context->simultaneous_ssl == context->simultaneous_ssl_restriction) @@ -74,7 +72,7 @@ #endif /* listen socket got an unencrypted connection... */ - clilen = sizeof(cli_addr); + filt.clilen = sizeof(filt.cli_addr); /* * We cannot identify the peer who is in the listen @@ -83,38 +81,41 @@ * block the connect queue for other legit peers. */ - accept_fd = accept((int)pollfd->fd, - (struct sockaddr *)&cli_addr, &clilen); - if (accept_fd == LWS_SOCK_INVALID) { + filt.accept_fd = accept((int)pollfd->fd, + (struct sockaddr *)&filt.cli_addr, + &filt.clilen); + if (filt.accept_fd == LWS_SOCK_INVALID) { if (LWS_ERRNO == LWS_EAGAIN || LWS_ERRNO == LWS_EWOULDBLOCK) { break; } - lwsl_err("accept: %s\n", strerror(LWS_ERRNO)); + lwsl_err("accept: errno %d\n", LWS_ERRNO); + return LWS_HPI_RET_HANDLED; } if (context->being_destroyed) { - compatible_close(accept_fd); + compatible_close(filt.accept_fd); + return LWS_HPI_RET_PLEASE_CLOSE_ME; } - lws_plat_set_socket_options(wsi->vhost, accept_fd, 0); + lws_plat_set_socket_options(wsi->a.vhost, filt.accept_fd, 0); #if defined(LWS_WITH_IPV6) lwsl_debug("accepted new conn port %u on fd=%d\n", - ((cli_addr.ss_family == AF_INET6) ? - ntohs(((struct sockaddr_in6 *) &cli_addr)->sin6_port) : - ntohs(((struct sockaddr_in *) &cli_addr)->sin_port)), - accept_fd); + ((filt.cli_addr.ss_family == AF_INET6) ? + ntohs(((struct sockaddr_in6 *) &filt.cli_addr)->sin6_port) : + ntohs(((struct sockaddr_in *) &filt.cli_addr)->sin_port)), + filt.accept_fd); #else { struct sockaddr_in sain; - memcpy(&sain, &cli_addr, sizeof(sain)); + memcpy(&sain, &filt.cli_addr, sizeof(sain)); lwsl_debug("accepted new conn port %u on fd=%d\n", ntohs(sain.sin_port), - accept_fd); + filt.accept_fd); } #endif @@ -124,36 +125,36 @@ * protocol selected yet so we issue this to * protocols[0] */ - if ((wsi->vhost->protocols[0].callback)(wsi, + if ((wsi->a.vhost->protocols[0].callback)(wsi, LWS_CALLBACK_FILTER_NETWORK_CONNECTION, - NULL, - (void *)(lws_intptr_t)accept_fd, 0)) { + (void *)&filt, + (void *)(lws_intptr_t)filt.accept_fd, 0)) { lwsl_debug("Callback denied net connection\n"); - compatible_close(accept_fd); + compatible_close(filt.accept_fd); return LWS_HPI_RET_HANDLED; } - if (!(wsi->vhost->options & + if (!(wsi->a.vhost->options & LWS_SERVER_OPTION_ADOPT_APPLY_LISTEN_ACCEPT_CONFIG)) opts |= LWS_ADOPT_HTTP; #if defined(LWS_WITH_TLS) - if (!wsi->vhost->tls.use_ssl) + if (!wsi->a.vhost->tls.use_ssl) #endif opts &= ~LWS_ADOPT_ALLOW_SSL; - fd.sockfd = accept_fd; - cwsi = lws_adopt_descriptor_vhost(wsi->vhost, opts, fd, - NULL, NULL); + fd.sockfd = filt.accept_fd; + cwsi = lws_adopt_descriptor_vhost(wsi->a.vhost, opts, fd, + wsi->a.vhost->listen_accept_protocol, NULL); if (!cwsi) { lwsl_info("%s: vh %s: adopt failed\n", __func__, - wsi->vhost->name); + wsi->a.vhost->name); /* already closed cleanly as necessary */ return LWS_HPI_RET_WSI_ALREADY_DIED; } /* - if (lws_server_socket_service_ssl(cwsi, accept_fd)) { + if (lws_server_socket_service_ssl(cwsi, accept_fd, 1)) { lws_close_free_wsi(cwsi, LWS_CLOSE_STATUS_NOSTATUS, "listen svc fail"); return LWS_HPI_RET_WSI_ALREADY_DIED; diff -Nru libwebsockets-4.0.20/lib/roles/mqtt/client/client-mqtt.c libwebsockets-4.1.6/lib/roles/mqtt/client/client-mqtt.c --- libwebsockets-4.0.20/lib/roles/mqtt/client/client-mqtt.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/mqtt/client/client-mqtt.c 2020-12-01 17:40:26.000000000 +0000 @@ -44,7 +44,7 @@ static int lws_mqtt_generate_id(struct lws* wsi, lws_mqtt_str_t **ms, const char *client_id) { - struct lws_context *context = wsi->context; + struct lws_context *context = wsi->a.context; uint16_t ran[24]; /* 16-bit so wrap bias from %62 diluted by ~1000 */ size_t n, len; uint8_t *buf; @@ -81,7 +81,11 @@ buf[len] = '\0'; } - lws_mqtt_str_advance(*ms, (uint16_t)len); + if (lws_mqtt_str_advance(*ms, (uint16_t)len)) { + lws_mqtt_str_free(ms); + + return 1; + } return 0; } @@ -171,7 +175,7 @@ lws_mqtt_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd, struct lws *wsi_conn) { - struct lws_context *context = wsi->context; + struct lws_context *context = wsi->a.context; struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; int n = 0, m = 0; struct lws_tokens ebuf; @@ -266,7 +270,7 @@ lws_now_usecs() - wsi->detlat.earliest_write_req_pre_write; wsi->detlat.latencies[LAT_DUR_USERCB] = 0; - lws_det_lat_cb(wsi->context, &wsi->detlat); + lws_det_lat_cb(wsi->a.context, &wsi->detlat); } #endif #if 0 @@ -325,10 +329,10 @@ case LRS_MQTTC_AWAIT_CONNACK: buffered = 0; ebuf.token = pt->serv_buf; - ebuf.len = wsi->context->pt_serv_buf_size; + ebuf.len = wsi->a.context->pt_serv_buf_size; - if ((unsigned int)ebuf.len > wsi->context->pt_serv_buf_size) - ebuf.len = wsi->context->pt_serv_buf_size; + if ((unsigned int)ebuf.len > wsi->a.context->pt_serv_buf_size) + ebuf.len = wsi->a.context->pt_serv_buf_size; if ((int)pending > ebuf.len) pending = ebuf.len; diff -Nru libwebsockets-4.0.20/lib/roles/mqtt/CMakeLists.txt libwebsockets-4.1.6/lib/roles/mqtt/CMakeLists.txt --- libwebsockets-4.0.20/lib/roles/mqtt/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/mqtt/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,48 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +if (LWS_WITH_CLIENT) + list(APPEND SOURCES + roles/mqtt/mqtt.c + roles/mqtt/ops-mqtt.c + roles/mqtt/primitives.c + roles/mqtt/client/client-mqtt.c + roles/mqtt/client/client-mqtt-handshake.c + ) +endif() + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() diff -Nru libwebsockets-4.0.20/lib/roles/mqtt/mqtt.c libwebsockets-4.1.6/lib/roles/mqtt/mqtt.c --- libwebsockets-4.0.20/lib/roles/mqtt/mqtt.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/mqtt/mqtt.c 2020-12-01 17:40:26.000000000 +0000 @@ -42,11 +42,8 @@ */ #include "private-lib-core.h" -/* #include "lws-mqtt.h" */ - #include #include -#include #include typedef enum { @@ -261,7 +258,7 @@ lws_role_transition(wsi, LWSIFR_CLIENT, LRS_ESTABLISHED, &role_ops_mqtt); - if (user_callback_handle_rxflow(wsi->protocol->callback, + if (user_callback_handle_rxflow(wsi->a.protocol->callback, wsi, LWS_CALLBACK_MQTT_CLIENT_ESTABLISHED, wsi->user_space, NULL, 0) < 0) { lwsl_err("%s: MQTT_ESTABLISHED failed\n", __func__); @@ -993,7 +990,7 @@ /* we were under SENT_CLIENT_HANDSHAKE timeout */ lws_set_timeout(wsi, 0, 0); - w = lws_create_new_server_wsi(wsi->vhost, + w = lws_create_new_server_wsi(wsi->a.vhost, wsi->tsi); if (!w) { lwsl_notice("%s: sid 1 migrate failed\n", @@ -1023,7 +1020,7 @@ if (!wsi->mqtt) return -1; w->mqtt->wsi = w; - w->protocol = wsi->protocol; + w->a.protocol = wsi->a.protocol; if (w->user_space && !w->user_space_externally_allocated) lws_free_set_NULL(w->user_space); @@ -1033,8 +1030,8 @@ wsi->user_space_externally_allocated; if (lws_ensure_user_space(w)) goto bail1; - w->opaque_user_data = wsi->opaque_user_data; - wsi->opaque_user_data = NULL; + w->a.opaque_user_data = wsi->a.opaque_user_data; + wsi->a.opaque_user_data = NULL; w->stash = wsi->stash; wsi->stash = NULL; @@ -1044,7 +1041,7 @@ __func__, wsi, w); #if defined(LWS_WITH_SERVER_STATUS) - wsi->vhost->conn_stats.h2_subs++; + wsi->a.vhost->conn_stats.h2_subs++; #endif /* @@ -1068,11 +1065,11 @@ wsi->mux.child_list = w->mux.sibling_list; wsi->mux.child_count--; - w->context->count_wsi_allocated--; + w->a.context->count_wsi_allocated--; if (w->user_space) lws_free_set_NULL(w->user_space); - w->vhost->protocols[0].callback(w, + w->a.vhost->protocols[0].callback(w, LWS_CALLBACK_WSI_DESTROY, NULL, NULL, 0); lws_vhost_unbind_wsi(w); @@ -1097,7 +1094,7 @@ w->mqtt->unacked_publish = 0; if (user_callback_handle_rxflow( - w->protocol->callback, + w->a.protocol->callback, w, LWS_CALLBACK_MQTT_ACK, w->user_space, NULL, 0) < 0) { lwsl_info("%s: MQTT_ACK requests close\n", @@ -1111,9 +1108,7 @@ * no need for ACK timeout wait * any more */ - lws_sul_schedule(lws_get_context(w), 0, - &w->mqtt->sul_qos1_puback_wait, NULL, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&w->mqtt->sul_qos1_puback_wait); if (requested_close) { __lws_close_free_wsi(w, @@ -1165,7 +1160,7 @@ w->mqtt->ack_pkt_id == par->cpkt_id) { w->mqtt->inside_subscribe = 0; if (user_callback_handle_rxflow( - w->protocol->callback, + w->a.protocol->callback, w, LWS_CALLBACK_MQTT_SUBSCRIBED, w->user_space, NULL, 0) < 0) { lwsl_err("%s: MQTT_SUBSCRIBE failed\n", @@ -1215,7 +1210,7 @@ w->mqtt->inside_unsubscribe = 0; if (user_callback_handle_rxflow( - w->protocol->callback, + w->a.protocol->callback, w, LWS_CALLBACK_MQTT_UNSUBSCRIBED, w->user_space, NULL, 0) < 0) { lwsl_info("%s: MQTT_UNSUBACK requests close\n", @@ -1277,7 +1272,7 @@ wsi->mux.child_list) { if (lws_mqtt_find_sub(w->mqtt, pub->topic)) - if (w->protocol->callback( + if (w->a.protocol->callback( w, n, w->user_space, (void *)pub, @@ -1587,7 +1582,7 @@ lwsl_notice("%s: wsi %p\n", __func__, mqtt->wsi); - if (mqtt->wsi->protocol->callback(mqtt->wsi, LWS_CALLBACK_MQTT_RESEND, + if (mqtt->wsi->a.protocol->callback(mqtt->wsi, LWS_CALLBACK_MQTT_RESEND, mqtt->wsi->user_space, NULL, 0)) lws_set_timeout(mqtt->wsi, 1, LWS_TO_KILL_ASYNC); } @@ -1596,7 +1591,7 @@ lws_mqtt_client_send_publish(struct lws *wsi, lws_mqtt_publish_param_t *pub, const void *buf, uint32_t len, int is_complete) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; uint8_t *b = (uint8_t *)pt->serv_buf, *start, *p; struct lws *nwsi = lws_get_network_wsi(wsi); lws_mqtt_str_t mqtt_vh_payload; @@ -1649,7 +1644,7 @@ /* Will the chunk of payload fit? */ if ((vh_len + len) >= - (wsi->context->pt_serv_buf_size - LWS_PRE)) { + (wsi->a.context->pt_serv_buf_size - LWS_PRE)) { lwsl_err("%s: Payload is too big\n", __func__); return 1; } @@ -1733,7 +1728,7 @@ * so the user callback logic is the same for QoS0 or * QoS1 */ - if (wsi->protocol->callback(wsi, LWS_CALLBACK_MQTT_ACK, + if (wsi->a.protocol->callback(wsi, LWS_CALLBACK_MQTT_ACK, wsi->user_space, NULL, 0)) { lwsl_err("%s: ACK callback exited\n", __func__); return 1; @@ -1745,8 +1740,9 @@ /* For QoS1, if no PUBACK coming after 3s, we must RETRY the publish */ wsi->mqtt->sul_qos1_puback_wait.cb = lws_mqtt_publish_resend; - __lws_sul_insert(&pt->pt_sul_owner, &wsi->mqtt->sul_qos1_puback_wait, - 3 * LWS_USEC_PER_SEC); + __lws_sul_insert_us(&pt->pt_sul_owner[wsi->conn_validity_wakesuspend], + &wsi->mqtt->sul_qos1_puback_wait, + 3 * LWS_USEC_PER_SEC); return 0; } @@ -1754,7 +1750,7 @@ int lws_mqtt_client_send_subcribe(struct lws *wsi, lws_mqtt_subscribe_param_t *sub) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; uint8_t *b = (uint8_t *)pt->serv_buf + LWS_PRE, *start = b, *p = start; struct lws *nwsi = lws_get_network_wsi(wsi); lws_mqtt_str_t mqtt_vh_payload; @@ -1818,7 +1814,7 @@ */ lwsl_notice("%s: all topics already subscribed\n", __func__); if (user_callback_handle_rxflow( - wsi->protocol->callback, + wsi->a.protocol->callback, wsi, LWS_CALLBACK_MQTT_SUBSCRIBED, wsi->user_space, NULL, 0) < 0) { lwsl_err("%s: MQTT_SUBSCRIBE failed\n", @@ -1857,7 +1853,7 @@ p += lws_mqtt_vbi_encode(rem_len, p); if ((rem_len + lws_ptr_diff(p, start)) >= - wsi->context->pt_serv_buf_size) { + wsi->a.context->pt_serv_buf_size) { lwsl_err("%s: Payload is too big\n", __func__); return 1; } @@ -1935,7 +1931,7 @@ lws_mqtt_client_send_unsubcribe(struct lws *wsi, const lws_mqtt_subscribe_param_t *unsub) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; uint8_t *b = (uint8_t *)pt->serv_buf + LWS_PRE, *start = b, *p = start; struct lws *nwsi = lws_get_network_wsi(wsi); lws_mqtt_str_t mqtt_vh_payload; @@ -1957,7 +1953,7 @@ unsub->topic[n].name); assert(mysub); - if (--mysub->ref_count == 0) { + if (mysub && --mysub->ref_count == 0) { lwsl_notice("%s: Need to send UNSUB\n", __func__); send_unsub[n] = 1; orphaned++; @@ -1974,7 +1970,7 @@ */ lwsl_notice("%s: unsubscribed!\n", __func__); if (user_callback_handle_rxflow( - wsi->protocol->callback, + wsi->a.protocol->callback, wsi, LWS_CALLBACK_MQTT_UNSUBSCRIBED, wsi->user_space, NULL, 0) < 0) { /* @@ -2020,7 +2016,7 @@ p += lws_mqtt_vbi_encode(rem_len, p); if ((rem_len + lws_ptr_diff(p, start)) >= - wsi->context->pt_serv_buf_size) { + wsi->a.context->pt_serv_buf_size) { lwsl_err("%s: Payload is too big\n", __func__); return 1; } @@ -2108,7 +2104,7 @@ lws_callback_on_writable(wsi); #if defined(LWS_WITH_SERVER_STATUS) - wsi->vhost->conn_stats.mqtt_subs++; + wsi->a.vhost->conn_stats.mqtt_subs++; #endif return wsi; @@ -2121,7 +2117,7 @@ if (wsi->user_space) lws_free_set_NULL(wsi->user_space); - wsi->protocol->callback(wsi, LWS_CALLBACK_WSI_DESTROY, NULL, NULL, 0); + wsi->a.protocol->callback(wsi, LWS_CALLBACK_WSI_DESTROY, NULL, NULL, 0); lws_free(wsi); return NULL; diff -Nru libwebsockets-4.0.20/lib/roles/mqtt/ops-mqtt.c libwebsockets-4.1.6/lib/roles/mqtt/ops-mqtt.c --- libwebsockets-4.0.20/lib/roles/mqtt/ops-mqtt.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/mqtt/ops-mqtt.c 2020-12-01 17:40:26.000000000 +0000 @@ -34,7 +34,7 @@ char buffered = 0; lwsl_debug("%s: wsistate 0x%x, %s pollout %d\n", __func__, - (unsigned int)wsi->wsistate, wsi->protocol->name, + (unsigned int)wsi->wsistate, wsi->a.protocol->name, pollfd->revents); /* @@ -119,10 +119,10 @@ buffered = 0; ebuf.token = pt->serv_buf; - ebuf.len = wsi->context->pt_serv_buf_size; + ebuf.len = wsi->a.context->pt_serv_buf_size; - if ((unsigned int)ebuf.len > wsi->context->pt_serv_buf_size) - ebuf.len = wsi->context->pt_serv_buf_size; + if ((unsigned int)ebuf.len > wsi->a.context->pt_serv_buf_size) + ebuf.len = wsi->a.context->pt_serv_buf_size; if ((int)pending > ebuf.len) pending = ebuf.len; @@ -160,7 +160,6 @@ lwsl_notice("%s: lws_read_mqtt returned %d\n", __func__, n); /* we closed wsi */ - n = 0; goto fail; } // lws_buflist_describe(&wsi->buflist, wsi, __func__); @@ -175,8 +174,8 @@ pending = lws_ssl_pending(wsi); if (pending) { - pending = pending > wsi->context->pt_serv_buf_size ? - wsi->context->pt_serv_buf_size : pending; + pending = pending > wsi->a.context->pt_serv_buf_size ? + wsi->a.context->pt_serv_buf_size : pending; goto read; } @@ -215,11 +214,11 @@ LRS_ESTABLISHED, &role_ops_mqtt); if (vh_prot_name) - lws_bind_protocol(wsi, wsi->protocol, __func__); + lws_bind_protocol(wsi, wsi->a.protocol, __func__); else /* this is the only time he will transition */ lws_bind_protocol(wsi, - &wsi->vhost->protocols[wsi->vhost->mqtt_protocol_index], + &wsi->a.vhost->protocols[wsi->a.vhost->mqtt_protocol_index], __func__); return 1; /* bound */ @@ -422,8 +421,7 @@ c = &wsi->mqtt->client; - __lws_sul_insert(&pt->pt_sul_owner, &wsi->mqtt->sul_qos1_puback_wait, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&wsi->mqtt->sul_qos1_puback_wait); lws_mqtt_str_free(&c->username); lws_mqtt_str_free(&c->password); diff -Nru libwebsockets-4.0.20/lib/roles/mqtt/primitives.c libwebsockets-4.1.6/lib/roles/mqtt/primitives.c --- libwebsockets-4.0.20/lib/roles/mqtt/primitives.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/mqtt/primitives.c 2020-12-01 17:40:26.000000000 +0000 @@ -27,11 +27,9 @@ */ #include "private-lib-core.h" -/* #include "lws-mqtt.h" */ #include #include -#include #include diff -Nru libwebsockets-4.0.20/lib/roles/pipe/ops-pipe.c libwebsockets-4.1.6/lib/roles/pipe/ops-pipe.c --- libwebsockets-4.0.20/lib/roles/pipe/ops-pipe.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/pipe/ops-pipe.c 2020-12-01 17:40:26.000000000 +0000 @@ -30,8 +30,14 @@ { #if defined(LWS_HAVE_EVENTFD) eventfd_t value; - if (eventfd_read(wsi->desc.sockfd, &value) < 0) + int n; + + n = eventfd_read(wsi->desc.sockfd, &value); + if (n < 0) { + lwsl_notice("%s: eventfd read %d bailed errno %d\n", __func__, + wsi->desc.sockfd, LWS_ERRNO); return LWS_HPI_RET_PLEASE_CLOSE_ME; + } #elif !defined(WIN32) && !defined(_WIN32) char s[100]; int n; diff -Nru libwebsockets-4.0.20/lib/roles/private-lib-roles.h libwebsockets-4.1.6/lib/roles/private-lib-roles.h --- libwebsockets-4.0.20/lib/roles/private-lib-roles.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/private-lib-roles.h 2020-12-01 17:40:26.000000000 +0000 @@ -341,6 +341,8 @@ LWS_UPG_RET_BAIL }; +#define LWS_CONNECT_COMPLETION_GOOD (-99) + int lws_role_call_adoption_bind(struct lws *wsi, int type, const char *prot); diff -Nru libwebsockets-4.0.20/lib/roles/raw-file/CMakeLists.txt libwebsockets-4.1.6/lib/roles/raw-file/CMakeLists.txt --- libwebsockets-4.0.20/lib/roles/raw-file/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/raw-file/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,40 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +list(APPEND SOURCES roles/raw-file/ops-raw-file.c) + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() \ No newline at end of file diff -Nru libwebsockets-4.0.20/lib/roles/raw-file/ops-raw-file.c libwebsockets-4.1.6/lib/roles/raw-file/ops-raw-file.c --- libwebsockets-4.0.20/lib/roles/raw-file/ops-raw-file.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/raw-file/ops-raw-file.c 2020-12-01 17:40:26.000000000 +0000 @@ -41,7 +41,7 @@ } if (pollfd->revents & LWS_POLLIN) { - if (user_callback_handle_rxflow(wsi->protocol->callback, + if (user_callback_handle_rxflow(wsi->a.protocol->callback, wsi, LWS_CALLBACK_RAW_RX_FILE, wsi->user_space, NULL, 0)) { lwsl_debug("raw rx callback closed it\n"); @@ -67,12 +67,12 @@ lws_role_transition(wsi, 0, LRS_ESTABLISHED, &role_ops_raw_file); if (!vh_prot_name) { - if (wsi->vhost->default_protocol_index >= - wsi->vhost->count_protocols) + if (wsi->a.vhost->default_protocol_index >= + wsi->a.vhost->count_protocols) return 0; - wsi->protocol = &wsi->vhost->protocols[ - wsi->vhost->default_protocol_index]; + wsi->a.protocol = &wsi->a.vhost->protocols[ + wsi->a.vhost->default_protocol_index]; } return 1; /* bound */ diff -Nru libwebsockets-4.0.20/lib/roles/raw-proxy/CMakeLists.txt libwebsockets-4.1.6/lib/roles/raw-proxy/CMakeLists.txt --- libwebsockets-4.0.20/lib/roles/raw-proxy/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/raw-proxy/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,42 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +list(APPEND SOURCES + roles/raw-proxy/ops-raw-proxy.c) + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() + diff -Nru libwebsockets-4.0.20/lib/roles/raw-proxy/ops-raw-proxy.c libwebsockets-4.1.6/lib/roles/raw-proxy/ops-raw-proxy.c --- libwebsockets-4.0.20/lib/roles/raw-proxy/ops-raw-proxy.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/raw-proxy/ops-raw-proxy.c 2020-12-01 17:40:26.000000000 +0000 @@ -80,7 +80,7 @@ case LWS_SSL_CAPABLE_MORE_SERVICE: goto try_pollout; } - n = user_callback_handle_rxflow(wsi->protocol->callback, + n = user_callback_handle_rxflow(wsi->a.protocol->callback, wsi, lwsi_role_client(wsi) ? LWS_CALLBACK_RAW_PROXY_CLI_RX : LWS_CALLBACK_RAW_PROXY_SRV_RX, @@ -145,11 +145,11 @@ &role_ops_raw_proxy); if (vh_prot_name) - lws_bind_protocol(wsi, wsi->protocol, __func__); + lws_bind_protocol(wsi, wsi->a.protocol, __func__); else /* this is the only time he will transition */ lws_bind_protocol(wsi, - &wsi->vhost->protocols[wsi->vhost->raw_protocol_index], + &wsi->a.vhost->protocols[wsi->a.vhost->raw_protocol_index], __func__); return 1; /* bound */ diff -Nru libwebsockets-4.0.20/lib/roles/raw-skt/CMakeLists.txt libwebsockets-4.1.6/lib/roles/raw-skt/CMakeLists.txt --- libwebsockets-4.0.20/lib/roles/raw-skt/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/raw-skt/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,46 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +list(APPEND SOURCES + roles/raw-skt/ops-raw-skt.c) + +if (LWS_WITH_ABSTRACT) + list(APPEND SOURCES + abstract/transports/raw-skt.c) +endif() + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() diff -Nru libwebsockets-4.0.20/lib/roles/raw-skt/ops-raw-skt.c libwebsockets-4.1.6/lib/roles/raw-skt/ops-raw-skt.c --- libwebsockets-4.0.20/lib/roles/raw-skt/ops-raw-skt.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/raw-skt/ops-raw-skt.c 2020-12-01 17:40:26.000000000 +0000 @@ -60,7 +60,8 @@ if (lwsi_state(wsi) != LRS_SSL_INIT) if (lws_server_socket_service_ssl(wsi, - LWS_SOCK_INVALID)) + LWS_SOCK_INVALID, + !!(pollfd->revents & pollfd->events & LWS_POLLIN))) return LWS_HPI_RET_PLEASE_CLOSE_ME; return LWS_HPI_RET_HANDLED; @@ -139,15 +140,15 @@ } #if defined(LWS_WITH_UDP) - if (wsi->context->udp_loss_sim_rx_pc) { + if (wsi->a.context->udp_loss_sim_rx_pc) { uint16_t u16; /* * We should randomly drop some of these */ - if (lws_get_random(wsi->context, &u16, 2) == 2 && + if (lws_get_random(wsi->a.context, &u16, 2) == 2 && ((u16 * 100) / 0xffff) <= - wsi->context->udp_loss_sim_rx_pc) { + wsi->a.context->udp_loss_sim_rx_pc) { lwsl_warn("%s: dropping udp rx\n", __func__); /* pretend it was handled */ n = ebuf.len; @@ -156,7 +157,7 @@ } #endif - n = user_callback_handle_rxflow(wsi->protocol->callback, + n = user_callback_handle_rxflow(wsi->a.protocol->callback, wsi, LWS_CALLBACK_RAW_RX, wsi->user_space, ebuf.token, ebuf.len); @@ -213,7 +214,7 @@ wsi->active_writable_req_us = 0; } #endif - n = user_callback_handle_rxflow(wsi->protocol->callback, + n = user_callback_handle_rxflow(wsi->a.protocol->callback, wsi, LWS_CALLBACK_RAW_WRITEABLE, wsi->user_space, NULL, 0); if (n < 0) { @@ -250,11 +251,11 @@ LRS_ESTABLISHED, &role_ops_raw_skt); if (vh_prot_name) - lws_bind_protocol(wsi, wsi->protocol, __func__); + lws_bind_protocol(wsi, wsi->a.protocol, __func__); else /* this is the only time he will transition */ lws_bind_protocol(wsi, - &wsi->vhost->protocols[wsi->vhost->raw_protocol_index], + &wsi->a.vhost->protocols[wsi->a.vhost->raw_protocol_index], __func__); return 1; /* bound */ diff -Nru libwebsockets-4.0.20/lib/roles/ws/client-parser-ws.c libwebsockets-4.1.6/lib/roles/ws/client-parser-ws.c --- libwebsockets-4.0.20/lib/roles/ws/client-parser-ws.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/ws/client-parser-ws.c 2020-12-01 17:40:26.000000000 +0000 @@ -82,7 +82,7 @@ #endif wsi->ws->continuation_possible = 1; wsi->ws->check_utf8 = lws_check_opt( - wsi->context->options, + wsi->a.context->options, LWS_SERVER_OPTION_VALIDATE_UTF8); wsi->ws->utf8 = 0; wsi->ws->first_fragment = 1; @@ -362,12 +362,12 @@ * if there's no protocol max frame size given, we are * supposed to default to context->pt_serv_buf_size */ - if (!wsi->protocol->rx_buffer_size && - wsi->ws->rx_ubuf_head != wsi->context->pt_serv_buf_size) + if (!wsi->a.protocol->rx_buffer_size && + wsi->ws->rx_ubuf_head != wsi->a.context->pt_serv_buf_size) break; - if (wsi->protocol->rx_buffer_size && - wsi->ws->rx_ubuf_head != wsi->protocol->rx_buffer_size) + if (wsi->a.protocol->rx_buffer_size && + wsi->ws->rx_ubuf_head != wsi->a.protocol->rx_buffer_size) break; /* spill because we filled our rx buffer */ @@ -386,7 +386,7 @@ switch (wsi->ws->opcode) { case LWSWSOPC_CLOSE: pp = &wsi->ws->rx_ubuf[LWS_PRE]; - if (lws_check_opt(wsi->context->options, + if (lws_check_opt(wsi->a.context->options, LWS_SERVER_OPTION_VALIDATE_UTF8) && wsi->ws->rx_ubuf_head > 2 && lws_check_utf8(&wsi->ws->utf8, pp + 2, @@ -422,7 +422,7 @@ } } if (user_callback_handle_rxflow( - wsi->protocol->callback, wsi, + wsi->a.protocol->callback, wsi, LWS_CALLBACK_WS_PEER_INITIATED_CLOSE, wsi->user_space, pp, wsi->ws->rx_ubuf_head)) @@ -554,6 +554,7 @@ return -1; } if (n == PMDR_DID_NOTHING) + /* ie, not PMDR_NOTHING_WE_SHOULD_DO */ break; #endif lwsl_ext("%s: post inflate ebuf in len %d / out len %d\n", @@ -619,7 +620,7 @@ pmdrx.eb_out.token[pmdrx.eb_out.len] = '\0'; - if (!wsi->protocol->callback) + if (!wsi->a.protocol->callback) goto already_done; if (callback_action == LWS_CALLBACK_CLIENT_RECEIVE_PONG) @@ -651,7 +652,7 @@ ) pmdrx.eb_in.len -= pmdrx.eb_out.len; - m = wsi->protocol->callback(wsi, + m = wsi->a.protocol->callback(wsi, (enum lws_callback_reasons)callback_action, wsi->user_space, pmdrx.eb_out.token, pmdrx.eb_out.len); diff -Nru libwebsockets-4.0.20/lib/roles/ws/client-ws.c libwebsockets-4.1.6/lib/roles/ws/client-ws.c --- libwebsockets-4.0.20/lib/roles/ws/client-ws.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/ws/client-ws.c 2020-12-01 17:40:26.000000000 +0000 @@ -131,7 +131,7 @@ */ if (lws_ws_client_rx_sm(wsi, *(*buf)++)) { - lwsl_notice("%s: client_rx_sm exited, DROPPING %d\n", + lwsl_info("%s: client_rx_sm exited, DROPPING %d\n", __func__, (int)len); return -1; } @@ -156,7 +156,7 @@ /* * create the random key */ - if (lws_get_random(wsi->context, hash, 16) != 16) { + if (lws_get_random(wsi->a.context, hash, 16) != 16) { lwsl_err("Unable to read from random dev %s\n", SYSTEM_RANDOM_FILEPATH); return NULL; @@ -179,10 +179,10 @@ /* tell the server what extensions we could support */ #if !defined(LWS_WITHOUT_EXTENSIONS) - ext = wsi->vhost->ws.extensions; + ext = wsi->a.vhost->ws.extensions; while (ext && ext->callback) { - n = wsi->vhost->protocols[0].callback(wsi, + n = wsi->a.vhost->protocols[0].callback(wsi, LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED, wsi->user_space, (char *)ext->name, 0); @@ -234,14 +234,14 @@ int lws_client_ws_upgrade(struct lws *wsi, const char **cce) { - struct lws_context *context = wsi->context; + struct lws_context *context = wsi->a.context; struct lws_tokenize ts; int n, len, okay = 0; lws_tokenize_elem e; char *p, buf[64]; const char *pc; #if !defined(LWS_WITHOUT_EXTENSIONS) - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; char *sb = (char *)&pt->serv_buf[0]; const struct lws_ext_options *opts; const struct lws_extension *ext; @@ -349,15 +349,15 @@ * default to first protocol */ - if (wsi->protocol) { - p = (char *)wsi->protocol->name; + if (wsi->a.protocol) { + p = (char *)wsi->a.protocol->name; goto identify_protocol; } /* no choice but to use the default protocol */ n = 0; - wsi->protocol = &wsi->vhost->protocols[0]; + wsi->a.protocol = &wsi->a.vhost->protocols[0]; goto check_extensions; } @@ -395,18 +395,18 @@ n = 0; /* keep client connection pre-bound protocol */ if (!lwsi_role_client(wsi)) - wsi->protocol = NULL; + wsi->a.protocol = NULL; - while (n < wsi->vhost->count_protocols) { - if (!wsi->protocol && - strcmp(p, wsi->vhost->protocols[n].name) == 0) { - wsi->protocol = &wsi->vhost->protocols[n]; + while (n < wsi->a.vhost->count_protocols) { + if (!wsi->a.protocol && + strcmp(p, wsi->a.vhost->protocols[n].name) == 0) { + wsi->a.protocol = &wsi->a.vhost->protocols[n]; break; } n++; } - if (n == wsi->vhost->count_protocols) { /* no match */ + if (n == wsi->a.vhost->count_protocols) { /* no match */ /* if server, that's already fatal */ if (!lwsi_role_client(wsi)) { lwsl_info("%s: fail protocol %s\n", __func__, p); @@ -417,19 +417,19 @@ /* for client, find the index of our pre-bound protocol */ n = 0; - while (wsi->vhost->protocols[n].callback) { - if (wsi->protocol && strcmp(wsi->protocol->name, - wsi->vhost->protocols[n].name) == 0) { - wsi->protocol = &wsi->vhost->protocols[n]; + while (wsi->a.vhost->protocols[n].callback) { + if (wsi->a.protocol && strcmp(wsi->a.protocol->name, + wsi->a.vhost->protocols[n].name) == 0) { + wsi->a.protocol = &wsi->a.vhost->protocols[n]; break; } n++; } - if (!wsi->vhost->protocols[n].callback) { - if (wsi->protocol) + if (!wsi->a.vhost->protocols[n].callback) { + if (wsi->a.protocol) lwsl_err("Failed to match protocol %s\n", - wsi->protocol->name); + wsi->a.protocol->name); else lwsl_err("No protocol on client\n"); *cce = "ws protocol no match"; @@ -437,7 +437,7 @@ } } - lwsl_debug("Selected protocol %s\n", wsi->protocol->name); + lwsl_debug("Selected protocol %s\n", wsi->a.protocol->name); check_extensions: /* @@ -507,7 +507,7 @@ lwsl_notice("checking client ext %s\n", ext_name); n = 0; - ext = wsi->vhost->ws.extensions; + ext = wsi->a.vhost->ws.extensions; while (ext && ext->callback) { if (strcmp(ext_name, ext->name)) { ext++; @@ -539,7 +539,7 @@ * wants to */ ext_name[0] = '\0'; - if (user_callback_handle_rxflow(wsi->protocol->callback, + if (user_callback_handle_rxflow(wsi->a.protocol->callback, wsi, LWS_CALLBACK_WS_EXT_DEFAULTS, (char *)ext->name, ext_name, sizeof(ext_name))) { @@ -623,7 +623,7 @@ * we seem to be good to go, give client last chance to check * headers and OK it */ - if (wsi->protocol->callback(wsi, + if (wsi->a.protocol->callback(wsi, LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH, wsi->user_space, NULL, 0)) { *cce = "HS: Rejected by filter cb"; @@ -646,7 +646,7 @@ * size mentioned in the protocol definition. If 0 there, then * use a big default for compatibility */ - n = (int)wsi->protocol->rx_buffer_size; + n = (int)wsi->a.protocol->rx_buffer_size; if (!n) n = context->pt_serv_buf_size; n += LWS_PRE; @@ -659,11 +659,11 @@ } wsi->ws->rx_ubuf_alloc = n; - lwsl_debug("handshake OK for protocol %s\n", wsi->protocol->name); + lwsl_debug("handshake OK for protocol %s\n", wsi->a.protocol->name); /* call him back to inform him he is up */ - if (wsi->protocol->callback(wsi, LWS_CALLBACK_CLIENT_ESTABLISHED, + if (wsi->a.protocol->callback(wsi, LWS_CALLBACK_CLIENT_ESTABLISHED, wsi->user_space, NULL, 0)) { *cce = "HS: Rejected at CLIENT_ESTABLISHED"; goto bail3; diff -Nru libwebsockets-4.0.20/lib/roles/ws/CMakeLists.txt libwebsockets-4.1.6/lib/roles/ws/CMakeLists.txt --- libwebsockets-4.0.20/lib/roles/ws/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/ws/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,61 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +list(APPEND SOURCES + roles/ws/ops-ws.c) + +if (NOT LWS_WITHOUT_CLIENT) + list(APPEND SOURCES + roles/ws/client-ws.c + roles/ws/client-parser-ws.c) +endif() + +if (NOT LWS_WITHOUT_SERVER) + list(APPEND SOURCES + roles/ws/server-ws.c) +endif() + +if (NOT LWS_WITHOUT_EXTENSIONS) + list(APPEND HDR_PRIVATE + roles/ws/ext/extension-permessage-deflate.h) + list(APPEND SOURCES + roles/ws/ext/extension.c + roles/ws/ext/extension-permessage-deflate.c) +endif() + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() + diff -Nru libwebsockets-4.0.20/lib/roles/ws/ext/extension.c libwebsockets-4.1.6/lib/roles/ws/ext/extension.c --- libwebsockets-4.0.20/lib/roles/ws/ext/extension.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/ws/ext/extension.c 2020-12-01 17:40:26.000000000 +0000 @@ -220,10 +220,10 @@ int n = 0, m, handled = 0; const struct lws_extension *ext; - if (!wsi || !wsi->vhost || !wsi->ws) + if (!wsi || !wsi->a.vhost || !wsi->ws) return 0; - ext = wsi->vhost->ws.extensions; + ext = wsi->a.vhost->ws.extensions; while (ext && ext->callback && !handled) { m = ext->callback(context, ext, wsi, reason, @@ -333,7 +333,7 @@ lws_any_extension_handled(struct lws *wsi, enum lws_extension_callback_reasons r, void *v, size_t len) { - struct lws_context *context = wsi->context; + struct lws_context *context = wsi->a.context; int n, handled = 0; if (!wsi->ws) @@ -376,7 +376,7 @@ oa.start = opt_val; oa.len = 0; - return wsi->ws->active_extensions[idx]->callback(wsi->context, + return wsi->ws->active_extensions[idx]->callback(wsi->a.context, wsi->ws->active_extensions[idx], wsi, LWS_EXT_CB_NAMED_OPTION_SET, wsi->ws->act_ext_user[idx], &oa, 0); diff -Nru libwebsockets-4.0.20/lib/roles/ws/ext/extension-permessage-deflate.c libwebsockets-4.1.6/lib/roles/ws/ext/extension-permessage-deflate.c --- libwebsockets-4.0.20/lib/roles/ws/ext/extension-permessage-deflate.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/ws/ext/extension-permessage-deflate.c 2020-12-01 17:40:26.000000000 +0000 @@ -52,9 +52,9 @@ /* cap the RX buf at the nearest power of 2 to protocol rx buf */ - n = wsi->context->pt_serv_buf_size; - if (wsi->protocol->rx_buffer_size) - n = (int)wsi->protocol->rx_buffer_size; + n = wsi->a.context->pt_serv_buf_size; + if (wsi->a.protocol->rx_buffer_size) + n = (int)wsi->a.protocol->rx_buffer_size; extra = 7; while (n >= 1 << (extra + 1)) @@ -130,13 +130,13 @@ case LWS_EXT_CB_CONSTRUCT: n = context->pt_serv_buf_size; - if (wsi->protocol->rx_buffer_size) - n = (int)wsi->protocol->rx_buffer_size; + if (wsi->a.protocol->rx_buffer_size) + n = (int)wsi->a.protocol->rx_buffer_size; if (n < 128) { lwsl_info(" permessage-deflate requires the protocol " "(%s) to have an RX buffer >= 128\n", - wsi->protocol->name); + wsi->a.protocol->name); return -1; } @@ -192,10 +192,20 @@ lwsl_ext(" %s: LWS_EXT_CB_PAYLOAD_RX: in %d, existing in %d\n", __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)) - 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 @@ -379,7 +389,7 @@ n = deflateInit2(&priv->tx, priv->args[PMD_COMP_LEVEL], Z_DEFLATED, -priv->args[PMD_SERVER_MAX_WINDOW_BITS + - (wsi->vhost->listen_port <= 0)], + (wsi->a.vhost->listen_port <= 0)], priv->args[PMD_MEM_LEVEL], Z_DEFAULT_STRATEGY); if (n != Z_OK) { diff -Nru libwebsockets-4.0.20/lib/roles/ws/ops-ws.c libwebsockets-4.1.6/lib/roles/ws/ops-ws.c --- libwebsockets-4.0.20/lib/roles/ws/ops-ws.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/ws/ops-ws.c 2020-12-01 17:40:26.000000000 +0000 @@ -156,7 +156,7 @@ switch (wsi->ws->opcode) { case LWSWSOPC_TEXT_FRAME: wsi->ws->check_utf8 = lws_check_opt( - wsi->context->options, + wsi->a.context->options, LWS_SERVER_OPTION_VALIDATE_UTF8); /* fallthru */ case LWSWSOPC_BINARY_FRAME: @@ -422,12 +422,12 @@ * if there's no protocol max frame size given, we are * supposed to default to context->pt_serv_buf_size */ - if (!wsi->protocol->rx_buffer_size && - wsi->ws->rx_ubuf_head != wsi->context->pt_serv_buf_size) + if (!wsi->a.protocol->rx_buffer_size && + wsi->ws->rx_ubuf_head != wsi->a.context->pt_serv_buf_size) break; - if (wsi->protocol->rx_buffer_size && - wsi->ws->rx_ubuf_head != wsi->protocol->rx_buffer_size) + if (wsi->a.protocol->rx_buffer_size && + wsi->ws->rx_ubuf_head != wsi->a.protocol->rx_buffer_size) break; /* spill because we filled our rx buffer */ @@ -437,7 +437,7 @@ * layer? If so service it and hide it from the user callback */ - lwsl_parser("spill on %s\n", wsi->protocol->name); + lwsl_parser("spill on %s\n", wsi->a.protocol->name); switch (wsi->ws->opcode) { case LWSWSOPC_CLOSE: @@ -448,7 +448,7 @@ wsi->ws->peer_has_sent_close = 1; pp = &wsi->ws->rx_ubuf[LWS_PRE]; - if (lws_check_opt(wsi->context->options, + if (lws_check_opt(wsi->a.context->options, LWS_SERVER_OPTION_VALIDATE_UTF8) && wsi->ws->rx_ubuf_head > 2 && lws_check_utf8(&wsi->ws->utf8, pp + 2, @@ -498,7 +498,7 @@ } if (user_callback_handle_rxflow( - wsi->protocol->callback, wsi, + wsi->a.protocol->callback, wsi, LWS_CALLBACK_WS_PEER_INITIATED_CLOSE, wsi->user_space, &wsi->ws->rx_ubuf[LWS_PRE], @@ -633,6 +633,7 @@ return -1; } if (n == PMDR_DID_NOTHING) + /* ie, not PMDR_NOTHING_WE_SHOULD_DO */ break; #endif lwsl_debug("%s: post ext ret %d, ebuf in %d / out %d\n", @@ -691,7 +692,8 @@ /* 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) || n == PMDR_UNKNOWN @@ -706,14 +708,14 @@ if (pmdrx.eb_out.len) pmdrx.eb_out.token[pmdrx.eb_out.len] = '\0'; - if (wsi->protocol->callback && + if (wsi->a.protocol->callback && !(already_processed & ALREADY_PROCESSED_NO_CB)) { if (callback_action == LWS_CALLBACK_RECEIVE_PONG) lwsl_info("Doing pong callback\n"); ret = user_callback_handle_rxflow( - wsi->protocol->callback, wsi, + wsi->a.protocol->callback, wsi, (enum lws_callback_reasons) callback_action, wsi->user_space, @@ -764,7 +766,7 @@ lws_add_wsi_to_draining_ext_list(struct lws *wsi) { #if !defined(LWS_WITHOUT_EXTENSIONS) - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; if (wsi->ws->rx_draining_ext) return; @@ -781,7 +783,7 @@ lws_remove_wsi_from_draining_ext_list(struct lws *wsi) { #if !defined(LWS_WITHOUT_EXTENSIONS) - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; struct lws **w = &pt->ws.rx_draining_ext_list; if (!wsi->ws->rx_draining_ext) @@ -836,9 +838,9 @@ * a big default for compatibility */ - n = (int)wsi->protocol->rx_buffer_size; + n = (int)wsi->a.protocol->rx_buffer_size; if (!n) - n = wsi->context->pt_serv_buf_size; + n = wsi->a.context->pt_serv_buf_size; n += LWS_PRE; wsi->ws->rx_ubuf = lws_malloc(n + 4 /* 0x0000ffff zlib */, "rx_ubuf"); if (!wsi->ws->rx_ubuf) { @@ -849,8 +851,8 @@ /* notify user code that we're ready to roll */ - if (wsi->protocol->callback) - if (wsi->protocol->callback(wsi, LWS_CALLBACK_ESTABLISHED, + if (wsi->a.protocol->callback) + if (wsi->a.protocol->callback(wsi, LWS_CALLBACK_ESTABLISHED, wsi->user_space, #ifdef LWS_WITH_TLS wsi->tls.ssl, @@ -954,7 +956,7 @@ return LWS_HPI_RET_PLEASE_CLOSE_ME; } - // lwsl_notice("%s: %s\n", __func__, wsi->protocol->name); + // lwsl_notice("%s: %s\n", __func__, wsi->a.protocol->name); //lwsl_info("%s: wsistate 0x%x, pollout %d\n", __func__, // wsi->wsistate, pollfd->revents & LWS_POLLOUT); @@ -1123,10 +1125,10 @@ if (lwsi_role_ws(wsi)) ebuf.len = wsi->ws->rx_ubuf_alloc; else - ebuf.len = wsi->context->pt_serv_buf_size; + ebuf.len = wsi->a.context->pt_serv_buf_size; - if ((unsigned int)ebuf.len > wsi->context->pt_serv_buf_size) - ebuf.len = wsi->context->pt_serv_buf_size; + if ((unsigned int)ebuf.len > wsi->a.context->pt_serv_buf_size) + ebuf.len = wsi->a.context->pt_serv_buf_size; if ((int)pending > ebuf.len) pending = ebuf.len; @@ -1209,13 +1211,20 @@ } pending = lws_ssl_pending(wsi); + +#if defined(LWS_WITH_CLIENT) + if (!pending && (wsi->flags & LCCSCF_PRIORITIZE_READS) && + lws_buflist_total_len(&wsi->buflist)) + pending = 9999999; +#endif + if (pending) { if (lws_is_ws_with_ext(wsi)) pending = pending > wsi->ws->rx_ubuf_alloc ? wsi->ws->rx_ubuf_alloc : pending; else - pending = pending > wsi->context->pt_serv_buf_size ? - wsi->context->pt_serv_buf_size : pending; + pending = pending > wsi->a.context->pt_serv_buf_size ? + wsi->a.context->pt_serv_buf_size : pending; goto read; } @@ -1246,7 +1255,7 @@ #if !defined(LWS_WITHOUT_EXTENSIONS) lwsl_debug("%s: %s: wsi->ws->tx_draining_ext %d\n", __func__, - wsi->protocol->name, wsi->ws->tx_draining_ext); + wsi->a.protocol->name, wsi->ws->tx_draining_ext); #endif /* Priority 3: pending control packets (pong or close) @@ -1317,7 +1326,7 @@ wsi->ws->send_check_ping) { lwsl_info("%s: issuing ping on wsi %p: %s %s h2: %d\n", __func__, wsi, - wsi->role_ops->name, wsi->protocol->name, + wsi->role_ops->name, wsi->a.protocol->name, wsi->mux_substream); wsi->ws->send_check_ping = 0; n = lws_write(wsi, &wsi->ws->ping_payload_buf[LWS_PRE], @@ -1565,7 +1574,7 @@ enum lws_write_protocol *wp) { #if !defined(LWS_WITHOUT_EXTENSIONS) - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; enum lws_write_protocol wpt; #endif struct lws_ext_pm_deflate_rx_ebufs pmdrx; @@ -1960,11 +1969,14 @@ sizeof(struct lws_extension) * m); plugin = vh->context->plugin_list; while (plugin) { + const lws_plugin_protocol_t *plpr = + (const lws_plugin_protocol_t *)plugin->hdr; + memcpy((struct lws_extension *)&vh->ws.extensions[m], - plugin->caps.extensions, + plpr->extensions, sizeof(struct lws_extension) * - plugin->caps.count_extensions); - m += plugin->caps.count_extensions; + plpr->count_extensions); + m += plpr->count_extensions; plugin = plugin->list; } } else diff -Nru libwebsockets-4.0.20/lib/roles/ws/server-ws.c libwebsockets-4.1.6/lib/roles/ws/server-ws.c --- libwebsockets-4.0.20/lib/roles/ws/server-ws.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/roles/ws/server-ws.c 2020-12-01 17:40:26.000000000 +0000 @@ -30,7 +30,7 @@ static int lws_extension_server_handshake(struct lws *wsi, char **p, int budget) { - struct lws_context *context = wsi->context; + struct lws_context *context = wsi->a.context; struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; char ext_name[64], *args, *end = (*p) + budget - 1; const struct lws_ext_options *opts, *po; @@ -112,7 +112,7 @@ /* check a client's extension against our support */ - ext = wsi->vhost->ws.extensions; + ext = wsi->a.vhost->ws.extensions; while (ext && ext->callback) { @@ -135,7 +135,7 @@ * ask user code if it's OK to apply it on this * particular connection + protocol */ - m = (wsi->protocol->callback)(wsi, + m = (wsi->a.protocol->callback)(wsi, LWS_CALLBACK_CONFIRM_EXTENSION_OKAY, wsi->user_space, ext_name, 0); @@ -254,7 +254,7 @@ int lws_process_ws_upgrade2(struct lws *wsi) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; #if defined(LWS_WITH_HTTP_BASIC_AUTH) const struct lws_protocol_vhost_options *pvos = NULL; const char *ws_prot_basic_auth = NULL; @@ -268,7 +268,7 @@ * section, as a pvo. */ - pvos = lws_vhost_protocol_options(wsi->vhost, wsi->protocol->name); + pvos = lws_vhost_protocol_options(wsi->a.vhost, wsi->a.protocol->name); if (pvos && pvos->options && !lws_pvo_get_str((void *)pvos->options, "basic-auth", &ws_prot_basic_auth)) { @@ -297,10 +297,37 @@ lws_pt_lock(pt, __func__); - if (!wsi->h2_stream_carries_ws) + /* + * Switch roles if we're upgrading away from http + */ + + if (!wsi->h2_stream_carries_ws) { lws_role_transition(wsi, LWSIFR_SERVER, LRS_ESTABLISHED, &role_ops_ws); +#if defined(LWS_WITH_SECURE_STREAMS) && defined(LWS_WITH_SERVER) + + /* + * If we're a SS server object, we have to switch to ss-ws + * protocol handler too + */ + if (wsi->a.vhost->ss_handle) { + lwsl_info("%s: Server SS %p switching to ws protocol\n", + __func__, wsi->a.vhost->ss_handle); + wsi->a.protocol = &protocol_secstream_ws; + + /* + * inform the SS user code that this has done a one-way + * upgrade to some other protocol... it will likely + * want to treat subsequent payloads differently + */ + + (void)lws_ss_event_helper(wsi->a.vhost->ss_handle, + LWSSSCS_SERVER_UPGRADE); + } +#endif + } + lws_pt_unlock(pt); /* allocate the ws struct for the wsi */ @@ -325,7 +352,7 @@ * Give the user code a chance to study the request and * have the opportunity to deny it */ - if ((wsi->protocol->callback)(wsi, + if ((wsi->a.protocol->callback)(wsi, LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION, wsi->user_space, lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL), 0)) { @@ -362,13 +389,12 @@ * validity checking */ - __lws_sul_insert(&pt->pt_sul_owner, &wsi->sul_validity, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&wsi->sul_validity); } else #endif { lwsl_parser("lws_parse calling handshake_04\n"); - if (handshake_0405(wsi->context, wsi)) { + if (handshake_0405(wsi->a.context, wsi)) { lwsl_notice("hs0405 has failed the connection\n"); return 1; } @@ -376,7 +402,10 @@ break; } - lws_server_init_wsi_for_ws(wsi); + if (lws_server_init_wsi_for_ws(wsi)) { + lwsl_notice("%s: user ESTABLISHED failed connection\n", __func__); + return 1; + } lwsl_parser("accepted v%02d connection\n", wsi->ws->ietf_spec_revision); #if defined(LWS_WITH_ACCESS_LOG) @@ -391,7 +420,7 @@ lws_strnncpy(dotstar, uptr, l, sizeof(dotstar)); l = lws_snprintf(combo, sizeof(combo), "%s (%s)", dotstar, - wsi->protocol->name); + wsi->a.protocol->name); if (meth < 0) meth = 0; @@ -415,7 +444,7 @@ lws_tokenize_elem e; int n; - if (!wsi->protocol) + if (!wsi->a.protocol) lwsl_err("NULL protocol at lws_read\n"); /* @@ -507,7 +536,7 @@ } ts.len = n; if (!ts.len) { - int n = wsi->vhost->default_protocol_index; + int n = wsi->a.vhost->default_protocol_index; /* * Some clients only have one protocol and do not send the * protocol list header... allow it and match to the vhost's @@ -518,7 +547,7 @@ * these "no protocol" ws connections to be rejected. */ - if (n >= wsi->vhost->count_protocols) { + if (n >= wsi->a.vhost->count_protocols) { lwsl_notice("%s: rejecting ws upg with no protocol\n", __func__); @@ -527,12 +556,39 @@ lwsl_info("%s: defaulting to prot handler %d\n", __func__, n); - lws_bind_protocol(wsi, &wsi->vhost->protocols[n], + lws_bind_protocol(wsi, &wsi->a.vhost->protocols[n], "ws upgrade default pcol"); goto alloc_ws; } +#if defined(LWS_WITH_SECURE_STREAMS) && defined(LWS_WITH_SERVER) + if (wsi->a.vhost->ss_handle) { + lws_ss_handle_t *sssh = wsi->a.vhost->ss_handle; + + /* + * At the moment, once we see it's a ss ws server, whatever + * he asked for we bind him to the ss-ws protocol handler. + * + * In the response subprotocol header, we need to name + * + * sssh->policy->u.http.u.ws.subprotocol + * + * though... + */ + + if (sssh->policy->u.http.u.ws.subprotocol) { + pcol = lws_vhost_name_to_protocol(wsi->a.vhost, + "lws-secstream-ws"); + if (pcol) { + lws_bind_protocol(wsi, pcol, "ss ws upg pcol"); + + goto alloc_ws; + } + } + } +#endif + /* otherwise go through the user-provided protocol list */ do { @@ -546,7 +602,7 @@ return 1; } lwsl_debug("checking %s\n", name); - pcol = lws_vhost_name_to_protocol(wsi->vhost, name); + pcol = lws_vhost_name_to_protocol(wsi->a.vhost, name); if (pcol) { /* if we know it, bind to it and stop looking */ lws_bind_protocol(wsi, pcol, "ws upg pcol"); @@ -640,15 +696,36 @@ * - one came in, and ... */ if (lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL) && /* - it is not an empty string */ - wsi->protocol->name && - wsi->protocol->name[0]) { - const char *prot = wsi->protocol->name; + wsi->a.protocol->name && + wsi->a.protocol->name[0]) { + const char *prot = wsi->a.protocol->name; #if defined(LWS_WITH_HTTP_PROXY) if (wsi->proxied_ws_parent && wsi->child_list) prot = wsi->child_list->ws->actual_protocol; #endif +#if defined(LWS_WITH_SECURE_STREAMS) && defined(LWS_WITH_SERVER) + { + lws_ss_handle_t *sssh = wsi->a.vhost->ss_handle; + + /* + * At the moment, once we see it's a ss ws server, whatever + * he asked for we bind him to the ss-ws protocol handler. + * + * In the response subprotocol header, we need to name + * + * sssh->policy->u.http.u.ws.subprotocol + * + * though... + */ + + if (sssh && sssh->policy && + sssh->policy->u.http.u.ws.subprotocol) + prot = sssh->policy->u.http.u.ws.subprotocol; + } +#endif + LWS_CPYAPP(p, "\x0d\x0aSec-WebSocket-Protocol: "); p += lws_snprintf(p, 128, "%s", prot); } @@ -668,7 +745,7 @@ args.p = p; args.max_len = lws_ptr_diff((char *)pt->serv_buf + context->pt_serv_buf_size, p); - if (user_callback_handle_rxflow(wsi->protocol->callback, wsi, + if (user_callback_handle_rxflow(wsi->a.protocol->callback, wsi, LWS_CALLBACK_ADD_HEADERS, wsi->user_space, &args, 0)) goto bail; @@ -705,7 +782,7 @@ const struct lws_http_mount *hit = lws_find_mount(wsi, uri_ptr, uri_len); if (hit && hit->cgienv && - wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP_PMO, + wsi->a.protocol->callback(wsi, LWS_CALLBACK_HTTP_PMO, wsi->user_space, (void *)hit->cgienv, 0)) return 1; } @@ -747,10 +824,10 @@ if (!wsi->ws->count_act_ext) #endif { - if (wsi->protocol->rx_buffer_size) - avail = (int)wsi->protocol->rx_buffer_size; + if (wsi->a.protocol->rx_buffer_size) + avail = (int)wsi->a.protocol->rx_buffer_size; else - avail = wsi->context->pt_serv_buf_size; + avail = wsi->a.context->pt_serv_buf_size; } /* do not consume more than we should */ @@ -837,12 +914,12 @@ old_packet_length && /* we gave the inflator new input */ !wsi->ws->rx_packet_length && /* raw ws packet payload all gone */ wsi->ws->final && /* the raw ws packet is a FIN guy */ - wsi->protocol->callback && + wsi->a.protocol->callback && !wsi->wsistate_pre_close) { lwsl_ext("%s: issuing zero length FIN pkt\n", __func__); - if (user_callback_handle_rxflow(wsi->protocol->callback, wsi, + if (user_callback_handle_rxflow(wsi->a.protocol->callback, wsi, LWS_CALLBACK_RECEIVE, wsi->user_space, NULL, 0)) return -1; @@ -889,8 +966,8 @@ } } - if (wsi->protocol->callback && !wsi->wsistate_pre_close) - if (user_callback_handle_rxflow(wsi->protocol->callback, wsi, + if (wsi->a.protocol->callback && !wsi->wsistate_pre_close) + if (user_callback_handle_rxflow(wsi->a.protocol->callback, wsi, LWS_CALLBACK_RECEIVE, wsi->user_space, pmdrx.eb_out.token, @@ -943,7 +1020,6 @@ * We dealt with it by trimming the existing * rxflow cache HEAD to account for what we used. * - * indicate we didn't use anything to the caller * so he doesn't do any consumed processing */ lwsl_info("%s: trimming inside rxflow cache\n", diff -Nru libwebsockets-4.0.20/lib/secure-streams/CMakeLists.txt libwebsockets-4.1.6/lib/secure-streams/CMakeLists.txt --- libwebsockets-4.0.20/lib/secure-streams/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/secure-streams/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,133 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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_directories(.) + +if (LWS_WITH_CLIENT) + list(APPEND SOURCES + secure-streams/secure-streams.c + secure-streams/policy-common.c + secure-streams/system/captive-portal-detect/captive-portal-detect.c + secure-streams/protocols/ss-raw.c + ) + if (NOT LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) + list(APPEND SOURCES + secure-streams/policy-json.c + secure-streams/system/fetch-policy/fetch-policy.c + ) + endif() + if (LWS_ROLE_H1) + list(APPEND SOURCES + secure-streams/protocols/ss-h1.c + ) + endif() + if (LWS_ROLE_H2) + list(APPEND SOURCES + secure-streams/protocols/ss-h2.c + ) + endif() + if (LWS_ROLE_WS) + list(APPEND SOURCES + secure-streams/protocols/ss-ws.c + ) + endif() + if (LWS_ROLE_MQTT) + list(APPEND SOURCES + secure-streams/protocols/ss-mqtt.c + ) + endif() + + if (LWS_WITH_SECURE_STREAMS_PROXY_API) + list(APPEND SOURCES + secure-streams/secure-streams-serialize.c + secure-streams/secure-streams-client.c + ) + endif() + + if (LWS_WITH_SECURE_STREAMS_PROXY_API) + list(APPEND SOURCES + secure-streams/secure-streams-process.c + ) + endif() + + if (LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM AND + LWS_WITH_SYS_STATE) + list(APPEND SOURCES + secure-streams/system/auth-api.amazon.com/auth.c + ) + endif() + + + # + # Helper function for adding a secure stream plugin + # + macro(create_ss_plugin NAME S2 S3 S4 S5 S6) + + set(SSP_SRCS) + set(SSP_PUBLIC_HDR) + set(SSP_HDR) + + if ("${S2}" STREQUAL "") + else() + list(APPEND SSP_SRCS plugins/${NAME}/${S2}) + endif() + if ("${S3}" STREQUAL "") + else() + list(APPEND SSP_SRCS plugins/${NAME}/${S3}) + endif() + if ("${S4}" STREQUAL "") + else() + list(APPEND SSP_SRCS plugins/${NAME}/${S4}) + endif() + if ("${S5}" STREQUAL "") + else() + list(APPEND SSP_SRCS plugins/${NAME}/${S5}) + endif() + if ("${S6}" STREQUAL "") + else() + list(APPEND SSP_SRCS plugins/${NAME}/${S6}) + endif() + + source_group("Headers Private" FILES ${SSP_HDR}) + source_group("Sources" FILES ${SSP_SRCS}) + + add_library( ${NAME} STATIC + ${SSP_HDR} ${SSP_PUBLIC_HDR} ${SSP_SRCS} ) + + target_include_directories(${NAME} PRIVATE "${LWS_LIB_INCLUDES}" ${LWS_LIB_BUILD_INC_PATHS}) + + if (NOT LWS_PLAT_FREERTOS) + add_dependencies(${NAME} websockets_shared) + endif() + list(APPEND SS_PLUGINS_LIST ${NAME}) + endmacro() + + # create_ss_plugin(ssp-h1url "h1url.c" "" "" "" "") +endif() + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() diff -Nru libwebsockets-4.0.20/lib/secure-streams/policy.c libwebsockets-4.1.6/lib/secure-streams/policy.c --- libwebsockets-4.0.20/lib/secure-streams/policy.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/secure-streams/policy.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,987 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2019 - 2020 Andy Green - * - * 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 - -typedef struct backoffs { - struct backoffs *next; - const char *name; - lws_retry_bo_t r; -} backoff_t; - -static const char * const lejp_tokens_policy[] = { - "release", - "product", - "schema-version", - "via-socks5", - "retry[].*.backoff", - "retry[].*.conceal", - "retry[].*.jitterpc", - "retry[].*.svalidping", - "retry[].*.svalidhup", - "retry[].*", - "certs[].*", - "trust_stores[].name", - "trust_stores[].stack", - "s[].*.endpoint", - "s[].*.via-socks5", - "s[].*.protocol", - "s[].*.port", - "s[].*.plugins", - "s[].*.tls", - "s[].*.client_cert", - "s[].*.opportunistic", - "s[].*.nailed_up", - "s[].*.urgent_tx", - "s[].*.urgent_rx", - "s[].*.long_poll", - "s[].*.retry", - "s[].*.tls_trust_store", - "s[].*.metadata", - "s[].*.metadata[].*", - - "s[].*.http_auth_header", - "s[].*.http_dsn_header", - "s[].*.http_fwv_header", - "s[].*.http_devtype_header", - - "s[].*.http_auth_preamble", - - "s[].*.http_no_content_length", - "s[].*.rideshare", /* streamtype name this rides shotgun with */ - "s[].*.payload_fmt", - "s[].*.http_method", - "s[].*.http_url", - "s[].*.nghttp2_quirk_end_stream", - "s[].*.h2q_oflow_txcr", - "s[].*.http_multipart_name", - "s[].*.http_multipart_filename", - "s[].*.http_mime_content_type", - "s[].*.http_www_form_urlencoded", - "s[].*.ws_subprotocol", - "s[].*.ws_binary", - "s[].*.local_sink", - "s[].*.mqtt_topic", - "s[].*.mqtt_subscribe", - "s[].*.mqtt_qos", - "s[].*.mqtt_keep_alive", - "s[].*.mqtt_clean_start", - "s[].*.mqtt_will_topic", - "s[].*.mqtt_will_message", - "s[].*.mqtt_will_qos", - "s[].*.mqtt_will_retain", - "s[].*", -}; - -typedef enum { - LSSPPT_RELEASE, - LSSPPT_PRODUCT, - LSSPPT_SCHEMA_VERSION, - LSSPPT_VIA_SOCKS5, - LSSPPT_BACKOFF, - LSSPPT_CONCEAL, - LSSPPT_JITTERPC, - LSSPPT_VALIDPING_S, - LSSPPT_VALIDHUP_S, - LSSPPT_RETRY, - LSSPPT_CERTS, - LSSPPT_TRUST_STORES_NAME, - LSSPPT_TRUST_STORES_STACK, - LSSPPT_ENDPOINT, - LSSPPT_VH_VIA_SOCKS5, - LSSPPT_PROTOCOL, - LSSPPT_PORT, - LSSPPT_PLUGINS, - LSSPPT_TLS, - LSSPPT_TLS_CLIENT_CERT, - LSSPPT_OPPORTUNISTIC, - LSSPPT_NAILED_UP, - LSSPPT_URGENT_TX, - LSSPPT_URGENT_RX, - LSSPPT_LONG_POLL, - LSSPPT_RETRYPTR, - LSSPPT_TRUST, - LSSPPT_METADATA, - LSSPPT_METADATA_ITEM, - - LSSPPT_HTTP_AUTH_HEADER, - LSSPPT_HTTP_DSN_HEADER, - LSSPPT_HTTP_FWV_HEADER, - LSSPPT_HTTP_TYPE_HEADER, - - LSSPPT_HTTP_AUTH_PREAMBLE, - LSSPPT_HTTP_NO_CONTENT_LENGTH, - LSSPPT_RIDESHARE, - LSSPPT_PAYLOAD_FORMAT, - LSSPPT_HTTP_METHOD, - LSSPPT_HTTP_URL, - LSSPPT_NGHTTP2_QUIRK_END_STREAM, - LSSPPT_H2_QUIRK_OVERFLOWS_TXCR, - LSSPPT_HTTP_MULTIPART_NAME, - LSSPPT_HTTP_MULTIPART_FILENAME, - LSSPPT_HTTP_MULTIPART_CONTENT_TYPE, - LSSPPT_HTTP_WWW_FORM_URLENCODED, - LSSPPT_WS_SUBPROTOCOL, - LSSPPT_WS_BINARY, - LSSPPT_LOCAL_SINK, - LSSPPT_MQTT_TOPIC, - LSSPPT_MQTT_SUBSCRIBE, - LSSPPT_MQTT_QOS, - LSSPPT_MQTT_KEEPALIVE, - LSSPPT_MQTT_CLEAN_START, - LSSPPT_MQTT_WILL_TOPIC, - LSSPPT_MQTT_WILL_MESSAGE, - LSSPPT_MQTT_WILL_QOS, - LSSPPT_MQTT_WILL_RETAIN, - LSSPPT_STREAMTYPES -} policy_token_t; - -union u { - backoff_t *b; - lws_ss_x509_t *x; - lws_ss_trust_store_t *t; - lws_ss_policy_t *p; -}; - -enum { - LTY_BACKOFF, - LTY_X509, - LTY_TRUSTSTORE, - LTY_POLICY, - - _LTY_COUNT /* always last */ -}; - -struct policy_cb_args { - struct lejp_ctx jctx; - struct lws_context *context; - struct lwsac *ac; - - const char *socks5_proxy; - - struct lws_b64state b64; - - union u heads[_LTY_COUNT]; - union u curr[_LTY_COUNT]; - - uint8_t *p; - - int count; -}; - -#define POL_AC_INITIAL 2048 -#define POL_AC_GRAIN 800 -#define MAX_CERT_TEMP 2048 /* used to discover actual cert size for realloc */ - -static uint8_t sizes[] = { - sizeof(backoff_t), - sizeof(lws_ss_x509_t), - sizeof(lws_ss_trust_store_t), - sizeof(lws_ss_policy_t), -}; - -static const char *protonames[] = { - "h1", /* LWSSSP_H1 */ - "h2", /* LWSSSP_H2 */ - "ws", /* LWSSSP_WS */ - "mqtt", /* LWSSSP_MQTT */ -}; - -lws_ss_metadata_t * -lws_ss_policy_metadata(const lws_ss_policy_t *p, const char *name) -{ - lws_ss_metadata_t *pmd = p->metadata; - - while (pmd) { - if (pmd->name && !strcmp(name, pmd->name)) - return pmd; - pmd = pmd->next; - } - - return NULL; -} - -lws_ss_metadata_t * -lws_ss_policy_metadata_index(const lws_ss_policy_t *p, size_t index) -{ - lws_ss_metadata_t *pmd = p->metadata; - - while (pmd) { - if (pmd->length == index) - return pmd; - pmd = pmd->next; - } - - return NULL; -} - -int -lws_ss_set_metadata(struct lws_ss_handle *h, const char *name, - void *value, size_t len) -{ - lws_ss_metadata_t *omd = lws_ss_policy_metadata(h->policy, name); - - if (!omd) { - lwsl_err("%s: unknown metadata %s\n", __func__, name); - return 1; - } - - h->metadata[omd->length].name = name; - h->metadata[omd->length].value = value; - h->metadata[omd->length].length = len; - - return 0; -} - -lws_ss_metadata_t * -lws_ss_get_handle_metadata(struct lws_ss_handle *h, const char *name) -{ - lws_ss_metadata_t *omd = lws_ss_policy_metadata(h->policy, name); - - if (!omd) - return NULL; - - return &h->metadata[omd->length]; -} - -static signed char -lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason) -{ - struct policy_cb_args *a = (struct policy_cb_args *)ctx->user; - const lws_ss_plugin_t **pin; - char **pp, dotstar[32], *q; - lws_ss_trust_store_t *ts; - lws_ss_metadata_t *pmd; - lws_retry_bo_t *b; - size_t inl, outl; - lws_ss_x509_t *x; - uint8_t *extant; - backoff_t *bot; - int n = -1; - - lwsl_debug("%s: %d %d %s\n", __func__, reason, ctx->path_match - 1, - ctx->path); - - switch (ctx->path_match - 1) { - case LSSPPT_RETRY: - n = LTY_BACKOFF; - break; - case LSSPPT_CERTS: - n = LTY_X509; - break; - case LSSPPT_TRUST_STORES_NAME: - case LSSPPT_TRUST_STORES_STACK: - n = LTY_TRUSTSTORE; - break; - case LSSPPT_STREAMTYPES: - n = LTY_POLICY; - break; - } - - if (reason == LEJPCB_ARRAY_START && - (ctx->path_match - 1 == LSSPPT_PLUGINS || - ctx->path_match - 1 == LSSPPT_METADATA)) - a->count = 0; - - if (reason == LEJPCB_ARRAY_END && - ctx->path_match - 1 == LSSPPT_TRUST_STORES_STACK && !a->count) { - lwsl_err("%s: at least one cert required in trust store\n", - __func__); - goto oom; - } - - if (reason == LEJPCB_OBJECT_END && a->p) { - /* - * Allocate a just-the-right-size buf for the cert DER now - * we decoded it into the a->p temp buffer and know the exact - * size - */ - a->curr[LTY_X509].x->ca_der = lws_malloc(a->count, "ssx509"); - if (!a->curr[LTY_X509].x->ca_der) - goto oom; - memcpy((uint8_t *)a->curr[LTY_X509].x->ca_der, a->p, a->count); - a->curr[LTY_X509].x->ca_der_len = a->count; - - /* - * ... and then we can free the temp buffer - */ - lws_free_set_NULL(a->p); - - return 0; - } - - if (reason == LEJPCB_PAIR_NAME && n != -1 && n != LTY_TRUSTSTORE) { - /* - * We do the pointers always as .b, all of the participating - * structs begin with .next and .name - */ - a->curr[n].b = lwsac_use_zero(&a->ac, sizes[n], POL_AC_GRAIN); - if (!a->curr[n].b) - goto oom; - - if (n == LTY_X509) { - a->p = lws_malloc(MAX_CERT_TEMP, "cert temp"); - if (!a->p) - goto oom; - memset(&a->b64, 0, sizeof(a->b64)); - } - - a->count = 0; - a->curr[n].b->next = a->heads[n].b; - a->heads[n].b = a->curr[n].b; - pp = (char **)&a->curr[n].b->name; - - goto string1; - } - - if (!(reason & LEJP_FLAG_CB_IS_VALUE) || !ctx->path_match) - return 0; - - switch (ctx->path_match - 1) { - - /* strings */ - - case LSSPPT_RELEASE: - break; - - case LSSPPT_PRODUCT: - break; - - case LSSPPT_SCHEMA_VERSION: - break; - - case LSSPPT_VIA_SOCKS5: - /* the global / default proxy */ - pp = (char **)&a->socks5_proxy; - goto string2; - - case LSSPPT_BACKOFF: - b = &a->curr[LTY_BACKOFF].b->r; - if (b->retry_ms_table_count == 8) { - lwsl_err("%s: > 8 backoff levels\n", __func__); - return 1; - } - if (!b->retry_ms_table_count) { - b->retry_ms_table = (uint32_t *)lwsac_use_zero(&a->ac, - sizeof(uint32_t) * 8, POL_AC_GRAIN); - if (!b->retry_ms_table) - goto oom; - } - - ((uint32_t *)b->retry_ms_table) - [b->retry_ms_table_count++] = atoi(ctx->buf); - break; - - case LSSPPT_CONCEAL: - a->curr[LTY_BACKOFF].b->r.conceal_count = atoi(ctx->buf); - break; - - case LSSPPT_JITTERPC: - a->curr[LTY_BACKOFF].b->r.jitter_percent = atoi(ctx->buf); - break; - - case LSSPPT_VALIDPING_S: - a->curr[LTY_BACKOFF].b->r.secs_since_valid_ping = atoi(ctx->buf); - break; - - case LSSPPT_VALIDHUP_S: - a->curr[LTY_BACKOFF].b->r.secs_since_valid_hangup = atoi(ctx->buf); - break; - - case LSSPPT_CERTS: - if (a->count + ctx->npos >= MAX_CERT_TEMP) { - lwsl_err("%s: cert too big\n", __func__); - goto oom; - } - inl = ctx->npos; - outl = MAX_CERT_TEMP - a->count; - - lws_b64_decode_stateful(&a->b64, ctx->buf, &inl, - a->p + a->count, &outl, - reason == LEJPCB_VAL_STR_END); - a->count += outl; - if (inl != ctx->npos) { - lwsl_err("%s: b64 decode fail\n", __func__); - goto oom; - } - break; - - case LSSPPT_TRUST_STORES_NAME: - /* - * We do the pointers always as .b, all of the participating - * structs begin with .next and .name - */ - a->curr[LTY_TRUSTSTORE].b = lwsac_use_zero(&a->ac, - sizes[LTY_TRUSTSTORE], POL_AC_GRAIN); - if (!a->curr[LTY_TRUSTSTORE].b) - goto oom; - - a->count = 0; - a->curr[LTY_TRUSTSTORE].b->next = a->heads[LTY_TRUSTSTORE].b; - a->heads[LTY_TRUSTSTORE].b = a->curr[LTY_TRUSTSTORE].b; - pp = (char **)&a->curr[LTY_TRUSTSTORE].b->name; - - goto string2; - - case LSSPPT_TRUST_STORES_STACK: - if (a->count >= (int)LWS_ARRAY_SIZE( - a->curr[LTY_TRUSTSTORE].t->ssx509)) { - lwsl_err("%s: trust store too big\n", __func__); - goto oom; - } - lwsl_debug("%s: trust stores stack %.*s\n", __func__, - ctx->npos, ctx->buf); - x = a->heads[LTY_X509].x; - while (x) { - if (!strncmp(x->vhost_name, ctx->buf, ctx->npos)) { - a->curr[LTY_TRUSTSTORE].t->ssx509[a->count++] = x; - a->curr[LTY_TRUSTSTORE].t->count++; - - return 0; - } - x = x->next; - } - lws_strnncpy(dotstar, ctx->buf, ctx->npos, sizeof(dotstar)); - lwsl_err("%s: unknown trust store entry %s\n", __func__, - dotstar); - goto oom; - - case LSSPPT_ENDPOINT: - pp = (char **)&a->curr[LTY_POLICY].p->endpoint; - goto string2; - - case LSSPPT_VH_VIA_SOCKS5: - pp = (char **)&a->curr[LTY_POLICY].p->socks5_proxy; - goto string2; - - case LSSPPT_PORT: - a->curr[LTY_POLICY].p->port = atoi(ctx->buf); - break; - - case LSSPPT_HTTP_METHOD: - pp = (char **)&a->curr[LTY_POLICY].p->u.http.method; - goto string2; - - case LSSPPT_HTTP_URL: - pp = (char **)&a->curr[LTY_POLICY].p->u.http.url; - goto string2; - - case LSSPPT_RIDESHARE: - pp = (char **)&a->curr[LTY_POLICY].p->rideshare_streamtype; - goto string2; - - case LSSPPT_PAYLOAD_FORMAT: - pp = (char **)&a->curr[LTY_POLICY].p->payload_fmt; - goto string2; - - case LSSPPT_PLUGINS: - pin = a->context->pss_plugins; - if (a->count == - (int)LWS_ARRAY_SIZE(a->curr[LTY_POLICY].p->plugins)) { - lwsl_err("%s: too many plugins\n", __func__); - - goto oom; - } - if (!pin) - break; - while (*pin) { - if (!strncmp((*pin)->name, ctx->buf, ctx->npos)) { - a->curr[LTY_POLICY].p->plugins[a->count++] = *pin; - return 0; - } - pin++; - } - lwsl_err("%s: unknown plugin\n", __func__); - goto oom; - - case LSSPPT_TLS: - if (reason == LEJPCB_VAL_TRUE) - a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_TLS; - break; - - case LSSPPT_TLS_CLIENT_CERT: - a->curr[LTY_POLICY].p->client_cert = atoi(ctx->buf) + 1; - break; - - case LSSPPT_OPPORTUNISTIC: - if (reason == LEJPCB_VAL_TRUE) - a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_OPPORTUNISTIC; - break; - case LSSPPT_NAILED_UP: - if (reason == LEJPCB_VAL_TRUE) - a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_NAILED_UP; - break; - case LSSPPT_URGENT_TX: - if (reason == LEJPCB_VAL_TRUE) - a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_URGENT_TX; - break; - case LSSPPT_URGENT_RX: - if (reason == LEJPCB_VAL_TRUE) - a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_URGENT_RX; - break; - case LSSPPT_LONG_POLL: - if (reason == LEJPCB_VAL_TRUE) - a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_LONG_POLL; - break; - case LSSPPT_HTTP_WWW_FORM_URLENCODED: - if (reason == LEJPCB_VAL_TRUE) - a->curr[LTY_POLICY].p->flags |= - LWSSSPOLF_HTTP_X_WWW_FORM_URLENCODED; - break; - - case LSSPPT_RETRYPTR: - bot = a->heads[LTY_BACKOFF].b; - while (bot) { - if (!strncmp(ctx->buf, bot->name, ctx->npos)) { - a->curr[LTY_POLICY].p->retry_bo = &bot->r; - - return 0; - } - bot = bot->next; - } - lwsl_err("%s: unknown backoff scheme\n", __func__); - - return -1; - - case LSSPPT_TRUST: - ts = a->heads[LTY_TRUSTSTORE].t; - while (ts) { - if (!strncmp(ctx->buf, ts->name, ctx->npos)) { - a->curr[LTY_POLICY].p->trust_store = ts; - return 0; - } - ts = ts->next; - } - lws_strnncpy(dotstar, ctx->buf, ctx->npos, sizeof(dotstar)); - lwsl_err("%s: unknown trust store name %s\n", __func__, - dotstar); - - return -1; - - case LSSPPT_METADATA: - break; - - case LSSPPT_METADATA_ITEM: - pmd = a->curr[LTY_POLICY].p->metadata; - a->curr[LTY_POLICY].p->metadata = lwsac_use_zero(&a->ac, - sizeof(lws_ss_metadata_t) + ctx->npos + - (ctx->path_match_len - ctx->st[ctx->sp - 2].p + 1) + 2, - POL_AC_GRAIN); - a->curr[LTY_POLICY].p->metadata->next = pmd; - - q = (char *)a->curr[LTY_POLICY].p->metadata + - sizeof(lws_ss_metadata_t); - a->curr[LTY_POLICY].p->metadata->name = q; - memcpy(q, ctx->path + ctx->st[ctx->sp - 2].p + 1, - ctx->path_match_len - ctx->st[ctx->sp - 2].p); - - q += ctx->path_match_len - ctx->st[ctx->sp - 2].p; - a->curr[LTY_POLICY].p->metadata->value = q; - memcpy(q, ctx->buf, ctx->npos); - - a->curr[LTY_POLICY].p->metadata->length = /* the index in handle->metadata */ - a->curr[LTY_POLICY].p->metadata_count++; - break; - - case LSSPPT_HTTP_AUTH_HEADER: - case LSSPPT_HTTP_DSN_HEADER: - case LSSPPT_HTTP_FWV_HEADER: - case LSSPPT_HTTP_TYPE_HEADER: - pp = (char **)&a->curr[LTY_POLICY].p->u.http.blob_header[ - (ctx->path_match - 1) - LSSPPT_HTTP_AUTH_HEADER]; - goto string2; - - case LSSPPT_HTTP_AUTH_PREAMBLE: - pp = (char **)&a->curr[LTY_POLICY].p->u.http.auth_preamble; - goto string2; - - case LSSPPT_HTTP_NO_CONTENT_LENGTH: - if (reason == LEJPCB_VAL_TRUE) - a->curr[LTY_POLICY].p->flags |= - LWSSSPOLF_HTTP_NO_CONTENT_LENGTH; - break; - - case LSSPPT_NGHTTP2_QUIRK_END_STREAM: - if (reason == LEJPCB_VAL_TRUE) - a->curr[LTY_POLICY].p->flags |= - LWSSSPOLF_QUIRK_NGHTTP2_END_STREAM; - break; - case LSSPPT_H2_QUIRK_OVERFLOWS_TXCR: - if (reason == LEJPCB_VAL_TRUE) - a->curr[LTY_POLICY].p->flags |= - LWSSSPOLF_H2_QUIRK_OVERFLOWS_TXCR; - break; - case LSSPPT_HTTP_MULTIPART_NAME: - a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_HTTP_MULTIPART; - pp = (char **)&a->curr[LTY_POLICY].p->u.http.multipart_name; - goto string2; - case LSSPPT_HTTP_MULTIPART_FILENAME: - a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_HTTP_MULTIPART; - pp = (char **)&a->curr[LTY_POLICY].p->u.http.multipart_filename; - goto string2; - case LSSPPT_HTTP_MULTIPART_CONTENT_TYPE: - a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_HTTP_MULTIPART; - pp = (char **)&a->curr[LTY_POLICY].p->u.http.multipart_content_type; - goto string2; - case LSSPPT_WS_SUBPROTOCOL: - pp = (char **)&a->curr[LTY_POLICY].p->u.http.u.ws.subprotocol; - goto string2; - - case LSSPPT_WS_BINARY: - a->curr[LTY_POLICY].p->u.http.u.ws.binary = - reason == LEJPCB_VAL_TRUE; - break; - case LSSPPT_LOCAL_SINK: - if (reason == LEJPCB_VAL_TRUE) - a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_LOCAL_SINK; - break; - - case LSSPPT_MQTT_TOPIC: - pp = (char **)&a->curr[LTY_POLICY].p->u.mqtt.topic; - goto string2; - - case LSSPPT_MQTT_SUBSCRIBE: - pp = (char **)&a->curr[LTY_POLICY].p->u.mqtt.subscribe; - goto string2; - - case LSSPPT_MQTT_QOS: - a->curr[LTY_POLICY].p->u.mqtt.qos = atoi(ctx->buf); - break; - - case LSSPPT_MQTT_KEEPALIVE: - a->curr[LTY_POLICY].p->u.mqtt.keep_alive = atoi(ctx->buf); - break; - - case LSSPPT_MQTT_CLEAN_START: - a->curr[LTY_POLICY].p->u.mqtt.clean_start = - reason == LEJPCB_VAL_TRUE; - break; - case LSSPPT_MQTT_WILL_TOPIC: - pp = (char **)&a->curr[LTY_POLICY].p->u.mqtt.will_topic; - goto string2; - - case LSSPPT_MQTT_WILL_MESSAGE: - pp = (char **)&a->curr[LTY_POLICY].p->u.mqtt.will_message; - goto string2; - - case LSSPPT_MQTT_WILL_QOS: - a->curr[LTY_POLICY].p->u.mqtt.will_qos = atoi(ctx->buf); - break; - case LSSPPT_MQTT_WILL_RETAIN: - a->curr[LTY_POLICY].p->u.mqtt.will_retain = - reason == LEJPCB_VAL_TRUE; - break; - - case LSSPPT_PROTOCOL: - a->curr[LTY_POLICY].p->protocol = 0xff; - for (n = 0; n < (int)LWS_ARRAY_SIZE(protonames); n++) - if (strlen(protonames[n]) == ctx->npos && - !strncmp(ctx->buf, protonames[n], ctx->npos)) - a->curr[LTY_POLICY].p->protocol = (uint8_t)n; - - if (a->curr[LTY_POLICY].p->protocol != 0xff) - break; - lws_strnncpy(dotstar, ctx->buf, ctx->npos, sizeof(dotstar)); - lwsl_err("%s: unknown protocol name %s\n", __func__, dotstar); - return -1; - } - - return 0; - -string2: - /* - * If we can do const string folding, reuse the existing string rather - * than make a new entry - */ - extant = lwsac_scan_extant(a->ac, (uint8_t *)ctx->buf, ctx->npos, 1); - if (extant) { - *pp = (char *)extant; - - return 0; - } - *pp = lwsac_use_backfill(&a->ac, ctx->npos + 1, POL_AC_GRAIN); - if (!*pp) - goto oom; - memcpy(*pp, ctx->buf, ctx->npos); - (*pp)[ctx->npos] = '\0'; - - return 0; - -string1: - n = ctx->st[ctx->sp].p; - *pp = lwsac_use_backfill(&a->ac, ctx->path_match_len + 1 - n, - POL_AC_GRAIN); - if (!*pp) - goto oom; - memcpy(*pp, ctx->path + n, ctx->path_match_len - n); - (*pp)[ctx->path_match_len - n] = '\0'; - - return 0; - -oom: - lwsl_err("%s: OOM\n", __func__); - lws_free_set_NULL(a->p); - lwsac_free(&a->ac); - - return -1; -} - -int -lws_ss_policy_parse_begin(struct lws_context *context) -{ - struct policy_cb_args *args; - char *p; - - args = lws_zalloc(sizeof(struct policy_cb_args), __func__); - if (!args) { - lwsl_err("%s: OOM\n", __func__); - - return 1; - } - - context->pol_args = args; - args->context = context; - p = lwsac_use(&args->ac, 1, POL_AC_INITIAL); - if (!p) { - lwsl_err("%s: OOM\n", __func__); - lws_free_set_NULL(context->pol_args); - - return -1; - } - *p = 0; - lejp_construct(&args->jctx, lws_ss_policy_parser_cb, args, - lejp_tokens_policy, LWS_ARRAY_SIZE(lejp_tokens_policy)); - - return 0; -} - -int -lws_ss_policy_parse_abandon(struct lws_context *context) -{ - struct policy_cb_args *args = (struct policy_cb_args *)context->pol_args; - - lejp_destruct(&args->jctx); - lws_free_set_NULL(context->pol_args); - - return 0; -} - -int -lws_ss_policy_parse(struct lws_context *context, const uint8_t *buf, size_t len) -{ - struct policy_cb_args *args = (struct policy_cb_args *)context->pol_args; - int m; - - m = (int)(signed char)lejp_parse(&args->jctx, buf, len); - if (m == LEJP_CONTINUE || m >= 0) - return m; - - lwsl_err("%s: parse failed: %d: %s\n", __func__, m, - lejp_error_to_string(m)); - lws_ss_policy_parse_abandon(context); - - return m; -} - -int -lws_ss_policy_set(struct lws_context *context, const char *name) -{ - struct policy_cb_args *args = (struct policy_cb_args *)context->pol_args; - struct lws_context_creation_info i; - lws_ss_trust_store_t *ts; - struct lws_vhost *v; - lws_ss_x509_t *x; - char buf[16]; - int m, ret = 0; - - /* - * Parsing seems to have succeeded, and we're going to use the new - * policy that's laid out in args->ac - */ - - lejp_destruct(&args->jctx); - - if (context->ac_policy) { - - /* - * So this is a bit fun-filled, we already had a policy in - * force, perhaps it was the default policy that's just good for - * fetching the real policy, and we're doing that now. - * - * We can destroy all the policy-related direct allocations - * easily because they're cleanly in a single lwsac... - */ - lwsac_free(&context->ac_policy); - - /* - * ...but when we did the trust stores, we created vhosts for - * each. We need to destroy those now too, and recreate new - * ones from the new policy, perhaps with different X.509s. - */ - - v = context->vhost_list; - while (v) { - if (v->from_ss_policy) { - struct lws_vhost *vh = v->vhost_next; - lwsl_debug("%s: destroying vh %p\n", __func__, v); - lws_vhost_destroy(v); - v = vh; - continue; - } - v = v->vhost_next; - } - - lws_check_deferred_free(context, 0, 1); - } - - context->pss_policies = args->heads[LTY_POLICY].p; - context->ac_policy = args->ac; - - lws_humanize(buf, sizeof(buf), lwsac_total_alloc(args->ac), - humanize_schema_si_bytes); - if (lwsac_total_alloc(args->ac)) - m = (int)((lwsac_total_overhead(args->ac) * 100) / - lwsac_total_alloc(args->ac)); - else - m = 0; - - lwsl_notice("%s: %s, pad %d%c: %s\n", __func__, buf, m, '%', name); - - /* Create vhosts for each type of trust store */ - - ts = args->heads[LTY_TRUSTSTORE].t; - while (ts) { - memset(&i, 0, sizeof(i)); - - /* - * We get called from context creation... instantiates - * vhosts with client tls contexts set up for each unique CA. - * - * Create the vhost with the first (mandatory) entry in the - * trust store... - */ - - v = lws_get_vhost_by_name(context, ts->name); - if (!v) { - int n; - - i.options = context->options; - i.vhost_name = ts->name; - lwsl_debug("%s: %s\n", __func__, i.vhost_name); - i.client_ssl_ca_mem = ts->ssx509[0]->ca_der; - i.client_ssl_ca_mem_len = ts->ssx509[0]->ca_der_len; - i.port = CONTEXT_PORT_NO_LISTEN; - lwsl_info("%s: %s trust store initial '%s'\n", __func__, - ts->name, ts->ssx509[0]->vhost_name); - - v = lws_create_vhost(context, &i); - if (!v) { - lwsl_err("%s: failed to create vhost %s\n", - __func__, ts->name); - ret = 1; - } else - v->from_ss_policy = 1; - - for (n = 1; v && n < ts->count; n++) { - lwsl_info("%s: add '%s' to trust store\n", - __func__, ts->ssx509[n]->vhost_name); - if (lws_tls_client_vhost_extra_cert_mem(v, - ts->ssx509[n]->ca_der, - ts->ssx509[n]->ca_der_len)) { - lwsl_err("%s: add extra cert failed\n", - __func__); - ret = 1; - } - } - } - - ts = ts->next; - } - if (!context->vhost_list) { - /* corner case... there's no trust store used */ - memset(&i, 0, sizeof(i)); - i.options = context->options; - i.vhost_name = "_ss_default"; - i.port = CONTEXT_PORT_NO_LISTEN; - v = lws_create_vhost(context, &i); - if (!v) - lwsl_err("%s: failed to create vhost %s\n", - __func__, i.vhost_name); - } -#if defined(LWS_WITH_SOCKS5) - - /* - * ... we need to go through every vhost updating its understanding of - * which socks5 proxy to use... - */ - - v = context->vhost_list; - while (v) { - lws_set_socks(v, args->socks5_proxy); - v = v->vhost_next; - } - if (context->vhost_system) - lws_set_socks(context->vhost_system, args->socks5_proxy); - - if (args->socks5_proxy) - lwsl_notice("%s: global socks5 proxy: %s\n", __func__, - args->socks5_proxy); -#endif - - /* now we processed the x.509 CAs, we can free all of our originals */ - - x = args->heads[LTY_X509].x; - while (x) { - /* - * Free all the DER buffers now they have been parsed into - * tls library X.509 objects - */ - lws_free((void *)x->ca_der); - x->ca_der = NULL; - x = x->next; - } - - /* and we can discard the parsing args object now, invalidating args */ - - lws_free_set_NULL(context->pol_args); - - return ret; -} - -const lws_ss_policy_t * -lws_ss_policy_lookup(const struct lws_context *context, const char *streamtype) -{ - const lws_ss_policy_t *p = context->pss_policies; - - if (!streamtype) - return NULL; - - while (p) { - if (!strcmp(p->streamtype, streamtype)) - return p; - p = p->next; - } - - return NULL; -} diff -Nru libwebsockets-4.0.20/lib/secure-streams/policy-common.c libwebsockets-4.1.6/lib/secure-streams/policy-common.c --- libwebsockets-4.0.20/lib/secure-streams/policy-common.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/secure-streams/policy-common.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,388 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + * This file contains the stuff related to secure streams policy, it's always + * built if LWS_WITH_SECURE_STREAMS enabled. + */ + +#include + +#if defined(LWS_WITH_SYS_SMD) +const lws_ss_policy_t pol_smd = { + .flags = 0, /* have to set something for windows */ +}; +#endif + +const lws_ss_policy_t * +lws_ss_policy_lookup(const struct lws_context *context, const char *streamtype) +{ + const lws_ss_policy_t *p = context->pss_policies; + + if (!streamtype) + return NULL; + +#if defined(LWS_WITH_SYS_SMD) + if (!strcmp(streamtype, LWS_SMD_STREAMTYPENAME)) + return &pol_smd; +#endif + + while (p) { + if (!strcmp(p->streamtype, streamtype)) + return p; + p = p->next; + } + + return NULL; +} + +int +lws_ss_set_metadata(struct lws_ss_handle *h, const char *name, + const void *value, size_t len) +{ + lws_ss_metadata_t *omd = lws_ss_policy_metadata(h->policy, name); + + if (!omd) { + lwsl_info("%s: unknown metadata %s\n", __func__, name); + return 1; + } + + h->metadata[omd->length].name = name; + h->metadata[omd->length].value = (void *)value; + h->metadata[omd->length].length = len; + + return 0; +} + +lws_ss_metadata_t * +lws_ss_get_handle_metadata(struct lws_ss_handle *h, const char *name) +{ + lws_ss_metadata_t *omd = lws_ss_policy_metadata(h->policy, name); + + if (!omd) + return NULL; + + return &h->metadata[omd->length]; +} + +lws_ss_metadata_t * +lws_ss_policy_metadata(const lws_ss_policy_t *p, const char *name) +{ + lws_ss_metadata_t *pmd = p->metadata; + + while (pmd) { + if (pmd->name && !strcmp(name, pmd->name)) + return pmd; + pmd = pmd->next; + } + + return NULL; +} + +lws_ss_metadata_t * +lws_ss_policy_metadata_index(const lws_ss_policy_t *p, size_t index) +{ + lws_ss_metadata_t *pmd = p->metadata; + + while (pmd) { + if (pmd->length == index) + return pmd; + pmd = pmd->next; + } + + return NULL; +} + +#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) +static int +fe_lws_ss_destroy(struct lws_dll2 *d, void *user) +{ + lws_ss_handle_t *h = lws_container_of(d, lws_ss_handle_t, list); + + lws_ss_destroy(&h); + + return 0; +} +#endif + +/* + * Dynamic policy: we want to one-time create the vhost for the policy and the + * trust store behind it. + * + * Static policy: We want to make use of a trust store / vhost from the policy and add to its + * ss-refcount. + */ + +struct lws_vhost * +lws_ss_policy_ref_trust_store(struct lws_context *context, + const lws_ss_policy_t *pol, char doref) +{ + struct lws_context_creation_info i; + struct lws_vhost *v; + int n; + + memset(&i, 0, sizeof(i)); + + if (!pol->trust.store) { + v = lws_get_vhost_by_name(context, "_ss_default"); + if (!v) { + /* corner case... there's no trust store used */ + i.options = context->options; + i.vhost_name = "_ss_default"; + i.port = CONTEXT_PORT_NO_LISTEN; + v = lws_create_vhost(context, &i); + if (!v) { + lwsl_err("%s: failed to create vhost %s\n", + __func__, i.vhost_name); + + return NULL; + } + } + + goto accepted; + } + v = lws_get_vhost_by_name(context, pol->trust.store->name); + if (v) { + lwsl_debug("%s: vh already exists\n", __func__); + goto accepted; + } + + i.options = context->options; + i.vhost_name = pol->trust.store->name; + lwsl_debug("%s: %s\n", __func__, i.vhost_name); +#if defined(LWS_WITH_TLS) && defined(LWS_WITH_CLIENT) + i.client_ssl_ca_mem = pol->trust.store->ssx509[0]->ca_der; + i.client_ssl_ca_mem_len = (unsigned int) + pol->trust.store->ssx509[0]->ca_der_len; +#endif + i.port = CONTEXT_PORT_NO_LISTEN; + lwsl_info("%s: %s trust store initial '%s'\n", __func__, + i.vhost_name, pol->trust.store->ssx509[0]->vhost_name); + + v = lws_create_vhost(context, &i); + if (!v) { + lwsl_err("%s: failed to create vhost %s\n", + __func__, i.vhost_name); + return NULL; + } else + v->from_ss_policy = 1; + + for (n = 1; v && n < pol->trust.store->count; n++) { + lwsl_info("%s: add '%s' to trust store\n", __func__, + pol->trust.store->ssx509[n]->vhost_name); +#if defined(LWS_WITH_TLS) + if (lws_tls_client_vhost_extra_cert_mem(v, + pol->trust.store->ssx509[n]->ca_der, + pol->trust.store->ssx509[n]->ca_der_len)) { + lwsl_err("%s: add extra cert failed\n", + __func__); + return NULL; + } +#endif + } + +accepted: +#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) + if (doref) + v->ss_refcount++; +#endif + + return v; +} + +#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) +int +lws_ss_policy_unref_trust_store(struct lws_context *context, + const lws_ss_policy_t *pol) +{ + struct lws_vhost *v; + const char *name = "_ss_default"; + + if (pol->trust.store) + name = pol->trust.store->name; + + v = lws_get_vhost_by_name(context, name); + if (!v || !v->from_ss_policy) + return 0; + + assert(v->ss_refcount); + + v->ss_refcount--; + if (!v->ss_refcount) { + lwsl_notice("%s: destroying vh %s\n", __func__, name); + lws_vhost_destroy(v); + } + + return 1; +} +#endif + +int +lws_ss_policy_set(struct lws_context *context, const char *name) +{ + int ret = 0; + +#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) + struct policy_cb_args *args = (struct policy_cb_args *)context->pol_args; + const lws_ss_policy_t *pol; + struct lws_vhost *v; + lws_ss_x509_t *x; + char buf[16]; + int m; + + /* + * Parsing seems to have succeeded, and we're going to use the new + * policy that's laid out in args->ac + */ + + lejp_destruct(&args->jctx); + + if (context->ac_policy) { + int n; + + /* + * any existing ss created with the old policy have to go away + * now, since they point to the shortly-to-be-destroyed old + * policy + */ + + for (n = 0; n < context->count_threads; n++) { + struct lws_context_per_thread *pt = &context->pt[n]; + + lws_dll2_foreach_safe(&pt->ss_owner, NULL, fe_lws_ss_destroy); + } + + /* + * So this is a bit fun-filled, we already had a policy in + * force, perhaps it was the default policy that's just good for + * fetching the real policy, and we're doing that now. + * + * We can destroy all the policy-related direct allocations + * easily because they're cleanly in a single lwsac... + */ + lwsac_free(&context->ac_policy); + + /* + * ...but when we did the trust stores, we created vhosts for + * each. We need to destroy those now too, and recreate new + * ones from the new policy, perhaps with different X.509s. + */ + + v = context->vhost_list; + while (v) { + if (v->from_ss_policy) { + struct lws_vhost *vh = v->vhost_next; + lwsl_debug("%s: destroying vh %p\n", __func__, v); + lws_vhost_destroy(v); + v = vh; + continue; + } + v = v->vhost_next; + } + + lws_check_deferred_free(context, 0, 1); + } + + context->pss_policies = args->heads[LTY_POLICY].p; + context->ac_policy = args->ac; + + lws_humanize(buf, sizeof(buf), lwsac_total_alloc(args->ac), + humanize_schema_si_bytes); + if (lwsac_total_alloc(args->ac)) + m = (int)((lwsac_total_overhead(args->ac) * 100) / + lwsac_total_alloc(args->ac)); + else + m = 0; + + (void)m; + lwsl_info("%s: %s, pad %d%c: %s\n", __func__, buf, m, '%', name); + + /* Create vhosts for each type of trust store */ + + /* + * We get called from context creation... instantiates + * vhosts with client tls contexts set up for each unique CA. + * + * We create the vhosts by walking streamtype list and create vhosts + * using trust store name if it's a client connection that doesn't + * already exist. + */ + + pol = context->pss_policies; + while (pol) { + if (!(pol->flags & LWSSSPOLF_SERVER)) { + v = lws_ss_policy_ref_trust_store(context, pol, + 0 /* no refcount inc */); + if (!v) + ret = 1; + } + + pol = pol->next; + } + +#if defined(LWS_WITH_SOCKS5) + + /* + * ... we need to go through every vhost updating its understanding of + * which socks5 proxy to use... + */ + + v = context->vhost_list; + while (v) { + lws_set_socks(v, args->socks5_proxy); + v = v->vhost_next; + } + if (context->vhost_system) + lws_set_socks(context->vhost_system, args->socks5_proxy); + + if (args->socks5_proxy) + lwsl_notice("%s: global socks5 proxy: %s\n", __func__, + args->socks5_proxy); +#endif + + /* + * For dynamic policy case, now we processed the x.509 CAs, we can free + * all of our originals. For static policy, they're in .rodata, nothing + * to free. + */ + + x = args->heads[LTY_X509].x; + while (x) { + /* + * Free all the client DER buffers now they have been parsed + * into tls library X.509 objects + */ + if (!x->keep) { /* used for server */ + lws_free((void *)x->ca_der); + x->ca_der = NULL; + } + + x = x->next; + } + + /* and we can discard the parsing args object now, invalidating args */ + + lws_free_set_NULL(context->pol_args); +#endif + + return ret; +} diff -Nru libwebsockets-4.0.20/lib/secure-streams/policy-json.c libwebsockets-4.1.6/lib/secure-streams/policy-json.c --- libwebsockets-4.0.20/lib/secure-streams/policy-json.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/secure-streams/policy-json.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,896 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + * This file contains the stuff related to JSON-provided policy, it's not built + * if LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY enabled. + */ + +#include + +static const char * const lejp_tokens_policy[] = { + "release", + "product", + "schema-version", + "via-socks5", + "retry[].*.backoff", + "retry[].*.conceal", + "retry[].*.jitterpc", + "retry[].*.svalidping", + "retry[].*.svalidhup", + "retry[].*", + "certs[].*", + "trust_stores[].name", + "trust_stores[].stack", + "s[].*.endpoint", + "s[].*.via-socks5", + "s[].*.protocol", + "s[].*.port", + "s[].*.plugins", + "s[].*.tls", + "s[].*.client_cert", + "s[].*.opportunistic", + "s[].*.nailed_up", + "s[].*.allow_redirects", + "s[].*.urgent_tx", + "s[].*.urgent_rx", + "s[].*.long_poll", + "s[].*.retry", + "s[].*.timeout_ms", + "s[].*.tls_trust_store", + "s[].*.metadata", + "s[].*.metadata[].*", + + "s[].*.http_auth_header", + "s[].*.http_dsn_header", + "s[].*.http_fwv_header", + "s[].*.http_devtype_header", + + "s[].*.http_auth_preamble", + + "s[].*.http_no_content_length", + "s[].*.rideshare", /* streamtype name this rides shotgun with */ + "s[].*.payload_fmt", + "s[].*.http_method", + "s[].*.http_url", + "s[].*.nghttp2_quirk_end_stream", + "s[].*.h2q_oflow_txcr", + "s[].*.http_multipart_name", + "s[].*.http_multipart_filename", + "s[].*.http_mime_content_type", + "s[].*.http_www_form_urlencoded", + "s[].*.http_expect", + "s[].*.http_fail_redirect", + "s[].*.http_multipart_ss_in", + "s[].*.ws_subprotocol", + "s[].*.ws_binary", + "s[].*.local_sink", + "s[].*.server", + "s[].*.server_cert", + "s[].*.server_key", + "s[].*.mqtt_topic", + "s[].*.mqtt_subscribe", + "s[].*.mqtt_qos", + "s[].*.mqtt_keep_alive", + "s[].*.mqtt_clean_start", + "s[].*.mqtt_will_topic", + "s[].*.mqtt_will_message", + "s[].*.mqtt_will_qos", + "s[].*.mqtt_will_retain", + "s[].*.swake_validity", + "s[].*", +}; + +typedef enum { + LSSPPT_RELEASE, + LSSPPT_PRODUCT, + LSSPPT_SCHEMA_VERSION, + LSSPPT_VIA_SOCKS5, + LSSPPT_BACKOFF, + LSSPPT_CONCEAL, + LSSPPT_JITTERPC, + LSSPPT_VALIDPING_S, + LSSPPT_VALIDHUP_S, + LSSPPT_RETRY, + LSSPPT_CERTS, + LSSPPT_TRUST_STORES_NAME, + LSSPPT_TRUST_STORES_STACK, + LSSPPT_ENDPOINT, + LSSPPT_VH_VIA_SOCKS5, + LSSPPT_PROTOCOL, + LSSPPT_PORT, + LSSPPT_PLUGINS, + LSSPPT_TLS, + LSSPPT_TLS_CLIENT_CERT, + LSSPPT_OPPORTUNISTIC, + LSSPPT_NAILED_UP, + LSSPPT_ALLOW_REDIRECTS, + LSSPPT_URGENT_TX, + LSSPPT_URGENT_RX, + LSSPPT_LONG_POLL, + LSSPPT_RETRYPTR, + LSSPPT_DEFAULT_TIMEOUT_MS, + LSSPPT_TRUST, + LSSPPT_METADATA, + LSSPPT_METADATA_ITEM, + + LSSPPT_HTTP_AUTH_HEADER, + LSSPPT_HTTP_DSN_HEADER, + LSSPPT_HTTP_FWV_HEADER, + LSSPPT_HTTP_TYPE_HEADER, + + LSSPPT_HTTP_AUTH_PREAMBLE, + LSSPPT_HTTP_NO_CONTENT_LENGTH, + LSSPPT_RIDESHARE, + LSSPPT_PAYLOAD_FORMAT, + LSSPPT_HTTP_METHOD, + LSSPPT_HTTP_URL, + LSSPPT_NGHTTP2_QUIRK_END_STREAM, + LSSPPT_H2_QUIRK_OVERFLOWS_TXCR, + LSSPPT_HTTP_MULTIPART_NAME, + LSSPPT_HTTP_MULTIPART_FILENAME, + LSSPPT_HTTP_MULTIPART_CONTENT_TYPE, + LSSPPT_HTTP_WWW_FORM_URLENCODED, + LSSPPT_HTTP_EXPECT, + LSSPPT_HTTP_FAIL_REDIRECT, + LSSPPT_HTTP_MULTIPART_SS_IN, + LSSPPT_WS_SUBPROTOCOL, + LSSPPT_WS_BINARY, + LSSPPT_LOCAL_SINK, + LSSPPT_SERVER, + LSSPPT_SERVER_CERT, + LSSPPT_SERVER_KEY, + LSSPPT_MQTT_TOPIC, + LSSPPT_MQTT_SUBSCRIBE, + LSSPPT_MQTT_QOS, + LSSPPT_MQTT_KEEPALIVE, + LSSPPT_MQTT_CLEAN_START, + LSSPPT_MQTT_WILL_TOPIC, + LSSPPT_MQTT_WILL_MESSAGE, + LSSPPT_MQTT_WILL_QOS, + LSSPPT_MQTT_WILL_RETAIN, + LSSPPT_SWAKE_VALIDITY, + LSSPPT_STREAMTYPES, + +} policy_token_t; + +#define POL_AC_INITIAL 2048 +#define POL_AC_GRAIN 800 +#define MAX_CERT_TEMP 3072 /* used to discover actual cert size for realloc */ + +static uint8_t sizes[] = { + sizeof(backoff_t), + sizeof(lws_ss_x509_t), + sizeof(lws_ss_trust_store_t), + sizeof(lws_ss_policy_t), +}; + +static const char *protonames[] = { + "h1", /* LWSSSP_H1 */ + "h2", /* LWSSSP_H2 */ + "ws", /* LWSSSP_WS */ + "mqtt", /* LWSSSP_MQTT */ + "raw", /* LWSSSP_RAW */ +}; + +static signed char +lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason) +{ + struct policy_cb_args *a = (struct policy_cb_args *)ctx->user; +#if defined(LWS_WITH_SSPLUGINS) + const lws_ss_plugin_t **pin; +#endif + char **pp, dotstar[32], *q; + lws_ss_trust_store_t *ts; + lws_ss_metadata_t *pmd; + lws_ss_x509_t *x, **py; + lws_ss_policy_t *p2; + lws_retry_bo_t *b; + size_t inl, outl; + uint8_t *extant; + backoff_t *bot; + int n = -1; + + lwsl_debug("%s: %d %d %s\n", __func__, reason, ctx->path_match - 1, + ctx->path); + + switch (ctx->path_match - 1) { + case LSSPPT_RETRY: + n = LTY_BACKOFF; + break; + case LSSPPT_CERTS: + n = LTY_X509; + break; + case LSSPPT_TRUST_STORES_NAME: + case LSSPPT_TRUST_STORES_STACK: + n = LTY_TRUSTSTORE; + break; + case LSSPPT_STREAMTYPES: + n = LTY_POLICY; + break; + } + + if (reason == LEJPCB_ARRAY_START && + (ctx->path_match - 1 == LSSPPT_PLUGINS || + ctx->path_match - 1 == LSSPPT_METADATA)) + a->count = 0; + + if (reason == LEJPCB_ARRAY_END && + ctx->path_match - 1 == LSSPPT_TRUST_STORES_STACK && !a->count) { + lwsl_err("%s: at least one cert required in trust store\n", + __func__); + goto oom; + } + + if (reason == LEJPCB_OBJECT_END && a->p) { + /* + * Allocate a just-the-right-size buf for the cert DER now + * we decoded it into the a->p temp buffer and know the exact + * size. + * + * The struct *x is in the lwsac... the ca_der it points to + * is individually allocated from the heap + */ + a->curr[LTY_X509].x->ca_der = lws_malloc(a->count, "ssx509"); + if (!a->curr[LTY_X509].x->ca_der) + goto oom; + memcpy((uint8_t *)a->curr[LTY_X509].x->ca_der, a->p, a->count); + a->curr[LTY_X509].x->ca_der_len = a->count; + + /* + * ... and then we can free the temp buffer + */ + lws_free_set_NULL(a->p); + + return 0; + } + + if (reason == LEJPCB_PAIR_NAME && n != -1 && n != LTY_TRUSTSTORE) { + + p2 = NULL; + if (n == LTY_POLICY) { + /* + * We want to allow for the possibility of overlays... + * eg, we come later with a JSON snippet that overrides + * select streamtype members of a streamtype that was + * already defined + */ + p2 = (lws_ss_policy_t *)a->context->pss_policies; + + while (p2) { + if (!strncmp(p2->streamtype, + ctx->path + ctx->st[ctx->sp].p, + ctx->path_match_len - + ctx->st[ctx->sp].p)) { + lwsl_info("%s: overriding s[] %s\n", + __func__, p2->streamtype); + break; + } + + p2 = p2->next; + } + } + + /* + * We do the pointers always as .b union member, all of the + * participating structs begin with .next and .name the same + */ + if (p2) /* we may be overriding existing streamtype... */ + a->curr[n].b = (backoff_t *)p2; + else + a->curr[n].b = lwsac_use_zero(&a->ac, sizes[n], POL_AC_GRAIN); + if (!a->curr[n].b) + goto oom; + + if (n == LTY_X509) { + a->p = lws_malloc(MAX_CERT_TEMP, "cert temp"); + if (!a->p) + goto oom; + memset(&a->b64, 0, sizeof(a->b64)); + } + + a->count = 0; + if (!p2) { + a->curr[n].b->next = a->heads[n].b; + a->heads[n].b = a->curr[n].b; + pp = (char **)&a->curr[n].b->name; + + goto string1; + } + + return 0; /* overriding */ + } + + if (!(reason & LEJP_FLAG_CB_IS_VALUE) || !ctx->path_match) + return 0; + + switch (ctx->path_match - 1) { + + /* strings */ + + case LSSPPT_RELEASE: + break; + + case LSSPPT_PRODUCT: + break; + + case LSSPPT_SCHEMA_VERSION: + break; + + case LSSPPT_VIA_SOCKS5: + /* the global / default proxy */ + pp = (char **)&a->socks5_proxy; + goto string2; + + case LSSPPT_BACKOFF: + b = &a->curr[LTY_BACKOFF].b->r; + if (b->retry_ms_table_count == 8) { + lwsl_err("%s: > 8 backoff levels\n", __func__); + return 1; + } + if (!b->retry_ms_table_count) { + b->retry_ms_table = (uint32_t *)lwsac_use_zero(&a->ac, + sizeof(uint32_t) * 8, POL_AC_GRAIN); + if (!b->retry_ms_table) + goto oom; + } + + ((uint32_t *)b->retry_ms_table) + [b->retry_ms_table_count++] = atoi(ctx->buf); + break; + + case LSSPPT_CONCEAL: + a->curr[LTY_BACKOFF].b->r.conceal_count = atoi(ctx->buf); + break; + + case LSSPPT_JITTERPC: + a->curr[LTY_BACKOFF].b->r.jitter_percent = atoi(ctx->buf); + break; + + case LSSPPT_VALIDPING_S: + a->curr[LTY_BACKOFF].b->r.secs_since_valid_ping = atoi(ctx->buf); + break; + + case LSSPPT_VALIDHUP_S: + a->curr[LTY_BACKOFF].b->r.secs_since_valid_hangup = atoi(ctx->buf); + break; + + case LSSPPT_CERTS: + if (a->count + ctx->npos >= MAX_CERT_TEMP) { + lwsl_err("%s: cert too big\n", __func__); + goto oom; + } + inl = ctx->npos; + outl = MAX_CERT_TEMP - a->count; + + lws_b64_decode_stateful(&a->b64, ctx->buf, &inl, + a->p + a->count, &outl, + reason == LEJPCB_VAL_STR_END); + a->count += (int)outl; + if (inl != ctx->npos) { + lwsl_err("%s: b64 decode fail\n", __func__); + goto oom; + } + break; + + case LSSPPT_TRUST_STORES_NAME: + /* + * We do the pointers always as .b, all of the participating + * structs begin with .next and .name + */ + a->curr[LTY_TRUSTSTORE].b = lwsac_use_zero(&a->ac, + sizes[LTY_TRUSTSTORE], POL_AC_GRAIN); + if (!a->curr[LTY_TRUSTSTORE].b) + goto oom; + + a->count = 0; + a->curr[LTY_TRUSTSTORE].b->next = a->heads[LTY_TRUSTSTORE].b; + a->heads[LTY_TRUSTSTORE].b = a->curr[LTY_TRUSTSTORE].b; + pp = (char **)&a->curr[LTY_TRUSTSTORE].b->name; + + goto string2; + + case LSSPPT_TRUST_STORES_STACK: + if (a->count >= (int)LWS_ARRAY_SIZE( + a->curr[LTY_TRUSTSTORE].t->ssx509)) { + lwsl_err("%s: trust store too big\n", __func__); + goto oom; + } + lwsl_debug("%s: trust stores stack %.*s\n", __func__, + ctx->npos, ctx->buf); + x = a->heads[LTY_X509].x; + while (x) { + if (!strncmp(x->vhost_name, ctx->buf, ctx->npos)) { + a->curr[LTY_TRUSTSTORE].t->ssx509[a->count++] = x; + a->curr[LTY_TRUSTSTORE].t->count++; + + return 0; + } + x = x->next; + } + lws_strnncpy(dotstar, ctx->buf, ctx->npos, sizeof(dotstar)); + lwsl_err("%s: unknown trust store entry %s\n", __func__, + dotstar); + goto oom; + + case LSSPPT_SERVER_CERT: + case LSSPPT_SERVER_KEY: + + /* iterate through the certs */ + + py = &a->heads[LTY_X509].x; + x = a->heads[LTY_X509].x; + while (x) { + if (!strncmp(x->vhost_name, ctx->buf, ctx->npos) && + !x->vhost_name[ctx->npos]) { + if ((ctx->path_match - 1) == LSSPPT_SERVER_CERT) + a->curr[LTY_POLICY].p->trust.server.cert = x; + else + a->curr[LTY_POLICY].p->trust.server.key = x; + /* + * Certs that are for servers need to stick + * around in DER form, so the vhost can be + * instantiated when the server is brought up + */ + x->keep = 1; + lwsl_notice("%s: server '%s' keep %d %p\n", + __func__, x->vhost_name, + ctx->path_match - 1, x); + + /* + * Server DER we need to move it to another + * list just for destroying it when the context + * is destroyed... snip us out of the live + * X.509 list + */ + + *py = x->next; + + /* + * ... and instead put us on the list of things + * to keep hold of for context destruction + */ + + x->next = a->context->server_der_list; + a->context->server_der_list = x; + + return 0; + } + py = &x->next; + x = x->next; + } + lws_strnncpy(dotstar, ctx->buf, ctx->npos, sizeof(dotstar)); + lwsl_err("%s: unknown cert / key %s\n", __func__, dotstar); + goto oom; + + case LSSPPT_ENDPOINT: + pp = (char **)&a->curr[LTY_POLICY].p->endpoint; + goto string2; + + case LSSPPT_VH_VIA_SOCKS5: + pp = (char **)&a->curr[LTY_POLICY].p->socks5_proxy; + goto string2; + + case LSSPPT_PORT: + a->curr[LTY_POLICY].p->port = atoi(ctx->buf); + break; + + case LSSPPT_HTTP_METHOD: + pp = (char **)&a->curr[LTY_POLICY].p->u.http.method; + goto string2; + + case LSSPPT_HTTP_URL: + pp = (char **)&a->curr[LTY_POLICY].p->u.http.url; + goto string2; + + case LSSPPT_RIDESHARE: + pp = (char **)&a->curr[LTY_POLICY].p->rideshare_streamtype; + goto string2; + + case LSSPPT_PAYLOAD_FORMAT: + pp = (char **)&a->curr[LTY_POLICY].p->payload_fmt; + goto string2; + + case LSSPPT_PLUGINS: +#if defined(LWS_WITH_SSPLUGINS) + pin = a->context->pss_plugins; + if (a->count == + (int)LWS_ARRAY_SIZE(a->curr[LTY_POLICY].p->plugins)) { + lwsl_err("%s: too many plugins\n", __func__); + + goto oom; + } + if (!pin) + break; + while (*pin) { + if (!strncmp((*pin)->name, ctx->buf, ctx->npos)) { + a->curr[LTY_POLICY].p->plugins[a->count++] = *pin; + return 0; + } + pin++; + } + lwsl_err("%s: unknown plugin\n", __func__); + goto oom; +#else + break; +#endif + + case LSSPPT_TLS: + if (reason == LEJPCB_VAL_TRUE) + a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_TLS; + break; + + case LSSPPT_TLS_CLIENT_CERT: + a->curr[LTY_POLICY].p->client_cert = atoi(ctx->buf) + 1; + break; + + case LSSPPT_HTTP_EXPECT: + a->curr[LTY_POLICY].p->u.http.resp_expect = atoi(ctx->buf); + break; + + case LSSPPT_DEFAULT_TIMEOUT_MS: + a->curr[LTY_POLICY].p->timeout_ms = atoi(ctx->buf); + break; + + case LSSPPT_OPPORTUNISTIC: + if (reason == LEJPCB_VAL_TRUE) + a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_OPPORTUNISTIC; + break; + case LSSPPT_NAILED_UP: + if (reason == LEJPCB_VAL_TRUE) + a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_NAILED_UP; + break; + case LSSPPT_URGENT_TX: + if (reason == LEJPCB_VAL_TRUE) + a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_URGENT_TX; + break; + case LSSPPT_URGENT_RX: + if (reason == LEJPCB_VAL_TRUE) + a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_URGENT_RX; + break; + case LSSPPT_LONG_POLL: + if (reason == LEJPCB_VAL_TRUE) + a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_LONG_POLL; + break; + case LSSPPT_HTTP_WWW_FORM_URLENCODED: + if (reason == LEJPCB_VAL_TRUE) + a->curr[LTY_POLICY].p->flags |= + LWSSSPOLF_HTTP_X_WWW_FORM_URLENCODED; + break; + case LSSPPT_SWAKE_VALIDITY: + if (reason == LEJPCB_VAL_TRUE) + a->curr[LTY_POLICY].p->flags |= + LWSSSPOLF_WAKE_SUSPEND__VALIDITY; + break; + case LSSPPT_ALLOW_REDIRECTS: + if (reason == LEJPCB_VAL_TRUE) + a->curr[LTY_POLICY].p->flags |= + LWSSSPOLF_ALLOW_REDIRECTS; + break; + case LSSPPT_HTTP_MULTIPART_SS_IN: + if (reason == LEJPCB_VAL_TRUE) + a->curr[LTY_POLICY].p->flags |= + LWSSSPOLF_HTTP_MULTIPART_IN; + return 0; + + case LSSPPT_RETRYPTR: + bot = a->heads[LTY_BACKOFF].b; + while (bot) { + if (!strncmp(ctx->buf, bot->name, ctx->npos)) { + a->curr[LTY_POLICY].p->retry_bo = &bot->r; + + return 0; + } + bot = bot->next; + } + lwsl_err("%s: unknown backoff scheme\n", __func__); + + return -1; + + case LSSPPT_TRUST: + ts = a->heads[LTY_TRUSTSTORE].t; + while (ts) { + if (!strncmp(ctx->buf, ts->name, ctx->npos)) { + a->curr[LTY_POLICY].p->trust.store = ts; + return 0; + } + ts = ts->next; + } + lws_strnncpy(dotstar, ctx->buf, ctx->npos, sizeof(dotstar)); + lwsl_err("%s: unknown trust store name %s\n", __func__, + dotstar); + + return -1; + + case LSSPPT_METADATA: + break; + + case LSSPPT_METADATA_ITEM: + pmd = a->curr[LTY_POLICY].p->metadata; + a->curr[LTY_POLICY].p->metadata = lwsac_use_zero(&a->ac, + sizeof(lws_ss_metadata_t) + ctx->npos + + (ctx->path_match_len - ctx->st[ctx->sp - 2].p + 1) + 2, + POL_AC_GRAIN); + a->curr[LTY_POLICY].p->metadata->next = pmd; + + q = (char *)a->curr[LTY_POLICY].p->metadata + + sizeof(lws_ss_metadata_t); + a->curr[LTY_POLICY].p->metadata->name = q; + memcpy(q, ctx->path + ctx->st[ctx->sp - 2].p + 1, + ctx->path_match_len - ctx->st[ctx->sp - 2].p); + + q += ctx->path_match_len - ctx->st[ctx->sp - 2].p; + a->curr[LTY_POLICY].p->metadata->value = q; + memcpy(q, ctx->buf, ctx->npos); + + a->curr[LTY_POLICY].p->metadata->length = /* the index in handle->metadata */ + a->curr[LTY_POLICY].p->metadata_count++; + break; + +#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) + case LSSPPT_HTTP_AUTH_HEADER: + case LSSPPT_HTTP_DSN_HEADER: + case LSSPPT_HTTP_FWV_HEADER: + case LSSPPT_HTTP_TYPE_HEADER: + pp = (char **)&a->curr[LTY_POLICY].p->u.http.blob_header[ + (ctx->path_match - 1) - LSSPPT_HTTP_AUTH_HEADER]; + goto string2; + + case LSSPPT_HTTP_AUTH_PREAMBLE: + pp = (char **)&a->curr[LTY_POLICY].p->u.http.auth_preamble; + goto string2; + + case LSSPPT_HTTP_NO_CONTENT_LENGTH: + if (reason == LEJPCB_VAL_TRUE) + a->curr[LTY_POLICY].p->flags |= + LWSSSPOLF_HTTP_NO_CONTENT_LENGTH; + break; + + case LSSPPT_NGHTTP2_QUIRK_END_STREAM: + if (reason == LEJPCB_VAL_TRUE) + a->curr[LTY_POLICY].p->flags |= + LWSSSPOLF_QUIRK_NGHTTP2_END_STREAM; + break; + case LSSPPT_H2_QUIRK_OVERFLOWS_TXCR: + if (reason == LEJPCB_VAL_TRUE) + a->curr[LTY_POLICY].p->flags |= + LWSSSPOLF_H2_QUIRK_OVERFLOWS_TXCR; + break; + case LSSPPT_HTTP_MULTIPART_NAME: + a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_HTTP_MULTIPART; + pp = (char **)&a->curr[LTY_POLICY].p->u.http.multipart_name; + goto string2; + case LSSPPT_HTTP_MULTIPART_FILENAME: + a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_HTTP_MULTIPART; + pp = (char **)&a->curr[LTY_POLICY].p->u.http.multipart_filename; + goto string2; + case LSSPPT_HTTP_MULTIPART_CONTENT_TYPE: + a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_HTTP_MULTIPART; + pp = (char **)&a->curr[LTY_POLICY].p->u.http.multipart_content_type; + goto string2; + + case LSSPPT_HTTP_FAIL_REDIRECT: + a->curr[LTY_POLICY].p->u.http.fail_redirect = + reason == LEJPCB_VAL_TRUE; + break; +#endif + +#if defined(LWS_ROLE_WS) + + case LSSPPT_WS_SUBPROTOCOL: + pp = (char **)&a->curr[LTY_POLICY].p->u.http.u.ws.subprotocol; + goto string2; + + case LSSPPT_WS_BINARY: + a->curr[LTY_POLICY].p->u.http.u.ws.binary = + reason == LEJPCB_VAL_TRUE; + break; +#endif + + case LSSPPT_LOCAL_SINK: + if (reason == LEJPCB_VAL_TRUE) + a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_LOCAL_SINK; + break; + + case LSSPPT_SERVER: + if (reason == LEJPCB_VAL_TRUE) + a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_SERVER; + break; + +#if defined(LWS_ROLE_MQTT) + case LSSPPT_MQTT_TOPIC: + pp = (char **)&a->curr[LTY_POLICY].p->u.mqtt.topic; + goto string2; + + case LSSPPT_MQTT_SUBSCRIBE: + pp = (char **)&a->curr[LTY_POLICY].p->u.mqtt.subscribe; + goto string2; + + case LSSPPT_MQTT_QOS: + a->curr[LTY_POLICY].p->u.mqtt.qos = atoi(ctx->buf); + break; + + case LSSPPT_MQTT_KEEPALIVE: + a->curr[LTY_POLICY].p->u.mqtt.keep_alive = atoi(ctx->buf); + break; + + case LSSPPT_MQTT_CLEAN_START: + a->curr[LTY_POLICY].p->u.mqtt.clean_start = + reason == LEJPCB_VAL_TRUE; + break; + case LSSPPT_MQTT_WILL_TOPIC: + pp = (char **)&a->curr[LTY_POLICY].p->u.mqtt.will_topic; + goto string2; + + case LSSPPT_MQTT_WILL_MESSAGE: + pp = (char **)&a->curr[LTY_POLICY].p->u.mqtt.will_message; + goto string2; + + case LSSPPT_MQTT_WILL_QOS: + a->curr[LTY_POLICY].p->u.mqtt.will_qos = atoi(ctx->buf); + break; + case LSSPPT_MQTT_WILL_RETAIN: + a->curr[LTY_POLICY].p->u.mqtt.will_retain = + reason == LEJPCB_VAL_TRUE; + break; +#endif + + case LSSPPT_PROTOCOL: + a->curr[LTY_POLICY].p->protocol = 0xff; + for (n = 0; n < (int)LWS_ARRAY_SIZE(protonames); n++) + if (strlen(protonames[n]) == ctx->npos && + !strncmp(ctx->buf, protonames[n], ctx->npos)) + a->curr[LTY_POLICY].p->protocol = (uint8_t)n; + + if (a->curr[LTY_POLICY].p->protocol != 0xff) + break; + lws_strnncpy(dotstar, ctx->buf, ctx->npos, sizeof(dotstar)); + lwsl_err("%s: unknown protocol name %s\n", __func__, dotstar); + return -1; + + default: + break; + } + + return 0; + +string2: + /* + * If we can do const string folding, reuse the existing string rather + * than make a new entry + */ + extant = lwsac_scan_extant(a->ac, (uint8_t *)ctx->buf, ctx->npos, 1); + if (extant) { + *pp = (char *)extant; + + return 0; + } + *pp = lwsac_use_backfill(&a->ac, ctx->npos + 1, POL_AC_GRAIN); + if (!*pp) + goto oom; + memcpy(*pp, ctx->buf, ctx->npos); + (*pp)[ctx->npos] = '\0'; + + return 0; + +string1: + n = ctx->st[ctx->sp].p; + *pp = lwsac_use_backfill(&a->ac, ctx->path_match_len + 1 - n, + POL_AC_GRAIN); + if (!*pp) + goto oom; + memcpy(*pp, ctx->path + n, ctx->path_match_len - n); + (*pp)[ctx->path_match_len - n] = '\0'; + + return 0; + +oom: + lwsl_err("%s: OOM\n", __func__); + lws_free_set_NULL(a->p); + lwsac_free(&a->ac); + + return -1; +} + +int +lws_ss_policy_parse_begin(struct lws_context *context, int overlay) +{ + struct policy_cb_args *args; + char *p; + + args = lws_zalloc(sizeof(struct policy_cb_args), __func__); + if (!args) { + lwsl_err("%s: OOM\n", __func__); + + return 1; + } + if (overlay) + /* continue to use the existing lwsac */ + args->ac = context->ac_policy; + else + /* we don't want to see any old policy */ + context->pss_policies = NULL; + + context->pol_args = args; + args->context = context; + p = lwsac_use(&args->ac, 1, POL_AC_INITIAL); + if (!p) { + lwsl_err("%s: OOM\n", __func__); + lws_free_set_NULL(context->pol_args); + + return -1; + } + *p = 0; + lejp_construct(&args->jctx, lws_ss_policy_parser_cb, args, + lejp_tokens_policy, LWS_ARRAY_SIZE(lejp_tokens_policy)); + + return 0; +} + +int +lws_ss_policy_parse_abandon(struct lws_context *context) +{ + struct policy_cb_args *args = (struct policy_cb_args *)context->pol_args; + + lejp_destruct(&args->jctx); + lwsac_free(&args->ac); + lws_free_set_NULL(context->pol_args); + + return 0; +} + +int +lws_ss_policy_parse(struct lws_context *context, const uint8_t *buf, size_t len) +{ + struct policy_cb_args *args = (struct policy_cb_args *)context->pol_args; + int m; + + m = lejp_parse(&args->jctx, buf, (int)len); + if (m == LEJP_CONTINUE || m >= 0) + return m; + + lwsl_err("%s: parse failed line %u: %d: %s\n", __func__, + (unsigned int)args->jctx.line, m, lejp_error_to_string(m)); + lws_ss_policy_parse_abandon(context); + assert(0); + + return m; +} + +int +lws_ss_policy_overlay(struct lws_context *context, const char *overlay) +{ + lws_ss_policy_parse_begin(context, 1); + return lws_ss_policy_parse(context, (const uint8_t *)overlay, + strlen(overlay)); +} + +const lws_ss_policy_t * +lws_ss_policy_get(struct lws_context *context) +{ + struct policy_cb_args *args = (struct policy_cb_args *)context->pol_args; + + if (!args) + return NULL; + + return args->heads[LTY_POLICY].p; +} diff -Nru libwebsockets-4.0.20/lib/secure-streams/private-lib-secure-streams.h libwebsockets-4.1.6/lib/secure-streams/private-lib-secure-streams.h --- libwebsockets-4.0.20/lib/secure-streams/private-lib-secure-streams.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/secure-streams/private-lib-secure-streams.h 2020-12-01 17:40:26.000000000 +0000 @@ -54,15 +54,18 @@ struct lws_sequencer *seq; /**< owning sequencer if any */ struct lws *wsi; /**< the stream wsi if any */ +#if defined(LWS_WITH_SSPLUGINS) void *nauthi; /**< the nauth plugin instance data */ void *sauthi; /**< the sauth plugin instance data */ +#endif lws_ss_metadata_t *metadata; const lws_ss_policy_t *rideshare; - struct lws_ss_handle *h_sink; /**< sink we are bound to, or NULL */ - void *sink_obj;/**< sink's private object representing us */ + //struct lws_ss_handle *h_sink; /**< sink we are bound to, or NULL */ + //void *sink_obj;/**< sink's private object representing us */ + lws_sorted_usec_list_t sul_timeout; lws_sorted_usec_list_t sul; lws_ss_tx_ordinal_t txord; @@ -92,10 +95,19 @@ union { struct { /* LWSSSP_H1 */ +#if defined(WIN32) + uint8_t dummy; +#endif } h1; struct { /* LWSSSP_H2 */ +#if defined(WIN32) + uint8_t dummy; +#endif } h2; struct { /* LWSSSP_WS */ +#if defined(WIN32) + uint8_t dummy; +#endif } ws; } u; } http; @@ -106,8 +118,18 @@ lws_mqtt_topic_elem_t topic_qos; lws_mqtt_topic_elem_t sub_top; lws_mqtt_subscribe_param_t sub_info; + /* allocation that must be destroyed with conn */ + void *heap_baggage; + const char *subscribe_to; + size_t subscribe_to_len; } mqtt; #endif +#if defined(LWS_WITH_SYS_SMD) + struct { + struct lws_smd_peer *smd_peer; + lws_sorted_usec_list_t sul_write; + } smd; +#endif } u; unsigned long writeable_len; @@ -115,6 +137,10 @@ lws_ss_constate_t connstate;/**< public connection state */ lws_ss_seq_state_t seqstate; /**< private connection state */ +#if defined(LWS_WITH_SERVER) + int txn_resp; +#endif + uint16_t retry; /**< retry / backoff tracking */ int16_t temp16; @@ -122,9 +148,12 @@ uint8_t subseq; /**< emulate SOM tracking */ uint8_t txn_ok; /**< 1 = transaction was OK */ + uint8_t txn_resp_set:1; /**< user code set one */ + uint8_t txn_resp_pending:1; /**< we have yet to send */ uint8_t hanging_som:1; uint8_t inside_msg:1; uint8_t being_serialized:1; /* we are not the consumer */ + uint8_t destroying:1; } lws_ss_handle_t; /* connection helper that doesn't need to hang around after connection starts */ @@ -132,6 +161,10 @@ union lws_ss_contemp { #if defined(LWS_ROLE_MQTT) lws_mqtt_client_connect_param_t ccp; +#else +#if defined(WIN32) + uint8_t dummy; +#endif #endif }; @@ -209,6 +242,14 @@ /* the value of length .len is overallocated after this */ } lws_sspc_metadata_t; +/* state of the upstream proxy onward connection */ + +enum { + LWSSSPC_ONW_NONE, + LWSSSPC_ONW_REQ, + LWSSSPC_ONW_ONGOING, + LWSSSPC_ONW_CONN, +}; typedef struct lws_sspc_handle { char rideshare_list[128]; @@ -229,19 +270,79 @@ lws_usec_t us_earliest_write_req; - lws_ss_conn_states_t state; + unsigned long writeable_len; - int16_t temp16; + lws_ss_conn_states_t state; + uint32_t timeout_ms; uint32_t ord; + int16_t temp16; + uint8_t rideshare_ofs[4]; - uint8_t conn_req; uint8_t rsidx; + uint8_t conn_req_state:2; uint8_t destroying:1; + uint8_t non_wsi:1; + uint8_t ignore_txc:1; + uint8_t pending_timeout_update:1; + uint8_t pending_writeable_len:1; + uint8_t creating_cb_done:1; } lws_sspc_handle_t; +typedef struct backoffs { + struct backoffs *next; + const char *name; + lws_retry_bo_t r; +} backoff_t; + +union u { + backoff_t *b; + lws_ss_x509_t *x; + lws_ss_trust_store_t *t; + lws_ss_policy_t *p; +}; + +enum { + LTY_BACKOFF, + LTY_X509, + LTY_TRUSTSTORE, + LTY_POLICY, + + _LTY_COUNT /* always last */ +}; + + +struct policy_cb_args { + struct lejp_ctx jctx; + struct lws_context *context; + struct lwsac *ac; + + const char *socks5_proxy; + + struct lws_b64state b64; + + union u heads[_LTY_COUNT]; + union u curr[_LTY_COUNT]; + + uint8_t *p; + + int count; +}; + +#if defined(LWS_WITH_SYS_SMD) +extern const lws_ss_policy_t pol_smd; +#endif + + +/* + * returns one of + * + * LWSSSSRET_OK + * LWSSSSRET_DISCONNECT_ME + * LWSSSSRET_DESTROY_ME + */ int lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, struct lws_context *context, @@ -272,29 +373,23 @@ int lws_sspc_destroy_dll(struct lws_dll2 *d, void *user); - -int -lws_ss_policy_parse_begin(struct lws_context *context); - -int -lws_ss_policy_parse(struct lws_context *context, const uint8_t *buf, size_t len); - int lws_ss_policy_set(struct lws_context *context, const char *name); int -lws_ss_policy_parse_abandon(struct lws_context *context); - -int lws_ss_sys_fetch_policy(struct lws_context *context); -int +lws_ss_state_return_t lws_ss_event_helper(lws_ss_handle_t *h, lws_ss_constate_t cs); -int +lws_ss_state_return_t lws_ss_backoff(lws_ss_handle_t *h); int +_lws_ss_handle_state_ret(lws_ss_state_return_t r, struct lws *wsi, + lws_ss_handle_t **ph); + +int lws_ss_set_timeout_us(lws_ss_handle_t *h, lws_usec_t us); void @@ -321,6 +416,16 @@ int _lws_ss_client_connect(lws_ss_handle_t *h, int is_retry); +struct lws_vhost * +lws_ss_policy_ref_trust_store(struct lws_context *context, + const lws_ss_policy_t *pol, char doref); + +#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) +int +lws_ss_policy_unref_trust_store(struct lws_context *context, + const lws_ss_policy_t *pol); +#endif + int lws_ss_sys_cpd(struct lws_context *cx); @@ -335,19 +440,21 @@ struct ss_pcols { const char *name; const char *alpn; - const char *protocol_name; - const secstream_protocol_connect_munge_t munge; - const secstream_protocol_add_txcr_t tx_cr_add; - const secstream_protocol_get_txcr_t tx_cr_est; + const struct lws_protocols *protocol; + secstream_protocol_connect_munge_t munge; + secstream_protocol_add_txcr_t tx_cr_add; + secstream_protocol_get_txcr_t tx_cr_est; }; extern const struct ss_pcols ss_pcol_h1; extern const struct ss_pcols ss_pcol_h2; extern const struct ss_pcols ss_pcol_ws; extern const struct ss_pcols ss_pcol_mqtt; +extern const struct ss_pcols ss_pcol_raw; extern const struct lws_protocols protocol_secstream_h1; extern const struct lws_protocols protocol_secstream_h2; extern const struct lws_protocols protocol_secstream_ws; extern const struct lws_protocols protocol_secstream_mqtt; +extern const struct lws_protocols protocol_secstream_raw; diff -Nru libwebsockets-4.0.20/lib/secure-streams/protocols/ss-h1.c libwebsockets-4.1.6/lib/secure-streams/protocols/ss-h1.c --- libwebsockets-4.0.20/lib/secure-streams/protocols/ss-h1.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/secure-streams/protocols/ss-h1.c 2020-12-01 17:40:26.000000000 +0000 @@ -152,6 +152,58 @@ } #endif +static int +lws_apply_metadata(lws_ss_handle_t *h, struct lws *wsi, uint8_t *buf, + uint8_t **pp, uint8_t *end) +{ + int m; + + for (m = 0; m < h->policy->metadata_count; m++) { + lws_ss_metadata_t *polmd; + + /* has to have a header string listed */ + if (!h->metadata[m].value) + continue; + + polmd = lws_ss_policy_metadata_index(h->policy, m); + + assert(polmd); + if (!polmd) + return -1; + + /* has to have a value */ + if (polmd->value && ((uint8_t *)polmd->value)[0]) { + if (lws_add_http_header_by_name(wsi, + polmd->value, + h->metadata[m].value, + (int)h->metadata[m].length, pp, end)) + return -1; + } + } + + /* + * Content-length on POST / PUT if we have the length information + */ + + if (h->policy->u.http.method && ( + (!strcmp(h->policy->u.http.method, "POST") || + !strcmp(h->policy->u.http.method, "PUT"))) && + wsi->http.writeable_len) { + if (!(h->policy->flags & + LWSSSPOLF_HTTP_NO_CONTENT_LENGTH)) { + int n = lws_snprintf((char *)buf, 20, "%u", + (unsigned int)wsi->http.writeable_len); + if (lws_add_http_header_by_token(wsi, + WSI_TOKEN_HTTP_CONTENT_LENGTH, + buf, n, pp, end)) + return -1; + } + lws_client_http_body_pending(wsi, 1); + } + + return 0; +} + static const uint8_t blob_idx[] = { LWS_SYSBLOB_TYPE_AUTH, LWS_SYSBLOB_TYPE_DEVICE_SERIAL, @@ -165,41 +217,67 @@ { lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); uint8_t buf[LWS_PRE + 1520], *p = &buf[LWS_PRE], +#if defined(LWS_WITH_SERVER) + *start = p, +#endif *end = &buf[sizeof(buf) - 1]; - int f = 0, m, status, txr; + lws_ss_state_return_t r; + int f = 0, m, status; char conceal_eom = 0; size_t buflen; switch (reason) { - /* because we are protocols[0] ... */ case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: - assert(h); + if (!h) + break; assert(h->policy); lwsl_info("%s: h: %p, %s CLIENT_CONNECTION_ERROR: %s\n", __func__, h, h->policy->streamtype, in ? (char *)in : "(null)"); - lws_ss_event_helper(h, LWSSSCS_UNREACHABLE); + /* already disconnected, no action for DISCONNECT_ME */ + r = lws_ss_event_helper(h, LWSSSCS_UNREACHABLE); + if (r) + return _lws_ss_handle_state_ret(r, wsi, &h); + h->wsi = NULL; - lws_ss_backoff(h); + r = lws_ss_backoff(h); + if (r != LWSSSSRET_OK) + return _lws_ss_handle_state_ret(r, wsi, &h); break; + case LWS_CALLBACK_CLIENT_HTTP_REDIRECT: + if (h->policy->u.http.fail_redirect) + lws_system_cpd_set(lws_get_context(wsi), + LWS_CPD_CAPTIVE_PORTAL); + /* unless it's explicitly allowed, reject to follow it */ + return !(h->policy->flags & LWSSSPOLF_ALLOW_REDIRECTS); + + case LWS_CALLBACK_CLOSED_HTTP: /* server */ case LWS_CALLBACK_CLOSED_CLIENT_HTTP: if (!h) break; + + lws_sul_cancel(&h->sul_timeout); lwsl_info("%s: h: %p, %s LWS_CALLBACK_CLOSED_CLIENT_HTTP\n", __func__, h, h->policy ? h->policy->streamtype : "no policy"); h->wsi = NULL; - //bad = status != 200; - //lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ + if (h->policy && !(h->policy->flags & LWSSSPOLF_OPPORTUNISTIC) && - !h->txn_ok && !wsi->context->being_destroyed) - lws_ss_backoff(h); - else +#if defined(LWS_WITH_SERVER) + !(h->info.flags & LWSSSINFLAGS_ACCEPTED) && /* not server */ +#endif + !h->txn_ok && !wsi->a.context->being_destroyed) { + r = lws_ss_backoff(h); + if (r != LWSSSSRET_OK) + return _lws_ss_handle_state_ret(r, wsi, &h); + break; + } else h->seqstate = SSSEQ_IDLE; - - if (lws_ss_event_helper(h, LWSSSCS_DISCONNECTED)) - lws_ss_destroy(&h); + /* already disconnected, no action for DISCONNECT_ME */ + r = lws_ss_event_helper(h, LWSSSCS_DISCONNECTED); + if (r != LWSSSSRET_OK) + return _lws_ss_handle_state_ret(r, wsi, &h); break; @@ -209,22 +287,32 @@ // if (!status) /* it's just telling use we connected / joined the nwsi */ // break; - h->u.http.good_respcode = (status >= 200 && status < 300); + + if (h->policy->u.http.resp_expect) + h->u.http.good_respcode = + status == h->policy->u.http.resp_expect; + else + h->u.http.good_respcode = (status >= 200 && status < 300); // lwsl_err("%s: good resp %d %d\n", __func__, status, h->u.http.good_respcode); if (h->u.http.good_respcode) lwsl_info("%s: Connected streamtype %s, %d\n", __func__, h->policy->streamtype, status); else - lwsl_warn("%s: Connected streamtype %s, BAD %d\n", __func__, - h->policy->streamtype, status); + if (h->u.http.good_respcode) + lwsl_warn("%s: Connected streamtype %s, BAD %d\n", + __func__, h->policy->streamtype, + status); h->hanging_som = 0; h->retry = 0; h->seqstate = SSSEQ_CONNECTED; - lws_ss_set_timeout_us(h, LWS_SET_TIMER_USEC_CANCEL); - lws_ss_event_helper(h, LWSSSCS_CONNECTED); + lws_sul_cancel(&h->sul); + + r = lws_ss_event_helper(h, LWSSSCS_CONNECTED); + if (r != LWSSSSRET_OK) + return _lws_ss_handle_state_ret(r, wsi, &h); /* * Since it's an http transaction we initiated... this is @@ -234,6 +322,14 @@ #if defined(LWS_WITH_SS_RIDESHARE) + /* + * There are two ways we might want to deal with multipart, + * one is pass it through raw (although the user code needs + * a helping hand for learning the boundary), and the other + * is to deframe it and provide basically submessages in the + * different parts. + */ + if (lws_hdr_copy(wsi, (char *)buf, sizeof(buf), WSI_TOKEN_HTTP_CONTENT_TYPE) > 0 && /* multipart/form-data; @@ -269,7 +365,8 @@ lws_strnncpy(h->u.http.boundary + 4, ts.token, ts.token_len, sizeof(h->u.http.boundary) - 4); - h->u.http.boundary_len = ts.token_len + 4; + h->u.http.boundary_len = + (uint8_t)(ts.token_len + 4); h->u.http.boundary_seq = 2; h->u.http.boundary_dashes = 0; } @@ -279,7 +376,8 @@ /* inform the ss that a related message group begins */ - if (h->u.http.boundary[0]) + if ((h->policy->flags & LWSSSPOLF_HTTP_MULTIPART_IN) && + h->u.http.boundary[0]) h->info.rx(ss_to_userobj(h), NULL, 0, LWSSS_FLAG_RELATED_START); @@ -306,6 +404,7 @@ */ for (m = 0; m < _LWSSS_HBI_COUNT; m++) { + lws_system_blob_t *ab; int o = 0, n; if (!h->policy->u.http.blob_header[m]) @@ -319,10 +418,12 @@ if (o > (int)sizeof(buf) - 2) return -1; + ab = lws_system_get_blob(wsi->a.context, blob_idx[m], 0); + if (!ab) + return -1; + buflen = sizeof(buf) - o - 2; - n = lws_system_blob_get( - lws_system_get_blob(wsi->context, blob_idx[m], 0), - buf + o, &buflen, 0); + n = lws_system_blob_get(ab, buf + o, &buflen, 0); if (n < 0) return -1; @@ -330,8 +431,8 @@ lwsl_debug("%s: adding blob %d: %s\n", __func__, m, buf); if (lws_add_http_header_by_name(wsi, - (uint8_t *)h->policy->u.http.blob_header[m], - buf, buflen + o, p, end)) + (uint8_t *)h->policy->u.http.blob_header[m], + buf, (int)(buflen + o), p, end)) return -1; } @@ -339,62 +440,43 @@ * metadata-based headers */ - for (m = 0; m < h->policy->metadata_count; m++) { - lws_ss_metadata_t *polmd; - - /* has to have a header string listed */ - if (!h->metadata[m].value) - continue; + if (lws_apply_metadata(h, wsi, buf, p, end)) + return -1; - polmd = lws_ss_policy_metadata_index(h->policy, m); + (void)oin; + // if (*p != oin) + // lwsl_hexdump_notice(oin, lws_ptr_diff(*p, oin)); - assert(polmd); - /* has to have a value */ - if (polmd->value && ((uint8_t *)polmd->value)[0]) { - if (lws_add_http_header_by_name(wsi, - polmd->value, - h->metadata[m].value, - h->metadata[m].length, p, end)) - return -1; - } } /* - * Content-length on POST / PUT if we have the length information + * So when proxied, for POST we have to synthesize a CONNECTED + * state, so it can request a writeable and deliver the POST + * body */ - - if ((!strcmp(h->policy->u.http.method, "POST") || - !strcmp(h->policy->u.http.method, "PUT")) && - wsi->http.writeable_len) { - if (!(h->policy->flags & - LWSSSPOLF_HTTP_NO_CONTENT_LENGTH)) { - int n = lws_snprintf((char *)buf, 20, "%u", - (unsigned int)wsi->http.writeable_len); - if (lws_add_http_header_by_token(wsi, - WSI_TOKEN_HTTP_CONTENT_LENGTH, - buf, n, p, end)) - return -1; - } - lws_client_http_body_pending(wsi, 1); - } - - (void)oin; - // if (*p != oin) - // lwsl_hexdump_notice(oin, lws_ptr_diff(*p, oin)); - + if ((h->policy->protocol == LWSSSP_H1 || + h->policy->protocol == LWSSSP_H2) && + h->being_serialized && ( + !strcmp(h->policy->u.http.method, "PUT") || + !strcmp(h->policy->u.http.method, "POST"))) { + r = lws_ss_event_helper(h, LWSSSCS_CONNECTED); + if (r) + return _lws_ss_handle_state_ret(r, wsi, &h); } break; /* chunks of chunked content, with header removed */ + case LWS_CALLBACK_HTTP_BODY: case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: lwsl_debug("%s: RECEIVE_CLIENT_HTTP_READ: read %d\n", __func__, (int)len); - if (!h) + if (!h || !h->info.rx) return 0; #if defined(LWS_WITH_SS_RIDESHARE) - if (h->u.http.boundary[0]) + if ((h->policy->flags & LWSSSPOLF_HTTP_MULTIPART_IN) && + h->u.http.boundary[0]) return ss_http_multipart_parser(h, in, len); #endif @@ -407,8 +489,9 @@ // lwsl_notice("%s: HTTP_READ: client side sent len %d fl 0x%x\n", // __func__, (int)len, (int)f); - if (h->info.rx(ss_to_userobj(h), (const uint8_t *)in, len, f) < 0) - return -1; + r = h->info.rx(ss_to_userobj(h), (const uint8_t *)in, len, f); + if (r != LWSSSSRET_OK) + return _lws_ss_handle_state_ret(r, wsi, &h); return 0; /* don't passthru */ @@ -418,8 +501,9 @@ char *px = (char *)buf + LWS_PRE; /* guarantees LWS_PRE */ int lenx = sizeof(buf) - LWS_PRE; - if (lws_http_client_read(wsi, &px, &lenx) < 0) - return -1; + m = lws_http_client_read(wsi, &px, &lenx); + if (m < 0) + return m; } lws_set_timeout(wsi, 99, 30); @@ -431,28 +515,75 @@ h->info.rx(ss_to_userobj(h), NULL, 0, LWSSS_FLAG_EOM); wsi->http.writeable_len = h->writeable_len = 0; + lws_sul_cancel(&h->sul_timeout); - if (h->u.http.good_respcode) - lws_ss_event_helper(h, LWSSSCS_QOS_ACK_REMOTE); - else - lws_ss_event_helper(h, LWSSSCS_QOS_NACK_REMOTE); - - h->wsi = NULL; h->txn_ok = 1; - //bad = status != 200; + + r = lws_ss_event_helper(h, h->u.http.good_respcode ? + LWSSSCS_QOS_ACK_REMOTE : + LWSSSCS_QOS_NACK_REMOTE); + if (r != LWSSSSRET_OK) + return _lws_ss_handle_state_ret(r, wsi, &h); + lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ break; + case LWS_CALLBACK_HTTP_WRITEABLE: case LWS_CALLBACK_CLIENT_HTTP_WRITEABLE: - lwsl_info("%s: LWS_CALLBACK_CLIENT_HTTP_WRITEABLE\n", __func__); - if (!h) + //lwsl_info("%s: wsi %p, par %p, HTTP_WRITEABLE\n", __func__, + // wsi, wsi->mux.parent_wsi); + if (!h || !h->info.tx) { + lwsl_notice("%s: no handle / tx %p\n", __func__, h); + return 0; + } + +#if defined(LWS_WITH_SERVER) + if (h->txn_resp_pending) { + /* + * If we're going to start sending something, we need to + * to take care of the http response header for it first + */ + h->txn_resp_pending = 0; + + if (lws_add_http_common_headers(wsi, + h->txn_resp_set ? + (h->txn_resp ? h->txn_resp : 200) : + HTTP_STATUS_NOT_FOUND, + NULL, h->wsi->http.writeable_len, + &p, end)) + return 1; + + /* + * metadata-based headers + */ + + if (lws_apply_metadata(h, wsi, buf, &p, end)) + return -1; + + if (lws_finalize_write_http_header(wsi, start, &p, end)) + return 1; + + /* write the body separately */ + lws_callback_on_writable(wsi); + return 0; + } +#endif + + if ( +#if defined(LWS_WITH_SERVER) + !(h->info.flags & LWSSSINFLAGS_ACCEPTED) && /* not accepted */ +#endif + !h->rideshare) - if (!h->rideshare) h->rideshare = h->policy; #if defined(LWS_WITH_SS_RIDESHARE) - if (!h->inside_msg && h->rideshare->u.http.multipart_name) + if ( +#if defined(LWS_WITH_SERVER) + !(h->info.flags & LWSSSINFLAGS_ACCEPTED) && /* not accepted */ +#endif + !h->inside_msg && h->rideshare->u.http.multipart_name) lws_client_http_multipart(wsi, h->rideshare->u.http.multipart_name, h->rideshare->u.http.multipart_filename, @@ -462,42 +593,41 @@ buflen = lws_ptr_diff(end, p); if (h->policy->u.http.multipart_name) buflen -= 24; /* allow space for end of multipart */ - +#else + buflen = lws_ptr_diff(end, p); #endif - - txr = h->info.tx(ss_to_userobj(h), h->txord++, p, &buflen, &f); - if (txr < 0) { - lwsl_debug("%s: tx handler asked to close\n", __func__); - return -1; - } - if (txr > 0) { - /* don't want to send anything */ - lwsl_debug("%s: dont want to write\n", __func__); + r = h->info.tx(ss_to_userobj(h), h->txord++, p, &buflen, &f); + if (r == LWSSSSRET_TX_DONT_SEND) return 0; - } + if (r < 0) + return _lws_ss_handle_state_ret(r, wsi, &h); - lwsl_info("%s: WRITEABLE: user tx says len %d fl 0x%x\n", - __func__, (int)buflen, (int)f); + // lwsl_notice("%s: WRITEABLE: user tx says len %d fl 0x%x\n", + // __func__, (int)buflen, (int)f); p += buflen; if (f & LWSSS_FLAG_EOM) { -#if defined(LWS_WITH_SS_RIDESHARE) +#if defined(LWS_WITH_SERVER) + if (!(h->info.flags & LWSSSINFLAGS_ACCEPTED)) { +#endif conceal_eom = 1; /* end of rideshares */ if (!h->rideshare->rideshare_streamtype) { lws_client_http_body_pending(wsi, 0); +#if defined(LWS_WITH_SS_RIDESHARE) if (h->rideshare->u.http.multipart_name) lws_client_http_multipart(wsi, NULL, NULL, NULL, (char **)&p, (char *)end); conceal_eom = 0; - } else { #endif - h->rideshare = lws_ss_policy_lookup(wsi->context, + } else { + h->rideshare = lws_ss_policy_lookup(wsi->a.context, h->rideshare->rideshare_streamtype); lws_callback_on_writable(wsi); -#if defined(LWS_WITH_SS_RIDESHARE) } +#if defined(LWS_WITH_SERVER) + } #endif h->inside_msg = 0; @@ -513,16 +643,70 @@ lws_ptr_diff(p, buf + LWS_PRE), f); if (lws_write(wsi, buf + LWS_PRE, lws_ptr_diff(p, buf + LWS_PRE), - (!conceal_eom && (f & LWSSS_FLAG_EOM)) ? + (!conceal_eom && (f & LWSSS_FLAG_EOM)) ? LWS_WRITE_HTTP_FINAL : LWS_WRITE_HTTP) != (int)lws_ptr_diff(p, buf + LWS_PRE)) { lwsl_err("%s: write failed\n", __func__); return -1; } +#if defined(LWS_WITH_SERVER) + if (!(h->info.flags & LWSSSINFLAGS_ACCEPTED) && + (f & LWSSS_FLAG_EOM) && + lws_http_transaction_completed(wsi)) + return -1; +#else lws_set_timeout(wsi, 0, 0); +#endif break; +#if defined(LWS_WITH_SERVER) + case LWS_CALLBACK_HTTP: + + lwsl_notice("%s: LWS_CALLBACK_HTTP\n", __func__); + { + + h->txn_resp_set = 0; + h->txn_resp_pending = 1; + h->writeable_len = 0; + +#if defined(LWS_ROLE_H2) + m = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COLON_METHOD); + if (m) { + lws_ss_set_metadata(h, "method", + lws_hdr_simple_ptr(wsi, + WSI_TOKEN_HTTP_COLON_METHOD), m); + m = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COLON_PATH); + lws_ss_set_metadata(h, "path", + lws_hdr_simple_ptr(wsi, + WSI_TOKEN_HTTP_COLON_PATH), m); + } else +#endif + { + m = lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI); + if (m) { + lws_ss_set_metadata(h, "path", + lws_hdr_simple_ptr(wsi, + WSI_TOKEN_GET_URI), m); + lws_ss_set_metadata(h, "method", "GET", 3); + } else { + m = lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI); + if (m) { + lws_ss_set_metadata(h, "path", + lws_hdr_simple_ptr(wsi, + WSI_TOKEN_POST_URI), m); + lws_ss_set_metadata(h, "method", "POST", 4); + } + } + } + } + + r = lws_ss_event_helper(h, LWSSSCS_SERVER_TXN); + if (r) + return _lws_ss_handle_state_ret(r, wsi, &h); + return 0; +#endif + default: break; } @@ -551,10 +735,16 @@ struct lws_client_connect_info *i, union lws_ss_contemp *ct) { + const char *pbasis = h->policy->u.http.url; size_t used_in, used_out; lws_strexp_t exp; - if (!h->policy->u.http.url) + /* i.path on entry is used to override the policy urlpath if not "" */ + + if (i->path[0]) + pbasis = i->path; + + if (!pbasis) return 0; #if defined(LWS_WITH_SS_RIDESHARE) @@ -572,8 +762,7 @@ lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, buf + 1, len - 1); - if (lws_strexp_expand(&exp, h->policy->u.http.url, - strlen(h->policy->u.http.url), + if (lws_strexp_expand(&exp, pbasis, strlen(pbasis), &used_in, &used_out) != LSTRX_DONE) return 1; @@ -584,7 +773,7 @@ const struct ss_pcols ss_pcol_h1 = { "h1", "http/1.1", - "lws-secstream-h1", + &protocol_secstream_h1, secstream_connect_munge_h1, NULL }; diff -Nru libwebsockets-4.0.20/lib/secure-streams/protocols/ss-h2.c libwebsockets-4.1.6/lib/secure-streams/protocols/ss-h2.c --- libwebsockets-4.0.20/lib/secure-streams/protocols/ss-h2.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/secure-streams/protocols/ss-h2.c 2020-12-01 17:40:26.000000000 +0000 @@ -33,6 +33,7 @@ void *in, size_t len) { lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); + lws_ss_state_return_t r; int n; switch (reason) { @@ -63,11 +64,13 @@ case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: // lwsl_err("%s: h2 COMPLETED_CLIENT_HTTP\n", __func__); - h->info.rx(ss_to_userobj(h), NULL, 0, LWSSS_FLAG_EOM); + r = h->info.rx(ss_to_userobj(h), NULL, 0, LWSSS_FLAG_EOM); + /* decouple the fates of the wsi and the ss */ h->wsi = NULL; h->txn_ok = 1; - //bad = status != 200; lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ + if (r != LWSSSSRET_OK) + return _lws_ss_handle_state_ret(r, wsi, &h); break; case LWS_CALLBACK_WSI_TX_CREDIT_GET: @@ -112,6 +115,15 @@ struct lws_client_connect_info *i, union lws_ss_contemp *ct) { + const char *pbasis = h->policy->u.http.url; + size_t used_in, used_out; + lws_strexp_t exp; + + /* i.path on entry is used to override the policy urlpath if not "" */ + + if (i->path[0]) + pbasis = i->path; + if (h->policy->flags & LWSSSPOLF_QUIRK_NGHTTP2_END_STREAM) i->ssl_connection |= LCCSCF_H2_QUIRK_NGHTTP2_END_STREAM; @@ -137,13 +149,19 @@ i->manual_initial_tx_credit); } - if (!h->policy->u.http.url) + if (!pbasis) return 0; /* protocol aux is the path part */ i->path = buf; - lws_snprintf(buf, len, "/%s", h->policy->u.http.url); + buf[0] = '/'; + + lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, buf + 1, len - 1); + + if (lws_strexp_expand(&exp, pbasis, strlen(pbasis), + &used_in, &used_out) != LSTRX_DONE) + return 1; return 0; } @@ -176,7 +194,7 @@ const struct ss_pcols ss_pcol_h2 = { "h2", NULL, - "lws-secstream-h2", + &protocol_secstream_h2, secstream_connect_munge_h2, secstream_tx_credit_add_h2, secstream_tx_credit_est_h2 diff -Nru libwebsockets-4.0.20/lib/secure-streams/protocols/ss-mqtt.c libwebsockets-4.1.6/lib/secure-streams/protocols/ss-mqtt.c --- libwebsockets-4.0.20/lib/secure-streams/protocols/ss-mqtt.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/secure-streams/protocols/ss-mqtt.c 2020-12-01 17:40:26.000000000 +0000 @@ -31,8 +31,9 @@ lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); lws_mqtt_publish_param_t mqpp, *pmqpp; uint8_t buf[LWS_PRE + 1400]; - int f = 0, txr; + lws_ss_state_return_t r; size_t buflen; + int f = 0; switch (reason) { @@ -42,26 +43,46 @@ in ? (char *)in : "(null)"); if (!h) break; - lws_ss_event_helper(h, LWSSSCS_UNREACHABLE); + r = lws_ss_event_helper(h, LWSSSCS_UNREACHABLE); h->wsi = NULL; - lws_ss_backoff(h); + + if (h->u.mqtt.heap_baggage) { + lws_free(h->u.mqtt.heap_baggage); + h->u.mqtt.heap_baggage = NULL; + } + + if (r == LWSSSSRET_DESTROY_ME) + return _lws_ss_handle_state_ret(r, wsi, &h); + + r = lws_ss_backoff(h); + if (r != LWSSSSRET_OK) + return _lws_ss_handle_state_ret(r, wsi, &h); + break; case LWS_CALLBACK_MQTT_CLIENT_CLOSED: if (!h) break; - f = lws_ss_event_helper(h, LWSSSCS_DISCONNECTED); + lws_sul_cancel(&h->sul_timeout); + r= lws_ss_event_helper(h, LWSSSCS_DISCONNECTED); if (h->wsi) lws_set_opaque_user_data(h->wsi, NULL); h->wsi = NULL; - if (f) { - lws_ss_destroy(&h); - break; + + if (h->u.mqtt.heap_baggage) { + lws_free(h->u.mqtt.heap_baggage); + h->u.mqtt.heap_baggage = NULL; } + if (r) + return _lws_ss_handle_state_ret(r, wsi, &h); + if (h->policy && !(h->policy->flags & LWSSSPOLF_OPPORTUNISTIC) && - !h->txn_ok && !wsi->context->being_destroyed) - lws_ss_backoff(h); + !h->txn_ok && !wsi->a.context->being_destroyed) { + r = lws_ss_backoff(h); + if (r != LWSSSSRET_OK) + return _lws_ss_handle_state_ret(r, wsi, &h); + } break; case LWS_CALLBACK_MQTT_CLIENT_ESTABLISHED: @@ -72,15 +93,17 @@ h->wsi = wsi; h->retry = 0; h->seqstate = SSSEQ_CONNECTED; - lws_ss_set_timeout_us(h, LWS_SET_TIMER_USEC_CANCEL); - lws_ss_event_helper(h, LWSSSCS_CONNECTED); + lws_sul_cancel(&h->sul); + r = lws_ss_event_helper(h, LWSSSCS_CONNECTED); + if (r != LWSSSSRET_OK) + return _lws_ss_handle_state_ret(r, wsi, &h); if (h->policy->u.mqtt.topic) lws_callback_on_writable(wsi); break; case LWS_CALLBACK_MQTT_CLIENT_RX: // lwsl_user("LWS_CALLBACK_CLIENT_RECEIVE: read %d\n", (int)len); - if (!h) + if (!h || !h->info.rx) return 0; pmqpp = (lws_mqtt_publish_param_t *)in; @@ -93,9 +116,10 @@ h->subseq = 1; - if (h->info.rx(ss_to_userobj(h), (const uint8_t *)pmqpp->payload, - len, f) < 0) - return -1; + r = h->info.rx(ss_to_userobj(h), (const uint8_t *)pmqpp->payload, + len, f); + if (r != LWSSSSRET_OK) + return _lws_ss_handle_state_ret(r, wsi, &h); return 0; /* don't passthru */ @@ -105,11 +129,14 @@ break; case LWS_CALLBACK_MQTT_ACK: - lws_ss_event_helper(h, LWSSSCS_QOS_ACK_REMOTE); + lws_sul_cancel(&h->sul_timeout); + r = lws_ss_event_helper(h, LWSSSCS_QOS_ACK_REMOTE); + if (r != LWSSSSRET_OK) + return _lws_ss_handle_state_ret(r, wsi, &h); break; case LWS_CALLBACK_MQTT_CLIENT_WRITEABLE: - if (!h) + if (!h || !h->info.tx) return 0; lwsl_notice("%s: ss %p: WRITEABLE\n", __func__, h); @@ -118,17 +145,20 @@ break; } - if (h->policy->u.mqtt.subscribe && !wsi->mqtt->done_subscribe) { + if (h->policy->u.mqtt.subscribe && + !wsi->mqtt->done_subscribe) { /* * The policy says to subscribe to something, and we - * haven't done it yet + * haven't done it yet. Do it using the pre-prepared + * string-substituted version of the policy string. */ - lwsl_warn("%s: subscribing %s\n", __func__, h->policy->u.mqtt.subscribe); + lwsl_notice("%s: subscribing %s\n", __func__, + h->u.mqtt.subscribe_to); memset(&h->u.mqtt.sub_top, 0, sizeof(h->u.mqtt.sub_top)); - h->u.mqtt.sub_top.name = h->policy->u.mqtt.subscribe; + h->u.mqtt.sub_top.name = h->u.mqtt.subscribe_to; h->u.mqtt.sub_top.qos = h->policy->u.mqtt.qos; memset(&h->u.mqtt.sub_info, 0, sizeof(h->u.mqtt.sub_info)); h->u.mqtt.sub_info.num_topics = 1; @@ -144,18 +174,17 @@ buflen = sizeof(buf) - LWS_PRE; - txr = h->info.tx(ss_to_userobj(h), h->txord++, buf + LWS_PRE, - &buflen, &f); - if (txr < 0) { - lwsl_debug("%s: tx handler asked to close\n", __func__); - return -1; - } - if (txr > 0) - /* don't want to send anything */ + r = h->info.tx(ss_to_userobj(h), h->txord++, buf + LWS_PRE, + &buflen, &f); + if (r == LWSSSSRET_TX_DONT_SEND) return 0; + if (r < 0) + return _lws_ss_handle_state_ret(r, wsi, &h); + memset(&mqpp, 0, sizeof(mqpp)); - mqpp.topic = (char *)h->policy->u.mqtt.topic; + /* this is the string-substituted h->policy->u.mqtt.topic */ + mqpp.topic = (char *)h->u.mqtt.topic_qos.name; mqpp.topic_len = strlen(mqpp.topic); mqpp.packet_id = h->txord - 1; mqpp.payload = buf + LWS_PRE; @@ -164,7 +193,8 @@ else mqpp.payload_len = buflen; - lwsl_notice("%s: payload len %d\n", __func__, (int)mqpp.payload_len); + lwsl_notice("%s: payload len %d\n", __func__, + (int)mqpp.payload_len); mqpp.qos = h->policy->u.mqtt.qos; @@ -202,25 +232,103 @@ * For ws, protocol aux is ; */ +enum { + SSCMM_STRSUB_WILL_TOPIC, + SSCMM_STRSUB_WILL_MESSAGE, + SSCMM_STRSUB_SUBSCRIBE, + SSCMM_STRSUB_TOPIC +}; + static int secstream_connect_munge_mqtt(lws_ss_handle_t *h, char *buf, size_t len, struct lws_client_connect_info *i, union lws_ss_contemp *ct) { + const char *sources[4] = { + /* we're going to string-substitute these before use */ + h->policy->u.mqtt.will_topic, + h->policy->u.mqtt.will_message, + h->policy->u.mqtt.subscribe, + h->policy->u.mqtt.topic + }; + size_t used_in, olen[4] = { 0, 0, 0, 0 }, tot = 0; + lws_strexp_t exp; + char *p, *ps[4]; + int n; + memset(&ct->ccp, 0, sizeof(ct->ccp)); ct->ccp.client_id = "lwsMqttClient"; ct->ccp.keep_alive = h->policy->u.mqtt.keep_alive; ct->ccp.clean_start = h->policy->u.mqtt.clean_start; - ct->ccp.will_param.topic = h->policy->u.mqtt.will_topic; - ct->ccp.will_param.message = h->policy->u.mqtt.will_message; ct->ccp.will_param.qos = h->policy->u.mqtt.will_qos; ct->ccp.will_param.retain = h->policy->u.mqtt.will_retain; + h->u.mqtt.topic_qos.qos = h->policy->u.mqtt.qos; + + /* + * We're going to string-substitute several of these parameters, which + * have unknown, possibly large size. And, as their usage is deferred + * inside the asynchronous lifetime of the MQTT connection, they need + * to live on the heap. + * + * Notice these allocations at h->u.mqtt.heap_baggage belong to the + * underlying MQTT stream lifetime, not the logical SS lifetime, and + * are destroyed if present at connection error or close of the + * underlying connection. + * + * + * First, compute the length of each without producing strsubst output, + * and keep a running total. + */ + + for (n = 0; n < (int)LWS_ARRAY_SIZE(sources); n++) { + lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, + NULL, (size_t)-1); + if (lws_strexp_expand(&exp, sources[n], strlen(sources[n]), + &used_in, &olen[n]) != LSTRX_DONE) { + lwsl_err("%s: failed to subsitute %s\n", __func__, + sources[n]); + return 1; + } + tot += olen[n] + 1; + } - lwsl_notice("%s\n", __func__); + /* + * Then, allocate enough space on the heap for the total of the + * substituted results + */ + + h->u.mqtt.heap_baggage = lws_malloc(tot, __func__); + if (!h->u.mqtt.heap_baggage) + return 1; + + /* + * Finally, issue the subsitutions one after the other into the single + * allocated result buffer and prepare pointers into them + */ + + p = h->u.mqtt.heap_baggage; + for (n = 0; n < (int)LWS_ARRAY_SIZE(sources); n++) { + lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, + p, (size_t)-1); + ps[n] = p; + if (lws_strexp_expand(&exp, sources[n], strlen(sources[n]), + &used_in, &olen[n]) != LSTRX_DONE) + return 1; + + p += olen[n] + 1; + } - h->u.mqtt.topic_qos.name = h->policy->u.mqtt.subscribe; - h->u.mqtt.topic_qos.qos = h->policy->u.mqtt.qos; + /* + * Point the guys who want the substituted content at the substituted + * strings + */ + + ct->ccp.will_param.topic = ps[SSCMM_STRSUB_WILL_TOPIC]; + ct->ccp.will_param.message = ps[SSCMM_STRSUB_WILL_MESSAGE]; + h->u.mqtt.subscribe_to = ps[SSCMM_STRSUB_SUBSCRIBE]; + h->u.mqtt.subscribe_to_len = olen[SSCMM_STRSUB_SUBSCRIBE]; + h->u.mqtt.topic_qos.name = ps[SSCMM_STRSUB_TOPIC]; i->method = "MQTT"; i->mqtt_cp = &ct->ccp; @@ -230,25 +338,12 @@ /* share connections where possible */ i->ssl_connection |= LCCSCF_PIPELINE; -/* - if (!h->policy->u.http.url) - return 0; - - // protocol aux is the path part ; ws subprotocol name - - i->path = NULL; - lws_snprintf(buf, len, "/%s", h->policy->u.mqtt.topic); - -// i->protocol = h->policy->u.mqtt.u.ws.subprotocol; - - lwsl_notice("%s: url %s, ws subprotocol %s\n", __func__, buf, i->protocol); -*/ return 0; } const struct ss_pcols ss_pcol_mqtt = { "MQTT", "x-amzn-mqtt-ca", //"mqtt/3.1.1", - "lws-secstream-mqtt", + &protocol_secstream_mqtt, secstream_connect_munge_mqtt }; diff -Nru libwebsockets-4.0.20/lib/secure-streams/protocols/ss-raw.c libwebsockets-4.1.6/lib/secure-streams/protocols/ss-raw.c --- libwebsockets-4.0.20/lib/secure-streams/protocols/ss-raw.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/secure-streams/protocols/ss-raw.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,166 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + * This is the glue that wires up raw-socket to Secure Streams. + */ + +#include + +int +secstream_raw(struct lws *wsi, enum lws_callback_reasons reason, void *user, + void *in, size_t len) +{ + lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); + uint8_t buf[LWS_PRE + 1520], *p = &buf[LWS_PRE], + *end = &buf[sizeof(buf) - 1]; + lws_ss_state_return_t r; + size_t buflen; + int f = 0; + + switch (reason) { + + case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: + assert(h); + assert(h->policy); + lwsl_info("%s: h: %p, %s CLIENT_CONNECTION_ERROR: %s\n", __func__, + h, h->policy->streamtype, in ? (char *)in : "(null)"); + r = lws_ss_event_helper(h, LWSSSCS_UNREACHABLE); + if (r == LWSSSSRET_DESTROY_ME) + return _lws_ss_handle_state_ret(r, wsi, &h); + h->wsi = NULL; + r = lws_ss_backoff(h); + if (r != LWSSSSRET_OK) + return _lws_ss_handle_state_ret(r, wsi, &h); + break; + + case LWS_CALLBACK_RAW_CLOSE: + if (!h) + break; + lws_sul_cancel(&h->sul_timeout); + lwsl_info("%s: h: %p, %s LWS_CALLBACK_CLOSED_CLIENT_HTTP\n", + __func__, h, + h->policy ? h->policy->streamtype : "no policy"); + h->wsi = NULL; + if (h->policy && !(h->policy->flags & LWSSSPOLF_OPPORTUNISTIC) && +#if defined(LWS_WITH_SERVER) + !(h->info.flags & LWSSSINFLAGS_ACCEPTED) && /* not server */ +#endif + !h->txn_ok && !wsi->a.context->being_destroyed) { + r = lws_ss_backoff(h); + if (r != LWSSSSRET_OK) + return _lws_ss_handle_state_ret(r, wsi, &h); + break; + } + /* wsi is going down anyway */ + r = lws_ss_event_helper(h, LWSSSCS_DISCONNECTED); + if (r == LWSSSSRET_DESTROY_ME) + return _lws_ss_handle_state_ret(r, wsi, &h); + break; + + case LWS_CALLBACK_RAW_CONNECTED: + lwsl_info("%s: RAW_CONNECTED\n", __func__); + + h->retry = 0; + h->seqstate = SSSEQ_CONNECTED; + lws_sul_cancel(&h->sul); + r = lws_ss_event_helper(h, LWSSSCS_CONNECTED); + if (r != LWSSSSRET_OK) + return _lws_ss_handle_state_ret(r, wsi, &h); + + lws_validity_confirmed(wsi); + break; + + case LWS_CALLBACK_RAW_ADOPT: + lwsl_info("%s: RAW_ADOPT\n", __func__); + break; + + /* chunks of chunked content, with header removed */ + case LWS_CALLBACK_RAW_RX: + if (!h || !h->info.rx) + return 0; + + r = h->info.rx(ss_to_userobj(h), (const uint8_t *)in, len, 0); + if (r != LWSSSSRET_OK) + return _lws_ss_handle_state_ret(r, wsi, &h); + + return 0; /* don't passthru */ + + case LWS_CALLBACK_RAW_WRITEABLE: + lwsl_info("%s: RAW_WRITEABLE\n", __func__); + if (!h || !h->info.tx) + return 0; + + buflen = lws_ptr_diff(end, p); + r = h->info.tx(ss_to_userobj(h), h->txord++, p, &buflen, &f); + if (r == LWSSSSRET_TX_DONT_SEND) + return 0; + if (r < 0) + return _lws_ss_handle_state_ret(r, wsi, &h); + + /* + * flags are ignored with raw, there are no protocol payload + * boundaries, just an arbitrarily-fragmented bytestream + */ + + p += buflen; + if (lws_write(wsi, buf + LWS_PRE, lws_ptr_diff(p, buf + LWS_PRE), + LWS_WRITE_HTTP) != (int)lws_ptr_diff(p, buf + LWS_PRE)) { + lwsl_err("%s: write failed\n", __func__); + return -1; + } + + lws_set_timeout(wsi, 0, 0); + break; + + default: + break; + } + + return 0; +} + +static int +secstream_connect_munge_raw(lws_ss_handle_t *h, char *buf, size_t len, + struct lws_client_connect_info *i, + union lws_ss_contemp *ct) +{ + i->method = "RAW"; + + return 0; +} + + +const struct lws_protocols protocol_secstream_raw = { + "lws-secstream-raw", + secstream_raw, + 0, + 0, +}; + +const struct ss_pcols ss_pcol_raw = { + "raw", + "", + &protocol_secstream_raw, + secstream_connect_munge_raw, + NULL +}; diff -Nru libwebsockets-4.0.20/lib/secure-streams/protocols/ss-ws.c libwebsockets-4.1.6/lib/secure-streams/protocols/ss-ws.c --- libwebsockets-4.0.20/lib/secure-streams/protocols/ss-ws.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/secure-streams/protocols/ss-ws.c 2020-12-01 17:40:26.000000000 +0000 @@ -30,7 +30,8 @@ { lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); uint8_t buf[LWS_PRE + 1400]; - int f = 0, f1, txr; + lws_ss_state_return_t r; + int f = 0, f1, n; size_t buflen; switch (reason) { @@ -41,39 +42,58 @@ in ? (char *)in : "(null)"); if (!h) break; - lws_ss_event_helper(h, LWSSSCS_UNREACHABLE); + r = lws_ss_event_helper(h, LWSSSCS_UNREACHABLE); + if (r == LWSSSSRET_DESTROY_ME) + return _lws_ss_handle_state_ret(r, wsi, &h); + h->wsi = NULL; - lws_ss_backoff(h); + r = lws_ss_backoff(h); + if (r != LWSSSSRET_OK) + return _lws_ss_handle_state_ret(r, wsi, &h); break; + case LWS_CALLBACK_CLOSED: /* server */ case LWS_CALLBACK_CLIENT_CLOSED: if (!h) break; - f = lws_ss_event_helper(h, LWSSSCS_DISCONNECTED); + lws_sul_cancel(&h->sul_timeout); + r = lws_ss_event_helper(h, LWSSSCS_DISCONNECTED); + if (r == LWSSSSRET_DESTROY_ME) + return _lws_ss_handle_state_ret(r, wsi, &h); + if (h->wsi) lws_set_opaque_user_data(h->wsi, NULL); h->wsi = NULL; - if (f) { - lws_ss_destroy(&h); - break; + if (reason == LWS_CALLBACK_CLIENT_CLOSED) { + if (h->policy && + !(h->policy->flags & LWSSSPOLF_OPPORTUNISTIC) && +#if defined(LWS_WITH_SERVER) + !(h->info.flags & LWSSSINFLAGS_ACCEPTED) && /* not server */ +#endif + !h->txn_ok && !wsi->a.context->being_destroyed) { + r = lws_ss_backoff(h); + if (r != LWSSSSRET_OK) + return _lws_ss_handle_state_ret(r, wsi, &h); + break; + } } - - if (h->policy && !(h->policy->flags & LWSSSPOLF_OPPORTUNISTIC) && - !h->txn_ok && !wsi->context->being_destroyed) - lws_ss_backoff(h); break; + case LWS_CALLBACK_ESTABLISHED: case LWS_CALLBACK_CLIENT_ESTABLISHED: h->retry = 0; h->seqstate = SSSEQ_CONNECTED; - lws_ss_set_timeout_us(h, LWS_SET_TIMER_USEC_CANCEL); - lws_ss_event_helper(h, LWSSSCS_CONNECTED); + lws_sul_cancel(&h->sul); + r = lws_ss_event_helper(h, LWSSSCS_CONNECTED); + if (r != LWSSSSRET_OK) + return _lws_ss_handle_state_ret(r, wsi, &h); break; + case LWS_CALLBACK_RECEIVE: case LWS_CALLBACK_CLIENT_RECEIVE: // lwsl_user("LWS_CALLBACK_CLIENT_RECEIVE: read %d\n", (int)len); - if (!h) + if (!h || !h->info.rx) return 0; if (lws_is_first_fragment(wsi)) f |= LWSSS_FLAG_SOM; @@ -83,15 +103,17 @@ h->subseq = 1; - if (h->info.rx(ss_to_userobj(h), (const uint8_t *)in, len, f) < 0) - return -1; + r = h->info.rx(ss_to_userobj(h), (const uint8_t *)in, len, f); + if (r != LWSSSSRET_OK) + return _lws_ss_handle_state_ret(r, wsi, &h); return 0; /* don't passthru */ + case LWS_CALLBACK_SERVER_WRITEABLE: case LWS_CALLBACK_CLIENT_WRITEABLE: - if (!h) - return 0; // lwsl_notice("%s: ss %p: WRITEABLE\n", __func__, h); + if (!h || !h->info.tx) + return 0; if (h->seqstate != SSSEQ_CONNECTED) { lwsl_warn("%s: seqstate %d\n", __func__, h->seqstate); @@ -99,22 +121,23 @@ } buflen = sizeof(buf) - LWS_PRE; - txr = h->info.tx(ss_to_userobj(h), h->txord++, buf + LWS_PRE, - &buflen, &f); - if (txr < 0) { - lwsl_debug("%s: tx handler asked to close\n", __func__); - return -1; - } - if (txr > 0) - /* don't want to send anything */ + r = h->info.tx(ss_to_userobj(h), h->txord++, buf + LWS_PRE, + &buflen, &f); + if (r == LWSSSSRET_TX_DONT_SEND) return 0; + if (r != LWSSSSRET_OK) + return _lws_ss_handle_state_ret(r, wsi, &h); - f1 = lws_write_ws_flags(LWS_WRITE_BINARY, + f1 = lws_write_ws_flags(h->policy->u.http.u.ws.binary ? + LWS_WRITE_BINARY : LWS_WRITE_TEXT, !!(f & LWSSS_FLAG_SOM), !!(f & LWSSS_FLAG_EOM)); - if (lws_write(wsi, buf + LWS_PRE, buflen, f1) != (int)buflen) { - lwsl_err("%s: write failed\n", __func__); + n = lws_write(wsi, buf + LWS_PRE, buflen, f1); + if (n < (int)buflen) { + lwsl_info("%s: write failed %d %d\n", __func__, + n, (int)buflen); + return -1; } @@ -149,15 +172,30 @@ struct lws_client_connect_info *i, union lws_ss_contemp *ct) { + const char *pbasis = h->policy->u.http.url; + size_t used_in, used_out; + lws_strexp_t exp; + lwsl_notice("%s\n", __func__); - if (!h->policy->u.http.url) + /* i.path on entry is used to override the policy urlpath if not "" */ + + if (i->path[0]) + pbasis = i->path; + + if (!pbasis) return 0; /* protocol aux is the path part ; ws subprotocol name */ - i->path = h->policy->u.http.url; - lws_snprintf(buf, len, "/%s", h->policy->u.http.url); + i->path = buf; + buf[0] = '/'; + + lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, buf + 1, len - 1); + + if (lws_strexp_expand(&exp, pbasis, strlen(pbasis), + &used_in, &used_out) != LSTRX_DONE) + return 1; i->protocol = h->policy->u.http.u.ws.subprotocol; @@ -167,5 +205,5 @@ } const struct ss_pcols ss_pcol_ws = { - "ws", "http/1.1", "lws-secstream-ws", secstream_connect_munge_ws + "ws", "http/1.1", &protocol_secstream_ws, secstream_connect_munge_ws }; diff -Nru libwebsockets-4.0.20/lib/secure-streams/README.md libwebsockets-4.1.6/lib/secure-streams/README.md --- libwebsockets-4.0.20/lib/secure-streams/README.md 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/secure-streams/README.md 2020-12-01 17:40:26.000000000 +0000 @@ -1,28 +1,114 @@ # Secure Streams -Secure Streams is a client api that strictly separates payload from any metadata. -That includes the endpoint address for the connection, the tls CA and even the -protocol used to connect to the endpoint. +Secure Streams is a networking api that strictly separates payload from any +metadata. That includes the client endpoint address for the connection, the tls +trust chain and even the protocol used to connect to the endpoint. -The user api just receives and transmits payload, and receives advisory connection -state information. +The user api just receives and transmits payload, and receives advisory +connection state information. The details about how the connections for different types of secure stream should be made are held in JSON "policy database" initially passed in to the context creation, but able to be updated from a remote copy. -![overview](../doc-assets/ss-explain.png) +Both client and server networking can be handled using Secure Streams APIS. + +![overview](../doc-assets/ss-operation-modes.png) + +## Secure Streams CLIENT State lifecycle + +![overview](../doc-assets/ss-state-flow.png) + +Secure Streams are created using `lws_ss_create()`, after that they may acquire +underlying connections, and lose them, but the lifecycle of the Secure Stream +itself is not directly related to any underlying connection. + +Once created, Secure Streams may attempt connections, these may fail and once +the number of failures exceeds the count of attempts to conceal in the retry / +backoff policy, the stream reaches `LWSSSCS_ALL_RETRIES_FAILED`. The stream becomes +idle again until another explicit connection attempt is given. + +Once connected, the user code can use `lws_ss_request_tx()` to ask for a slot +to write to the peer, when this if forthcoming the tx handler can send a message. +If the underlying protocol gives indications of transaction success, such as, +eg, a 200 for http, or an ACK from MQTT, the stream state is called back with +an `LWSSSCS_QOS_ACK_REMOTE` or `LWSSSCS_QOS_NACK_REMOTE`. + +## SS Callback return handling + +SS state(), rx() and tx() can indicate with their return code some common +situations that should be handled by the caller. + +Constant|Scope|Meaning +---|---|--- +LWSSSSRET_TX_DONT_SEND|tx|This opportunity to send something was passed on +LWSSSSRET_OK|state, rx, tx|No error, continue doing what we're doing +LWSSSSRET_DISCONNECT_ME|state, rx|assertively disconnect from peer +LWSSSSRET_DESTROY_ME|state, rx|Caller should now destroy the stream itself +LWSSSSRET_SS_HANDLE_DESTROYED|state|Something handled a request to destroy the stream + +Destruction of the stream we're calling back on inside the callback is tricky, +it's preferable to return `LWSSSSRET_DESTROY_ME` if it is required, and let the +caller handle it. But in some cases, helpers called from the callbacks may +destroy the handle themselves, in that case the handler should return +`LWSSSSRET_SS_HANDLE_DESTROYED` indicating that the handle is already destroyed. + +## Secure Streams SERVER State lifecycle + +![overview](../doc-assets/ss-state-flow-server.png) + +You can also run servers defined using Secure Streams, the main difference is +that the user code must assertively create a secure stream of the server type +in order to create the vhost and listening socket. When this stream is +destroyed, the vhost is destroyed and the listen socket closed, otherwise it +does not perform any rx or tx, it just represents the server lifecycle. + +When client connections randomly arrive at the listen socket, new Secure Stream +objects are created along with accept sockets to represent each client +connection. As they represent the incoming connection, their lifecycle is the +same as that of the underlying connection. There is no retry concept since as +with eg, http servers, the clients may typically not be routable for new +connections initiated by the server. + +Since connections at socket level are already established, new connections are +immediately taken through CREATING, CONNECTING, CONNECTED states for +consistency. + +Some underlying protocols like http are "transactional", the server receives +a logical request and must reply with a logical response. The additional +state `LWSSSCS_SERVER_TXN` provides a point where the user code can set +transaction metadata before or in place of sending any payload. It's also +possible to defer this until any rx related to the transaction was received, +but commonly with http requests, there is no rx / body. Configuring the +response there may look like + +``` + /* + * We do want to ack the transaction... + */ + lws_ss_server_ack(m->ss, 0); + /* + * ... it's going to be text/html... + */ + lws_ss_set_metadata(m->ss, "mime", "text/html", 9); + /* + * ...it's going to be 128 byte (and request tx) + */ + lws_ss_request_tx_len(m->ss, 128); +``` + +Otherwise the general api usage is very similar to client usage. ## Convention for rx and tx callback return Function|Return|Meaning ---|---|--- -tx|0|Send the amount of `buf` stored in `*len` -tx|>0|Do not send anything -tx|<0|Finished with stream +tx|`LWSSSSRET_OK`|Send the amount of `buf` stored in `*len` +tx|`LWSSSSRET_TX_DONT_SEND`|Do not send anything +tx|`LWSSSSRET_DISCONNECT_ME`|Close the current connection +tx|`LWSSSSRET_DESTROY_ME`|Destroy the Secure Stream rx|>=0|accepted -rx|<0|Finished with stream - +rx|<0|Close the current connection # JSON Policy Database @@ -128,9 +214,14 @@ These are an array of policies for the supported stream type names. +### `server` + +**SERVER ONLY**: if set to `true`, the policy describes a secure streams +server. + ### `endpoint` -The DNS address the secure stream should connect to. +**CLIENT**: The DNS address the secure stream should connect to. This may contain string symbols which will be replaced with the corresponding streamtype metadata value at runtime. Eg, if the @@ -139,14 +230,26 @@ attempting the connection setting the stream's metadata item "region" to the desired value, eg, "uk". +If the endpoint string begins with `+`, then it's understood to +mean a connection to a Unix Domain Socket, for Linux `+@` means +the following Unix Domain Socket is in the Linux Abstract +Namespace and doesn't have a filesystem footprint. This is only +supported on unix-type and windows platforms and when lws was +configured with `-DLWS_UNIX_SOCK=1` + +**SERVER**: If given, the network interface name or IP address the listen socket +should bind to. + ### `port` -The port number as an integer on the endpoint to connect to +**CLIENT**: The port number as an integer on the endpoint to connect to + +**SERVER**: The port number the server will listen on ### `protocol` -The wire protocol to connect to the endpoint with. Currently supported -streamtypes are +**CLIENT**: The wire protocol to connect to the endpoint with. Currently +supported streamtypes are |Wire protocol|Description| |---|---| @@ -154,10 +257,19 @@ |h2|http/2| |ws|http/1 Websockets| |mqtt|mqtt 3.1.1| +|raw|| + +Raw protocol is a bit different than the others in that there is no protocol framing, +whatever is received on the connection is passed to the user rx callback and whatever +the tx callback provides is issued on to the connection. Because tcp can be +arbitrarily fragmented by any intermediary, such streams have to be regarded as an +ordered bytestream that may be fragmented at any byte without any meaning in terms +of message boundaries, for that reason SOM and EOM are ignored with raw. -### `plugins` +### `allow_redirects` -Array of plugin names to apply to the stream, if any +By default redirects are not followed, if you wish a streamtype to observe them, eg, +because that's how it responds to a POST, set `"allow_redirects": true` ### `tls` @@ -183,11 +295,37 @@ The name of the policy described in the `retry` section to apply to this connection for retry + backoff +### `timeout_ms` + +Optional timeout associated with streams of this streamtype. + +If user code applies the `lws_ss_start_timeout()` api on a stream with a +timeout of LWSSS_TIMEOUT_FROM_POLICY, the `timeout_ms` entry given in the +policy is applied. + ### `tls_trust_store` The name of the trust store described in the `trust_stores` section to apply to validate the remote server cert. +### `server_cert` + +**SERVER ONLY**: subject to change... the name of the x.509 cert that is the +server's tls certificate + +### `server_key` + +**SERVER ONLY**: subject to change... the name of the x.509 cert that is the +server's tls key + +### `swake_validity` + +Set to `true` if this streamtype is important enough for the functioning of the +device that its locally-initiated periodic connection validity checks of the +interval described in the associated retry / backoff selection, are important +enough to wake the whole system from low power suspend so they happen on +schedule. + ## http transport ### `http_method` @@ -195,6 +333,23 @@ HTTP method to use with http-related protocols, like GET or POST. Not required for ws. +### `http_expect` + +Optionally indicates that success for HTTP transactions using this +streamtype is different than the default 200 - 299. + +Eg, you may choose to set this to 204 for Captive Portal Detect usage +if that's what you expect the server to reply with to indicate +success. In that case, anything other than 204 will be treated as a +connection failure. + +### `http_fail_redirect` + +Set to `true` if you want to fail the connection on meeting an +http redirect. This is needed to, eg, detect Captive Portals +correctly. Normally, if on https, you would want the default behaviour +of following the redirect. + ### `http_url` Url path to use with http-related protocols @@ -263,6 +418,10 @@ Set this to `true` if the peer server has the quirk it sends an maximum initial tx credit of 0x7fffffff and then later increments it illegally. +### `http_multipart_ss_in` + +Indicates that SS should parse any incoming multipart mime on this stream + ### `http_multipart_name` Indicates this stream goes out using multipart mime, and provides the name part of the @@ -290,7 +449,9 @@ ### `ws_subprotocol` -Name of the ws subprotocol to use. +** CLIENT **: Name of the ws subprotocol to request from the server + +** SERVER **: Name of the subprotocol we will accept ### `ws_binary` @@ -370,6 +531,65 @@ fetches its real policy from warmcat.com at startup using the built-in one. +## Applying streamtype policy overlays + +This is intended for modifying policies at runtime for testing, eg, to +force error paths to be taken. After the main policy is processed, you +may parse additional, usually smaller policy fragments on top of it. + +Where streamtype names in the new fragment already exist in the current +parsed policy, the settings in the fragment are applied over the parsed +policy, overriding settings. There's a simple api to enable this by +giving it the override JSON in one string + +``` +int +lws_ss_policy_overlay(struct lws_context *context, const char *overlay); +``` + +but there are also other apis available that can statefully process +larger overlay fragments if needed. + +An example overlay fragment looks like this + +``` + { "s": [{ "captive_portal_detect": { + "endpoint": "google.com", + "http_url": "/", + "port": 80 + }}]} +``` + +ie the overlay fragment completely follows the structure of the main policy, +just misses out anything it doesn't override. + +Currently ONLY streamtypes may be overridden. + +You can see an example of this in use in `minimal-secure-streams` example +where `--force-portal` and `--force-no-internet` options cause the captive +portal detect streamtype to be overridden to force the requested kind of +outcome. + +## Captive Portal Detection + +If the policy contains a streamtype `captive_portal_detect` then the +type of transaction described there is automatically performed after +acquiring a DHCP address to try to determine the captive portal +situation. + +``` + "captive_portal_detect": { + "endpoint": "connectivitycheck.android.com", + "port": 80, + "protocol": "h1", + "http_method": "GET", + "http_url": "generate_204", + "opportunistic": true, + "http_expect": 204, + "http_fail_redirect": true + } +``` + ## Stream serialization and proxying By default Secure Streams expects to make the outgoing connection described in @@ -388,6 +608,9 @@ processes that pass their SS API activity to the proxy for fulfilment (or onward proxying). +Each Secure Stream that is created then in turn creates a private Unix Domain +Socket connection to the proxy for each stream. + In this case the proxy uses secure-streams.c and policy.c as before to fulfil the inbound proxy streams, but uses secure-streams-serialize.c to serialize and deserialize the proxied SS API activity. The proxy clients define @@ -463,3 +686,45 @@ You can confirm this goes through the ssh socks5 proxy to get to the SS proxy and fulfil the connection. + +## Using static policies + +If one of your targets is too constrained to make use of dynamic JSON policies, but +using SS and the policies is attractive for wider reasons, you can use a static policy +built into the firmware for the constrained target. + +The secure-streams example "policy2c" (which runs on the build machine, not the device) + +https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/secure-streams/minimal-secure-streams-policy2c + +accepts a normal JSON policy on stdin, and emits a C code representation that can be +included directly in the firmware. + +https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/static-policy.h + +Using this technique it's possible to standardize on maintaining JSON policies across a +range of devices with different contraints, and use the C conversion of the policy on devices +that are too small. + +The Cmake option `LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY` should be enabled to use this +mode, it will not build the JSON parser (and the option for LEJP can also be disabled if +you're not otherwise using it, saving an additional couple of KB). + +Notice policy2c example tool must be built with `LWS_ROLE_H1`, `LWS_ROLE_H2`, `LWS_ROLE_WS` +and `LWS_ROLE_MQTT` enabled so it can handle any kind of policy. + +## HTTP and ws serving + +All ws servers start out as http servers... for that reason ws serving is +handled as part of http serving, if you give the `ws_subprotocol` entry to the +streamtype additionally, the server will also accept upgrades to ws. + +To help the user code understand if the upgrade occurred, there's a special +state `LWSSSCS_SERVER_UPGRADE`, so subsequent rx and tx can be understood to +have come from the upgraded protocol. To allow separation of rx and tx +handling between http and ws, there's a ss api `lws_ss_change_handlers()` +which allows dynamically setting SS handlers. + +Since the http and ws upgrade identity is encapsulated in one streamtype, the +user object for the server streamtype should contain related user data for both +http and ws underlying protocol identity. diff -Nru libwebsockets-4.0.20/lib/secure-streams/secure-streams.c libwebsockets-4.1.6/lib/secure-streams/secure-streams.c --- libwebsockets-4.0.20/lib/secure-streams/secure-streams.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/secure-streams/secure-streams.c 2020-12-01 17:40:26.000000000 +0000 @@ -45,6 +45,8 @@ #else NULL, #endif + &ss_pcol_raw, /* LWSSSP_RAW */ + NULL, }; static const char *state_names[] = { @@ -61,6 +63,9 @@ "LWSSSCS_QOS_NACK_REMOTE", "LWSSSCS_QOS_ACK_LOCAL", "LWSSSCS_QOS_NACK_LOCAL", + "LWSSSCS_TIMEOUT", + "LWSSSCS_SERVER_TXN", + "LWSSSCS_SERVER_UPGRADE", }; const char * @@ -72,11 +77,13 @@ return state_names[state]; } -int +lws_ss_state_return_t lws_ss_event_helper(lws_ss_handle_t *h, lws_ss_constate_t cs) { + lws_ss_state_return_t r; + if (!h) - return 0; + return LWSSSSRET_OK; #if defined(LWS_WITH_SEQUENCER) /* @@ -88,10 +95,31 @@ (void *)h, NULL); #endif - if (h->h_sink &&h->h_sink->info.state(h->sink_obj, h->h_sink, cs, 0)) - return 1; + if (h->info.state) { + r = h->info.state(ss_to_userobj(h), NULL, cs, 0); +#if defined(LWS_WITH_SERVER) + if ((h->info.flags & LWSSSINFLAGS_ACCEPTED) && + cs == LWSSSCS_DISCONNECTED) + r = LWSSSSRET_DESTROY_ME; +#endif + return r; + } - return h->info.state(ss_to_userobj(h), NULL, cs, 0); + return LWSSSSRET_OK; +} + +int +_lws_ss_handle_state_ret(lws_ss_state_return_t r, struct lws *wsi, + lws_ss_handle_t **ph) +{ + if (r == LWSSSSRET_DESTROY_ME) { + if (wsi) + lws_set_opaque_user_data(wsi, NULL); + (*ph)->wsi = NULL; + lws_ss_destroy(ph); + } + + return -1; /* close connection */ } static void @@ -99,7 +127,8 @@ { lws_ss_handle_t *h = lws_container_of(sul, lws_ss_handle_t, sul); - lwsl_err("%s: retrying ss h %p after backoff\n", __func__, h); + lwsl_notice("%s: retrying ss h %p (%s) after backoff\n", __func__, h, + h->policy->streamtype); /* we want to retry... */ h->seqstate = SSSEQ_DO_RETRY; @@ -132,7 +161,8 @@ if (total < budget) budget = total; - memcpy(out + *pos, replace + (*exp_ofs), budget); + if (out) + memcpy(out + *pos, replace + (*exp_ofs), budget); *exp_ofs += budget; *pos += budget; @@ -148,19 +178,21 @@ struct lws_context_per_thread *pt = &h->context->pt[h->tsi]; h->sul.cb = lws_ss_timeout_sul_check_cb; - __lws_sul_insert(&pt->pt_sul_owner, &h->sul, us); + __lws_sul_insert_us(&pt->pt_sul_owner[ + !!(h->policy->flags & LWSSSPOLF_WAKE_SUSPEND__VALIDITY)], + &h->sul, us); return 0; } -int +lws_ss_state_return_t lws_ss_backoff(lws_ss_handle_t *h) { uint64_t ms; char conceal; if (h->seqstate == SSSEQ_RECONNECT_WAIT) - return 0; + return LWSSSSRET_OK; /* figure out what we should do about another retry */ @@ -170,8 +202,8 @@ if (!conceal) { lwsl_info("%s: ss %p: abandon conn attempt \n",__func__, h); h->seqstate = SSSEQ_IDLE; - lws_ss_event_helper(h, LWSSSCS_ALL_RETRIES_FAILED); - return 1; + + return lws_ss_event_helper(h, LWSSSCS_ALL_RETRIES_FAILED); } h->seqstate = SSSEQ_RECONNECT_WAIT; @@ -179,17 +211,95 @@ lwsl_info("%s: ss %p: retry wait %"PRIu64"ms\n", __func__, h, ms); + return LWSSSSRET_OK; +} + +#if defined(LWS_WITH_SYS_SMD) + +/* + * Local SMD <-> SS + * + * We pass received messages through to the SS handler synchronously, using the + * lws service thread context. + * + * After the SS is created and registered, still nothing is going to come here + * until the peer sends us his rx_class_mask and we update his registration with + * it, because from SS creation his rx_class_mask defaults to 0. + */ + +static int +lws_smd_ss_cb(void *opaque, lws_smd_class_t _class, + lws_usec_t timestamp, void *buf, size_t len) +{ + lws_ss_handle_t *h = (lws_ss_handle_t *)opaque; + uint8_t *p = (uint8_t *)buf - LWS_SMD_SS_RX_HEADER_LEN; + + /* + * When configured with SS enabled, lws over-allocates + * LWS_SMD_SS_RX_HEADER_LEN bytes behind the payload of the queued + * message, for prepending serialized class and timestamp data in-band + * with the payload. + */ + + lws_ser_wu64be(p, _class); + lws_ser_wu64be(p + 8, timestamp); + + if (h->info.rx) + h->info.rx((void *)&h[1], p, len + LWS_SMD_SS_RX_HEADER_LEN, + LWSSS_FLAG_SOM | LWSSS_FLAG_EOM); + return 0; } +static void +lws_ss_smd_tx_cb(lws_sorted_usec_list_t *sul) +{ + lws_ss_handle_t *h = lws_container_of(sul, lws_ss_handle_t, u.smd.sul_write); + uint8_t buf[LWS_SMD_SS_RX_HEADER_LEN + LWS_SMD_MAX_PAYLOAD], *p; + size_t len = sizeof(buf); + lws_smd_class_t _class; + int flags = 0, n; + + if (!h->info.tx) + return; + + n = h->info.tx(&h[1], h->txord++, buf, &len, &flags); + if (n) + /* nonzero return means don't want to send anything */ + return; + + // lwsl_notice("%s: (SS %p bound to _lws_smd creates message) tx len %d\n", __func__, h, (int)len); + // lwsl_hexdump_notice(buf, len); + + assert(len >= LWS_SMD_SS_RX_HEADER_LEN); + _class = (lws_smd_class_t)lws_ser_ru64be(buf); + p = lws_smd_msg_alloc(h->context, _class, len - LWS_SMD_SS_RX_HEADER_LEN); + if (!p) { + // this can be rejected if nobody listening for this class + //lwsl_notice("%s: failed to alloc\n", __func__); + return; + } + + memcpy(p, buf + LWS_SMD_SS_RX_HEADER_LEN, len - LWS_SMD_SS_RX_HEADER_LEN); + if (lws_smd_msg_send(h->context, p)) { + lwsl_notice("%s: failed to queue\n", __func__); + return; + } +} + +#endif + int _lws_ss_client_connect(lws_ss_handle_t *h, int is_retry) { + const char *prot, *_prot, *ipath, *_ipath, *ads, *_ads; struct lws_client_connect_info i; const struct ss_pcols *ssp; size_t used_in, used_out; union lws_ss_contemp ct; - char path[128], ep[96]; + char path[1024], ep[96]; + lws_ss_state_return_t r; + int port, _port, tls; lws_strexp_t exp; if (!h->policy) { @@ -202,55 +312,120 @@ * We are already bound to a sink? */ - if (h->h_sink) - return 0; +// if (h->h_sink) +// return 0; if (!is_retry) h->retry = 0; +#if defined(LWS_WITH_SYS_SMD) + if (h->policy == &pol_smd) { + + if (h->u.smd.smd_peer) + return 0; + + // lwsl_notice("%s: received connect for _lws_smd, registering for class mask 0x%x\n", + // __func__, h->info.manual_initial_tx_credit); + + h->u.smd.smd_peer = lws_smd_register(h->context, h, + (h->info.flags & LWSSSINFLAGS_PROXIED) ? + LWSSMDREG_FLAG_PROXIED_SS : 0, + h->info.manual_initial_tx_credit, + lws_smd_ss_cb); + if (!h->u.smd.smd_peer) + return -1; + + if (lws_ss_event_helper(h, LWSSSCS_CONNECTING)) + return -1; + // lwsl_err("%s: registered SS SMD\n", __func__); + if (lws_ss_event_helper(h, LWSSSCS_CONNECTED)) + return -1; + return 0; + } +#endif + + /* + * We're going to substitute ${metadata} in the endpoint at connection- + * time, so this can be set dynamically... + */ + + lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, ep, sizeof(ep)); + + if (lws_strexp_expand(&exp, h->policy->endpoint, + strlen(h->policy->endpoint), + &used_in, &used_out) != LSTRX_DONE) { + lwsl_err("%s: address strexp failed\n", __func__); + + return -1; + } + + /* + * ... in some cases, we might want the user to be able to override + * some policy settings by what he provided in there. For example, + * if he set the endpoint to "https://myendpoint.com:4443/mypath" it + * might be quite convenient to override the policy to follow the info + * that was given for at least server, port and the url path. + */ + + _port = port = h->policy->port; + _prot = prot = NULL; + _ipath = ipath = ""; + _ads = ads = ep; + + if (strchr(ep, ':') && + !lws_parse_uri(ep, &_prot, &_ads, &_port, &_ipath)) { + lwsl_debug("%s: using uri parse results '%s' '%s' %d '%s'\n", + __func__, _prot, _ads, _port, _ipath); + prot = _prot; + ads = _ads; + port = _port; + ipath = _ipath; + } + memset(&i, 0, sizeof i); /* otherwise uninitialized garbage */ i.context = h->context; + tls = !!(h->policy->flags & LWSSSPOLF_TLS); - if (h->policy->flags & LWSSSPOLF_TLS) { + if (prot && (!strcmp(prot, "http") || !strcmp(prot, "ws") || + !strcmp(prot, "mqtt"))) + tls = 0; + + if (tls) { lwsl_info("%s: using tls\n", __func__); i.ssl_connection = LCCSCF_USE_SSL; - if (!h->policy->trust_store) + if (!h->policy->trust.store) lwsl_info("%s: using platform trust store\n", __func__); else { i.vhost = lws_get_vhost_by_name(h->context, - h->policy->trust_store->name); + h->policy->trust.store->name); if (!i.vhost) { - lwsl_err("%s: missing vh for policy ca\n", __func__); + lwsl_err("%s: missing vh for policy %s\n", + __func__, + h->policy->trust.store->name); return -1; } } } - /* expand metadata ${symbols} that may be inside the endpoint string */ - - lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, ep, sizeof(ep)); - - if (lws_strexp_expand(&exp, h->policy->endpoint, - strlen(h->policy->endpoint), - &used_in, &used_out) != LSTRX_DONE) { - lwsl_err("%s: address strexp failed\n", __func__); - - return -1; - } - - i.address = ep; - i.port = h->policy->port; - i.host = i.address; - i.origin = i.address; - i.opaque_user_data = h; - i.seq = h->seq; - i.retry_and_idle_policy = h->policy->retry_bo; - i.sys_tls_client_cert = h->policy->client_cert; + if (h->policy->flags & LWSSSPOLF_WAKE_SUSPEND__VALIDITY) + i.ssl_connection |= LCCSCF_WAKE_SUSPEND__VALIDITY; - i.path = ""; + i.address = ads; + i.port = port; + i.host = i.address; + i.origin = i.address; + i.opaque_user_data = h; + i.seq = h->seq; + i.retry_and_idle_policy = h->policy->retry_bo; + i.sys_tls_client_cert = h->policy->client_cert; + + i.path = ipath; + /* if this is not "", munge should use it instead of policy + * url path + */ ssp = ss_pcols[(int)h->policy->protocol]; if (!ssp) { @@ -265,26 +440,35 @@ * the protocol-specific munge callback below if not http */ i.method = h->policy->u.http.method; - i.protocol = ssp->protocol_name; /* lws protocol name */ + i.protocol = ssp->protocol->name; /* lws protocol name */ i.local_protocol_name = i.protocol; - ssp->munge(h, path, sizeof(path), &i, &ct); + if (ssp->munge) /* eg, raw doesn't use; endpoint strexp already done */ + ssp->munge(h, path, sizeof(path), &i, &ct); i.pwsi = &h->wsi; +#if defined(LWS_WITH_SSPLUGINS) if (h->policy->plugins[0] && h->policy->plugins[0]->munge) h->policy->plugins[0]->munge(h, path, sizeof(path)); +#endif lwsl_info("%s: connecting %s, '%s' '%s' %s\n", __func__, i.method, i.alpn, i.address, i.path); h->txn_ok = 0; - if (lws_ss_event_helper(h, LWSSSCS_CONNECTING)) - return -1; + r = lws_ss_event_helper(h, LWSSSCS_CONNECTING); + if (r) + return r; if (!lws_client_connect_via_info(&i)) { - lws_ss_event_helper(h, LWSSSCS_UNREACHABLE); - lws_ss_backoff(h); + r = lws_ss_event_helper(h, LWSSSCS_UNREACHABLE); + if (r) + return r; + + r = lws_ss_backoff(h); + if (r) + return r; return 1; } @@ -327,7 +511,7 @@ return 1; } - if (ssi->register_sink) { + if (ssi->flags & LWSSSINFLAGS_REGISTER_SINK) { /* * This can register a secure streams sink as well as normal * secure streams connections. If that's what's happening, @@ -366,10 +550,12 @@ */ size = sizeof(*h) + ssi->user_alloc + strlen(ssi->streamtype) + 1; +#if defined(LWS_WITH_SSPLUGINS) if (pol->plugins[0]) size += pol->plugins[0]->alloc; if (pol->plugins[1]) size += pol->plugins[1]->alloc; +#endif size += pol->metadata_count * sizeof(lws_ss_metadata_t); h = lws_zalloc(size, __func__); @@ -395,6 +581,7 @@ p += ssi->user_alloc; +#if defined(LWS_WITH_SSPLUGINS) if (pol->plugins[0]) { h->nauthi = p; p += pol->plugins[0]->alloc; @@ -403,6 +590,7 @@ h->sauthi = p; p += pol->plugins[1]->alloc; } +#endif if (pol->metadata_count) { h->metadata = (lws_ss_metadata_t *)p; @@ -423,6 +611,9 @@ } memcpy(p, ssi->streamtype, strlen(ssi->streamtype) + 1); + /* don't mark accepted ss as being the server */ + if (ssi->flags & LWSSSINFLAGS_SERVER) + h->info.flags &= ~LWSSSINFLAGS_SERVER; h->info.streamtype = p; lws_pt_lock(pt, __func__); @@ -435,22 +626,162 @@ if (ppayload_fmt) *ppayload_fmt = pol->payload_fmt; - if (ssi->register_sink) { + if (ssi->flags & LWSSSINFLAGS_SERVER) + /* + * return early for accepted connection flow + */ + return 0; + +#if defined(LWS_WITH_SYS_SMD) + /* + * For a local Secure Streams connection + */ + if (!(ssi->flags & LWSSSINFLAGS_PROXIED) && + pol == &pol_smd) { + lws_ss_state_return_t r; /* + * So he has asked to be wired up to SMD over a SS link. + * Register him as an smd participant in his own right. * + * Just for this case, ssi->manual_initial_tx_credit is used + * to set the rx class mask (this is part of the SS serialization + * format as well) + */ + h->u.smd.smd_peer = lws_smd_register(context, h, 0, + ssi->manual_initial_tx_credit, + lws_smd_ss_cb); + if (!h->u.smd.smd_peer) + goto late_bail; + lwsl_info("%s: registered SS SMD\n", __func__); + r = lws_ss_event_helper(h, LWSSSCS_CONNECTING); + if (r) + return r; + r = lws_ss_event_helper(h, LWSSSCS_CONNECTED); + if (r) + return r; + } +#endif + +#if defined(LWS_WITH_SERVER) + if (h->policy->flags & LWSSSPOLF_SERVER) { + const struct lws_protocols *pprot[3], **ppp = &pprot[0]; + struct lws_context_creation_info i; + struct lws_vhost *vho; + + lwsl_info("%s: creating server\n", __func__); + + /* + * This streamtype represents a server, we're being asked to + * instantiate a corresponding vhost for it + */ + + memset(&i, 0, sizeof i); + + i.iface = h->policy->endpoint; + i.vhost_name = h->policy->streamtype; + i.port = h->policy->port; + + if (!ss_pcols[h->policy->protocol]) { + lwsl_err("%s: unsupp protocol", __func__); + goto late_bail; + } + + *ppp++ = ss_pcols[h->policy->protocol]->protocol; +#if defined(LWS_ROLE_WS) + if (h->policy->u.http.u.ws.subprotocol) + /* + * He names a ws subprotocol, ie, we want to support + * ss-ws protocol in this vhost + */ + *ppp++ = &protocol_secstream_ws; +#endif + *ppp = NULL; + i.pprotocols = pprot; + +#if defined(LWS_WITH_TLS) + if (h->policy->flags & LWSSSPOLF_TLS) { + i.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + i.server_ssl_cert_mem = + h->policy->trust.server.cert->ca_der; + i.server_ssl_cert_mem_len = (unsigned int) + h->policy->trust.server.cert->ca_der_len; + i.server_ssl_private_key_mem = + h->policy->trust.server.key->ca_der; + i.server_ssl_private_key_mem_len = (unsigned int) + h->policy->trust.server.key->ca_der_len; + } +#endif + + vho = lws_create_vhost(context, &i); + if (!vho) { + lwsl_err("%s: failed to create vh", __func__); + goto late_bail; + } + + /* + * Mark this vhost as having to apply ss server semantics to + * any incoming accepted connection */ + vho->ss_handle = h; + + lwsl_notice("%s: created server %s\n", __func__, + h->policy->streamtype); + + return 0; } +#endif + +#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) - lws_ss_event_helper(h, LWSSSCS_CREATING); + /* + * For static policy case, dynamically ref / instantiate the related + * trust store and vhost. We do it by logical ss rather than connection + * because we don't want to expose the latency of creating the x.509 + * trust store at the first connection. + * + * But it might be given the tls linkup takes time anyway, it can move + * to the ss connect code instead. + */ - if (!ssi->register_sink && - ((h->policy->flags & LWSSSPOLF_NAILED_UP))) - if (_lws_ss_client_connect(h, 0)) - lws_ss_backoff(h); + if (!lws_ss_policy_ref_trust_store(context, h->policy, 1 /* do the ref */)) { + lwsl_err("%s: unable to get vhost / trust store\n", __func__); + goto late_bail; + } +#endif + + if (lws_ss_event_helper(h, LWSSSCS_CREATING)) { +late_bail: + lws_pt_lock(pt, __func__); + lws_dll2_remove(&h->list); + lws_pt_unlock(pt); + lws_free(h); + + return 1; + } + + if (!(ssi->flags & LWSSSINFLAGS_REGISTER_SINK) && + ((h->policy->flags & LWSSSPOLF_NAILED_UP) +#if defined(LWS_WITH_SYS_SMD) + || ((h->policy == &pol_smd) //&& + //(ssi->flags & LWSSSINFLAGS_PROXIED)) + ) +#endif + )) + if (_lws_ss_client_connect(h, 0)) { + if (lws_ss_backoff(h)) + /* has been destroyed */ + return 1; + } return 0; } +void * +lws_ss_to_user_object(struct lws_ss_handle *h) +{ + return (void *)&h[1]; +} + void lws_ss_destroy(lws_ss_handle_t **ppss) { @@ -461,22 +792,41 @@ if (!h) return; + if (h->destroying) { + lwsl_info("%s: reentrant destroy\n", __func__); + return; + } + h->destroying = 1; + if (h->wsi) { /* * Don't let the wsi point to us any more, * we (the ss object bound to the wsi) are going away now */ -// lws_set_opaque_user_data(h->wsi, NULL); + lws_set_opaque_user_data(h->wsi, NULL); lws_set_timeout(h->wsi, 1, LWS_TO_KILL_SYNC); } + /* + * if we bound an smd registration to the SS, unregister it + */ + +#if defined(LWS_WITH_SYS_SMD) + if (h->policy == &pol_smd && h->u.smd.smd_peer) { + lws_smd_unregister(h->u.smd.smd_peer); + h->u.smd.smd_peer = NULL; + } +#endif + pt = &h->context->pt[h->tsi]; lws_pt_lock(pt, __func__); *ppss = NULL; lws_dll2_remove(&h->list); lws_dll2_remove(&h->to_list); - lws_ss_event_helper(h, LWSSSCS_DESTROYING); + lws_sul_cancel(&h->sul_timeout); + + (void)lws_ss_event_helper(h, LWSSSCS_DESTROYING); lws_pt_unlock(pt); /* in proxy case, metadata value on heap may need cleaning up */ @@ -489,45 +839,126 @@ pmd = pmd->next; } - lws_sul_schedule(h->context, 0, &h->sul, NULL, LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&h->sul); + +#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) + + /* + * For static policy case, dynamically ref / instantiate the related + * trust store and vhost. We do it by logical ss rather than connection + * because we don't want to expose the latency of creating the x.509 + * trust store at the first connection. + * + * But it might be given the tls linkup takes time anyway, it can move + * to the ss connect code instead. + */ + + + lws_ss_policy_unref_trust_store(h->context, h->policy); +#endif + +#if defined(LWS_WITH_SERVER) + if (h->policy->flags & LWSSSPOLF_SERVER) { + struct lws_vhost *v = lws_get_vhost_by_name(h->context, + h->policy->streamtype); + + /* + * For server, the policy describes a vhost that implements the + * server, when we take down the ss, we take down the related + * vhost (if it got that far) + */ + if (v) + lws_vhost_destroy(v); + } +#endif + + /* confirm no sul left scheduled in handle or user allocation object */ + lws_sul_debug_zombies(h->context, h, sizeof(*h) + h->info.user_alloc, + __func__); lws_free_set_NULL(h); } +#if defined(LWS_WITH_SERVER) void +lws_ss_server_ack(struct lws_ss_handle *h, int nack) +{ + h->txn_resp = nack; + h->txn_resp_set = 1; +} +#endif + +lws_ss_state_return_t lws_ss_request_tx(lws_ss_handle_t *h) { - lwsl_info("%s: wsi %p\n", __func__, h->wsi); + lws_ss_state_return_t r; + + // lwsl_notice("%s: h %p, wsi %p\n", __func__, h, h->wsi); if (h->wsi) { lws_callback_on_writable(h->wsi); - return; + return LWSSSSRET_OK; + } + + if (h->policy->flags & LWSSSPOLF_SERVER) + return LWSSSSRET_OK; + + /* + * there's currently no wsi / connection associated with the ss handle + */ + +#if defined(LWS_WITH_SYS_SMD) + if (h->policy == &pol_smd) { + /* + * He's an _lws_smd... and no wsi... since we're just going + * to queue it, we could call his tx() right here, but rather + * than surprise him let's set a sul to do it next time around + * the event loop + */ + + lws_sul_schedule(h->context, 0, &h->u.smd.sul_write, + lws_ss_smd_tx_cb, 1); + + return LWSSSSRET_OK; } +#endif if (h->seqstate != SSSEQ_IDLE && h->seqstate != SSSEQ_DO_RETRY) - return; + return LWSSSSRET_OK; h->seqstate = SSSEQ_TRY_CONNECT; - lws_ss_event_helper(h, LWSSSCS_POLL); + r = lws_ss_event_helper(h, LWSSSCS_POLL); + if (r) + return r; /* * Retries operate via lws_ss_request_tx(), explicitly ask for a * reconnection to clear the retry limit */ - if (_lws_ss_client_connect(h, 1)) - lws_ss_backoff(h); + r = _lws_ss_client_connect(h, 1); + if (r == LWSSSSRET_DESTROY_ME) + return r; + + if (r) + return lws_ss_backoff(h); + + return LWSSSSRET_OK; } -void +lws_ss_state_return_t lws_ss_request_tx_len(lws_ss_handle_t *h, unsigned long len) { - if (h->wsi) + if (h->wsi && + (h->policy->protocol == LWSSSP_H1 || + h->policy->protocol == LWSSSP_H2 || + h->policy->protocol == LWSSSP_WS)) h->wsi->http.writeable_len = len; else h->writeable_len = len; - lws_ss_request_tx(h); + + return lws_ss_request_tx(h); } /* @@ -592,3 +1023,58 @@ return 0; } + +/* + * protocol-independent handler for ss timeout + */ + +static void +lws_ss_to_cb(lws_sorted_usec_list_t *sul) +{ + lws_ss_handle_t *h = lws_container_of(sul, lws_ss_handle_t, sul_timeout); + lws_ss_state_return_t r; + + lwsl_info("%s: ss %p timeout fired\n", __func__, h); + + r = lws_ss_event_helper(h, LWSSSCS_TIMEOUT); + if (r == LWSSSSRET_DESTROY_ME) { + if (h->wsi) + lws_set_timeout(h->wsi, 1, LWS_TO_KILL_ASYNC); + _lws_ss_handle_state_ret(r, NULL, &h); + } +} + +void +lws_ss_start_timeout(struct lws_ss_handle *h, unsigned int timeout_ms) +{ + if (!timeout_ms && !h->policy->timeout_ms) + return; + + lws_sul_schedule(h->context, 0, &h->sul_timeout, lws_ss_to_cb, + (timeout_ms ? timeout_ms : h->policy->timeout_ms) * + LWS_US_PER_MS); +} + +void +lws_ss_cancel_timeout(struct lws_ss_handle *h) +{ + lws_sul_cancel(&h->sul_timeout); +} + +void +lws_ss_change_handlers(struct lws_ss_handle *h, + lws_ss_state_return_t (*rx)(void *userobj, const uint8_t *buf, + size_t len, int flags), + lws_ss_state_return_t (*tx)(void *userobj, lws_ss_tx_ordinal_t ord, + uint8_t *buf, size_t *len, int *flags), + lws_ss_state_return_t (*state)(void *userobj, void *h_src /* ss handle type */, + lws_ss_constate_t state, + lws_ss_tx_ordinal_t ack)) +{ + if (rx) + h->info.rx = rx; + if (tx) + h->info.tx = tx; + if (state) + h->info.state = state; +} diff -Nru libwebsockets-4.0.20/lib/secure-streams/secure-streams-client.c libwebsockets-4.1.6/lib/secure-streams/secure-streams-client.c --- libwebsockets-4.0.20/lib/secure-streams/secure-streams-client.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/secure-streams/secure-streams-client.c 2020-12-01 17:40:26.000000000 +0000 @@ -57,10 +57,12 @@ return; } + + lwsl_notice("%s: sspc ss wsi %p\n", __func__, h->cwsi); } static int -lws_sspc_serialize_metadata(lws_sspc_metadata_t *md, uint8_t *p) +lws_sspc_serialize_metadata(lws_sspc_metadata_t *md, uint8_t *p, uint8_t *end) { int n, txc; @@ -82,6 +84,12 @@ p[0] = LWSSS_SER_TXPRE_METADATA; txc = strlen(md->name); n = txc + 1 + md->len; + if (n > 0xffff) + /* we can't serialize this metadata in 16b length */ + return -1; + if (n > lws_ptr_diff(end, &p[4])) + /* we don't have space for this metadata */ + return -1; lws_ser_wu16be(&p[1], n); p[3] = txc; memcpy(&p[4], md->name, txc); @@ -100,7 +108,8 @@ void *user, void *in, size_t len) { lws_sspc_handle_t *h = (lws_sspc_handle_t *)lws_get_opaque_user_data(wsi); - uint8_t s[32], pkt[LWS_PRE + 1400], *p = pkt + LWS_PRE; + uint8_t s[32], pkt[LWS_PRE + 2048], *p = pkt + LWS_PRE, + *end = p + sizeof(pkt) - LWS_PRE; void *m = (void *)((uint8_t *)&h[1]); const uint8_t *cp; lws_usec_t us; @@ -126,7 +135,7 @@ return -1; lwsl_info("%s: CONNECTED (%s)\n", __func__, h->ssi.streamtype); - h->state = LPCS_SENDING_INITIAL_TX; + h->state = LPCSCLI_SENDING_INITIAL_TX; h->dsh = lws_dsh_create(NULL, (LWS_PRE + LWS_SS_MTU) * 160, 1); if (!h->dsh) return -1; @@ -139,12 +148,22 @@ /* * our ss proxy Unix Domain socket has closed... */ - lwsl_notice("%s: LWS_CALLBACK_RAW_CLOSE: proxy conn down\n", __func__); - h->cwsi = NULL; - //lws_sspc_destroy(&h); + lwsl_notice("%s: LWS_CALLBACK_RAW_CLOSE: proxy conn down\n", + __func__); + if (h) { + h->cwsi = NULL; + /* + * schedule a reconnect in 1s + */ + lws_sul_schedule(h->context, 0, &h->sul_retry, + lws_sspc_sul_retry_cb, LWS_US_PER_SEC); + } break; case LWS_CALLBACK_RAW_RX: + /* + * ie, the proxy has sent us something + */ lwsl_info("%s: RAW_RX: rx %d\n", __func__, (int)len); if (!h || !h->cwsi) { @@ -153,12 +172,22 @@ return -1; } - if (lws_ss_deserialize_parse(&h->parser, lws_get_context(wsi), + n = lws_ss_deserialize_parse(&h->parser, lws_get_context(wsi), h->dsh, in, len, &h->state, h, - (lws_ss_handle_t **)m, &h->ssi, 1)) + (lws_ss_handle_t **)m, &h->ssi, 1); + switch (n) { + case LWSSSSRET_OK: + break; + case LWSSSSRET_DISCONNECT_ME: + return -1; + case LWSSSSRET_DESTROY_ME: + lws_set_opaque_user_data(wsi, NULL); + lws_sspc_destroy(&h); return -1; + } - if (wsi && h->state == LPCS_LOCAL_CONNECTED) + if (h->state == LPCSCLI_LOCAL_CONNECTED || + h->state == LPCSCLI_ONWARD_CONNECT) lws_set_timeout(wsi, 0, 0); break; @@ -172,14 +201,44 @@ if (!h) break; - lwsl_info("%s: WRITEABLE %p: (%s) state %d\n", __func__, wsi, + lwsl_debug("%s: WRITEABLE %p: (%s) state %d\n", __func__, wsi, h->ssi.streamtype, h->state); + /* + * Management of ss timeout can happen any time and doesn't + * depend on wsi existence or state + */ + n = 0; cp = s; + + if (h->pending_timeout_update) { + s[0] = LWSSS_SER_TXPRE_TIMEOUT_UPDATE; + s[1] = 0; + s[2] = 4; + /* + * 0: use policy timeout value + * 0xffffffff: cancel the timeout + */ + lws_ser_wu32be(&s[3], h->timeout_ms); + /* in case anything else to write */ + lws_callback_on_writable(h->cwsi); + h->pending_timeout_update = 0; + n = 7; + goto do_write; + } + s[1] = 0; + /* + * This is the state of the link that connects us to the onward + * proxy + */ switch (h->state) { - case LPCS_SENDING_INITIAL_TX: + case LPCSCLI_SENDING_INITIAL_TX: + /* + * We are negotating the opening of a particular + * streamtype + */ n = strlen(h->ssi.streamtype) + 4; s[0] = LWSSS_SER_TXPRE_STREAMTYPE; @@ -188,12 +247,12 @@ //h->txcr_out = txc; lws_strncpy((char *)&s[7], h->ssi.streamtype, sizeof(s) - 7); n += 3; - h->state = LPCS_WAITING_CREATE_RESULT; + h->state = LPCSCLI_WAITING_CREATE_RESULT; break; - case LPCS_LOCAL_CONNECTED: - if (!h->conn_req) - break; + case LPCSCLI_LOCAL_CONNECTED: + + // lwsl_notice("%s: LPCSCLI_LOCAL_CONNECTED\n", __func__); /* * Do we need to prioritize sending any metadata @@ -206,32 +265,53 @@ lws_sspc_metadata_t, list); cp = p; - n = lws_sspc_serialize_metadata(md, p); + n = lws_sspc_serialize_metadata(md, p, end); + if (n < 0) + goto metadata_hangup; - /* in case anything else to write */ - lws_callback_on_writable(h->cwsi); + lwsl_debug("%s: (local_conn) metadata\n", __func__); + goto req_write_and_issue; + } + + if (h->pending_writeable_len) { + lwsl_debug("%s: (local_conn) PAYLOAD_LENGTH_HINT %u\n", + __func__, (unsigned int)h->writeable_len); + s[0] = LWSSS_SER_TXPRE_PAYLOAD_LENGTH_HINT; + lws_ser_wu16be(&s[1], 4); + lws_ser_wu32be(&s[3], h->writeable_len); + h->pending_writeable_len = 0; + n = 7; + goto req_write_and_issue; + } + + if (h->conn_req_state >= LWSSSPC_ONW_ONGOING) { + lwsl_info("%s: conn_req_state %d\n", __func__, + h->conn_req_state); break; } + lwsl_info("%s: (local_conn) onward connect\n", __func__); + + h->conn_req_state = LWSSSPC_ONW_ONGOING; - h->conn_req = 0; s[0] = LWSSS_SER_TXPRE_ONWARD_CONNECT; s[1] = 0; s[2] = 0; n = 3; break; - case LPCS_OPERATIONAL: + case LPCSCLI_OPERATIONAL: - /* - * Do we want to adjust the peer's ability to write - * to us? - */ + lwsl_notice("%s: LPCSCLI_OPERATIONAL\n", __func__); /* - * Do we need to prioritize sending any metadata - * changes? + * + * - Do we need to prioritize sending any metadata + * changes? (includes txcr updates) + * + * - Do we need to forward a hint about the payload + * length? */ if (h->metadata_owner.count) { @@ -240,27 +320,40 @@ lws_sspc_metadata_t, list); cp = p; - n = lws_sspc_serialize_metadata(md, p); + n = lws_sspc_serialize_metadata(md, p, end); + if (n < 0) + goto metadata_hangup; - /* in case anything else to write */ - lws_callback_on_writable(h->cwsi); - - break; + goto req_write_and_issue; } + if (h->pending_writeable_len) { + lwsl_info("%s: PAYLOAD_LENGTH_HINT %u\n", + __func__, (unsigned int)h->writeable_len); + s[0] = LWSSS_SER_TXPRE_PAYLOAD_LENGTH_HINT; + lws_ser_wu16be(&s[1], 4); + lws_ser_wu32be(&s[3], h->writeable_len); + h->pending_writeable_len = 0; + n = 7; + goto req_write_and_issue; + } /* we can't write anything if we don't have credit */ - if (h->txc.tx_cr <= 0) { - lwsl_notice("%s: WRITEABLE / OPERATIONAL:" + if (!h->ignore_txc && h->txc.tx_cr <= 0) { + lwsl_info("%s: WRITEABLE / OPERATIONAL:" " lack credit (%d)\n", __func__, h->txc.tx_cr); - break; + // break; } len = sizeof(pkt) - LWS_PRE - 19; flags = 0; - if (h->ssi.tx(m, h->ord++, pkt + LWS_PRE + 19, &len, &flags)) + n = h->ssi.tx(m, h->ord++, pkt + LWS_PRE + 19, &len, + &flags); + if (n == LWSSSSRET_TX_DONT_SEND) { + n = 0; break; + } h->txc.tx_cr -= len; @@ -286,11 +379,12 @@ break; } +do_write_nz: + if (!n) break; - // lwsl_hexdump_notice(cp, n); - +do_write: n = lws_write(wsi, (uint8_t *)cp, n, LWS_WRITE_RAW); if (n < 0) { lwsl_notice("%s: WRITEABLE: %d\n", __func__, n); @@ -305,10 +399,18 @@ return lws_callback_http_dummy(wsi, reason, user, in, len); +metadata_hangup: + lwsl_err("%s: metadata too large\n", __func__); + hangup: lwsl_warn("hangup\n"); /* hang up on him */ return -1; + +req_write_and_issue: + /* in case anything else to write */ + lws_callback_on_writable(h->cwsi); + goto do_write_nz; } const struct lws_protocols lws_sspc_protocols[] = { @@ -337,6 +439,8 @@ h = malloc(sizeof(lws_sspc_handle_t) + ssi->user_alloc + strlen(ssi->streamtype) + 1); + if (!h) + return 1; memset(h, 0, sizeof(*h)); memcpy(&h->ssi, ssi, sizeof(*ssi)); ua = (uint8_t *)&h[1]; @@ -345,11 +449,15 @@ memcpy(p, ssi->streamtype, strlen(ssi->streamtype) + 1); h->ssi.streamtype = (const char *)p; h->context = context; + if (!ssi->manual_initial_tx_credit) h->txc.peer_tx_cr_est = 500000000; else h->txc.peer_tx_cr_est = ssi->manual_initial_tx_credit; + if (!strcmp(ssi->streamtype, "_lws_smd")) + h->ignore_txc = 1; + lws_dll2_add_head(&h->client_list, &context->pt[tsi].ss_client_owner); /* fill in the things the real api does for the caller */ @@ -399,17 +507,13 @@ h->destroying = 1; - lws_sul_schedule(h->context, 0, &h->sul_retry, NULL, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&h->sul_retry); lws_dll2_remove(&h->client_list); if (h->dsh) lws_dsh_destroy(&h->dsh); - if (h->cwsi) { - struct lws *wsi = h->cwsi; + if (h->cwsi) h->cwsi = NULL; - lws_set_timeout(wsi, 1, LWS_TO_KILL_SYNC); - } /* clean out any pending metadata changes that didn't make it */ @@ -428,26 +532,85 @@ free(h); } -void +lws_ss_state_return_t lws_sspc_request_tx(lws_sspc_handle_t *h) { if (!h || !h->cwsi) - return; + return LWSSSSRET_OK; + + if (!h->us_earliest_write_req) + h->us_earliest_write_req = lws_now_usecs(); + + if (h->state == LPCSCLI_LOCAL_CONNECTED && + h->conn_req_state == LWSSSPC_ONW_NONE) + h->conn_req_state = LWSSSPC_ONW_REQ; + + lws_callback_on_writable(h->cwsi); + + return LWSSSSRET_OK; +} + +/* + * Currently we fulfil the writeable part locally by just enabling POLLOUT on + * the UDS link, without serialization footprint, which is reasonable as far as + * it goes. + * + * But for the ..._len() variant, the expected payload length hint we are being + * told is something that must be serialized to the onward peer, since either + * that guy or someone upstream of him is the guy who will compose the framing + * with it that actually goes out. + * + * This information is needed at the upstream guy before we have sent any + * payload, eg, for http POST, he has to prepare the content-length in the + * headers, before any payload. So we have to issue a serialization of the + * length at this point. + */ + +lws_ss_state_return_t +lws_sspc_request_tx_len(lws_sspc_handle_t *h, unsigned long len) +{ + /* + * for client conns, they cannot even complete creation of the handle + * without the onwared connection to the proxy, it's not legal to start + * using it until it's operation and has the onward connection (and has + * called CREATED state) + */ + + if (!h) + return LWSSSSRET_OK; + + lwsl_notice("%s: setting h %p writeable_len %u\n", __func__, h, + (unsigned int)len); + h->writeable_len = len; + h->pending_writeable_len = 1; if (!h->us_earliest_write_req) h->us_earliest_write_req = lws_now_usecs(); + if (h->state == LPCSCLI_LOCAL_CONNECTED && + h->conn_req_state == LWSSSPC_ONW_NONE) + h->conn_req_state = LWSSSPC_ONW_REQ; + + /* + * We're going to use this up with serializing h->writeable_len... that + * will request again. + */ + lws_callback_on_writable(h->cwsi); + + return LWSSSSRET_OK; } int lws_sspc_client_connect(lws_sspc_handle_t *h) { - if (!h || h->state == LPCS_OPERATIONAL) + if (!h || h->state == LPCSCLI_OPERATIONAL) return 0; - assert(h->state == LPCS_LOCAL_CONNECTED); - h->conn_req = 1; + assert(h->state == LPCSCLI_LOCAL_CONNECTED); + if (h->state == LPCSCLI_LOCAL_CONNECTED && + h->conn_req_state == LWSSSPC_ONW_NONE) + h->conn_req_state = LWSSSPC_ONW_REQ; if (h->cwsi) lws_callback_on_writable(h->cwsi); @@ -493,7 +656,7 @@ static int _lws_sspc_set_metadata(struct lws_sspc_handle *h, const char *name, - void *value, size_t len, int tx_cr_adjust) + const void *value, size_t len, int tx_cr_adjust) { lws_sspc_metadata_t *md; @@ -555,7 +718,7 @@ int lws_sspc_set_metadata(struct lws_sspc_handle *h, const char *name, - void *value, size_t len) + const void *value, size_t len) { return _lws_sspc_set_metadata(h, name, value, len, 0); } @@ -572,3 +735,39 @@ { return h->txc.peer_tx_cr_est; } + +void +lws_sspc_start_timeout(struct lws_sspc_handle *h, unsigned int timeout_ms) +{ + h->timeout_ms = (uint32_t)timeout_ms; + h->pending_timeout_update = 1; + lws_callback_on_writable(h->cwsi); +} + +void +lws_sspc_cancel_timeout(struct lws_sspc_handle *h) +{ + lws_sspc_start_timeout(h, (unsigned int)-1); +} + +void * +lws_sspc_to_user_object(struct lws_sspc_handle *h) +{ + return (void *)&h[1]; +} + +void +lws_sspc_change_handlers(struct lws_sspc_handle *h, + lws_ss_state_return_t (*rx)(void *userobj, const uint8_t *buf, size_t len, int flags), + lws_ss_state_return_t (*tx)(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, + size_t *len, int *flags), + lws_ss_state_return_t (*state)(void *userobj, void *h_src /* ss handle type */, + lws_ss_constate_t state, lws_ss_tx_ordinal_t ack)) +{ + if (rx) + h->ssi.rx = rx; + if (tx) + h->ssi.tx = tx; + if (state) + h->ssi.state = state; +} diff -Nru libwebsockets-4.0.20/lib/secure-streams/secure-streams-process.c libwebsockets-4.1.6/lib/secure-streams/secure-streams-process.c --- libwebsockets-4.0.20/lib/secure-streams/secure-streams-process.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/secure-streams/secure-streams-process.c 2020-12-01 17:40:26.000000000 +0000 @@ -84,13 +84,15 @@ /* secure streams payload interface */ -static int +static lws_ss_state_return_t ss_proxy_onward_rx(void *userobj, const uint8_t *buf, size_t len, int flags) { ss_proxy_t *m = (ss_proxy_t *)userobj; const char *rsp = NULL; int n; + // lwsl_notice("%s: len %d\n", __func__, (int)len); + /* * The onward secure stream connection has received something. */ @@ -114,7 +116,7 @@ * we are transmitting buffered payload originally from the client on to the ss */ -static int +static lws_ss_state_return_t ss_proxy_onward_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, size_t *len, int *flags) { @@ -122,7 +124,7 @@ void *p; size_t si; - if (!m->conn->ss || m->conn->state != LPCS_OPERATIONAL) { + if (!m->conn->ss || m->conn->state != LPCSPROX_OPERATIONAL) { lwsl_notice("%s: ss not ready\n", __func__); *len = 0; @@ -159,7 +161,7 @@ return 0; } -static int +static lws_ss_state_return_t ss_proxy_onward_state(void *userobj, void *sh, lws_ss_constate_t state, lws_ss_tx_ordinal_t ack) { @@ -225,7 +227,7 @@ callback_ss_proxy(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; struct raw_pss *pss = (struct raw_pss *)user; const lws_ss_policy_t *rsp; struct conn *conn = NULL; @@ -270,7 +272,7 @@ } pss->conn->wsi = wsi; - pss->conn->state = LPCS_WAIT_INITIAL_TX; + pss->conn->state = LPCSPROX_WAIT_INITIAL_TX; /* * Client is expected to follow the unix domain socket @@ -284,20 +286,35 @@ case LWS_CALLBACK_RAW_CLOSE: lwsl_info("LWS_CALLBACK_RAW_CLOSE:\n"); - /* - * the client unix domain socket connection has closed... - * eg, client has exited or otherwise has definitively finished - * with the proxying and onward connection - */ - if (!conn) break; + /* + * the client unix domain socket connection (wsi / conn->wsi) + * has closed... eg, client has exited or otherwise has + * definitively finished with the proxying and onward connection + * + * But right now, the SS and possibly the SS onward wsi are + * still live... + */ + if (conn->ss) { - lwsl_info("%s: destroying ss\n", __func__); + struct lws *cw = conn->ss->wsi; + /* + * The onward connection is around + */ + lwsl_info("%s: destroying ss.h=%p, ss.wsi=%p\n", + __func__, conn->ss, conn->ss->wsi); /* sever relationship with ss about to be deleted */ lws_set_opaque_user_data(wsi, NULL); - + if (wsi != cw) + /* + * The wsi doing the onward connection can no + * longer relate to the conn... otherwise when + * he gets callbacks he wants to bind to + * the ss we are about to delete + */ + lws_wsi_close(cw, LWS_TO_KILL_ASYNC); conn->wsi = NULL; @@ -306,7 +323,7 @@ break; } - if (conn->state == LPCS_DESTROYED || !conn->ss) { + if (conn->state == LPCSPROX_DESTROYED || !conn->ss) { /* * There's no onward secure stream and our client * connection is closing. Destroy the conn. @@ -320,6 +337,9 @@ break; case LWS_CALLBACK_RAW_RX: + /* + * ie, the proxy is receiving something from a client + */ lwsl_info("%s: RX: rx %d\n", __func__, (int)len); if (!conn || !conn->wsi) { @@ -330,7 +350,7 @@ // lwsl_hexdump_info(in, len); - if (conn->state == LPCS_WAIT_INITIAL_TX) { + if (conn->state == LPCSPROX_WAIT_INITIAL_TX) { memset(&ssi, 0, sizeof(ssi)); ssi.user_alloc = sizeof(ss_proxy_t); ssi.handle_offset = offsetof(ss_proxy_t, ss); @@ -338,18 +358,26 @@ offsetof(ss_proxy_t, conn); ssi.rx = ss_proxy_onward_rx; ssi.tx = ss_proxy_onward_tx; - ssi.state = ss_proxy_onward_state; } + ssi.state = ss_proxy_onward_state; + ssi.flags = 0; - if (lws_ss_deserialize_parse(&conn->parser, + n = lws_ss_deserialize_parse(&conn->parser, lws_get_context(wsi), conn->dsh, in, len, - &conn->state, conn, &conn->ss, &ssi, 0)) { - lwsl_err("%s: RAW_RX: deserialize_parse fail\n", __func__); + &conn->state, conn, &conn->ss, &ssi, 0); + switch (n) { + case LWSSSSRET_OK: + break; + case LWSSSSRET_DISCONNECT_ME: + return -1; + case LWSSSSRET_DESTROY_ME: + if (conn->ss) + lws_ss_destroy(&conn->ss); return -1; } - if (conn->state == LPCS_REPORTING_FAIL || - conn->state == LPCS_REPORTING_OK) + if (conn->state == LPCSPROX_REPORTING_FAIL || + conn->state == LPCSPROX_REPORTING_OK) lws_callback_on_writable(conn->wsi); break; @@ -370,10 +398,10 @@ s[3] = 0; cp = (const uint8_t *)s; switch (conn->state) { - case LPCS_REPORTING_FAIL: + case LPCSPROX_REPORTING_FAIL: s[3] = 1; /* fallthru */ - case LPCS_REPORTING_OK: + case LPCSPROX_REPORTING_OK: s[0] = LWSSS_SER_RXPRE_CREATE_RESULT; s[1] = 0; s[2] = 1; @@ -385,21 +413,23 @@ * first 4 bytes or the create result, comma-separated */ - rsp = conn->ss->policy; + if (conn->ss) { + rsp = conn->ss->policy; - while (rsp) { - if (n != 4 && n < (int)sizeof(s) - 2) - s[n++] = ','; - n += lws_snprintf(&s[n], sizeof(s) - n, - "%s", rsp->streamtype); - rsp = lws_ss_policy_lookup(wsi->context, - rsp->rideshare_streamtype); + while (rsp) { + if (n != 4 && n < (int)sizeof(s) - 2) + s[n++] = ','; + n += lws_snprintf(&s[n], sizeof(s) - n, + "%s", rsp->streamtype); + rsp = lws_ss_policy_lookup(wsi->a.context, + rsp->rideshare_streamtype); + } } s[2] = n - 3; - conn->state = LPCS_OPERATIONAL; + conn->state = LPCSPROX_OPERATIONAL; lws_set_timeout(wsi, 0, 0); break; - case LPCS_OPERATIONAL: + case LPCSPROX_OPERATIONAL: if (lws_dsh_get_head(conn->dsh, KIND_SS_TO_P, (void **)&p, &si)) break; @@ -407,7 +437,7 @@ #if defined(LWS_WITH_DETAILED_LATENCY) if (cp[0] == LWSSS_SER_RXPRE_RX_PAYLOAD && - wsi->context->detailed_latency_cb) { + wsi->a.context->detailed_latency_cb) { /* * we're fulfilling rx that came in on ss @@ -453,9 +483,9 @@ } switch (conn->state) { - case LPCS_REPORTING_FAIL: + case LPCSPROX_REPORTING_FAIL: goto hangup; - case LPCS_OPERATIONAL: + case LPCSPROX_OPERATIONAL: if (pay) lws_dsh_free((void **)&p); if (!lws_dsh_get_head(conn->dsh, KIND_SS_TO_P, @@ -482,7 +512,7 @@ hangup: //lws_ss_destroy(&conn->ss); - //conn->state = LPCS_DESTROYED; + //conn->state = LPCSPROX_DESTROYED; /* hang up on him */ return -1; diff -Nru libwebsockets-4.0.20/lib/secure-streams/secure-streams-serialize.c libwebsockets-4.1.6/lib/secure-streams/secure-streams-serialize.c --- libwebsockets-4.0.20/lib/secure-streams/secure-streams-serialize.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/secure-streams/secure-streams-serialize.c 2020-12-01 17:40:26.000000000 +0000 @@ -72,6 +72,10 @@ RPAR_TXCR0, + RPAR_TIMEOUT0, + + RPAR_PAYLEN0, + RPAR_RESULT_CREATION, RPAR_STATEINDEX, @@ -85,16 +89,17 @@ static const char *sn[] = { "unset", - "LPCS_WAIT_INITIAL_TX", - "LPCS_REPORTING_FAIL", - "LPCS_REPORTING_OK", - "LPCS_OPERATIONAL", - "LPCS_DESTROYED", - - "LPCS_SENDING_INITIAL_TX", - "LPCS_WAITING_CREATE_RESULT", - "LPCS_LOCAL_CONNECTED", - "LPCS_ONWARD_CONNECT", + "LPCSPROX_WAIT_INITIAL_TX", + "LPCSPROX_REPORTING_FAIL", + "LPCSPROX_REPORTING_OK", + "LPCSPROX_OPERATIONAL", + "LPCSPROX_DESTROYED", + + "LPCSCLI_SENDING_INITIAL_TX", + "LPCSCLI_WAITING_CREATE_RESULT", + "LPCSCLI_LOCAL_CONNECTED", + "LPCSCLI_ONWARD_CONNECT", + "LPCSCLI_OPERATIONAL", }; #endif @@ -127,6 +132,8 @@ * on a non-default rideshare */ assert(rsp); + if (!rsp) + return 1; l = strlen(rsp); est += 1 + l; } else @@ -185,7 +192,9 @@ if (*len <= si - 23 || si < 23) { /* - * What comes out of the dsh needs to fit in the tx buffer + * What comes out of the dsh needs to fit in the tx buffer... + * we have arrangements at the proxy rx of the client UDS to + * chop chunks larger than 1380 into seuqential lumps of 1380 */ lwsl_err("%s: *len = %d, si = %d\n", __func__, (int)*len, (int)si); assert(0); @@ -197,14 +206,23 @@ } *len = lws_ser_ru16be(&p[1]) - (23 - 3); - assert(*len == si - 23); + if (*len != si - 23) { + /* + * We cannot accept any length that doesn't reflect the actual + * length of what came in from the dsh, either something nasty + * happened with truncation or we are being attacked + */ + assert(0); + + return 1; + } memcpy(buf, p + 23, si - 23); *flags = lws_ser_ru32be(&p[3]); #if defined(LWS_WITH_DETAILED_LATENCY) - if (wsi && wsi->context->detailed_latency_cb) { + if (wsi && wsi->a.context->detailed_latency_cb) { /* * use the proxied latency information to compute the client * and our delays, and apply to wsi. @@ -244,18 +262,27 @@ lws_ss_serialize_state(struct lws_dsh *dsh, lws_ss_constate_t state, lws_ss_tx_ordinal_t ack) { - uint8_t pre[8]; + uint8_t pre[12]; + int n = 4; lwsl_info("%s: %s, ord 0x%x\n", __func__, lws_ss_state_name(state), (unsigned int)ack); pre[0] = LWSSS_SER_RXPRE_CONNSTATE; pre[1] = 0; - pre[2] = 5; - pre[3] = (uint8_t)state; - lws_ser_wu32be(&pre[4], ack); - if (lws_dsh_alloc_tail(dsh, KIND_SS_TO_P, pre, 8, NULL, 0)) { + if (state > 255) { + pre[2] = 8; + lws_ser_wu32be(&pre[3], state); + n = 7; + } else { + pre[2] = 5; + pre[3] = (uint8_t)state; + } + + lws_ser_wu32be(&pre[n], ack); + + if (lws_dsh_alloc_tail(dsh, KIND_SS_TO_P, pre, n + 4, NULL, 0)) { lwsl_err("%s: unable to alloc in dsh 2\n", __func__); return 1; @@ -294,8 +321,38 @@ * event loop side is consuming serialized data from the client via dsh, parse * it using a bytewise parser for the serialization header(s)... * it's possibly coalesced + * + * client: pss is pointing to the start of userdata. We can use + * pss_to_sspc_h(_pss, _ssi) to convert that to a pointer to the sspc + * handle + * + * proxy: pss is pointing to &conn->ss, a pointer to the ss handle + * + * Returns one of + * + * LWSSSSRET_OK + * LWSSSSRET_DISCONNECT_ME + * LWSSSSRET_DESTROY_ME */ +/* convert userdata ptr _pss to handle pointer, allowing for any layout in + * userdata */ +#define client_pss_to_sspc_h(_pss, _ssi) (*((lws_sspc_handle_t **) \ + ((uint8_t *)_pss) + _ssi->handle_offset)) +/* client pss to sspc userdata */ +#define client_pss_to_userdata(_pss) ((void *)_pss) +/* proxy convert pss to ss handle */ +#define proxy_pss_to_ss_h(_pss) (*_pss) + +/* convert userdata ptr _pss to handle pointer, allowing for any layout in + * userdata */ +#define client_pss_to_sspc_h(_pss, _ssi) (*((lws_sspc_handle_t **) \ + ((uint8_t *)_pss) + _ssi->handle_offset)) +/* client pss to sspc userdata */ +#define client_pss_to_userdata(_pss) ((void *)_pss) +/* proxy convert pss to ss handle */ +#define proxy_pss_to_ss_h(_pss) (*_pss) + int lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, struct lws_context *context, @@ -332,8 +389,9 @@ case LWSSS_SER_TXPRE_TX_PAYLOAD: if (client) goto hangup; - if (*state != LPCS_OPERATIONAL) + if (*state != LPCSPROX_OPERATIONAL) goto hangup; + par->ps = RPAR_FLAG_B3; break; @@ -347,17 +405,20 @@ case LWSSS_SER_TXPRE_ONWARD_CONNECT: if (client) goto hangup; - if (*state != LPCS_OPERATIONAL) + if (*state != LPCSPROX_OPERATIONAL) goto hangup; par->ps = RPAR_TYPE; - if (*pss) - _lws_ss_client_connect(*pss, 0); + lwsl_notice("%s: LWSSS_SER_TXPRE_ONWARD_CONNECT\n", __func__); + if (proxy_pss_to_ss_h(pss) && + !proxy_pss_to_ss_h(pss)->wsi) + _lws_ss_client_connect( + proxy_pss_to_ss_h(pss), 0); break; case LWSSS_SER_TXPRE_STREAMTYPE: if (client) goto hangup; - if (*state != LPCS_WAIT_INITIAL_TX) + if (*state != LPCSPROX_WAIT_INITIAL_TX) goto hangup; if (par->rem < 4) goto hangup; @@ -379,16 +440,33 @@ par->ctr = 0; break; + case LWSSS_SER_TXPRE_TIMEOUT_UPDATE: + if (client) + goto hangup; + if (par->rem != 4) + goto hangup; + par->ps = RPAR_TIMEOUT0; + par->ctr = 0; + break; + + case LWSSS_SER_TXPRE_PAYLOAD_LENGTH_HINT: + if (client) + goto hangup; + if (par->rem != 4) + goto hangup; + par->ps = RPAR_PAYLEN0; + par->ctr = 0; + break; + /* client side */ case LWSSS_SER_RXPRE_RX_PAYLOAD: if (!client) goto hangup; - if (*state != LPCS_OPERATIONAL && - *state != LPCS_LOCAL_CONNECTED) { - lwsl_err("rx in state %d\n", *state); + if (*state != LPCSCLI_OPERATIONAL && + *state != LPCSCLI_LOCAL_CONNECTED) goto hangup; - } + par->rideshare[0] = '\0'; par->ps = RPAR_FLAG_B3; break; @@ -396,30 +474,27 @@ case LWSSS_SER_RXPRE_CREATE_RESULT: if (!client) goto hangup; - if (*state != LPCS_WAITING_CREATE_RESULT) { - lwsl_err("a2\n"); + if (*state != LPCSCLI_WAITING_CREATE_RESULT) goto hangup; - } - if (par->rem < 1) { - lwsl_err("a3\n"); + + if (par->rem < 1) goto hangup; - } + par->ps = RPAR_RESULT_CREATION; break; case LWSSS_SER_RXPRE_CONNSTATE: if (!client) goto hangup; - if (*state != LPCS_LOCAL_CONNECTED && - *state != LPCS_OPERATIONAL) { - lwsl_err("a4\n"); + if (*state != LPCSCLI_LOCAL_CONNECTED && + *state != LPCSCLI_OPERATIONAL) goto hangup; - } - if (par->rem < 4) { - lwsl_err("a5\n"); + + if (par->rem < 5 || par->rem > 8) goto hangup; - } + par->ps = RPAR_STATEINDEX; + par->ctr = 0; break; case LWSSS_SER_RXPRE_TXCR_UPDATE: @@ -514,17 +589,44 @@ n = (int)len + 1; if (n > par->rem) n = par->rem; + /* + * We get called with a serialized buffer of a size + * chosen by the client. We can only create dsh entries + * with up to 1380 payload, to guarantee we can emit + * them on the onward connection atomically. + * + * If 1380 isn't enough to cover what was handed to us, + * we'll stop at 1380 and go around again and create + * more dsh entries for the rest, with their own + * headers. + */ + if (n > 1380) n = 1380; - /* deal with refragmented SOM / EOM flags */ + /* + * Since we're in the business of fragmenting client + * serialized payloads at 1380, we have to deal with + * refragmenting the SOM / EOM flags that covered the + * whole client serialized packet, so they apply to + * each dsh entry we split it into correctly + */ flags = par->flags & LWSSS_FLAG_RELATED_START; if (par->frag1) + /* + * Only set the first time we came to this + * state after deserialization of the header + */ flags |= par->flags & (LWSSS_FLAG_SOM | LWSSS_FLAG_POLL); if (par->rem == n) + /* + * We are going to complete the advertised + * payload length from the client on this dsh, + * so give him the EOM type flags if any + */ flags |= par->flags & (LWSSS_FLAG_EOM | LWSSS_FLAG_RELATED_END); @@ -537,16 +639,18 @@ * the client. * * The header for buffering private to the - * proxy is 23 bytes vs 19 to hold the + * proxy is 23 bytes vs 19, so we can hold the * current time when it was buffered + * additionally */ - lwsl_info("%s: C2P RX: len %d\n", __func__, (int)n); + lwsl_info("%s: C2P RX: len %d\n", __func__, + (int)n); p = pre; pre[0] = LWSSS_SER_TXPRE_TX_PAYLOAD; lws_ser_wu16be(&p[1], n + 23 - 3); - lws_ser_wu32be(&p[3], par->flags); + lws_ser_wu32be(&p[3], flags); /* us held at client before written */ lws_ser_wu32be(&p[7], par->usd_phandling); /* us taken for transit to proxy */ @@ -559,10 +663,12 @@ lwsl_err("%s: unable to alloc in dsh 3\n", __func__); - return 1; + return LWSSSSRET_DISCONNECT_ME; } - lws_ss_request_tx(*pss); + if (proxy_pss_to_ss_h(pss)) + lws_ss_request_tx( + proxy_pss_to_ss_h(pss)); } else { /* @@ -571,12 +677,26 @@ * Pass whatever payload we have to ss user */ - lwsl_info("%s: P2C RX: len %d\n", __func__, (int)n); + lwsl_info("%s: P2C RX: len %d\n", __func__, + (int)n); - h = lws_container_of(par, lws_sspc_handle_t, parser); + h = lws_container_of(par, lws_sspc_handle_t, + parser); h->txc.peer_tx_cr_est -= n; - ssi->rx((void *)pss, (uint8_t *)cp, n, flags); + if (client_pss_to_sspc_h(pss, ssi)) { + /* we still have an sspc handle */ + int ret = ssi->rx(client_pss_to_userdata(pss), + (uint8_t *)cp, n, flags); + switch (ret) { + case LWSSSSRET_OK: + break; + case LWSSSSRET_DISCONNECT_ME: + goto hangup; + case LWSSSSRET_DESTROY_ME: + return LWSSSSRET_DESTROY_ME; + } + } #if defined(LWS_WITH_DETAILED_LATENCY) if (lws_det_lat_active(context)) { @@ -600,6 +720,11 @@ cp += n; par->rem -= n; len = (len + 1) - n; + /* + * if we didn't consume it all, we'll come + * around again and produce more dsh entries up + * to 1380 each until it is gone + */ } if (!par->rem) par->ps = RPAR_TYPE; @@ -663,14 +788,17 @@ * on the onward connection towards it. */ #if defined(LWS_ROLE_H2) || defined(LWS_ROLE_MQTT) - if ((*pss)->wsi) { - lws_wsi_tx_credit((*pss)->wsi, + if (proxy_pss_to_ss_h(pss) && + proxy_pss_to_ss_h(pss)->wsi) { + lws_wsi_tx_credit( + proxy_pss_to_ss_h(pss)->wsi, LWSTXCR_PEER_TO_US, par->temp32); lwsl_notice("%s: proxy RX_PEER_TXCR: +%d (est %d)\n", __func__, par->temp32, - (*pss)->wsi->txc.peer_tx_cr_est); - lws_ss_request_tx(*pss); + proxy_pss_to_ss_h(pss)->wsi-> + txc.peer_tx_cr_est); + lws_ss_request_tx(proxy_pss_to_ss_h(pss)); } else #endif lwsl_info("%s: dropping TXCR\n", __func__); @@ -681,7 +809,8 @@ * remote peer, allowing the client to write to * it. */ - h = lws_container_of(par, lws_sspc_handle_t, parser); + h = lws_container_of(par, lws_sspc_handle_t, + parser); h->txc.tx_cr += par->temp32; lwsl_info("%s: client RX_PEER_TXCR: %d\n", __func__, par->temp32); @@ -690,6 +819,75 @@ par->ps = RPAR_TYPE; break; + case RPAR_TIMEOUT0: + + par->temp32 = (par->temp32 << 8) | *cp++; + if (++par->ctr < 4) { + if (!--par->rem) + goto hangup; + break; + } + + if (--par->rem) + goto hangup; + + /* + * Proxy... + * + * *pss may have gone away asynchronously inbetweentimes + */ + + if (proxy_pss_to_ss_h(pss)) { + + if ((unsigned int)par->temp32 == 0xffffffff) { + lwsl_notice("%s: cancel ss timeout\n", + __func__); + lws_ss_cancel_timeout( + proxy_pss_to_ss_h(pss)); + } else { + + if (!par->temp32) + par->temp32 = + proxy_pss_to_ss_h(pss)-> + policy->timeout_ms; + + lwsl_notice("%s: set ss timeout for +%ums\n", + __func__, par->temp32); + + lws_ss_start_timeout( + proxy_pss_to_ss_h(pss), + par->temp32); + } + } + + par->ps = RPAR_TYPE; + break; + + case RPAR_PAYLEN0: + /* + * It's the length from lws_ss_request_tx_len() being + * passed up to the proxy + */ + par->temp32 = (par->temp32 << 8) | *cp++; + if (++par->ctr < 4) { + if (!--par->rem) + goto hangup; + break; + } + + if (--par->rem) + goto hangup; + + lwsl_notice("%s: set payload len %u\n", __func__, + par->temp32); + + if (proxy_pss_to_ss_h(pss)) + lws_ss_request_tx_len(proxy_pss_to_ss_h(pss), + par->temp32); + + par->ps = RPAR_TYPE; + break; + case RPAR_METADATA_NAMELEN: if (!--par->rem) goto hangup; @@ -706,15 +904,19 @@ par->metadata_name[par->ctr++] = *cp++; if (par->ctr != par->slen) break; + par->metadata_name[par->ctr] = '\0'; par->ps = RPAR_METADATA_VALUE; - /* only non-client side can receive these */ + /* only proxy side can receive these */ + + if (!proxy_pss_to_ss_h(pss)) + goto hangup; /* * This is the policy's metadata list for the given * name */ - pm = lws_ss_policy_metadata((*pss)->policy, + pm = lws_ss_policy_metadata(proxy_pss_to_ss_h(pss)->policy, par->metadata_name); if (!pm) { lwsl_err("%s: metadata %s not in proxy policy\n", @@ -723,7 +925,7 @@ goto hangup; } - par->ssmd = &(*pss)->metadata[pm->length]; + par->ssmd = &proxy_pss_to_ss_h(pss)->metadata[pm->length]; if (par->ssmd->value_on_lws_heap) lws_free_set_NULL(par->ssmd->value); @@ -754,12 +956,24 @@ break; case RPAR_STREAMTYPE: + + /* only the proxy can get these */ + if (client) goto hangup; if (par->ctr == sizeof(par->streamtype) - 1) goto hangup; /* + * We can only expect to get this if we ourselves are + * in the state that we're waiting for it. If it comes + * later it's a protocol error. + */ + + if (*state != LPCSPROX_WAIT_INITIAL_TX) + goto hangup; + + /* * We're the proxy, creating an SS on behalf of a * client */ @@ -774,10 +988,18 @@ __func__, par->streamtype, par->txcr_out); ssi->streamtype = par->streamtype; - if (par->txcr_out) + if (par->txcr_out) // !!! ssi->manual_initial_tx_credit = par->txcr_out; - if (lws_ss_create(context, 0, ssi, parconn, pss, NULL, NULL)) { + /* + * Even for a synthetic SS proxing action like _lws_smd, + * we create an actual SS in the proxy representing the + * connection + */ + + ssi->flags |= LWSSSINFLAGS_PROXIED; + if (lws_ss_create(context, 0, ssi, parconn, pss, + NULL, NULL)) { /* * We're unable to create the onward secure * stream he asked for... schedule a chance to @@ -785,18 +1007,28 @@ */ lwsl_err("%s: create '%s' fail\n", __func__, par->streamtype); - *state = LPCS_REPORTING_FAIL; + *state = LPCSPROX_REPORTING_FAIL; } else { lwsl_debug("%s: create '%s' OK\n", __func__, par->streamtype); - *state = LPCS_REPORTING_OK; + *state = LPCSPROX_REPORTING_OK; } if (*pss) { (*pss)->being_serialized = 1; - lwsl_notice("%s: Created SS initial credit %d\n", - __func__, par->txcr_out); - (*pss)->info.manual_initial_tx_credit = par->txcr_out; +#if defined(LWS_WITH_SYS_SMD) + if ((*pss)->policy != &pol_smd) + /* + * In SMD case we overloaded the + * initial credit to be the class mask + */ +#endif + { + lwsl_info("%s: Created SS initial credit %d\n", + __func__, par->txcr_out); + + (*pss)->info.manual_initial_tx_credit = par->txcr_out; + } } /* parent needs to schedule write on client conn */ @@ -811,11 +1043,13 @@ goto hangup; } + /* + * Client + */ + lws_ss_serialize_state_transition(state, - LPCS_LOCAL_CONNECTED); + LPCSCLI_LOCAL_CONNECTED); h = lws_container_of(par, lws_sspc_handle_t, parser); - if (h->cwsi) - lws_callback_on_writable(h->cwsi); /* * This is telling us that the streamtype could be (and @@ -824,11 +1058,38 @@ * * We'll get a proxied state() coming later that informs * us about the situation with that. + * + * However at this point, we should choose to inform + * the client that his stream was created... we will + * later get a proxied CREATING state from the peer + * but we should do it now and suppress the later one. + * + * The reason is he may set metadata in CREATING, and + * we will try to do writeables to sync the stream to + * master and ultimately bring up the onward connection now + * now we are in LOCAL_CONNECTED. We need to do the + * CREATING now so we'll know the metadata to sync. */ + h->creating_cb_done = 1; + + n = ssi->state(client_pss_to_userdata(pss), + NULL, LWSSSCS_CREATING, 0); + switch (n) { + case LWSSSSRET_OK: + break; + case LWSSSSRET_DISCONNECT_ME: + goto hangup; + case LWSSSSRET_DESTROY_ME: + return LWSSSSRET_DESTROY_ME; + } + + if (h->cwsi) + lws_callback_on_writable(h->cwsi); + par->rsl_pos = 0; par->rsl_idx = 0; - h = lws_container_of(par, lws_sspc_handle_t, parser); + memset(&h->rideshare_ofs[0], 0, sizeof(h->rideshare_ofs[0])); h->rideshare_list[0] = '\0'; h->rsidx = 0; @@ -857,8 +1118,9 @@ break; case RPAR_STATEINDEX: - par->ctr = *cp++; - par->ps = RPAR_ORD3; + par->ctr = (par->ctr << 8) | (*cp++); + if (--par->rem == 4) + par->ps = RPAR_ORD3; break; case RPAR_ORD3: @@ -882,45 +1144,89 @@ par->ps = RPAR_TYPE; /* - * we received a proxied state change + * Client received a proxied state change */ + if (!client_pss_to_sspc_h(pss, ssi)) + /* + * Since we're being informed we need to have + * a stream to inform. Assume whatever set this + * to NULL has started to close it. + */ + break; + switch (par->ctr) { case LWSSSCS_DISCONNECTED: case LWSSSCS_UNREACHABLE: case LWSSSCS_AUTH_FAILED: lws_ss_serialize_state_transition(state, - LPCS_LOCAL_CONNECTED); + LPCSCLI_LOCAL_CONNECTED); + client_pss_to_sspc_h(pss, ssi)->conn_req_state = + LWSSSPC_ONW_NONE; break; case LWSSSCS_CONNECTED: lwsl_info("%s: CONNECTED %s\n", __func__, ssi->streamtype); + if (*state == LPCSCLI_OPERATIONAL) + /* + * Don't allow to see connected more + * than once for one connection + */ + goto swallow; lws_ss_serialize_state_transition(state, - LPCS_OPERATIONAL); + LPCSCLI_OPERATIONAL); + + client_pss_to_sspc_h(pss, ssi)->conn_req_state = + LWSSSPC_ONW_CONN; + break; + case LWSSSCS_TIMEOUT: break; default: break; } - if (par->ctr < 0 || par->ctr > 9) + if (par->ctr < 0) goto hangup; #if defined(_DEBUG) lwsl_info("%s: forwarding proxied state %s\n", - __func__, sn[par->ctr]); + __func__, lws_ss_state_name(par->ctr)); #endif - if (ssi->state((void *)pss, NULL, par->ctr, par->flags)) + + if (par->ctr == LWSSSCS_CREATING) { + if (h->creating_cb_done) + /* + * We have told him he's CREATING when + * we heard we had linked up to the + * proxy, so suppress the remote + * CREATING so that he only sees it once + */ + break; + + h->creating_cb_done = 1; + } + + n = ssi->state(client_pss_to_userdata(pss), + NULL, par->ctr, par->flags); + switch (n) { + case LWSSSSRET_OK: + break; + case LWSSSSRET_DISCONNECT_ME: goto hangup; - break; + case LWSSSSRET_DESTROY_ME: + return LWSSSSRET_DESTROY_ME; + } +swallow: + break; default: goto hangup; } } - return 0; + return LWSSSSRET_OK; hangup: - return -1; + return LWSSSSRET_DISCONNECT_ME; } diff -Nru libwebsockets-4.0.20/lib/secure-streams/system/auth-api.amazon.com/auth.c libwebsockets-4.1.6/lib/secure-streams/system/auth-api.amazon.com/auth.c --- libwebsockets-4.0.20/lib/secure-streams/system/auth-api.amazon.com/auth.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/secure-streams/system/auth-api.amazon.com/auth.c 2020-12-01 17:40:26.000000000 +0000 @@ -31,7 +31,6 @@ void *opaque_data; /* ... application specific state ... */ struct lejp_ctx jctx; - lws_sorted_usec_list_t sul; size_t pos; int expires_secs; } ss_api_amazon_auth_t; @@ -67,9 +66,7 @@ struct lws_context *context = lws_container_of(sul, struct lws_context, sul_api_amazon_com); - /* if nothing is there to intercept anything, go all the way */ - lws_state_transition_steps(&context->mgr_system, - LWS_SYSTATE_OPERATIONAL); + lws_ss_sys_auth_api_amazon_com(context); } static signed char @@ -77,6 +74,7 @@ { ss_api_amazon_auth_t *m = (ss_api_amazon_auth_t *)ctx->user; struct lws_context *context = (struct lws_context *)m->opaque_data; + lws_system_blob_t *blob; if (!(reason & LEJP_FLAG_CB_IS_VALUE) || !ctx->path_match) return 0; @@ -85,12 +83,17 @@ case LSSPPT_ACCESS_TOKEN: if (!ctx->npos) break; - if (lws_system_blob_heap_append(lws_system_get_blob(context, - LWS_SYSBLOB_TYPE_AUTH, - AUTH_IDX_LWA), + + blob = lws_system_get_blob(context, LWS_SYSBLOB_TYPE_AUTH, + AUTH_IDX_LWA); + if (!blob) + return -1; + + if (lws_system_blob_heap_append(blob, (const uint8_t *)ctx->buf, ctx->npos)) { lwsl_err("%s: unable to store auth token\n", __func__); + return -1; } break; @@ -107,7 +110,7 @@ /* secure streams payload interface */ -static int +static lws_ss_state_return_t ss_api_amazon_auth_rx(void *userobj, const uint8_t *buf, size_t len, int flags) { ss_api_amazon_auth_t *m = (ss_api_amazon_auth_t *)userobj; @@ -117,6 +120,9 @@ int n; ab = lws_system_get_blob(context, LWS_SYSBLOB_TYPE_AUTH, AUTH_IDX_LWA); + /* coverity */ + if (!ab) + return -1; if (buf) { if (flags & LWSSS_FLAG_SOM) { @@ -126,7 +132,7 @@ lws_system_blob_heap_empty(ab); } - n = (int)(signed char)lejp_parse(&m->jctx, buf, len); + n = lejp_parse(&m->jctx, buf, (int)len); if (n < 0) { lejp_destruct(&m->jctx); lws_system_blob_destroy( @@ -153,7 +159,7 @@ return 0; } -static int +static lws_ss_state_return_t ss_api_amazon_auth_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, size_t *len, int *flags) { @@ -169,6 +175,9 @@ */ ab = lws_system_get_blob(context, LWS_SYSBLOB_TYPE_AUTH, AUTH_IDX_ROOT); + if (!ab) + return LWSSSSRET_DESTROY_ME; + total = lws_system_blob_get_size(ab); n = lws_system_blob_get(ab, buf, len, m->pos); @@ -188,24 +197,32 @@ return 0; } -static int +static lws_ss_state_return_t ss_api_amazon_auth_state(void *userobj, void *sh, lws_ss_constate_t state, lws_ss_tx_ordinal_t ack) { ss_api_amazon_auth_t *m = (ss_api_amazon_auth_t *)userobj; struct lws_context *context = (struct lws_context *)m->opaque_data; + lws_system_blob_t *ab; size_t s; lwsl_info("%s: %s, ord 0x%x\n", __func__, lws_ss_state_name(state), (unsigned int)ack); + ab = lws_system_get_blob(context, LWS_SYSBLOB_TYPE_AUTH, AUTH_IDX_ROOT); + /* coverity */ + if (!ab) + return LWSSSSRET_DESTROY_ME; + switch (state) { case LWSSSCS_CREATING: + lws_ss_set_metadata(m->ss, "ctype", "application/json", 16); + /* fallthru */ case LWSSSCS_CONNECTING: - s = lws_system_blob_get_size( - lws_system_get_blob(context, LWS_SYSBLOB_TYPE_AUTH, - AUTH_IDX_ROOT)); - lws_ss_request_tx_len(m->ss, s); + s = lws_system_blob_get_size(ab); + if (!s) + lwsl_debug("%s: no auth blob\n", __func__); + lws_ss_request_tx_len(m->ss, (unsigned long)s); m->pos = 0; break; @@ -222,23 +239,15 @@ * when the close process for the auth wsi has completed and * the related tls is already freed. */ - s = lws_system_blob_get_size( - lws_system_get_blob(context, LWS_SYSBLOB_TYPE_AUTH, - AUTH_IDX_LWA)); + s = lws_system_blob_get_size(ab); - if (s) + if (s && context->mgr_system.state != LWS_SYSTATE_OPERATIONAL) lws_sul_schedule(context, 0, &context->sul_api_amazon_com_kick, lws_ss_sys_auth_api_amazon_com_kick, 1); - break; - case LWSSSCS_DESTROYING: - lws_sul_schedule(context, 0, &context->sul_api_amazon_com, - NULL, LWS_SET_TIMER_USEC_CANCEL); - lws_system_blob_destroy( - lws_system_get_blob(context, LWS_SYSBLOB_TYPE_AUTH, - AUTH_IDX_LWA)); - break; + context->hss_auth = NULL; + return LWSSSSRET_DESTROY_ME; default: break; diff -Nru libwebsockets-4.0.20/lib/secure-streams/system/captive-portal-detect/captive-portal-detect.c libwebsockets-4.1.6/lib/secure-streams/system/captive-portal-detect/captive-portal-detect.c --- libwebsockets-4.0.20/lib/secure-streams/system/captive-portal-detect/captive-portal-detect.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/secure-streams/system/captive-portal-detect/captive-portal-detect.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,89 @@ +/* + * Captive portal detect for Secure Streams + * + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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 + +typedef struct ss_cpd { + struct lws_ss_handle *ss; + void *opaque_data; + /* ... application specific state ... */ + + lws_sorted_usec_list_t sul; +} ss_cpd_t; + +static lws_ss_state_return_t +ss_cpd_state(void *userobj, void *sh, lws_ss_constate_t state, + lws_ss_tx_ordinal_t ack) +{ + ss_cpd_t *m = (ss_cpd_t *)userobj; + struct lws_context *cx = (struct lws_context *)m->opaque_data; + + lwsl_info("%s: %s, ord 0x%x\n", __func__, lws_ss_state_name(state), + (unsigned int)ack); + + switch (state) { + case LWSSSCS_CREATING: + lws_ss_request_tx(m->ss); + break; + case LWSSSCS_QOS_ACK_REMOTE: + lws_system_cpd_set(cx, LWS_CPD_INTERNET_OK); + return LWSSSSRET_DESTROY_ME; + + case LWSSSCS_ALL_RETRIES_FAILED: + case LWSSSCS_DISCONNECTED: + /* + * First result reported sticks... if nothing else, this will + * cover the situation we didn't connect to anything + */ + lws_system_cpd_set(cx, LWS_CPD_NO_INTERNET); + return LWSSSSRET_DESTROY_ME; + + default: + break; + } + + return LWSSSSRET_OK; +} + +static const lws_ss_info_t ssi_cpd = { + .handle_offset = offsetof(ss_cpd_t, ss), + .opaque_user_data_offset = offsetof(ss_cpd_t, opaque_data), + .state = ss_cpd_state, + .user_alloc = sizeof(ss_cpd_t), + .streamtype = "captive_portal_detect", +}; + +int +lws_ss_sys_cpd(struct lws_context *cx) +{ + if (lws_ss_create(cx, 0, &ssi_cpd, cx, NULL, NULL, NULL)) { + lwsl_info("%s: Create stream failed (policy?)\n", __func__); + + return 1; + } + + return 0; +} diff -Nru libwebsockets-4.0.20/lib/secure-streams/system/fetch-policy/fetch-policy.c libwebsockets-4.1.6/lib/secure-streams/system/fetch-policy/fetch-policy.c --- libwebsockets-4.0.20/lib/secure-streams/system/fetch-policy/fetch-policy.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/secure-streams/system/fetch-policy/fetch-policy.c 2020-12-01 17:40:26.000000000 +0000 @@ -38,20 +38,20 @@ /* secure streams payload interface */ -static int +static lws_ss_state_return_t ss_fetch_policy_rx(void *userobj, const uint8_t *buf, size_t len, int flags) { ss_fetch_policy_t *m = (ss_fetch_policy_t *)userobj; struct lws_context *context = (struct lws_context *)m->opaque_data; if (flags & LWSSS_FLAG_SOM) { - if (lws_ss_policy_parse_begin(context)) - return 1; + if (lws_ss_policy_parse_begin(context, 0)) + return LWSSSSRET_OK; m->partway = 1; } if (len && lws_ss_policy_parse(context, buf, len) < 0) - return 1; + return LWSSSSRET_OK; if (flags & LWSSS_FLAG_EOM) m->partway = 2; @@ -59,7 +59,7 @@ return 0; } -static int +static lws_ss_state_return_t ss_fetch_policy_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, size_t *len, int *flags) { @@ -77,16 +77,20 @@ * ss connection close that was using the vhost from the old policy */ + lws_ss_destroy(&m->ss); + if (lws_ss_policy_set(context, "updated")) lwsl_err("%s: policy set failed\n", __func__); else { context->policy_updated = 1; +#if defined(LWS_WITH_SYS_STATE) lws_state_transition_steps(&context->mgr_system, LWS_SYSTATE_OPERATIONAL); +#endif } } -static int +static lws_ss_state_return_t ss_fetch_policy_state(void *userobj, void *sh, lws_ss_constate_t state, lws_ss_tx_ordinal_t ack) { diff -Nru libwebsockets-4.0.20/lib/system/async-dns/async-dns.c libwebsockets-4.1.6/lib/system/async-dns/async-dns.c --- libwebsockets-4.0.20/lib/system/async-dns/async-dns.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/system/async-dns/async-dns.c 2020-12-01 17:40:26.000000000 +0000 @@ -88,8 +88,16 @@ __func__, q, c, c->refcount, c->refcount + 1); c->refcount++; } - w->adns_cb(w, (const char *)&q[1], c ? c->results : NULL, 0, - q->opaque); + lws_set_timeout(w, NO_PENDING_TIMEOUT, 0); + /* + * This may decide to close / delete w + */ + if (w->adns_cb(w, (const char *)&q[1], c ? c->results : NULL, 0, + q->opaque) == NULL) + lwsl_notice("%s: failed\n", __func__); + // lws_close_free_wsi(w, LWS_CLOSE_STATUS_NOSTATUS, + // "adopt udp2 fail"); + } lws_end_foreach_dll_safe(d, d1); if (q->standalone_cb) { @@ -214,8 +222,8 @@ n = lws_ptr_diff(p, pkt + LWS_PRE); m = lws_write(wsi, pkt + LWS_PRE, n, 0); if (m != n) { - lwsl_notice("%s: dns write failed %d %d\n", __func__, - m, n); + lwsl_notice("%s: dns write failed %d %d errno %d\n", __func__, + m, n, errno); goto qfail; } @@ -298,6 +306,11 @@ char ads[48]; int n; + if (!context->vhost_list) { /* coverity... system vhost always present */ + lwsl_err("%s: no system vhost\n", __func__); + return 1; + } + memset(&dns->sa46, 0, sizeof(dns->sa46)); #if defined(LWS_WITH_SYS_DHCP_CLIENT) @@ -472,7 +485,7 @@ void lws_async_dns_cancel(struct lws *wsi) { - lws_async_dns_t *dns = &wsi->context->async_dns; + lws_async_dns_t *dns = &wsi->a.context->async_dns; lws_dll2_foreach_safe(&dns->waiting, wsi, cancel); } @@ -577,7 +590,8 @@ m = c->results ? LADNS_RET_FOUND : LADNS_RET_FAILED; if (c->results) c->refcount++; - cb(wsi, name, c->results, m, opaque); + if (cb(wsi, name, c->results, m, opaque) == NULL) + return LADNS_RET_FAILED_WSI_CLOSED; return m; } diff -Nru libwebsockets-4.0.20/lib/system/CMakeLists.txt libwebsockets-4.1.6/lib/system/CMakeLists.txt --- libwebsockets-4.0.20/lib/system/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/system/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,65 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(./async-dns) + +list(APPEND SOURCES + system/system.c) + +if (LWS_WITH_NETWORK) + + if (LWS_WITH_SYS_ASYNC_DNS) + list(APPEND SOURCES + system/async-dns/async-dns.c + system/async-dns/async-dns-parse.c) + endif() + + if (LWS_WITH_SYS_NTPCLIENT) + list(APPEND SOURCES + system/ntpclient/ntpclient.c) + endif() + + if (LWS_WITH_SYS_DHCP_CLIENT) + list(APPEND SOURCES + system/dhcpclient/dhcpclient.c) + endif() + + if (LWS_WITH_SYS_SMD) + add_subdir_include_dirs(smd) + endif() + +endif() + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() diff -Nru libwebsockets-4.0.20/lib/system/dhcpclient/dhcpclient.c libwebsockets-4.1.6/lib/system/dhcpclient/dhcpclient.c --- libwebsockets-4.0.20/lib/system/dhcpclient/dhcpclient.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/system/dhcpclient/dhcpclient.c 2020-12-01 17:40:26.000000000 +0000 @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2020 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -220,7 +220,7 @@ r->wsi_raw->user_space = r; r->wsi_raw->user_space_externally_allocated = 1; - lws_get_random(r->wsi_raw->context, r->xid, 4); + lws_get_random(r->wsi_raw->a.context, r->xid, 4); } static void @@ -234,22 +234,6 @@ lws_callback_on_writable(r->wsi_raw); } -#if 0 -static int -lws_sys_dhcpc_notify_cb(lws_state_manager_t *mgr, lws_state_notify_link_t *l, - int current, int target) -{ - lws_dhcpc_req_t *r = lws_container_of(l, lws_dhcpc_req_t, notify_link); - - if (target != LWS_SYSTATE_TIME_VALID || v->set_time) - return 0; - - /* it's trying to do it ever since the protocol / vhost was set up */ - - return 1; -} -#endif - static int lws_dhcpc_prep(uint8_t *start, int bufsiz, lws_dhcpc_req_t *r, int op) { @@ -334,12 +318,11 @@ if (!r) break; r->wsi_raw = NULL; - lws_sul_schedule(r->context, 0, &r->sul_write, NULL, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&r->sul_write); if (r->state != LDHC_BOUND) { r->state = LDHC_INIT; - lws_retry_sul_schedule(r->context, 0, &r->sul_conn, &bo2, - lws_dhcpc_retry_conn, + lws_retry_sul_schedule(r->context, 0, &r->sul_conn, + &bo2, lws_dhcpc_retry_conn, &r->retry_count_conn); } break; @@ -480,7 +463,8 @@ #if defined(_DEBUG) /* dump what we have parsed out */ - for (n = 0; n < (int)LWS_ARRAY_SIZE(dhcp_entry_names); n++) + for (n = 0; n < (int)LWS_ARRAY_SIZE(dhcp_entry_names); + n++) if (n >= IPV4_LEASE_SECS) lwsl_info("%s: %s: %ds\n", __func__, dhcp_entry_names[n], @@ -553,16 +537,14 @@ /* clear timeouts related to the broadcast socket */ - lws_sul_schedule(r->context, 0, &r->sul_write, NULL, - LWS_SET_TIMER_USEC_CANCEL); - lws_sul_schedule(r->context, 0, &r->sul_conn, NULL, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&r->sul_write); + lws_sul_cancel(&r->sul_conn); lwsl_notice("%s: DHCP configured %s\n", __func__, (const char *)&r[1]); r->state = LDHC_BOUND; - lws_state_transition_steps(&wsi->context->mgr_system, + lws_state_transition_steps(&wsi->a.context->mgr_system, LWS_SYSTATE_OPERATIONAL); r->cb(r->opaque, r->af, @@ -636,7 +618,7 @@ return 0; retry_conn: - lws_retry_sul_schedule(wsi->context, 0, &r->sul_conn, &bo2, + lws_retry_sul_schedule(wsi->a.context, 0, &r->sul_conn, &bo2, lws_dhcpc_retry_conn, &r->retry_count_conn); @@ -647,14 +629,6 @@ } return 0; - -#if 0 -cancel_conn_timer: - lws_sul_schedule(r->context, 0, &r->sul_conn, NULL, - LWS_SET_TIMER_USEC_CANCEL); - - return 0; -#endif } struct lws_protocols lws_system_protocol_dhcpc = @@ -665,10 +639,8 @@ { lws_dhcpc_req_t *r = *pr; - lws_sul_schedule(r->context, 0, &r->sul_conn, NULL, - LWS_SET_TIMER_USEC_CANCEL); - lws_sul_schedule(r->context, 0, &r->sul_write, NULL, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&r->sul_conn); + lws_sul_cancel(&r->sul_write); if (r->wsi_raw) lws_set_timeout(r->wsi_raw, 1, LWS_TO_KILL_ASYNC); @@ -689,7 +661,8 @@ if (sa46) { memset(sa46, 0, sizeof(*sa46)); sa46->sa4.sin_family = AF_INET; - sa46->sa4.sin_addr.s_addr = r->ipv4[IPV4_DNS_SRV_1]; + sa46->sa4.sin_addr.s_addr = + r->ipv4[IPV4_DNS_SRV_1]; } return 1; } diff -Nru libwebsockets-4.0.20/lib/system/ntpclient/ntpclient.c libwebsockets-4.1.6/lib/system/ntpclient/ntpclient.c --- libwebsockets-4.0.20/lib/system/ntpclient/ntpclient.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/system/ntpclient/ntpclient.c 2020-12-01 17:40:26.000000000 +0000 @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2020 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -34,7 +34,6 @@ const struct lws_protocols *protocol; lws_sorted_usec_list_t sul_conn; lws_sorted_usec_list_t sul_write; /* track write retries */ - lws_state_notify_link_t notify_link; const char *ntp_server_ads; struct lws *wsi_udp; uint16_t retry_count_conn; @@ -50,7 +49,8 @@ * and the transaction forever. */ -static const uint32_t botable[] = { 1000, 1250, 1500, 2000, 3000 }; +static const uint32_t botable[] = + { 300, 500, 650, 800, 800, 900, 1000, 1100, 1500 }; static const lws_retry_bo_t bo = { botable, LWS_ARRAY_SIZE(botable), LWS_RETRY_CONCEAL_ALWAYS, 0, 0, 20 }; @@ -105,20 +105,6 @@ } static int -lws_sys_ntpc_notify_cb(lws_state_manager_t *mgr, lws_state_notify_link_t *l, - int current, int target) -{ - struct vhd_ntpc *v = lws_container_of(l, struct vhd_ntpc, notify_link); - - if (target != LWS_SYSTATE_TIME_VALID || v->set_time) - return 0; - - /* it's trying to do it ever since the protocol / vhost was set up */ - - return 1; -} - -static int callback_ntpc(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { @@ -126,6 +112,8 @@ lws_protocol_vh_priv_get(lws_get_vhost(wsi), lws_get_protocol(wsi)); uint8_t pkt[LWS_PRE + 48]; + struct timeval t1; + int64_t delta_us; uint64_t ns; switch (reason) { @@ -135,34 +123,38 @@ break; lwsl_debug("%s: LWS_CALLBACK_PROTOCOL_INIT:\n", __func__); - lws_protocol_vh_priv_zalloc(wsi->vhost, wsi->protocol, + lws_protocol_vh_priv_zalloc(wsi->a.vhost, wsi->a.protocol, sizeof(*v)); - v = (struct vhd_ntpc *)lws_protocol_vh_priv_get(wsi->vhost, - wsi->protocol); + v = (struct vhd_ntpc *)lws_protocol_vh_priv_get(wsi->a.vhost, + wsi->a.protocol); v->context = lws_get_context(wsi); v->vhost = lws_get_vhost(wsi); v->protocol = lws_get_protocol(wsi); - if (!lws_system_get_ops(wsi->context) || - !lws_system_get_ops(wsi->context)->set_clock) { + v->context->ntpclient_priv = v; + + if (!lws_system_get_ops(wsi->a.context) || + !lws_system_get_ops(wsi->a.context)->set_clock) { +#if !defined(LWS_ESP_PLATFORM) lwsl_err("%s: set up system ops for set_clock\n", __func__); +#endif // return -1; } /* register our lws_system notifier */ - v->notify_link.notify_cb = lws_sys_ntpc_notify_cb; - v->notify_link.name = "ntpclient"; - lws_state_reg_notifier(&wsi->context->mgr_system, &v->notify_link); - v->ntp_server_ads = "pool.ntp.org"; + lws_plat_ntpclient_config(v->context); lws_system_blob_get_single_ptr(lws_system_get_blob( v->context, LWS_SYSBLOB_TYPE_NTP_SERVER, 0), (const uint8_t **)&v->ntp_server_ads); + if (!v->ntp_server_ads || v->ntp_server_ads[0] == '\0') + v->ntp_server_ads = "pool.ntp.org"; - lws_ntpc_retry_conn(&v->sul_conn); + lwsl_info("%s: using ntp server %s\n", __func__, + v->ntp_server_ads); break; case LWS_CALLBACK_PROTOCOL_DESTROY: /* per vhost */ @@ -170,7 +162,6 @@ break; if (v->wsi_udp) lws_set_timeout(v->wsi_udp, 1, LWS_TO_KILL_ASYNC); - lws_state_reg_deregister(&v->notify_link); v->wsi_udp = NULL; goto cancel_conn_timer; @@ -191,8 +182,7 @@ v->wsi_udp = NULL; /* cancel any pending write retry */ - lws_sul_schedule(v->context, 0, &v->sul_write, NULL, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&v->sul_write); if (v->set_time) goto cancel_conn_timer; @@ -216,13 +206,37 @@ ns = lws_ser_ru32be(((uint8_t *)in) + 40) - 2208988800; ns = (ns * 1000000000) + lws_ser_ru32be(((uint8_t *)in) + 44); - lwsl_notice("%s: Unix time: %llu\n", __func__, - (unsigned long long)ns / 1000000000); + /* + * Compute the step + */ + + gettimeofday(&t1, NULL); + + delta_us = (ns / 1000) - + ((t1.tv_sec * LWS_US_PER_SEC) + t1.tv_usec); + + lwsl_notice("%s: Unix time: %llu, step: %lldus\n", __func__, + (unsigned long long)ns / 1000000000, + (long long)delta_us); - // lws_system_get_ops(wsi->context)->set_clock(ns / 1000); +#if defined(LWS_PLAT_FREERTOS) + { + struct timeval t; + + t.tv_sec = (unsigned long long)ns / 1000000000; + t.tv_usec = (ns % 1000000000) / 1000; + + lws_sul_nonmonotonic_adjust(wsi->a.context, delta_us); + + settimeofday(&t, NULL); + } +#endif + if (lws_system_get_ops(wsi->a.context) && + lws_system_get_ops(wsi->a.context)->set_clock) + lws_system_get_ops(wsi->a.context)->set_clock(ns / 1000); v->set_time = 1; - lws_state_transition_steps(&wsi->context->mgr_system, + lws_state_transition_steps(&wsi->a.context->mgr_system, LWS_SYSTATE_OPERATIONAL); /* close the wsi */ @@ -262,7 +276,7 @@ lwsl_err("%s: Failed to write ntp client req\n", __func__); retry_conn: - lws_retry_sul_schedule(wsi->context, 0, &v->sul_conn, &bo, + lws_retry_sul_schedule(wsi->a.context, 0, &v->sul_conn, &bo, lws_ntpc_retry_conn, &v->retry_count_conn); @@ -276,12 +290,21 @@ cancel_conn_timer: - lws_sul_schedule(v->context, 0, &v->sul_conn, NULL, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&v->sul_conn); return 0; } +void +lws_ntpc_trigger(struct lws_context *ctx) +{ + struct vhd_ntpc *v = (struct vhd_ntpc *)ctx->ntpclient_priv; + + lwsl_notice("%s\n", __func__); + v->retry_count_conn = 0; + lws_ntpc_retry_conn(&v->sul_conn); +} + struct lws_protocols lws_system_protocol_ntpc = { "lws-ntpclient", callback_ntpc, 0, 128, }; diff -Nru libwebsockets-4.0.20/lib/system/smd/CMakeLists.txt libwebsockets-4.1.6/lib/system/smd/CMakeLists.txt --- libwebsockets-4.0.20/lib/system/smd/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/system/smd/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,8 @@ +include_directories(.) + +list(APPEND SOURCES + system/smd/smd.c +) + +exports_to_parent_scope() + diff -Nru libwebsockets-4.0.20/lib/system/smd/private-lib-system-smd.h libwebsockets-4.1.6/lib/system/smd/private-lib-system-smd.h --- libwebsockets-4.0.20/lib/system/smd/private-lib-system-smd.h 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/system/smd/private-lib-system-smd.h 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,114 @@ +/* + * lws System Message Distribution + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + */ + +/* + * Number of seconds registered peers must remain as zombies to handle in-flight + * older messages correctly + */ +#if !defined(LWS_SMD_INFLIGHT_GRACE_SECS) +#define LWS_SMD_INFLIGHT_GRACE_SECS (2) +#endif +#if !defined(LWS_SMD_MAX_QUEUE_DEPTH) +#define LWS_SMD_MAX_QUEUE_DEPTH (12) +#endif + +#if defined(LWS_WITH_SECURE_STREAMS) +#define LWS_SMD_SS_RX_HEADER_LEN_EFF (LWS_SMD_SS_RX_HEADER_LEN) +#else +#define LWS_SMD_SS_RX_HEADER_LEN_EFF (0) +#endif + +typedef struct lws_smd_msg { + lws_dll2_t list; + + lws_usec_t timestamp; + lws_smd_class_t _class; + + uint16_t length; + uint16_t refcount; + + /* message itself is over-allocated after this */ +} lws_smd_msg_t; + +/* + * The peer's relationship to the lws instance doing the distribution + */ + +typedef enum { + LSMDT_SAME_PROCESS, /* we call him back ourselves */ + LSMDT_SECURE_STREAMS_LOCAL, /* we call him back ourselves */ + LSMDT_SECURE_STREAMS_PROXIED, /* we ask to write and wait */ +} lws_smd_type_t; + +typedef struct lws_smd_peer { + lws_dll2_t list; + + lws_usec_t timestamp_joined; + lws_usec_t timestamp_left; + +#if defined(LWS_WITH_SECURE_STREAMS) + lws_ss_handle_t *ss_handle; /* LSMDT_SECURE_STREAMS */ +#endif + + lws_smd_notification_cb_t cb; /* LSMDT_ */ + void *opaque; + + /* NULL, or next message we will handle */ + lws_smd_msg_t *tail; + + lws_smd_class_t _class_filter; + lws_smd_type_t type; +} lws_smd_peer_t; + +/* + * Manages message distribution + * + * There is one of these in the lws_context, but the distribution action also + * gets involved in delivering to pt event loops individually for SMP case + */ + +typedef struct lws_smd { + lws_dll2_owner_t owner_messages; /* lws_smd_msg_t */ + lws_mutex_t lock_messages; + lws_dll2_owner_t owner_peers; /* lws_smd_peer_t */ + lws_mutex_t lock_peers; + + /* union of peer class filters, suppress creation of msg classes not set */ + lws_smd_class_t _class_filter; + + lws_sorted_usec_list_t sul_tail_stale; + + char delivering; +} lws_smd_t; + +/* check if this tsi has pending messages to deliver */ + +int +lws_smd_message_pending(struct lws_context *ctx); + +int +lws_smd_msg_distribute(struct lws_context *ctx); + +int +_lws_smd_destroy(struct lws_context *ctx); diff -Nru libwebsockets-4.0.20/lib/system/smd/README.md libwebsockets-4.1.6/lib/system/smd/README.md --- libwebsockets-4.0.20/lib/system/smd/README.md 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/system/smd/README.md 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,223 @@ +# LWS System Message Distribution + +## Overview + +Independent pieces of a system may need to become aware of events and state +changes in the other pieces quickly, along with the new state if it is small. +These messages are local to inside a system, although they may be triggered by +events outside of it. Examples include keypresses, or networking state changes. +Individual OSes and frameworks typically have their own fragmented apis for +message-passing, but the lws apis operate the same across any platforms +including, eg, Windows and RTOS and allow crossplatform code to be written once. + +Message payloads are short, less than 384 bytes, below system limits for atomic +pipe or UDS datagrams and consistent with heap usage on smaller systems, but +large enough to carry JSON usefully. Messages are typically low duty cycle. + +Messages may be sent by any registered participant, they are allocated on heap +in a linked-list, and delivered no sooner than next time around the event loop. +This retains the ability to handle multiple event queuing in one event loop trip +while guaranteeing message handling is nonrecursive. Messages are passed to all +other registered participants before being destroyed. + +`lws_smd` apis allow publication and subscription of message objects between +participants that are in a single process and are informed by callback from lws +service thread context, and, via Secure Streams proxying as the IPC method, also +between those in different processes. Registering as a participant and sending +messages are threadsafe APIs. + +## Message Class + +Message class is a bitfield messages use to indicate their general type, eg, +network status, or UI event like a keypress. Participants set a bitmask to +filter what kind of messages they care about, classes that are 0 in the peer's +filter are never delivered to the peer. A message usually indicates it is a +single class, but it's possible to set multiple class bits and match on any. If +so, care must be taken the payload can be parsed by readers expecting any of the +indicated classes, eg, by using JSON. + +`lws_smd` tracks a global union mask for all participants' class mask. Requests +to allocate a message of a class that no participant listens for are rejected, +not at distribution-time but at message allocation-time, so no heap or cpu is +wasted on things that are not currently interesting; but such messages start to +appear as soon as a participant appears that wants them. The message generation +action should be bypassed without error in the case lws_smd_msg_alloc() +returns NULL. + +## Messaging guarantees + +Sent messages are delivered to all registered participants whose class mask +indicates they want it, including the sender. The send apis are threadsafe. + +Locally-delivered message delivery callbacks occur from lws event loop thread +context 0 (the only one in the default case LWS_MAX_SMP = 1). Clients in +different processes receive callbacks from the thread context of their UDS +networking thread. + +The message payload may be destroyed immediately when you return from the +callback, you can't store references to it or expect it to be there later. + +Messages are timestamped with a systemwide monotonic timestamp. When +participants are on the lws event loop, messages are delivered in-order. When +participants are on different threads, delivery order depends on platform lock +acquisition. External process participants are connected by the Unix Domain +Socket capability of Secure Streams, and may be delivered out-of-order; +receivers that care must consult the message creation timestamps. + +## Message Refcounting + +To avoid keeping a list of the length of the number of participants for each +message, a refcount is used in the message, computed at the time the message +arrived considering the number of active participants that indicated a desire to +receive messages of that class. + +Since peers may detach / close their link asynchronously, the logical peer +objects at the distributor defer destroying themselves until there is no more +possibility of messages arriving timestamped with the period they were active. +A grace period (default 2s) is used to ensure departing peers correctly account +for message refcounts before being destroyed. + +## Message creation + +Messages may contain arbitrary text or binary data depending on the class. JSON +is recommended since lws_smd messages are small and low duty cycle but have +open-ended content: JSON is maintainable, extensible, debuggable and self- +documenting and avoids, eg, fragile dependencies on header versions shared +between teams. To simplify issuing JSON, a threadsafe api to create and send +messages in one step using format strings is provided: + +``` +int +lws_smd_msg_printf(struct lws_context *ctx, lws_smd_class_t _class, + const char *format, ...); +``` + +## Secure Streams `lws_smd` streamtype + +When built with LWS_WITH_SECURE_STREAMS, lws_smd exposes a built-in streamtype +`_lws_smd` which user Secure Streams may use to interoperate with lws_smd using +SS payload semantics. + +When using `_lws_smd`, the SS info struct member `manual_initial_tx_credit` +provided by the user when creating the Secure Stream is overloaded to be used as +the RX class mask for the SMD connection associated with the Secure Stream. + +Both RX and TX payloads have a 16-byte binary header before the actual payload. +For TX, although the header is 16-bytes, only the first 64-bit class bitfield +needs setting, the timestamp is fetched and added by lws. + + - MSB-first 64-bit class bitfield (currently only 32 least-sig in use) + - MSB-First Order 64-bit us-resolution timestamp + +## Well-known message schema + +Class|Schema +---|--- +LWSSMDCL_INTERACTION|lws_button events +LWSSMDCL_NETWORK|captive portal detection requests and results +LWSSMDCL_SYSTEM_STATE|lws_system state progression + +### User interaction Button events + +Class: `LWSSMDCL_INTERACTION` + +Produced by lws_button when a user interacts with a defined button. + +Click-related events are produced alongside up and down related events, the +participant can choose which to attend to according to the meaning of the +interaction. + +Both kinds of event go through sophisticated filtering before being issued, see +`./lib/drivers/button/README.md` for details. + +#### SMD Button interaction event + +Schema: +``` +{ + "type": "button", + "src": "/", + "event": "" +} +``` + +For example, `{"type":"button","src":"bc/user","event":"doubleclick"}` + +Event name|Meaning +---|--- +down|The button passes a filter for being down, useful for duration-based response +up|The button has come up, useful for duration-based response +click|The button activity resulted in a classification as a single-click +longclick|The button activity resulted in a classification as a long-click +doubleclick|The button activity resulted in a classification as a double-click + +### Captive Portal Detection + +Class: `LWSSMDCL_NETWORK` + +Actively detects if the network can reach the internet or if it is +intercepted by a captive portal. The detection steps are programmable +via the Secure Streams Policy for a streamtype `captive_portal_detect`, eg + +``` + "captive_portal_detect": { + "endpoint": "connectivitycheck.android.com", + "http_url": "generate_204", + "port": 80, + "protocol": "h1", + "http_method": "GET", + "opportunistic": true, + "http_expect": 204, + "http_fail_redirect": true + } +``` + +#### SMD Report Result + +Schema: `{"type": "cpd", "result":""}` + +result|meaning +---|--- +OK|Internet is reachable +Captive|Internet is behind a captive portal +No internet|There is no connectivity + +#### SMD Request re-detection + +Schema: `{"trigger": "cpdcheck"}` + +### lws_system state progression + +Class: `LWSSMDCL_SYSTEM_STATE` + +Lws system state changes are forwarded to lws_smd messages so participants not +on the lws event loop directly can be aware of progress. Code registering a +lws_system notifier callback, on the main lws loop, can synchronously veto state +changes and hook proposed state changes, lws_smd events are asynchronous +notifications of state changes after they were decided only... however they are +available over the whole system. + +It's not possible to make validated TLS connections until the system has +acquired the date as well as acquired an IP on a non-captive portal connection, +for that reason user code will usually be dependent on the system reaching +"OPERATIONAL" state if lws is responsible for managing the boot process. + +#### System state event + +Schema: `{"state":""}"` + +State|Meaning +---|--- +CONTEXT_CREATED|We're creating the lws_context +INITIALIZED|Initial vhosts and protocols initialized +IFACE_COLDPLUG|Network interfaces discovered +DHCP|DHCP acquired +CPD_PRE_TIME|Captive portal detect hook before we have system time +TIME_VALID|Ntpclient has run +CPD_POST_TIME|Captive portal detect hook after system time (tls-based check) +POLICY_VALID|The system policy has been acquired and parsed +REGISTERED|This device is registered with an authority +AUTH1|We acquired auth1 from the authority using our registration info +AUTH2|We acquired auth2 from the authority using our registration info +OPERATIONAL|We are active and able to make authenticated tls connections +POLICY_INVALID|The policy is being changed diff -Nru libwebsockets-4.0.20/lib/system/smd/smd.c libwebsockets-4.1.6/lib/system/smd/smd.c --- libwebsockets-4.0.20/lib/system/smd/smd.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/system/smd/smd.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,524 @@ +/* + * lws System Message Distribution + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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" +#include + +void * +lws_smd_msg_alloc(struct lws_context *ctx, lws_smd_class_t _class, size_t len) +{ + lws_smd_msg_t *msg; + + /* only allow it if someone wants to consume this class of event */ + + if (!(ctx->smd._class_filter & _class)) { + lwsl_info("%s: rejecting class 0x%x as no participant wants it\n", __func__, + (unsigned int)_class); + return NULL; + } + + assert(len <= LWS_SMD_MAX_PAYLOAD); + + + /* + * If SS configured, over-allocate LWS_SMD_SS_RX_HEADER_LEN behind + * payload, ie, msg_t (gap LWS_SMD_SS_RX_HEADER_LEN) payload + */ + msg = lws_malloc(sizeof(*msg) + LWS_SMD_SS_RX_HEADER_LEN_EFF + len, + __func__); + if (!msg) + return NULL; + + memset(msg, 0, sizeof(*msg)); + msg->timestamp = lws_now_usecs(); + msg->length = (uint16_t)len; + msg->_class = _class; + + return ((uint8_t *)&msg[1]) + LWS_SMD_SS_RX_HEADER_LEN_EFF; +} + +void +lws_smd_msg_free(void **ppay) +{ + lws_smd_msg_t *msg = (lws_smd_msg_t *)(((uint8_t *)*ppay) - + LWS_SMD_SS_RX_HEADER_LEN_EFF - sizeof(*msg)); + + /* if SS configured, actual alloc is LWS_SMD_SS_RX_HEADER_LEN behind */ + lws_free(msg); + *ppay = NULL; +} + +/* + * Figure out what to set the initial refcount for the message to + */ + +static int +_lws_smd_msg_assess_peers_interested(lws_smd_t *smd, lws_smd_msg_t *msg) +{ + struct lws_context *ctx = lws_container_of(smd, struct lws_context, smd); + int interested = 0; + + lws_start_foreach_dll(struct lws_dll2 *, p, ctx->smd.owner_peers.head) { + lws_smd_peer_t *pr = lws_container_of(p, lws_smd_peer_t, list); + + /* + * In order to optimize the tail managment into a refcount, + * we have to account exactly for when peers arrived and + * departed (including deferring the logical peer destruction + * until no message pending he may have contributed to the + * refcount of) + */ + + if (pr->timestamp_joined <= msg->timestamp && + (!pr->timestamp_left || /* if zombie, only contribute to + * refcount if msg from before we + * left */ + pr->timestamp_left >= msg->timestamp) && + (msg->_class & pr->_class_filter)) + /* + * This peer wants to consume it + */ + interested++; + + } lws_end_foreach_dll(p); + + return interested; +} + +static int +_lws_smd_class_mask_union(lws_smd_t *smd) +{ + uint32_t mask = 0; + + lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1, + smd->owner_peers.head) { + lws_smd_peer_t *pr = lws_container_of(p, lws_smd_peer_t, list); + + /* may destroy pr if zombie */ + mask |= pr->_class_filter; + + } lws_end_foreach_dll_safe(p, p1); + + smd->_class_filter = mask; + + return 0; +} + +int +lws_smd_msg_send(struct lws_context *ctx, void *pay) +{ + lws_smd_msg_t *msg = (lws_smd_msg_t *)(((uint8_t *)pay) - + LWS_SMD_SS_RX_HEADER_LEN_EFF - sizeof(*msg)); + + if (ctx->smd.owner_messages.count >= LWS_SMD_MAX_QUEUE_DEPTH) + /* reject the message due to max queue depth reached */ + return 1; + + if (!ctx->smd.delivering) + lws_mutex_lock(ctx->smd.lock_peers); /* +++++++++++++++ peers */ + + msg->refcount = _lws_smd_msg_assess_peers_interested(&ctx->smd, msg); + + lws_mutex_lock(ctx->smd.lock_messages); /* +++++++++++++++++ messages */ + lws_dll2_add_tail(&msg->list, &ctx->smd.owner_messages); + lws_mutex_unlock(ctx->smd.lock_messages); /* --------------- messages */ + + /* + * Any peer with no active tail needs to check our class to see if we + * should become his tail + */ + + lws_start_foreach_dll(struct lws_dll2 *, p, ctx->smd.owner_peers.head) { + lws_smd_peer_t *pr = lws_container_of(p, lws_smd_peer_t, list); + + if (!pr->tail && (pr->_class_filter & msg->_class)) + pr->tail = msg; + + } lws_end_foreach_dll(p); + + if (!ctx->smd.delivering) + lws_mutex_unlock(ctx->smd.lock_peers); /* ------------- peers */ + + /* we may be happening from another thread context */ + lws_cancel_service(ctx); + + return 0; +} + +int +lws_smd_msg_printf(struct lws_context *ctx, lws_smd_class_t _class, + const char *format, ...) +{ + lws_smd_msg_t *msg; + va_list ap; + void *p; + int n; + + if (!(ctx->smd._class_filter & _class)) + /* + * There's nobody interested in messages of this class atm. + * Don't bother generating it, and act like all is well. + */ + return 0; + + va_start(ap, format); + n = vsnprintf(NULL, 0, format, ap); + va_end(ap); + if (n > LWS_SMD_MAX_PAYLOAD) + /* too large to send */ + return 1; + + p = lws_smd_msg_alloc(ctx, _class, (size_t)n + 2); + if (!p) + return 1; + msg = (lws_smd_msg_t *)(((uint8_t *)p) - LWS_SMD_SS_RX_HEADER_LEN_EFF - + sizeof(*msg)); + msg->length = (uint16_t)n; + va_start(ap, format); + vsnprintf((char*)p, n + 2, format, ap); + va_end(ap); + + /* + * locks taken and released in here + */ + + if (lws_smd_msg_send(ctx, p)) { + lws_smd_msg_free(&p); + return 1; + } + + return 0; +} + + +static void +_lws_smd_peer_finalize_destroy(lws_smd_peer_t *pr) +{ + lws_dll2_remove(&pr->list); + lws_free(pr); +} + +/* + * Peers that deregister may need to hang around as zombies, so they account + * for refcounts on messages they already contributed to. Because older + * messages may be in flight over UDS links, we have to stick around and make + * sure all cases have their refcount handled correctly. + */ + +static void +_lws_smd_peer_zombify(lws_smd_peer_t *pr) +{ + lws_smd_t *smd = lws_container_of(pr->list.owner, lws_smd_t, + owner_peers); + + /* update the class mask union to reflect this peer no longer active */ + _lws_smd_class_mask_union(smd); + + pr->timestamp_left = lws_now_usecs(); +} + +static lws_smd_msg_t * +_lws_smd_msg_next_matching_filter(lws_dll2_t *tail, lws_smd_class_t filter) +{ + lws_smd_msg_t *msg; + + do { + tail = tail->next; + if (!tail) + return NULL; + + msg = lws_container_of(tail, lws_smd_msg_t, list); + if (msg->_class & filter) + return msg; + } while (1); + + return NULL; +} + +/* + * Note: May destroy zombie peers when it sees grace period has expired. + * + * Delivers only one message to the peer and advances the tail, or sets to NULL + * if no more filtered queued messages. Returns nonzero if tail non-NULL. + * + * For Proxied SS, only asks for writeable and does not advance or change the + * tail. + * + * This is done so if multiple messages queued, we don't get a situation where + * one participant gets them all spammed, then the next etc. Instead they are + * delivered round-robin. + */ + +static int +_lws_smd_msg_deliver_peer(struct lws_context *ctx, lws_smd_peer_t *pr) +{ + lws_smd_msg_t *msg; + + if (!pr->tail) + return 0; + + msg = lws_container_of(pr->tail, lws_smd_msg_t, list); + + /* + * Check if zombie peer and the message predates our leaving + */ + + if (pr->timestamp_left && + msg->timestamp > pr->timestamp_left) { + /* + * We do not need to modify message refcount, if it was + * generated after we became a zombie, and so we + * definitely did not contribute to its refcount... + * + * ...have we waited out the grace period? + */ + + if (lws_now_usecs() - pr->timestamp_left > + LWS_SMD_INFLIGHT_GRACE_SECS * LWS_US_PER_SEC) + /* + * ... ok, it's time for the zombie to abandon + * its attachment to the Earth and rejoin the + * cosmic mandela + */ + _lws_smd_peer_finalize_destroy(pr); + + /* ... either way, nothing further to do for this guy */ + + return 0; + } + + if (!pr->timestamp_left) { + + /* + * Peer is not a zombie... deliver the tail + */ +#if 0 + if (pr->type == LSMDT_SECURE_STREAMS_PROXIED) { +#if defined(LWS_WITH_SECURE_STREAMS) + if (pr->ss_handle) + lws_ss_request_tx(pr->ss_handle); +#endif + return 0; + } +#endif + + pr->cb(pr->opaque, msg->_class, msg->timestamp, + ((uint8_t *)&msg[1]) + + LWS_SMD_SS_RX_HEADER_LEN_EFF, + (size_t)msg->length); + } + + assert(msg->refcount); + + /* + * If there is one, move forward to the next queued + * message that meets our filters + */ + pr->tail = _lws_smd_msg_next_matching_filter( + &pr->tail->list, pr->_class_filter); + + if (!--msg->refcount) { + /* + * We have fully delivered the message now, it + * can be unlinked and destroyed + */ + lws_dll2_remove(&msg->list); + lws_free(msg); + } + + /* + * Wait out the grace period even if no live messages + * for a zombie peer... there may be some in flight + */ + + return !!pr->tail; +} + +/* + * Called when the event loop could deliver messages synchronously, eg, on + * entry to idle + */ + +int +lws_smd_msg_distribute(struct lws_context *ctx) +{ + char more; + + /* commonly, no messages and nothing to do... */ + + if (!ctx->smd.owner_messages.count) + return 0; + + ctx->smd.delivering = 1; + + do { + more = 0; + lws_mutex_lock(ctx->smd.lock_peers); /* +++++++++++++++ peers */ + + lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1, + ctx->smd.owner_peers.head) { + lws_smd_peer_t *pr = lws_container_of(p, lws_smd_peer_t, list); + + /* may destroy pr if zombie, hence _safe iterator */ + more |= _lws_smd_msg_deliver_peer(ctx, pr); + + } lws_end_foreach_dll_safe(p, p1); + + lws_mutex_unlock(ctx->smd.lock_peers); /* ------------- peers */ + } while (more); + + ctx->smd.delivering = 0; + + return 0; +} + +struct lws_smd_peer * +lws_smd_register(struct lws_context *ctx, void *opaque, int flags, + lws_smd_class_t _class_filter, lws_smd_notification_cb_t cb) +{ + lws_smd_peer_t *pr = lws_zalloc(sizeof(*pr), __func__); + + if (!pr) + return NULL; + + pr->cb = cb; + pr->opaque = opaque; + pr->_class_filter = _class_filter; + pr->timestamp_joined = lws_now_usecs(); + + /* + * Figure out the type of peer from the situation... + */ + +#if 0 +#if defined(LWS_WITH_SECURE_STREAMS) + if (!ctx->smd.listen_vh) { + /* + * The guy who is regsitering is actually a SS proxy link + * between a client and SMD + */ + } else +#endif +#endif + pr->type = LSMDT_SAME_PROCESS; + + if (!ctx->smd.delivering) + lws_mutex_lock(ctx->smd.lock_peers); /* +++++++++++++++ peers */ + lws_dll2_add_tail(&pr->list, &ctx->smd.owner_peers); + + /* update the global class mask union to account for new peer mask */ + _lws_smd_class_mask_union(&ctx->smd); + if (!ctx->smd.delivering) + lws_mutex_unlock(ctx->smd.lock_peers); /* ------------- peers */ + + lwsl_debug("%s: registered\n", __func__); + + return pr; +} + +void +lws_smd_unregister(struct lws_smd_peer *pr) +{ + lws_smd_t *smd = lws_container_of(pr->list.owner, lws_smd_t, owner_peers); + + lws_mutex_lock(smd->lock_peers); /* +++++++++++++++++++++++++++ peers */ + _lws_smd_peer_zombify(pr); + lws_mutex_unlock(smd->lock_peers); /* ------------------------- peers */ +} + +int +lws_smd_message_pending(struct lws_context *ctx) +{ + int ret = 1; + + /* + * First cheaply check the common case no messages pending, so there's + * definitely nothing for this tsi or anything else + */ + + if (!ctx->smd.owner_messages.count) + return 0; + + /* + * Walk the peer list + */ + + lws_mutex_lock(ctx->smd.lock_peers); /* +++++++++++++++++++++++ peers */ + lws_start_foreach_dll(struct lws_dll2 *, p, ctx->smd.owner_peers.head) { + lws_smd_peer_t *pr = lws_container_of(p, lws_smd_peer_t, list); + + if (pr->tail && pr->type == LSMDT_SAME_PROCESS) + goto bail; + + } lws_end_foreach_dll(p); + + /* + * There's no message pending that we need to handle + */ + + ret = 0; + +bail: + lws_mutex_unlock(ctx->smd.lock_peers); /* --------------------- peers */ + + return ret; +} + +int +_lws_smd_destroy(struct lws_context *ctx) +{ + /* stop any message creation */ + + ctx->smd._class_filter = 0; + + /* + * Walk the message list, destroying them + */ + + lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1, + ctx->smd.owner_messages.head) { + lws_smd_msg_t *msg = lws_container_of(p, lws_smd_msg_t, list); + + lws_free(msg); + + } lws_end_foreach_dll_safe(p, p1); + + lws_mutex_destroy(ctx->smd.lock_messages); + + /* + * Walk the peer list, destroying them + */ + + lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1, + ctx->smd.owner_peers.head) { + lws_smd_peer_t *pr = lws_container_of(p, lws_smd_peer_t, list); + + _lws_smd_peer_finalize_destroy(pr); + + } lws_end_foreach_dll_safe(p, p1); + + lws_mutex_destroy(ctx->smd.lock_peers); + + return 0; +} diff -Nru libwebsockets-4.0.20/lib/system/system.c libwebsockets-4.1.6/lib/system/system.c --- libwebsockets-4.0.20/lib/system/system.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/system/system.c 2020-12-01 17:40:26.000000000 +0000 @@ -128,7 +128,7 @@ { if (!b) return; - lwsl_info("%s: blob %p\n", __func__, b); + // lwsl_info("%s: blob %p\n", __func__, b); if (!b->is_direct) lws_buflist_destroy_all_segments(&b->u.bl); } @@ -179,6 +179,7 @@ } *get = NULL; +#if defined(LWS_WITH_SYS_STATE) if (!pt->attach_owner.count) return 0; @@ -202,6 +203,7 @@ return 0; } } lws_end_foreach_dll(d); +#endif /* nobody ready to go... leave *get as NULL and return cleanly */ diff -Nru libwebsockets-4.0.20/lib/tls/CMakeLists.txt libwebsockets-4.1.6/lib/tls/CMakeLists.txt --- libwebsockets-4.0.20/lib/tls/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/tls/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,482 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# +# This converts everything about the tls support into +# +# - entries on SOURCES (modifications set back in PARENT_SCOPE) +# - entries on LIB_LIST (modifications set back in PARENT_SCOPE) +# - include_directories() +# - Api build-time discovery results set in PARENT_SCOPE +# +# Everything else is handled privately here. + +include_directories(.) + +# Allow the user to use the old CyaSSL options/library in stead of wolfSSL +if (LWS_WITH_CYASSL AND LWS_WITH_WOLFSSL) + message(FATAL_ERROR "LWS_WITH_CYASSL and LWS_WITH_WOLFSSL are mutually exclusive!") +endif() + +if (LWS_WITH_CYASSL) + # Copy CyaSSL options to the wolfSSL options + set(LWS_WITH_WOLFSSL ${LWS_WITH_CYASSL} CACHE BOOL "Use wolfSSL/CyaSSL instead of OpenSSL" FORCE PARENT_SCOPE) + set(LWS_WOLFSSL_LIBRARIES ${LWS_CYASSL_LIBRARIES} CACHE PATH "Path to wolfSSL/CyaSSL libraries" FORCE PARENT_SCOPE) + set(LWS_WOLFSSL_INCLUDE_DIRS ${LWS_CYASSL_INCLUDE_DIRS} CACHE PATH "Path to wolfSSL/CyaSSL header files" FORCE PARENT_SCOPE) +endif() + +set(LWS_OPENSSL_LIBRARIES CACHE PATH "Path to the OpenSSL library" ) +set(LWS_OPENSSL_INCLUDE_DIRS CACHE PATH "Path to the OpenSSL include directory" ) +set(LWS_WOLFSSL_LIBRARIES CACHE PATH "Path to the wolfSSL library" ) +set(LWS_WOLFSSL_INCLUDE_DIRS CACHE PATH "Path to the wolfSSL include directory" ) + + +if (LWS_WITH_BORINGSSL) + # boringssl deprecated EVP_PKEY + set (LWS_WITH_GENHASH OFF PARENT_SCOPE) +endif() + +if (LWS_WITH_SSL AND NOT LWS_WITH_WOLFSSL AND NOT LWS_WITH_MBEDTLS) + if ("${LWS_OPENSSL_LIBRARIES}" STREQUAL "" OR "${LWS_OPENSSL_INCLUDE_DIRS}" STREQUAL "") + else() + if (NOT LWS_PLAT_FREERTOS) + set(OPENSSL_LIBRARIES ${LWS_OPENSSL_LIBRARIES}) + endif() + set(OPENSSL_INCLUDE_DIRS ${LWS_OPENSSL_INCLUDE_DIRS}) + set(OPENSSL_FOUND 1) + endif() +endif() + +if (LWS_WITH_SSL AND LWS_WITH_WOLFSSL) + if ("${LWS_WOLFSSL_LIBRARIES}" STREQUAL "" OR "${LWS_WOLFSSL_INCLUDE_DIRS}" STREQUAL "") + if (NOT WOLFSSL_FOUND) + if (LWS_WITH_CYASSL) + message(FATAL_ERROR "You must set LWS_CYASSL_LIBRARIES and LWS_CYASSL_INCLUDE_DIRS when LWS_WITH_CYASSL is turned on.") + else() + message(FATAL_ERROR "You must set LWS_WOLFSSL_LIBRARIES and LWS_WOLFSSL_INCLUDE_DIRS when LWS_WITH_WOLFSSL is turned on.") + endif() + endif() + else() + set(WOLFSSL_LIBRARIES ${LWS_WOLFSSL_LIBRARIES}) + set(WOLFSSL_INCLUDE_DIRS ${LWS_WOLFSSL_INCLUDE_DIRS}) + set(WOLFSSL_FOUND 1) + endif() + set(USE_WOLFSSL 1) + set(USE_WOLFSSL 1 PARENT_SCOPE) + set(LWS_WITH_TLS 1 PARENT_SCOPE) + if (LWS_WITH_CYASSL) + set(USE_OLD_CYASSL 1) + endif() +endif() + +if (LWS_SSL_CLIENT_USE_OS_CA_CERTS) + set(LWS_SSL_CLIENT_USE_OS_CA_CERTS 1 PARENT_SCOPE) +endif() + +if (LWS_WITH_MBEDTLS) + add_subdirectory(mbedtls) + include_directories(${_CMAKE_INC_LIST}) +endif() + +# The base dir where the test-apps look for the SSL certs. +set(LWS_OPENSSL_CLIENT_CERTS ../share CACHE PATH "Server SSL certificate directory") +if (WIN32) + set(LWS_OPENSSL_CLIENT_CERTS . CACHE PATH "Client SSL certificate directory" PARENT_SCOPE) +else() + set(LWS_OPENSSL_CLIENT_CERTS /etc/pki/tls/certs/ CACHE PATH "Client SSL certificate directory") +endif() + +if (LWS_WITH_SSL) + list(APPEND SOURCES + tls/tls.c) + if (LWS_WITH_NETWORK) + list(APPEND SOURCES + tls/tls-network.c) + endif() + + if (LWS_WITH_MBEDTLS) + list(APPEND SOURCES + tls/mbedtls/mbedtls-tls.c + tls/mbedtls/mbedtls-x509.c) + if (LWS_WITH_NETWORK) + list(APPEND SOURCES + tls/mbedtls/mbedtls-ssl.c) + endif() + if (LWS_WITH_GENCRYPTO) + list(APPEND SOURCES + tls/mbedtls/lws-genhash.c + tls/mbedtls/lws-genrsa.c + tls/mbedtls/lws-genaes.c + tls/lws-genec-common.c + tls/mbedtls/lws-genec.c + tls/mbedtls/lws-gencrypto.c) + endif() + else() + list(APPEND SOURCES + tls/openssl/openssl-tls.c + tls/openssl/openssl-x509.c) + if (LWS_WITH_NETWORK) + list(APPEND SOURCES + tls/openssl/openssl-ssl.c) + endif() + if (LWS_WITH_GENCRYPTO) + list(APPEND SOURCES + tls/openssl/lws-genhash.c + tls/openssl/lws-genrsa.c + tls/openssl/lws-genaes.c + tls/lws-genec-common.c + tls/openssl/lws-genec.c + tls/openssl/lws-gencrypto.c) + endif() + endif() + + if (NOT LWS_WITHOUT_SERVER) + list(APPEND SOURCES + tls/tls-server.c) + if (LWS_WITH_MBEDTLS) + list(APPEND SOURCES + tls/mbedtls/mbedtls-server.c) + else() + list(APPEND SOURCES + tls/openssl/openssl-server.c) + endif() + endif() + if (NOT LWS_WITHOUT_CLIENT) + list(APPEND SOURCES + tls/tls-client.c) + if (LWS_WITH_MBEDTLS) + list(APPEND SOURCES + tls/mbedtls/mbedtls-client.c) + else() + list(APPEND SOURCES + tls/openssl/openssl-client.c) + endif() + + endif() +endif() + +set(SOURCES ${SOURCES} PARENT_SCOPE) + +# +# OpenSSL +# +if (LWS_WITH_SSL) + message("Compiling with SSL support") + set(chose_ssl 0) + if (LWS_WITH_WOLFSSL) + # Use wolfSSL as OpenSSL replacement. + # TODO: Add a find_package command for this also. + message("wolfSSL include dir: ${WOLFSSL_INCLUDE_DIRS}") + message("wolfSSL libraries: ${WOLFSSL_LIBRARIES}") + + # Additional to the root directory we need to include + # the wolfssl/ subdirectory which contains the OpenSSL + # compatibility layer headers. + + if (LWS_WITH_CYASSL) + foreach(inc ${WOLFSSL_INCLUDE_DIRS}) + set(OPENSSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIRS} ${inc} ${inc}/cyassl) + include_directories("${inc}" "${inc}/cyassl") + endforeach() + else() + foreach(inc ${WOLFSSL_INCLUDE_DIRS}) + set(OPENSSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIRS} ${inc} ${inc}/wolfssl) + include_directories("${inc}" "${inc}/wolfssl") + endforeach() + endif() + set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${OPENSSL_INCLUDE_DIRS}) + set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} PARENT_SCOPE) + set(OPENSSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIRS} PARENT_SCOPE) + set(VARIA wolfSSL_) + + list(INSERT LIB_LIST 0 "${WOLFSSL_LIBRARIES}") + message("LIB_LIST ${LIB_LIST}") + set(chose_ssl 1) + endif() + + if (LWS_WITH_MBEDTLS AND DEFINED MBEDTLS_INCLUDE_DIRS AND DEFINED MBEDTLS_LIBRARIES) + message("MBEDTLS include dir: ${MBEDTLS_INCLUDE_DIRS}") + message("MBEDTLS libraries: ${MBEDTLS_LIBRARIES}") + + foreach(inc ${MBEDTLS_INCLUDE_DIRS}) + include_directories("${inc}" "${inc}/mbedtls") + endforeach() + + list(INSERT LIB_LIST 0 "${MBEDTLS_LIBRARIES}") + endif() + + if (LWS_WITH_MBEDTLS) + set(chose_ssl 1) + endif() + + if (NOT chose_ssl) + if (NOT OPENSSL_FOUND AND NOT LWS_WITH_BORINGSSL) + # TODO: Add support for STATIC also. + if (NOT LWS_PLAT_FREERTOS) + find_package(PkgConfig QUIET) + pkg_check_modules(PC_OPENSSL openssl QUIET) + find_package(OpenSSL REQUIRED) + list(APPEND OPENSSL_LIBRARIES ${PC_OPENSSL_LIBRARIES}) + set(OPENSSL_LIBRARIES ${OPENSSL_LIBRARIES} PARENT_SCOPE) + endif() + set(OPENSSL_INCLUDE_DIRS "${OPENSSL_INCLUDE_DIR}") + endif() + + message("OpenSSL include dir: ${OPENSSL_INCLUDE_DIRS}") + if (NOT LWS_PLAT_FREERTOS) + message("OpenSSL libraries: ${OPENSSL_LIBRARIES}") + endif() + + if (OPENSSL_INCLUDE_DIRS) + include_directories("${OPENSSL_INCLUDE_DIRS}") + if (NOT LWS_PLAT_FREERTOS) + list(INSERT LIB_LIST 0 ${OPENSSL_LIBRARIES}) + endif() + + if (NOT LWS_WITH_MBEDTLS) + # older (0.98) Openssl lacks this + set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${OPENSSL_INCLUDE_DIRS} PARENT_SCOPE) + check_include_file(openssl/ecdh.h LWS_HAVE_OPENSSL_ECDH_H) + + if (LWS_SSL_SERVER_WITH_ECDH_CERT AND NOT LWS_HAVE_OPENSSL_ECDH_H) + message(FATAL_ERROR "Missing openssl/ecdh.h, so cannot use LWS_SSL_SERVER_WITH_ECDH_CERT") + endif() + else() + unset(LWS_HAVE_OPENSSL_ECDH_H PARENT_SCOPE) + endif(NOT LWS_WITH_MBEDTLS) + endif() + endif() + +endif(LWS_WITH_SSL) + +if (DEFINED OPENSSL_INCLUDE_DIRS) + set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS}) +endif() +if (DEFINED LIB_LIST) + set(CMAKE_REQUIRED_LIBRARIES ${LIB_LIST}) +endif() +if (UNIX AND NOT (${CMAKE_SYSTEM_NAME} MATCHES "QNX")) + set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} dl) +endif() +if ((CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) AND NOT (${CMAKE_SYSTEM_NAME} MATCHES "QNX")) + set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} pthread) +endif() + +if (NOT VARIA) + set(VARIA "") +endif() + +CHECK_FUNCTION_EXISTS(${VARIA}SSL_CTX_set1_param LWS_HAVE_SSL_CTX_set1_param PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}SSL_set_info_callback LWS_HAVE_SSL_SET_INFO_CALLBACK PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}X509_VERIFY_PARAM_set1_host LWS_HAVE_X509_VERIFY_PARAM_set1_host PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}RSA_set0_key LWS_HAVE_RSA_SET0_KEY PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}X509_get_key_usage LWS_HAVE_X509_get_key_usage PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}EVP_PKEY_new_raw_private_key LWS_HAVE_SSL_CTX_EVP_PKEY_new_raw_private_key PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}SSL_CTX_get0_certificate LWS_HAVE_SSL_CTX_get0_certificate PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}SSL_get0_alpn_selected LWS_HAVE_SSL_get0_alpn_selected PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}SSL_set_alpn_protos LWS_HAVE_SSL_set_alpn_protos PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_128_cfb8 LWS_HAVE_EVP_aes_128_cfb8 PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_128_cfb128 LWS_HAVE_EVP_aes_128_cfb128 PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_192_cfb8 LWS_HAVE_EVP_aes_192_cfb8 PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_192_cfb128 LWS_HAVE_EVP_aes_192_cfb128 PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_256_cfb8 LWS_HAVE_EVP_aes_256_cfb8 PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_256_cfb128 LWS_HAVE_EVP_aes_256_cfb128 PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_128_xts LWS_HAVE_EVP_aes_128_xts PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}RSA_verify_pss_mgf1 LWS_HAVE_RSA_verify_pss_mgf1 PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}HMAC_CTX_new LWS_HAVE_HMAC_CTX_new PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}SSL_CTX_set_ciphersuites LWS_HAVE_SSL_CTX_set_ciphersuites PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}EVP_PKEY_new_raw_private_key LWS_HAVE_EVP_PKEY_new_raw_private_key PARENT_SCOPE) + +if (LWS_WITH_SSL AND NOT LWS_WITH_MBEDTLS) + # we don't want to confuse what's in or out of the wrapper with + # what's in an openssl also installed on the build host +CHECK_C_SOURCE_COMPILES("#include \nint main(void) { STACK_OF(X509) *c = NULL; SSL_CTX *ctx = NULL; return (int)SSL_CTX_get_extra_chain_certs_only(ctx, &c); }\n" LWS_HAVE_SSL_EXTRA_CHAIN_CERTS) +CHECK_C_SOURCE_COMPILES("#include \nint main(void) { EVP_MD_CTX *md_ctx = NULL; EVP_MD_CTX_free(md_ctx); return 0; }\n" LWS_HAVE_EVP_MD_CTX_free) +set(LWS_HAVE_SSL_EXTRA_CHAIN_CERTS ${LWS_HAVE_SSL_EXTRA_CHAIN_CERTS} PARENT_SCOPE) +set(LWS_HAVE_EVP_MD_CTX_free ${LWS_HAVE_EVP_MD_CTX_free} PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}ECDSA_SIG_set0 LWS_HAVE_ECDSA_SIG_set0 PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}BN_bn2binpad LWS_HAVE_BN_bn2binpad PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_128_wrap LWS_HAVE_EVP_aes_128_wrap PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}EC_POINT_get_affine_coordinates LWS_HAVE_EC_POINT_get_affine_coordinates PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}SSL_CTX_load_verify_file LWS_HAVE_SSL_CTX_load_verify_file PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}SSL_CTX_load_verify_dir LWS_HAVE_SSL_CTX_load_verify_dir PARENT_SCOPE) +endif() + +if (LWS_WITH_MBEDTLS) + set(LWS_HAVE_TLS_CLIENT_METHOD 1 PARENT_SCOPE) + if (NOT LWS_PLAT_FREERTOS) + # not supported in esp-idf openssl wrapper yet, but is in our version + set(LWS_HAVE_X509_VERIFY_PARAM_set1_host 1 PARENT_SCOPE) + endif() + + CHECK_FUNCTION_EXISTS(mbedtls_ssl_conf_alpn_protocols LWS_HAVE_mbedtls_ssl_conf_alpn_protocols PARENT_SCOPE) + CHECK_FUNCTION_EXISTS(mbedtls_ssl_get_alpn_protocol LWS_HAVE_mbedtls_ssl_get_alpn_protocol PARENT_SCOPE) + CHECK_FUNCTION_EXISTS(mbedtls_ssl_conf_sni LWS_HAVE_mbedtls_ssl_conf_sni PARENT_SCOPE) + CHECK_FUNCTION_EXISTS(mbedtls_ssl_set_hs_ca_chain LWS_HAVE_mbedtls_ssl_set_hs_ca_chain PARENT_SCOPE) + CHECK_FUNCTION_EXISTS(mbedtls_ssl_set_hs_own_cert LWS_HAVE_mbedtls_ssl_set_hs_own_cert PARENT_SCOPE) + CHECK_FUNCTION_EXISTS(mbedtls_ssl_set_hs_authmode LWS_HAVE_mbedtls_ssl_set_hs_authmode PARENT_SCOPE) + CHECK_FUNCTION_EXISTS(mbedtls_net_init LWS_HAVE_mbedtls_net_init PARENT_SCOPE) + CHECK_FUNCTION_EXISTS(mbedtls_md_setup LWS_HAVE_mbedtls_md_setup PARENT_SCOPE) # not on xenial 2.2 + CHECK_FUNCTION_EXISTS(mbedtls_rsa_complete LWS_HAVE_mbedtls_rsa_complete PARENT_SCOPE) # not on xenial 2.2 + CHECK_FUNCTION_EXISTS(mbedtls_internal_aes_encrypt LWS_HAVE_mbedtls_internal_aes_encrypt PARENT_SCOPE) # not on xenial 2.2 +else() +CHECK_FUNCTION_EXISTS(${VARIA}TLS_client_method LWS_HAVE_TLS_CLIENT_METHOD PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}TLSv1_2_client_method LWS_HAVE_TLSV1_2_CLIENT_METHOD PARENT_SCOPE) +endif() + +# Generate self-signed SSL certs for the test-server. + +if (LWS_WITH_SSL AND NOT LWS_WITH_WOLFSSL) + message("Searching for OpenSSL executable and dlls") + find_package(OpenSSLbins) + if (DEFINED OPENSSL_EXECUTABLE) + message("OpenSSL executable: ${OPENSSL_EXECUTABLE}") + + if (OPENSSL_EXECUTABLE MATCHES "^$") + set(OPENSSL_EXECUTABLE openssl) + endif() + endif() + if (NOT DEFINED OPENSSL_EXECUTABLE) + set(OPENSSL_EXECUTABLE openssl) + endif() + +endif() + +set(GENCERTS 0) + +if (LWS_WITH_SSL AND OPENSSL_EXECUTABLE AND NOT LWS_WITHOUT_TEST_SERVER AND NOT LWS_WITHOUT_SERVER AND NOT LWS_WITHOUT_TESTAPPS) + set(GENCERTS 1) +endif() +if (LWS_PLAT_FREERTOS AND LWS_WITH_SSL) + set(GENCERTS 1) +endif() +message(" GENCERTS = ${GENCERTS}") +if (GENCERTS) + message("Generating SSL Certificates for the test-server...") + + set(TEST_SERVER_SSL_KEY "${PROJECT_BINARY_DIR}/libwebsockets-test-server.key.pem") + set(TEST_SERVER_SSL_CERT "${PROJECT_BINARY_DIR}/libwebsockets-test-server.pem") + + if (WIN32) + if (MINGW) + message("cmd = \"${OPENSSL_EXECUTABLE}\" req -new -newkey rsa:2048 -days 10000 -nodes -x509 -subj \"/C=GB/ST=Erewhon/L=All around/O=libwebsockets-test/CN=localhost\" -keyout \"${TEST_SERVER_SSL_KEY}\" -out \"${TEST_SERVER_SSL_CERT}\"") + execute_process( + COMMAND "${OPENSSL_EXECUTABLE}" req -new -newkey rsa:2048 -days 10000 -nodes -x509 -subj "/C=GB/ST=Erewhon/L=All around/O=libwebsockets-test/CN=localhost" -keyout "${TEST_SERVER_SSL_KEY}" -out "${TEST_SERVER_SSL_CERT}" + RESULT_VARIABLE OPENSSL_RETURN_CODE) + else() + file(WRITE "${PROJECT_BINARY_DIR}/openssl_input.txt" + "GB\n" + "Erewhon\n" + "All around\n" + "libwebsockets-test\n" + "localhost\n" + "none@invalid.org\n\n" + ) + + # The "type" command is a bit picky with paths. + file(TO_NATIVE_PATH "${PROJECT_BINARY_DIR}/openssl_input.txt" OPENSSL_INPUT_WIN_PATH) + message("OPENSSL_INPUT_WIN_PATH = ${OPENSSL_INPUT_WIN_PATH}") + message("cmd = \"${OPENSSL_EXECUTABLE}\" req -new -newkey rsa:2048 -days 10000 -nodes -x509 -keyout \"${TEST_SERVER_SSL_KEY}\" -out \"${TEST_SERVER_SSL_CERT}\"") + + execute_process( + COMMAND cmd /c type "${OPENSSL_INPUT_WIN_PATH}" + COMMAND "${OPENSSL_EXECUTABLE}" req -new -newkey rsa:2048 -days 10000 -nodes -x509 -keyout "${TEST_SERVER_SSL_KEY}" -out "${TEST_SERVER_SSL_CERT}" + RESULT_VARIABLE OPENSSL_RETURN_CODE + OUTPUT_QUIET ERROR_QUIET) + + message("\n") + endif() + + if (OPENSSL_RETURN_CODE) + message(WARNING "!!! Failed to generate SSL certificate for Test Server using cmd.exe !!!:\nOpenSSL return code = ${OPENSSL_RETURN_CODE}") + else() + message("SUCCSESFULLY generated SSL certificate") + endif() + else() + # Unix. + execute_process( + COMMAND printf "GB\\nErewhon\\nAll around\\nlibwebsockets-test\\n\\nlocalhost\\nnone@invalid.org\\n" + COMMAND "${OPENSSL_EXECUTABLE}" + req -new -newkey rsa:2048 -days 10000 -nodes -x509 -keyout "${TEST_SERVER_SSL_KEY}" -out "${TEST_SERVER_SSL_CERT}" + RESULT_VARIABLE OPENSSL_RETURN_CODE + # OUTPUT_QUIET ERROR_QUIET + ) + + if (OPENSSL_RETURN_CODE) + message(WARNING "!!! Failed to generate SSL certificate for Test Server!!!:\nOpenSSL return code = ${OPENSSL_RETURN_CODE}") + else() + message("SUCCESSFULLY generated SSL certificate") + endif() + endif() + + list(APPEND TEST_SERVER_DATA + "${TEST_SERVER_SSL_KEY}" + "${TEST_SERVER_SSL_CERT}") +endif() + +# +# Copy OpenSSL dlls to the output directory on Windows. +# (Otherwise we'll get an error when trying to run) +# +if (MSVC AND LWS_WITH_SSL AND NOT LWS_WITH_WOLFSSL) + if(OPENSSL_BIN_FOUND) + message("OpenSSL dlls found:") + message(" Libeay: ${LIBEAY_BIN}") + message(" SSLeay: ${SSLEAY_BIN}") + + foreach(TARGET_BIN ${TEST_APP_LIST}) + add_custom_command(TARGET ${TARGET_BIN} + POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E copy "${LIBEAY_BIN}" "$" VERBATIM) + add_custom_command(TARGET ${TARGET_BIN} + POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E copy "${SSLEAY_BIN}" "$" VERBATIM) + + # + # Win32: if we are using libuv, also need to copy it in the output dir + # + if (MSVC AND LWS_WITH_LIBUV) + STRING(REPLACE ".lib" ".dll" LIBUV_BIN ${LIBUV_LIBRARIES}) + add_custom_command(TARGET ${TARGET_BIN} + POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E copy "${LIBUV_BIN}" "$" VERBATIM) + endif() + endforeach() + endif() +endif() + +if (LWS_WITH_TLS AND (LWS_WITH_JOSE OR LWS_WITH_GENCRYPTO)) + list(APPEND SOURCES + tls/lws-gencrypto-common.c) +endif() + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() +set(LWS_HAVE_MBEDTLS_NET_SOCKETS ${LWS_HAVE_MBEDTLS_NET_SOCKETS} PARENT_SCOPE) +set(TEST_SERVER_SSL_KEY "${TEST_SERVER_SSL_KEY}" PARENT_SCOPE) +set(TEST_SERVER_SSL_CERT "${TEST_SERVER_SSL_CERT}" PARENT_SCOPE) +set(TEST_SERVER_DATA ${TEST_SERVER_DATA} PARENT_SCOPE) + diff -Nru libwebsockets-4.0.20/lib/tls/mbedtls/CMakeLists.txt libwebsockets-4.1.6/lib/tls/mbedtls/CMakeLists.txt --- libwebsockets-4.0.20/lib/tls/mbedtls/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lib/tls/mbedtls/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,130 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(wrapper/include wrapper/include/internal) + + set(LWS_WITH_SSL ON) + + include_directories(wrapper/include) + include_directories(wrapper/include/platform) + include_directories(wrapper/include/internal) + include_directories(wrapper/include/openssl) + + if (LWS_WITH_NETWORK) + list(APPEND HDR_PRIVATE + tls/mbedtls/wrapper/include/internal/ssl3.h + tls/mbedtls/wrapper/include/internal/ssl_cert.h + tls/mbedtls/wrapper/include/internal/ssl_code.h + tls/mbedtls/wrapper/include/internal/ssl_dbg.h + tls/mbedtls/wrapper/include/internal/ssl_lib.h + tls/mbedtls/wrapper/include/internal/ssl_methods.h + tls/mbedtls/wrapper/include/internal/ssl_pkey.h + tls/mbedtls/wrapper/include/internal/ssl_stack.h + tls/mbedtls/wrapper/include/internal/ssl_types.h + tls/mbedtls/wrapper/include/internal/ssl_x509.h + tls/mbedtls/wrapper/include/internal/tls1.h + tls/mbedtls/wrapper/include/internal/x509_vfy.h) + + list(APPEND HDR_PRIVATE + tls/mbedtls/wrapper/include/openssl/ssl.h) + + list(APPEND HDR_PRIVATE + tls/mbedtls/wrapper/include/platform/ssl_pm.h + tls/mbedtls/wrapper/include/platform/ssl_port.h) + + list(APPEND SOURCES + tls/mbedtls/wrapper/library/ssl_cert.c + tls/mbedtls/wrapper/library/ssl_lib.c + tls/mbedtls/wrapper/library/ssl_methods.c + tls/mbedtls/wrapper/library/ssl_pkey.c + tls/mbedtls/wrapper/library/ssl_stack.c + tls/mbedtls/wrapper/library/ssl_x509.c) + + list(APPEND SOURCES + tls/mbedtls/wrapper/platform/ssl_pm.c + tls/mbedtls/wrapper/platform/ssl_port.c) + endif() + + set(_WANT_MBT 0) + if (NOT LWS_PLAT_FREERTOS) + if (NOT DEFINED LWS_MBEDTLS_LIBRARIES) + set(_WANT_MBT 1) + endif() + if (NOT DEFINED LWS_MBEDTLS_INCLUDE_DIRS) + set(_WANT_MBT 1) + endif() + endif() + + if (_WANT_MBT) + + find_path(LWS_MBEDTLS_INCLUDE_DIRS mbedtls/ssl.h) + + find_library(MBEDTLS_LIBRARY mbedtls) + find_library(MBEDX509_LIBRARY mbedx509) + find_library(MBEDCRYPTO_LIBRARY mbedcrypto) + + set(LWS_MBEDTLS_LIBRARIES "${MBEDTLS_LIBRARY}" "${MBEDX509_LIBRARY}" "${MBEDCRYPTO_LIBRARY}") + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(MBEDTLS DEFAULT_MSG + LWS_MBEDTLS_INCLUDE_DIRS MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY) + + mark_as_advanced(LWS_MBEDTLS_INCLUDE_DIRS MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY) + + if ("${LWS_MBEDTLS_LIBRARIES}" STREQUAL "" OR "${LWS_MBEDTLS_INCLUDE_DIRS}" STREQUAL "") + message(FATAL_ERROR "You must set LWS_MBEDTLS_LIBRARIES and LWS_MBEDTLS_INCLUDE_DIRS when LWS_WITH_MBEDTLS is turned on.") + endif() + endif() + if (LWS_MBEDTLS_LIBRARIES) + set(MBEDTLS_LIBRARIES ${LWS_MBEDTLS_LIBRARIES}) + endif() + if (LWS_MBEDTLS_INCLUDE_DIRS) + set(MBEDTLS_INCLUDE_DIRS ${LWS_MBEDTLS_INCLUDE_DIRS}) + endif() + set(USE_MBEDTLS 1 PARENT_SCOPE) + if (DEFINED MBEDTLS_INCLUDE_DIRS) + include_directories(${MBEDTLS_INCLUDE_DIRS}) + endif() + + if (DEFINED MBEDTLS_LIBRARIES) + list(APPEND LIB_LIST ${MBEDTLS_LIBRARIES}) + endif() + +# old mbedtls has everything in mbedtls/net.h + +CHECK_C_SOURCE_COMPILES("#include \nint main(void) { return 0;}\n" LWS_HAVE_MBEDTLS_NET_SOCKETS) + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() +set(LWS_HAVE_MBEDTLS_NET_SOCKETS ${LWS_HAVE_MBEDTLS_NET_SOCKETS} PARENT_SCOPE) diff -Nru libwebsockets-4.0.20/lib/tls/mbedtls/lws-genaes.c libwebsockets-4.1.6/lib/tls/mbedtls/lws-genaes.c --- libwebsockets-4.0.20/lib/tls/mbedtls/lws-genaes.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/tls/mbedtls/lws-genaes.c 2020-12-01 17:40:26.000000000 +0000 @@ -25,7 +25,9 @@ * same whether you are using openssl or mbedtls hash functions underneath. */ #include "private-lib-core.h" +#if defined(LWS_WITH_JOSE) #include "private-lib-jose.h" +#endif static int operation_map[] = { MBEDTLS_AES_ENCRYPT, MBEDTLS_AES_DECRYPT }; @@ -161,6 +163,7 @@ return 0; } +#if defined(LWS_HAVE_mbedtls_internal_aes_encrypt) static int lws_genaes_rfc3394_wrap(int wrap, int cek_bits, const uint8_t *kek, int kek_bits, const uint8_t *in, uint8_t *out) @@ -271,6 +274,7 @@ return ret; } +#endif int lws_genaes_crypt(struct lws_genaes_ctx *ctx, const uint8_t *in, size_t len, @@ -282,6 +286,7 @@ switch (ctx->mode) { case LWS_GAESM_KW: +#if defined(LWS_HAVE_mbedtls_internal_aes_encrypt) /* a key of length ctx->k->len is wrapped by a 128-bit KEK */ n = lws_genaes_rfc3394_wrap(ctx->op == MBEDTLS_AES_ENCRYPT, ctx->op == MBEDTLS_AES_ENCRYPT ? len * 8 : @@ -289,6 +294,10 @@ ctx->k->len * 8, in, out); break; +#else + lwsl_err("%s: your mbedtls is too old\n", __func__); + return -1; +#endif case LWS_GAESM_CBC: memcpy(iv, iv_or_nonce_ctr_or_data_unit_16, 16); diff -Nru libwebsockets-4.0.20/lib/tls/mbedtls/lws-genhash.c libwebsockets-4.1.6/lib/tls/mbedtls/lws-genhash.c --- libwebsockets-4.0.20/lib/tls/mbedtls/lws-genhash.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/tls/mbedtls/lws-genhash.c 2020-12-01 17:40:26.000000000 +0000 @@ -28,10 +28,120 @@ #include #if (MBEDTLS_VERSION_NUMBER >= 0x02070000) -#define MBA(fn) fn##_ret + +/* + * We have the _ret variants available, check the return codes on everything + */ + +int +lws_genhash_init(struct lws_genhash_ctx *ctx, enum lws_genhash_types type) +{ + ctx->type = type; + + switch (ctx->type) { + case LWS_GENHASH_TYPE_MD5: + mbedtls_md5_init(&ctx->u.md5); + if (mbedtls_md5_starts_ret(&ctx->u.md5)) + return 1; + break; + case LWS_GENHASH_TYPE_SHA1: + mbedtls_sha1_init(&ctx->u.sha1); + if (mbedtls_sha1_starts_ret(&ctx->u.sha1)) + return 1; + break; + case LWS_GENHASH_TYPE_SHA256: + mbedtls_sha256_init(&ctx->u.sha256); + if (mbedtls_sha256_starts_ret(&ctx->u.sha256, 0)) + return 1; + break; + case LWS_GENHASH_TYPE_SHA384: + mbedtls_sha512_init(&ctx->u.sha512); + if (mbedtls_sha512_starts_ret(&ctx->u.sha512, 1 /* is384 */)) + return 1; + break; + case LWS_GENHASH_TYPE_SHA512: + mbedtls_sha512_init(&ctx->u.sha512); + if (mbedtls_sha512_starts_ret(&ctx->u.sha512, 0)) + return 1; + break; + default: + return 1; + } + + return 0; +} + +int +lws_genhash_update(struct lws_genhash_ctx *ctx, const void *in, size_t len) +{ + if (!len) + return 0; + + switch (ctx->type) { + case LWS_GENHASH_TYPE_MD5: + if (mbedtls_md5_update_ret(&ctx->u.md5, in, len)) + return 1; + break; + case LWS_GENHASH_TYPE_SHA1: + if (mbedtls_sha1_update_ret(&ctx->u.sha1, in, len)) + return 1; + break; + case LWS_GENHASH_TYPE_SHA256: + if (mbedtls_sha256_update_ret(&ctx->u.sha256, in, len)) + return 1; + break; + case LWS_GENHASH_TYPE_SHA384: + if (mbedtls_sha512_update_ret(&ctx->u.sha512, in, len)) + return 1; + break; + case LWS_GENHASH_TYPE_SHA512: + if (mbedtls_sha512_update_ret(&ctx->u.sha512, in, len)) + return 1; + break; + } + + return 0; +} + +int +lws_genhash_destroy(struct lws_genhash_ctx *ctx, void *result) +{ + switch (ctx->type) { + case LWS_GENHASH_TYPE_MD5: + if (mbedtls_md5_finish_ret(&ctx->u.md5, result)) + return 1; + mbedtls_md5_free(&ctx->u.md5); + break; + case LWS_GENHASH_TYPE_SHA1: + if (mbedtls_sha1_finish_ret(&ctx->u.sha1, result)) + return 1; + mbedtls_sha1_free(&ctx->u.sha1); + break; + case LWS_GENHASH_TYPE_SHA256: + if (mbedtls_sha256_finish_ret(&ctx->u.sha256, result)) + return 1; + mbedtls_sha256_free(&ctx->u.sha256); + break; + case LWS_GENHASH_TYPE_SHA384: + if (mbedtls_sha512_finish_ret(&ctx->u.sha512, result)) + return 1; + mbedtls_sha512_free(&ctx->u.sha512); + break; + case LWS_GENHASH_TYPE_SHA512: + if (mbedtls_sha512_finish_ret(&ctx->u.sha512, result)) + return 1; + mbedtls_sha512_free(&ctx->u.sha512); + break; + } + + return 0; +} + #else -#define MBA(fn) fn -#endif + +/* + * mbedtls is too old to have the _ret variants + */ int lws_genhash_init(struct lws_genhash_ctx *ctx, enum lws_genhash_types type) @@ -41,23 +151,23 @@ switch (ctx->type) { case LWS_GENHASH_TYPE_MD5: mbedtls_md5_init(&ctx->u.md5); - MBA(mbedtls_md5_starts)(&ctx->u.md5); + mbedtls_md5_starts(&ctx->u.md5); break; case LWS_GENHASH_TYPE_SHA1: mbedtls_sha1_init(&ctx->u.sha1); - MBA(mbedtls_sha1_starts)(&ctx->u.sha1); + mbedtls_sha1_starts(&ctx->u.sha1); break; case LWS_GENHASH_TYPE_SHA256: mbedtls_sha256_init(&ctx->u.sha256); - MBA(mbedtls_sha256_starts)(&ctx->u.sha256, 0); + mbedtls_sha256_starts(&ctx->u.sha256, 0); break; case LWS_GENHASH_TYPE_SHA384: mbedtls_sha512_init(&ctx->u.sha512); - MBA(mbedtls_sha512_starts)(&ctx->u.sha512, 1 /* is384 */); + mbedtls_sha512_starts(&ctx->u.sha512, 1 /* is384 */); break; case LWS_GENHASH_TYPE_SHA512: mbedtls_sha512_init(&ctx->u.sha512); - MBA(mbedtls_sha512_starts)(&ctx->u.sha512, 0); + mbedtls_sha512_starts(&ctx->u.sha512, 0); break; default: return 1; @@ -74,19 +184,19 @@ switch (ctx->type) { case LWS_GENHASH_TYPE_MD5: - MBA(mbedtls_md5_update)(&ctx->u.md5, in, len); + mbedtls_md5_update(&ctx->u.md5, in, len); break; case LWS_GENHASH_TYPE_SHA1: - MBA(mbedtls_sha1_update)(&ctx->u.sha1, in, len); + mbedtls_sha1_update(&ctx->u.sha1, in, len); break; case LWS_GENHASH_TYPE_SHA256: - MBA(mbedtls_sha256_update)(&ctx->u.sha256, in, len); + mbedtls_sha256_update(&ctx->u.sha256, in, len); break; case LWS_GENHASH_TYPE_SHA384: - MBA(mbedtls_sha512_update)(&ctx->u.sha512, in, len); + mbedtls_sha512_update(&ctx->u.sha512, in, len); break; case LWS_GENHASH_TYPE_SHA512: - MBA(mbedtls_sha512_update)(&ctx->u.sha512, in, len); + mbedtls_sha512_update(&ctx->u.sha512, in, len); break; } @@ -98,23 +208,23 @@ { switch (ctx->type) { case LWS_GENHASH_TYPE_MD5: - MBA(mbedtls_md5_finish)(&ctx->u.md5, result); + mbedtls_md5_finish(&ctx->u.md5, result); mbedtls_md5_free(&ctx->u.md5); break; case LWS_GENHASH_TYPE_SHA1: - MBA(mbedtls_sha1_finish)(&ctx->u.sha1, result); + mbedtls_sha1_finish(&ctx->u.sha1, result); mbedtls_sha1_free(&ctx->u.sha1); break; case LWS_GENHASH_TYPE_SHA256: - MBA(mbedtls_sha256_finish)(&ctx->u.sha256, result); + mbedtls_sha256_finish(&ctx->u.sha256, result); mbedtls_sha256_free(&ctx->u.sha256); break; case LWS_GENHASH_TYPE_SHA384: - MBA(mbedtls_sha512_finish)(&ctx->u.sha512, result); + mbedtls_sha512_finish(&ctx->u.sha512, result); mbedtls_sha512_free(&ctx->u.sha512); break; case LWS_GENHASH_TYPE_SHA512: - MBA(mbedtls_sha512_finish)(&ctx->u.sha512, result); + mbedtls_sha512_finish(&ctx->u.sha512, result); mbedtls_sha512_free(&ctx->u.sha512); break; } @@ -122,6 +232,8 @@ return 0; } +#endif + int lws_genhmac_init(struct lws_genhmac_ctx *ctx, enum lws_genhmac_types type, const uint8_t *key, size_t key_len) @@ -148,8 +260,13 @@ if (!ctx->hmac) return -1; +#if !defined(LWS_HAVE_mbedtls_md_setup) if (mbedtls_md_init_ctx(&ctx->ctx, ctx->hmac)) return -1; +#else + if (mbedtls_md_setup(&ctx->ctx, ctx->hmac, 1)) + return -1; +#endif if (mbedtls_md_hmac_starts(&ctx->ctx, key, key_len)) { mbedtls_md_free(&ctx->ctx); diff -Nru libwebsockets-4.0.20/lib/tls/mbedtls/lws-genrsa.c libwebsockets-4.1.6/lib/tls/mbedtls/lws-genrsa.c --- libwebsockets-4.0.20/lib/tls/mbedtls/lws-genrsa.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/tls/mbedtls/lws-genrsa.c 2020-12-01 17:40:26.000000000 +0000 @@ -85,8 +85,13 @@ if ( el[LWS_GENCRYPTO_RSA_KEYEL_D].len && !el[LWS_GENCRYPTO_RSA_KEYEL_P].len && !el[LWS_GENCRYPTO_RSA_KEYEL_Q].len) { +#if defined(LWS_HAVE_mbedtls_rsa_complete) if (mbedtls_rsa_complete(ctx->ctx)) { lwsl_notice("mbedtls_rsa_complete failed\n"); +#else + { + lwsl_notice("%s: you have to provide P and Q\n", __func__); +#endif lws_free_set_NULL(ctx->ctx); return -1; @@ -176,7 +181,9 @@ ctx->ctx->len = in_len; +#if defined(LWS_HAVE_mbedtls_rsa_complete) mbedtls_rsa_complete(ctx->ctx); +#endif switch(ctx->mode) { case LGRSAM_PKCS1_1_5: @@ -214,7 +221,9 @@ ctx->ctx->len = in_len; +#if defined(LWS_HAVE_mbedtls_rsa_complete) mbedtls_rsa_complete(ctx->ctx); +#endif switch(ctx->mode) { case LGRSAM_PKCS1_1_5: @@ -249,7 +258,9 @@ { int n; +#if defined(LWS_HAVE_mbedtls_rsa_complete) mbedtls_rsa_complete(ctx->ctx); +#endif switch(ctx->mode) { case LGRSAM_PKCS1_1_5: @@ -284,7 +295,9 @@ { int n; +#if defined(LWS_HAVE_mbedtls_rsa_complete) mbedtls_rsa_complete(ctx->ctx); +#endif switch(ctx->mode) { case LGRSAM_PKCS1_1_5: @@ -323,7 +336,9 @@ if (h < 0) return -1; +#if defined(LWS_HAVE_mbedtls_rsa_complete) mbedtls_rsa_complete(ctx->ctx); +#endif switch(ctx->mode) { case LGRSAM_PKCS1_1_5: @@ -358,7 +373,9 @@ if (h < 0) return -1; +#if defined(LWS_HAVE_mbedtls_rsa_complete) mbedtls_rsa_complete(ctx->ctx); +#endif /* * The "sig" buffer must be as large as the size of ctx->N diff -Nru libwebsockets-4.0.20/lib/tls/mbedtls/mbedtls-client.c libwebsockets-4.1.6/lib/tls/mbedtls/mbedtls-client.c --- libwebsockets-4.0.20/lib/tls/mbedtls/mbedtls-client.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/tls/mbedtls/mbedtls-client.c 2020-12-01 17:40:26.000000000 +0000 @@ -34,7 +34,7 @@ lws_ssl_client_bio_create(struct lws *wsi) { char hostname[128], *p; - const char *alpn_comma = wsi->context->tls.alpn_default; + const char *alpn_comma = wsi->a.context->tls.alpn_default; struct alpn_ctx protos; if (wsi->stash) @@ -60,13 +60,13 @@ p++; } - wsi->tls.ssl = SSL_new(wsi->vhost->tls.ssl_client_ctx); + wsi->tls.ssl = SSL_new(wsi->a.vhost->tls.ssl_client_ctx); if (!wsi->tls.ssl) { lwsl_info("%s: SSL_new() failed\n", __func__); return -1; } - if (wsi->vhost->tls.ssl_info_event_mask) + if (wsi->a.vhost->tls.ssl_info_event_mask) SSL_set_info_callback(wsi->tls.ssl, lws_ssl_info_callback); if (!(wsi->tls.use_ssl & LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK)) { @@ -77,8 +77,8 @@ X509_VERIFY_PARAM_set1_host(param, hostname, 0); } - if (wsi->vhost->tls.alpn) - alpn_comma = wsi->vhost->tls.alpn; + if (wsi->a.vhost->tls.alpn) + alpn_comma = wsi->a.vhost->tls.alpn; if (wsi->stash) { lws_strncpy(hostname, wsi->stash->cis[CIS_HOST], sizeof(hostname)); @@ -108,11 +108,14 @@ SSL_set_fd(wsi->tls.ssl, wsi->desc.sockfd); if (wsi->sys_tls_client_cert) { - lws_system_blob_t *b = lws_system_get_blob(wsi->context, + lws_system_blob_t *b = lws_system_get_blob(wsi->a.context, LWS_SYSBLOB_TYPE_CLIENT_CERT_DER, wsi->sys_tls_client_cert - 1); - const uint8_t *data; + const uint8_t *pem_data = NULL; + uint8_t *data = NULL; + lws_filepos_t flen; size_t size; + int err = 0; if (!b) goto no_client_cert; @@ -125,13 +128,21 @@ if (!size) goto no_client_cert; - if (lws_system_blob_get_single_ptr(b, &data)) + if (lws_system_blob_get_single_ptr(b, &pem_data)) goto no_client_cert; - if (SSL_use_certificate_ASN1(wsi->tls.ssl, data, size) != 1) + if (lws_tls_alloc_pem_to_der_file(wsi->a.context, NULL, + (const char *)pem_data, size, + &data, &flen)) goto no_client_cert; + size = (size_t) flen; - b = lws_system_get_blob(wsi->context, + err = SSL_use_certificate_ASN1(wsi->tls.ssl, data, size); + lws_free_set_NULL(data); + if (err != 1) + goto no_client_cert; + + b = lws_system_get_blob(wsi->a.context, LWS_SYSBLOB_TYPE_CLIENT_KEY_DER, wsi->sys_tls_client_cert - 1); if (!b) @@ -140,10 +151,18 @@ if (!size) goto no_client_cert; - if (lws_system_blob_get_single_ptr(b, &data)) + if (lws_system_blob_get_single_ptr(b, &pem_data)) goto no_client_cert; - if (SSL_use_PrivateKey_ASN1(0, wsi->tls.ssl, data, size) != 1) + if (lws_tls_alloc_pem_to_der_file(wsi->a.context, NULL, + (const char *)pem_data, size, + &data, &flen)) + goto no_client_cert; + size = (size_t) flen; + + err = SSL_use_PrivateKey_ASN1(0, wsi->tls.ssl, data, size); + lws_free_set_NULL(data); + if (err != 1) goto no_client_cert; /* no wrapper api for check key */ @@ -167,7 +186,7 @@ } enum lws_ssl_capable_status -lws_tls_client_connect(struct lws *wsi) +lws_tls_client_connect(struct lws *wsi, char *errbuf, int elen) { int m, n = SSL_connect(wsi->tls.ssl); const unsigned char *prot; @@ -191,6 +210,8 @@ if (!n) /* we don't know what he wants, but he says to retry */ return LWS_SSL_CAPABLE_MORE_SERVICE; + lws_snprintf(errbuf, elen, "mbedtls connect %d %d %d", n, m, errno); + return LWS_SSL_CAPABLE_ERROR; } @@ -199,7 +220,7 @@ { int n; X509 *peer = SSL_get_peer_certificate(wsi->tls.ssl); - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; char *sb = (char *)&pt->serv_buf[0]; if (!peer) { @@ -254,7 +275,10 @@ const char *cert_filepath, const void *cert_mem, unsigned int cert_mem_len, - const char *private_key_filepath) + const char *private_key_filepath, + const void *key_mem, + unsigned int key_mem_len + ) { X509 *d2i_X509(X509 **cert, const unsigned char *buffer, long len); SSL_METHOD *method = (SSL_METHOD *)TLS_client_method(); @@ -345,13 +369,13 @@ lwsl_notice("Loaded client cert %s\n", cert_filepath); #endif } else if (cert_mem && cert_mem_len) { - // lwsl_hexdump_notice(cert_mem, cert_mem_len - 1); + /* lwsl_hexdump_notice(cert_mem, cert_mem_len - 1); */ SSL_CTX_use_PrivateKey_ASN1(0, vh->tls.ssl_client_ctx, cert_mem, cert_mem_len - 1); n = SSL_CTX_use_certificate_ASN1(vh->tls.ssl_client_ctx, cert_mem_len, cert_mem); if (n < 1) { - lwsl_err("%s: problem interpreting client cert\n", + lwsl_err("%s: (mbedtls) problem interpreting client cert\n", __func__); lws_tls_err_describe_clear(); return 1; diff -Nru libwebsockets-4.0.20/lib/tls/mbedtls/mbedtls-server.c libwebsockets-4.1.6/lib/tls/mbedtls/mbedtls-server.c --- libwebsockets-4.0.20/lib/tls/mbedtls/mbedtls-server.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/tls/mbedtls/mbedtls-server.c 2020-12-01 17:40:26.000000000 +0000 @@ -24,6 +24,7 @@ #include "private-lib-core.h" #include +#include int lws_tls_server_client_cert_verify_config(struct lws_vhost *vh) @@ -152,9 +153,6 @@ */ cert = NULL; private_key = NULL; - - if (!mem_cert) - return 1; } if (lws_tls_alloc_pem_to_der_file(vhost->context, cert, mem_cert, mem_cert_len, &p, &flen)) { @@ -186,14 +184,6 @@ return 1; } - if (!private_key && !mem_privkey && vhost->protocols[0].callback(wsi, - LWS_CALLBACK_OPENSSL_CONTEXT_REQUIRES_PRIVATE_KEY, - vhost->tls.ssl_ctx, NULL, 0)) { - lwsl_err("ssl private key not set\n"); - - return 1; - } - vhost->tls.skipped_certs = 0; return 0; @@ -264,7 +254,7 @@ lws_tls_server_new_nonblocking(struct lws *wsi, lws_sockfd_type accept_fd) { errno = 0; - wsi->tls.ssl = SSL_new(wsi->vhost->tls.ssl_ctx); + wsi->tls.ssl = SSL_new(wsi->a.vhost->tls.ssl_ctx); if (wsi->tls.ssl == NULL) { lwsl_err("SSL_new failed: errno %d\n", errno); @@ -274,10 +264,10 @@ SSL_set_fd(wsi->tls.ssl, accept_fd); - if (wsi->vhost->tls.ssl_info_event_mask) + if (wsi->a.vhost->tls.ssl_info_event_mask) SSL_set_info_callback(wsi->tls.ssl, lws_ssl_info_callback); - SSL_set_sni_callback(wsi->tls.ssl, lws_mbedtls_sni_cb, wsi->context); + SSL_set_sni_callback(wsi->tls.ssl, lws_mbedtls_sni_cb, wsi->a.context); return 0; } @@ -306,7 +296,7 @@ wsi->skip_fallback = 1; if (n == 1) { - if (strstr(wsi->vhost->name, ".invalid")) { + if (strstr(wsi->a.vhost->name, ".invalid")) { lwsl_notice("%s: vhost has .invalid, " "rejecting accept\n", __func__); @@ -325,13 +315,18 @@ } m = SSL_get_error(wsi->tls.ssl, n); - lwsl_debug("%s: %p: accept SSL_get_error %d errno %d\n", __func__, + lwsl_notice("%s: %p: accept SSL_get_error %d errno %d\n", __func__, wsi, m, errno); // mbedtls wrapper only if (m == SSL_ERROR_SYSCALL && errno == 11) return LWS_SSL_CAPABLE_MORE_SERVICE_READ; +#if defined(__APPLE__) + if (m == SSL_ERROR_SYSCALL && errno == 35) + return LWS_SSL_CAPABLE_MORE_SERVICE_READ; +#endif + #if defined(WIN32) if (m == SSL_ERROR_SYSCALL && errno == 0) return LWS_SSL_CAPABLE_MORE_SERVICE_READ; diff -Nru libwebsockets-4.0.20/lib/tls/mbedtls/mbedtls-ssl.c libwebsockets-4.1.6/lib/tls/mbedtls/mbedtls-ssl.c --- libwebsockets-4.0.20/lib/tls/mbedtls/mbedtls-ssl.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/tls/mbedtls/mbedtls-ssl.c 2020-12-01 17:40:26.000000000 +0000 @@ -25,7 +25,6 @@ #include "private-lib-core.h" #include "private-lib-tls-mbedtls.h" - void lws_ssl_destroy(struct lws_vhost *vhost) { @@ -45,7 +44,7 @@ int lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, int len) { - struct lws_context *context = wsi->context; + struct lws_context *context = wsi->a.context; struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; int n = 0, m; @@ -107,11 +106,20 @@ return LWS_SSL_CAPABLE_ERROR; } +#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__, n); + lwsl_hexdump_notice(buf, n); +#endif + lws_stats_bump(pt, LWSSTATS_B_READ, n); #if defined(LWS_WITH_SERVER_STATUS) - if (wsi->vhost) - wsi->vhost->conn_stats.rx += n; + if (wsi->a.vhost) + wsi->a.vhost->conn_stats.rx += n; #endif #if defined(LWS_WITH_DETAILED_LATENCY) if (context->detailed_latency_cb) { @@ -121,7 +129,7 @@ wsi->detlat.latencies[LAT_DUR_PROXY_RX_TO_ONWARD_TX] = lws_now_usecs() - pt->ust_left_poll; wsi->detlat.latencies[LAT_DUR_USERCB] = 0; - lws_det_lat_cb(wsi->context, &wsi->detlat); + lws_det_lat_cb(wsi->a.context, &wsi->detlat); } #endif /* @@ -136,10 +144,12 @@ if (!wsi->tls.ssl) goto bail; - if (SSL_pending(wsi->tls.ssl) && - lws_dll2_is_detached(&wsi->tls.dll_pending_tls)) - lws_dll2_add_head(&wsi->tls.dll_pending_tls, - &pt->tls.dll_pending_tls_owner); + if (SSL_pending(wsi->tls.ssl)) { + if (lws_dll2_is_detached(&wsi->tls.dll_pending_tls)) + lws_dll2_add_head(&wsi->tls.dll_pending_tls, + &pt->tls.dll_pending_tls_owner); + } else + __lws_ssl_remove_wsi_from_buffered_list(wsi); return n; bail: @@ -162,6 +172,16 @@ { int n, m; +#if 0 + /* + * If using mbedtls type tls library, this is the last point for all + * paths before sending data into the tls tunnel, where you can dump it + * and see what is being sent. + */ + lwsl_notice("%s: len %d\n", __func__, len); + lwsl_hexdump_notice(buf, len); +#endif + if (!wsi->tls.ssl) return lws_ssl_capable_write_no_ssl(wsi, buf, len); @@ -209,13 +229,13 @@ if (!wsi) return; - if (!(where & wsi->vhost->tls.ssl_info_event_mask)) + if (!(where & wsi->a.vhost->tls.ssl_info_event_mask)) return; si.where = where; si.ret = ret; - if (user_callback_handle_rxflow(wsi->protocol->callback, + if (user_callback_handle_rxflow(wsi->a.protocol->callback, wsi, LWS_CALLBACK_SSL_INFO, wsi->user_space, &si, 0)) lws_set_timeout(wsi, PENDING_TIMEOUT_KILLED_BY_SSL_INFO, -1); @@ -234,7 +254,7 @@ /* kill ssl callbacks, becausse we will remove the fd from the * table linking it to the wsi */ - if (wsi->vhost->tls.ssl_info_event_mask) + if (wsi->a.vhost->tls.ssl_info_event_mask) SSL_set_info_callback(wsi->tls.ssl, NULL); #endif @@ -245,7 +265,7 @@ SSL_free(wsi->tls.ssl); wsi->tls.ssl = NULL; - lws_tls_restrict_return(wsi->context); + lws_tls_restrict_return(wsi->a.context); return 1; /* handled */ } @@ -286,7 +306,7 @@ switch (n) { case 1: /* successful completion */ - n = shutdown(wsi->desc.sockfd, SHUT_WR); + (void)shutdown(wsi->desc.sockfd, SHUT_WR); return LWS_SSL_CAPABLE_DONE; case 0: /* needs a retry */ diff -Nru libwebsockets-4.0.20/lib/tls/mbedtls/private-lib-tls-mbedtls.h libwebsockets-4.1.6/lib/tls/mbedtls/private-lib-tls-mbedtls.h --- libwebsockets-4.0.20/lib/tls/mbedtls/private-lib-tls-mbedtls.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/tls/mbedtls/private-lib-tls-mbedtls.h 2020-12-01 17:40:26.000000000 +0000 @@ -25,6 +25,7 @@ */ #include +#include struct lws_x509_cert { mbedtls_x509_crt cert; /* has a .next for linked-list / chain */ diff -Nru libwebsockets-4.0.20/lib/tls/mbedtls/wrapper/platform/ssl_pm.c libwebsockets-4.1.6/lib/tls/mbedtls/wrapper/platform/ssl_pm.c --- libwebsockets-4.0.20/lib/tls/mbedtls/wrapper/platform/ssl_pm.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/tls/mbedtls/wrapper/platform/ssl_pm.c 2020-12-01 17:40:26.000000000 +0000 @@ -67,6 +67,7 @@ unsigned int max_content_len; + /*********************************************************************************************/ /************************************ SSL arch interface *************************************/ @@ -185,7 +186,9 @@ goto mbedtls_err2; } - mbedtls_ssl_set_bio(&ssl_pm->ssl, &ssl_pm->fd, mbedtls_net_send, mbedtls_net_recv, NULL); + mbedtls_ssl_set_bio(&ssl_pm->ssl, &ssl_pm->fd, + lws_plat_mbedtls_net_send, + lws_plat_mbedtls_net_recv, NULL); ssl->ssl_pm = ssl_pm; @@ -548,6 +551,7 @@ int x509_pm_show_info(X509 *x) { +#if 0 int ret; char *buf; mbedtls_x509_crt *x509_crt; @@ -587,6 +591,9 @@ ssl_mem_free(buf); no_mem: return -1; +#else + return 0; +#endif } int x509_pm_new(X509 *x, X509 *m_x) diff -Nru libwebsockets-4.0.20/lib/tls/openssl/lws-genaes.c libwebsockets-4.1.6/lib/tls/openssl/lws-genaes.c --- libwebsockets-4.0.20/lib/tls/openssl/lws-genaes.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/tls/openssl/lws-genaes.c 2020-12-01 17:40:26.000000000 +0000 @@ -25,7 +25,9 @@ * same whether you are using openssl or mbedtls hash functions underneath. */ #include "private-lib-core.h" +#if defined(LWS_WITH_JOSE) #include "private-lib-jose.h" +#endif /* * Care: many openssl apis return 1 for success. These are translated to the diff -Nru libwebsockets-4.0.20/lib/tls/openssl/lws-genhash.c libwebsockets-4.1.6/lib/tls/openssl/lws-genhash.c --- libwebsockets-4.0.20/lib/tls/openssl/lws-genhash.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/tls/openssl/lws-genhash.c 2020-12-01 17:40:26.000000000 +0000 @@ -93,6 +93,78 @@ return ret; } +#if defined(LWS_HAVE_EVP_PKEY_new_raw_private_key) + +int +lws_genhmac_init(struct lws_genhmac_ctx *ctx, enum lws_genhmac_types type, + const uint8_t *key, size_t key_len) +{ + ctx->ctx = EVP_MD_CTX_create(); + if (!ctx->ctx) + return -1; + + ctx->evp_type = 0; + ctx->type = type; + + switch (type) { + case LWS_GENHMAC_TYPE_SHA256: + ctx->evp_type = EVP_sha256(); + break; + case LWS_GENHMAC_TYPE_SHA384: + ctx->evp_type = EVP_sha384(); + break; + case LWS_GENHMAC_TYPE_SHA512: + ctx->evp_type = EVP_sha512(); + break; + default: + lwsl_err("%s: unknown HMAC type %d\n", __func__, type); + goto bail; + } + + ctx->key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, key, key_len); + if (!ctx->key) + goto bail; + + if (EVP_DigestSignInit(ctx->ctx, NULL, ctx->evp_type, NULL, ctx->key) != 1) + goto bail1; + + return 0; + +bail1: + EVP_PKEY_free(ctx->key); +bail: + EVP_MD_CTX_free(ctx->ctx); + + return -1; +} + +int +lws_genhmac_update(struct lws_genhmac_ctx *ctx, const void *in, size_t len) +{ + + if (EVP_DigestSignUpdate(ctx->ctx, in, len) != 1) + return -1; + + return 0; +} + +int +lws_genhmac_destroy(struct lws_genhmac_ctx *ctx, void *result) +{ + size_t size = (size_t)lws_genhmac_size(ctx->type); + int n; + + n = EVP_DigestSignFinal(ctx->ctx, result, &size); + EVP_MD_CTX_free(ctx->ctx); + EVP_PKEY_free(ctx->key); + + if (n != 1) + return -1; + + return 0; +} + +#else int lws_genhmac_init(struct lws_genhmac_ctx *ctx, enum lws_genhmac_types type, @@ -172,3 +244,5 @@ return 0; } + +#endif diff -Nru libwebsockets-4.0.20/lib/tls/openssl/openssl-client.c libwebsockets-4.1.6/lib/tls/openssl/openssl-client.c --- libwebsockets-4.0.20/lib/tls/openssl/openssl-client.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/tls/openssl/openssl-client.c 2020-12-01 17:40:26.000000000 +0000 @@ -21,6 +21,12 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ + +#include "lws_config.h" +#ifdef LWS_HAVE_X509_VERIFY_PARAM_set1_host +/* Before glibc 2.10, strnlen required _GNU_SOURCE */ +#define _GNU_SOURCE +#endif #include #include "private-lib-core.h" @@ -100,7 +106,7 @@ return 0; } - n = lws_get_context_protocol(wsi->context, 0).callback(wsi, + n = lws_get_context_protocol(wsi->a.context, 0).callback(wsi, LWS_CALLBACK_OPENSSL_PERFORM_SERVER_CERT_VERIFICATION, x509_ctx, ssl, preverify_ok); @@ -138,7 +144,7 @@ #if defined(LWS_HAVE_SSL_set_alpn_protos) && \ defined(LWS_HAVE_SSL_get0_alpn_selected) uint8_t openssl_alpn[40]; - const char *alpn_comma = wsi->context->tls.alpn_default; + const char *alpn_comma = wsi->a.context->tls.alpn_default; int n; #endif @@ -173,7 +179,7 @@ p++; } - wsi->tls.ssl = SSL_new(wsi->vhost->tls.ssl_client_ctx); + wsi->tls.ssl = SSL_new(wsi->a.vhost->tls.ssl_client_ctx); if (!wsi->tls.ssl) { lwsl_err("SSL_new failed: %s\n", ERR_error_string(lws_ssl_get_error(wsi, 0), NULL)); @@ -182,23 +188,25 @@ } #if defined (LWS_HAVE_SSL_SET_INFO_CALLBACK) - if (wsi->vhost->tls.ssl_info_event_mask) + if (wsi->a.vhost->tls.ssl_info_event_mask) SSL_set_info_callback(wsi->tls.ssl, lws_ssl_info_callback); #endif -#if defined LWS_HAVE_X509_VERIFY_PARAM_set1_host +#if defined(LWS_HAVE_X509_VERIFY_PARAM_set1_host) if (!(wsi->tls.use_ssl & LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK)) { +#if !defined(USE_WOLFSSL) + X509_VERIFY_PARAM *param = SSL_get0_param(wsi->tls.ssl); -#if !defined(USE_WOLFSSL) /* Enable automatic hostname checks */ X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); -#endif /* Handle the case where the hostname is an IP address */ if (!X509_VERIFY_PARAM_set1_ip_asc(param, hostname)) X509_VERIFY_PARAM_set1_host(param, hostname, strnlen(hostname, sizeof(hostname))); +#endif + } #else if (!(wsi->tls.use_ssl & LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK)) { @@ -251,10 +259,10 @@ * Otherwise the connect will simply fail with error code -155 */ #ifdef USE_OLD_CYASSL - if (wsi->tls.use_ssl == 2) + if (wsi->tls.use_ssl & LCCSCF_ALLOW_SELFSIGNED) CyaSSL_set_verify(wsi->tls.ssl, SSL_VERIFY_NONE, NULL); #else - if (wsi->tls.use_ssl == 2) + if (wsi->tls.use_ssl & LCCSCF_ALLOW_SELFSIGNED) wolfSSL_set_verify(wsi->tls.ssl, SSL_VERIFY_NONE, NULL); #endif #endif /* USE_WOLFSSL */ @@ -275,8 +283,8 @@ #if defined(LWS_HAVE_SSL_set_alpn_protos) && \ defined(LWS_HAVE_SSL_get0_alpn_selected) - if (wsi->vhost->tls.alpn) - alpn_comma = wsi->vhost->tls.alpn; + if (wsi->a.vhost->tls.alpn) + alpn_comma = wsi->a.vhost->tls.alpn; if (wsi->stash) alpn_comma = wsi->stash->cis[CIS_ALPN]; #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) @@ -297,7 +305,7 @@ wsi); if (wsi->sys_tls_client_cert) { - lws_system_blob_t *b = lws_system_get_blob(wsi->context, + lws_system_blob_t *b = lws_system_get_blob(wsi->a.context, LWS_SYSBLOB_TYPE_CLIENT_CERT_DER, wsi->sys_tls_client_cert - 1); const uint8_t *data; @@ -327,7 +335,7 @@ goto no_client_cert; } - b = lws_system_get_blob(wsi->context, + b = lws_system_get_blob(wsi->a.context, LWS_SYSBLOB_TYPE_CLIENT_KEY_DER, wsi->sys_tls_client_cert - 1); if (!b) @@ -376,7 +384,7 @@ } enum lws_ssl_capable_status -lws_tls_client_connect(struct lws *wsi) +lws_tls_client_connect(struct lws *wsi, char *errbuf, int elen) { #if defined(LWS_HAVE_SSL_set_alpn_protos) && \ defined(LWS_HAVE_SSL_get0_alpn_selected) @@ -384,17 +392,13 @@ char a[32]; unsigned int len; #endif - int m, n; -#if defined(WIN32) || (_LWS_ENABLED_LOGS & LLL_INFO) - int en; -#endif + int m, n, en; errno = 0; ERR_clear_error(); n = SSL_connect(wsi->tls.ssl); -#if defined(WIN32) || (_LWS_ENABLED_LOGS & LLL_INFO) en = errno; -#endif + m = lws_ssl_get_error(wsi, n); if (m == SSL_ERROR_SYSCALL @@ -405,11 +409,15 @@ #if defined(WIN32) || (_LWS_ENABLED_LOGS & LLL_INFO) lwsl_info("%s: n %d, m %d, errno %d\n", __func__, n, m, en); #endif + lws_snprintf(errbuf, elen, "connect SYSCALL %d", en); return LWS_SSL_CAPABLE_ERROR; } - if (m == SSL_ERROR_SSL) + if (m == SSL_ERROR_SSL) { + n = lws_snprintf(errbuf, elen, "connect SSL err %d: ", m); + ERR_error_string_n(m, errbuf + n, elen - n); return LWS_SSL_CAPABLE_ERROR; + } if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.ssl)) return LWS_SSL_CAPABLE_MORE_SERVICE_READ; @@ -437,6 +445,8 @@ if (!n) /* we don't know what he wants, but he says to retry */ return LWS_SSL_CAPABLE_MORE_SERVICE; + lws_snprintf(errbuf, elen, "connect unk %d", m); + return LWS_SSL_CAPABLE_ERROR; } @@ -444,7 +454,7 @@ lws_tls_client_confirm_peer_cert(struct lws *wsi, char *ebuf, int ebuf_len) { #if !defined(USE_WOLFSSL) - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; char *p = (char *)&pt->serv_buf[0]; char *sb = p; int n; @@ -529,7 +539,10 @@ const char *cert_filepath, const void *cert_mem, unsigned int cert_mem_len, - const char *private_key_filepath) + const char *private_key_filepath, + const void *key_mem, + unsigned int key_mem_len + ) { struct lws_tls_client_reuse *tcr; X509_STORE *x509_store; @@ -720,15 +733,25 @@ /* openssl init for cert verification (for client sockets) */ if (!ca_filepath && (!ca_mem || !ca_mem_len)) { +#if defined(LWS_HAVE_SSL_CTX_load_verify_dir) + if (!SSL_CTX_load_verify_dir( + vh->tls.ssl_client_ctx, LWS_OPENSSL_CLIENT_CERTS)) +#else if (!SSL_CTX_load_verify_locations( vh->tls.ssl_client_ctx, NULL, LWS_OPENSSL_CLIENT_CERTS)) +#endif lwsl_err("Unable to load SSL Client certs from %s " "(set by LWS_OPENSSL_CLIENT_CERTS) -- " "client ssl isn't going to work\n", LWS_OPENSSL_CLIENT_CERTS); } else if (ca_filepath) { +#if defined(LWS_HAVE_SSL_CTX_load_verify_file) + if (!SSL_CTX_load_verify_file( + vh->tls.ssl_client_ctx, ca_filepath)) { +#else if (!SSL_CTX_load_verify_locations( vh->tls.ssl_client_ctx, ca_filepath, NULL)) { +#endif lwsl_err( "Unable to load SSL Client certs " "file from %s -- client ssl isn't " @@ -740,12 +763,11 @@ } else { lws_filepos_t amount = 0; - uint8_t *up1; const uint8_t *up; + uint8_t *up1; if (lws_tls_alloc_pem_to_der_file(vh->context, NULL, ca_mem, - ca_mem_len, &up1, - &amount)) { + ca_mem_len, &up1, &amount)) { lwsl_err("%s: Unable to decode x.509 mem\n", __func__); lwsl_hexdump_notice(ca_mem, ca_mem_len); return 1; @@ -784,6 +806,7 @@ */ /* support for client-side certificate authentication */ + if (cert_filepath) { if (lws_tls_use_any_upgrade_check_extant(cert_filepath) != LWS_TLS_EXTANT_YES && @@ -801,18 +824,33 @@ return 1; } lwsl_notice("Loaded client cert %s\n", cert_filepath); + } else if (cert_mem && cert_mem_len) { - n = SSL_CTX_use_certificate_ASN1(vh->tls.ssl_client_ctx, - cert_mem_len, cert_mem); + lws_filepos_t flen; + uint8_t *p; + + if (lws_tls_alloc_pem_to_der_file(vh->context, NULL, cert_mem, + cert_mem_len, &p, &flen)) { + lwsl_err("%s: couldn't read cert file\n", __func__); + + return 1; + } + + n = SSL_CTX_use_certificate_ASN1(vh->tls.ssl_client_ctx, (int)flen, p); + if (n < 1) { - lwsl_err("%s: problem interpreting client cert\n", - __func__); + lwsl_err("%s: problem interpreting client cert\n", __func__); lws_tls_err_describe_clear(); - return 1; } + + lws_free_set_NULL(p); + + if (n != 1) + return 1; + } if (private_key_filepath) { - lwsl_notice("%s: doing private key filepath\n", __func__); + lwsl_info("%s: using private key filepath\n", __func__); lws_ssl_bind_passphrase(vh->tls.ssl_client_ctx, 1, info); /* set the private key from KeyFile */ if (SSL_CTX_use_PrivateKey_file(vh->tls.ssl_client_ctx, @@ -822,7 +860,7 @@ lws_tls_err_describe_clear(); return 1; } - lwsl_notice("Loaded client cert private key %s\n", + lwsl_info("Loaded client cert private key %s\n", private_key_filepath); /* verify private key */ @@ -831,6 +869,33 @@ return 1; } } + else if (key_mem && key_mem_len) { + + lws_filepos_t flen; + uint8_t *p; + + if (lws_tls_alloc_pem_to_der_file(vh->context, NULL, key_mem, + key_mem_len, &p, &flen)) { + lwsl_err("%s: couldn't use mem cert\n", __func__); + + return 1; + } + + n = SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_RSA, vh->tls.ssl_client_ctx, p, + (long)(lws_intptr_t)flen); + if (n != 1) + n = SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_EC, + vh->tls.ssl_client_ctx, p, + (long)(lws_intptr_t)flen); + + lws_free_set_NULL(p); + + if (n != 1) { + lwsl_err("%s: unable to use key_mem\n", __func__); + + return 1; + } + } return 0; } diff -Nru libwebsockets-4.0.20/lib/tls/openssl/openssl-server.c libwebsockets-4.1.6/lib/tls/openssl/openssl-server.c --- libwebsockets-4.0.20/lib/tls/openssl/openssl-server.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/tls/openssl/openssl-server.c 2020-12-01 17:40:26.000000000 +0000 @@ -59,7 +59,7 @@ else lwsl_info("%s: couldn't get client cert CN\n", __func__); - n = wsi->vhost->protocols[0].callback(wsi, + n = wsi->a.vhost->protocols[0].callback(wsi, LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION, x509_ctx, ssl, preverify_ok); @@ -519,8 +519,13 @@ #endif if (info->ssl_ca_filepath && +#if defined(LWS_HAVE_SSL_CTX_load_verify_file) + !SSL_CTX_load_verify_file(vhost->tls.ssl_ctx, + info->ssl_ca_filepath)) { +#else !SSL_CTX_load_verify_locations(vhost->tls.ssl_ctx, info->ssl_ca_filepath, NULL)) { +#endif lwsl_err("%s: SSL_CTX_load_verify_locations unhappy\n", __func__); } @@ -560,7 +565,7 @@ errno = 0; ERR_clear_error(); - wsi->tls.ssl = SSL_new(wsi->vhost->tls.ssl_ctx); + wsi->tls.ssl = SSL_new(wsi->a.vhost->tls.ssl_ctx); if (wsi->tls.ssl == NULL) { lwsl_err("SSL_new failed: %d (errno %d)\n", lws_ssl_get_error(wsi, 0), errno); @@ -595,7 +600,7 @@ #endif #if defined (LWS_HAVE_SSL_SET_INFO_CALLBACK) - if (wsi->vhost->tls.ssl_info_event_mask) + if (wsi->a.vhost->tls.ssl_info_event_mask) SSL_set_info_callback(wsi->tls.ssl, lws_ssl_info_callback); #endif @@ -614,7 +619,7 @@ enum lws_ssl_capable_status lws_tls_server_accept(struct lws *wsi) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; union lws_tls_cert_info_results ir; int m, n; diff -Nru libwebsockets-4.0.20/lib/tls/openssl/openssl-ssl.c libwebsockets-4.1.6/lib/tls/openssl/openssl-ssl.c --- libwebsockets-4.0.20/lib/tls/openssl/openssl-ssl.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/tls/openssl/openssl-ssl.c 2020-12-01 17:40:26.000000000 +0000 @@ -59,12 +59,15 @@ m = SSL_get_error(wsi->tls.ssl, n); lwsl_debug("%s: %p %d -> %d (errno %d)\n", __func__, wsi->tls.ssl, n, m, errno); + if (m == SSL_ERROR_SSL) + lws_tls_err_describe_clear(); - assert (errno != 9); + // assert (errno != 9); return m; } +#if defined(LWS_WITH_SERVER) static int lws_context_init_ssl_pem_passwd_cb(char *buf, int size, int rwflag, void *userdata) @@ -77,7 +80,9 @@ return (int)strlen(buf); } +#endif +#if defined(LWS_WITH_CLIENT) static int lws_context_init_ssl_pem_passwd_client_cb(char *buf, int size, int rwflag, void *userdata) @@ -94,13 +99,23 @@ return (int)strlen(buf); } +#endif void lws_ssl_bind_passphrase(SSL_CTX *ssl_ctx, int is_client, const struct lws_context_creation_info *info) { - if (!info->ssl_private_key_password && - !info->client_ssl_private_key_password) + if ( +#if defined(LWS_WITH_SERVER) + !info->ssl_private_key_password +#endif +#if defined(LWS_WITH_SERVER) && defined(LWS_WITH_CLIENT) + && +#endif +#if defined(LWS_WITH_CLIENT) + !info->client_ssl_private_key_password +#endif + ) return; /* * password provided, set ssl callback and user data @@ -109,10 +124,20 @@ */ SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, (void *)info); SSL_CTX_set_default_passwd_cb(ssl_ctx, is_client ? +#if defined(LWS_WITH_CLIENT) lws_context_init_ssl_pem_passwd_client_cb: - lws_context_init_ssl_pem_passwd_cb); +#else + NULL: +#endif +#if defined(LWS_WITH_SERVER) + lws_context_init_ssl_pem_passwd_cb +#else + NULL +#endif + ); } +#if defined(LWS_WITH_CLIENT) static void lws_ssl_destroy_client_ctx(struct lws_vhost *vhost) { @@ -135,7 +160,7 @@ lws_dll2_remove(&tcr->cc_list); lws_free(tcr); } - +#endif void lws_ssl_destroy(struct lws_vhost *vhost) { @@ -145,8 +170,9 @@ if (vhost->tls.ssl_ctx) SSL_CTX_free(vhost->tls.ssl_ctx); - +#if defined(LWS_WITH_CLIENT) lws_ssl_destroy_client_ctx(vhost); +#endif // after 1.1.0 no need #if (OPENSSL_VERSION_NUMBER < 0x10100000) @@ -176,7 +202,7 @@ int lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, int len) { - struct lws_context *context = wsi->context; + struct lws_context *context = wsi->a.context; struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; int n = 0, m; @@ -264,15 +290,22 @@ /* keep on trucking it seems */ } +#if 0 + /* + * If using openssl 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__, n); + lwsl_hexdump_notice(buf, n); +#endif + lws_stats_bump(pt, LWSSTATS_B_READ, n); #if defined(LWS_WITH_SERVER_STATUS) - if (wsi->vhost) - wsi->vhost->conn_stats.rx += n; + if (wsi->a.vhost) + wsi->a.vhost->conn_stats.rx += n; #endif - // lwsl_hexdump_err(buf, n); - #if defined(LWS_WITH_DETAILED_LATENCY) if (context->detailed_latency_cb) { wsi->detlat.req_size = len; @@ -281,7 +314,7 @@ wsi->detlat.latencies[LAT_DUR_PROXY_RX_TO_ONWARD_TX] = lws_now_usecs() - pt->ust_left_poll; wsi->detlat.latencies[LAT_DUR_USERCB] = 0; - lws_det_lat_cb(wsi->context, &wsi->detlat); + lws_det_lat_cb(wsi->a.context, &wsi->detlat); } #endif @@ -297,10 +330,12 @@ if (!wsi->tls.ssl) goto bail; - if (SSL_pending(wsi->tls.ssl) && - lws_dll2_is_detached(&wsi->tls.dll_pending_tls)) - lws_dll2_add_head(&wsi->tls.dll_pending_tls, - &pt->tls.dll_pending_tls_owner); + if (SSL_pending(wsi->tls.ssl)) { + if (lws_dll2_is_detached(&wsi->tls.dll_pending_tls)) + lws_dll2_add_head(&wsi->tls.dll_pending_tls, + &pt->tls.dll_pending_tls_owner); + } else + __lws_ssl_remove_wsi_from_buffered_list(wsi); return n; bail: @@ -323,8 +358,15 @@ { int n, m; - // lwsl_notice("%s: len %d\n", __func__, len); - // lwsl_hexdump_notice(buf, len); +#if 0 + /* + * If using OpenSSL type tls library, this is the last point for all + * paths before sending data into the tls tunnel, where you can dump it + * and see what is being sent. + */ + lwsl_notice("%s: len %d\n", __func__, len); + lwsl_hexdump_notice(buf, len); +#endif if (!wsi->tls.ssl) return lws_ssl_capable_write_no_ssl(wsi, buf, len); @@ -366,6 +408,7 @@ struct lws *wsi; struct lws_context *context; struct lws_ssl_info si; + int fd; #ifndef USE_WOLFSSL context = (struct lws_context *)SSL_CTX_get_ex_data( @@ -378,17 +421,22 @@ #endif if (!context) return; - wsi = wsi_from_fd(context, SSL_get_fd(ssl)); + + fd = SSL_get_fd(ssl); + if (fd < 0 || (fd - lws_plat_socket_offset()) < 0) + return; + + wsi = wsi_from_fd(context, fd); if (!wsi) return; - if (!(where & wsi->vhost->tls.ssl_info_event_mask)) + if (!(where & wsi->a.vhost->tls.ssl_info_event_mask)) return; si.where = where; si.ret = ret; - if (user_callback_handle_rxflow(wsi->protocol->callback, + if (user_callback_handle_rxflow(wsi->a.protocol->callback, wsi, LWS_CALLBACK_SSL_INFO, wsi->user_space, &si, 0)) lws_set_timeout(wsi, PENDING_TIMEOUT_KILLED_BY_SSL_INFO, -1); @@ -407,7 +455,7 @@ /* kill ssl callbacks, because we will remove the fd from the * table linking it to the wsi */ - if (wsi->vhost->tls.ssl_info_event_mask) + if (wsi->a.vhost->tls.ssl_info_event_mask) SSL_set_info_callback(wsi->tls.ssl, NULL); #endif @@ -418,11 +466,11 @@ SSL_free(wsi->tls.ssl); wsi->tls.ssl = NULL; - lws_tls_restrict_return(wsi->context); + lws_tls_restrict_return(wsi->a.context); // lwsl_notice("%s: ssl restr %d, simul %d\n", __func__, - // wsi->context->simultaneous_ssl_restriction, - // wsi->context->simultaneous_ssl); + // wsi->a.context->simultaneous_ssl_restriction, + // wsi->a.context->simultaneous_ssl); return 1; /* handled */ } @@ -433,7 +481,9 @@ if (vhost->tls.ssl_ctx) SSL_CTX_free(vhost->tls.ssl_ctx); +#if defined(LWS_WITH_CLIENT) lws_ssl_destroy_client_ctx(vhost); +#endif #if defined(LWS_WITH_ACME) lws_tls_acme_sni_cert_destroy(vhost); diff -Nru libwebsockets-4.0.20/lib/tls/openssl/openssl-x509.c libwebsockets-4.1.6/lib/tls/openssl/openssl-x509.c --- libwebsockets-4.0.20/lib/tls/openssl/openssl-x509.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/tls/openssl/openssl-x509.c 2020-12-01 17:40:26.000000000 +0000 @@ -22,6 +22,7 @@ * IN THE SOFTWARE. */ +#define WIN32_LEAN_AND_MEAN #include "private-lib-core.h" #include "private-lib-tls-openssl.h" @@ -474,7 +475,7 @@ lws_x509_jwk_privkey_pem_pp_cb(char *buf, int size, int rwflag, void *u) { const char *pp = (const char *)u; - int n = strlen(pp); + int n = (int)strlen(pp); if (n > size - 1) return -1; diff -Nru libwebsockets-4.0.20/lib/tls/private-lib-tls.h libwebsockets-4.1.6/lib/tls/private-lib-tls.h --- libwebsockets-4.0.20/lib/tls/private-lib-tls.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/tls/private-lib-tls.h 2020-12-01 17:40:26.000000000 +0000 @@ -90,7 +90,7 @@ #ifdef LWS_HAVE_OPENSSL_ECDH_H #include #endif - #if !defined(LWS_HAVE_EVP_MD_CTX_free) + #if !defined(LWS_HAVE_EVP_MD_CTX_free) && !defined(USE_WOLFSSL) #define EVP_MD_CTX_free EVP_MD_CTX_destroy #endif #include diff -Nru libwebsockets-4.0.20/lib/tls/private-network.h libwebsockets-4.1.6/lib/tls/private-network.h --- libwebsockets-4.0.20/lib/tls/private-network.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/tls/private-network.h 2020-12-01 17:40:26.000000000 +0000 @@ -87,7 +87,8 @@ LWS_EXTERN int LWS_WARN_UNUSED_RESULT lws_ssl_pending(struct lws *wsi); LWS_EXTERN int LWS_WARN_UNUSED_RESULT -lws_server_socket_service_ssl(struct lws *new_wsi, lws_sockfd_type accept_fd); +lws_server_socket_service_ssl(struct lws *new_wsi, lws_sockfd_type accept_fd, + char is_pollin); LWS_EXTERN int lws_ssl_close(struct lws *wsi); LWS_EXTERN void @@ -101,7 +102,7 @@ LWS_EXTERN int lws_ssl_client_bio_create(struct lws *wsi); LWS_EXTERN int -lws_ssl_client_connect1(struct lws *wsi); +lws_ssl_client_connect1(struct lws *wsi, char *errbuf, int len); LWS_EXTERN int lws_ssl_client_connect2(struct lws *wsi, char *errbuf, int len); LWS_EXTERN int @@ -157,7 +158,7 @@ __lws_tls_shutdown(struct lws *wsi); LWS_EXTERN enum lws_ssl_capable_status -lws_tls_client_connect(struct lws *wsi); +lws_tls_client_connect(struct lws *wsi, char *errbuf, int len); LWS_EXTERN int lws_tls_client_confirm_peer_cert(struct lws *wsi, char *ebuf, int ebuf_len); LWS_EXTERN int @@ -170,7 +171,10 @@ const char *cert_filepath, const void *cert_mem, unsigned int cert_mem_len, - const char *private_key_filepath); + const char *private_key_filepath, + const void *key_mem, + unsigned int key_mem_len); + LWS_EXTERN lws_tls_ctx * lws_tls_ctx_from_wsi(struct lws *wsi); diff -Nru libwebsockets-4.0.20/lib/tls/tls-client.c libwebsockets-4.1.6/lib/tls/tls-client.c --- libwebsockets-4.0.20/lib/tls/tls-client.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/tls/tls-client.c 2020-12-01 17:40:26.000000000 +0000 @@ -25,11 +25,11 @@ #include "private-lib-core.h" int -lws_ssl_client_connect1(struct lws *wsi) +lws_ssl_client_connect1(struct lws *wsi, char *errbuf, int len) { int n; - n = lws_tls_client_connect(wsi); + n = lws_tls_client_connect(wsi, errbuf, len); switch (n) { case LWS_SSL_CAPABLE_ERROR: return -1; @@ -53,12 +53,12 @@ int n; if (lwsi_state(wsi) == LRS_WAITING_SSL) { - n = lws_tls_client_connect(wsi); + n = lws_tls_client_connect(wsi, errbuf, len); lwsl_debug("%s: SSL_connect says %d\n", __func__, n); switch (n) { case LWS_SSL_CAPABLE_ERROR: - lws_snprintf(errbuf, len, "client connect failed"); + // lws_snprintf(errbuf, len, "client connect failed"); return -1; case LWS_SSL_CAPABLE_DONE: break; /* connected */ @@ -87,7 +87,9 @@ const char *cert_filepath = info->ssl_cert_filepath; const char *ca_filepath = info->ssl_ca_filepath; const char *cipher_list = info->ssl_cipher_list; - struct lws *wsi = vhost->context->pt[0].fake_wsi; + lws_fakewsi_def_plwsa(&vhost->context->pt[0]); + + lws_fakewsi_prep_plwsa_ctx(vhost->context); if (vhost->options & LWS_SERVER_OPTION_ADOPT_APPLY_LISTEN_ACCEPT_CONFIG) return 0; @@ -118,6 +120,7 @@ if (vhost->tls.ssl_client_ctx) return 0; +#if !defined(LWS_WITH_MBEDTLS) if (info->provided_client_ssl_ctx) { /* use the provided OpenSSL context if given one */ vhost->tls.ssl_client_ctx = info->provided_client_ssl_ctx; @@ -126,6 +129,7 @@ return 0; } +#endif if (lws_tls_client_create_vhost_context(vhost, info, cipher_list, ca_filepath, @@ -134,7 +138,10 @@ cert_filepath, info->client_ssl_cert_mem, info->client_ssl_cert_mem_len, - private_key_filepath)) + private_key_filepath, + info->client_ssl_key_mem, + info->client_ssl_key_mem_len + )) return 1; lwsl_info("created client ssl context for %s\n", vhost->name); @@ -144,11 +151,9 @@ * lws_get_context() in the callback */ - wsi->vhost = vhost; /* not a real bound wsi */ - wsi->context = vhost->context; - wsi->protocol = NULL; + plwsa->vhost = vhost; /* not a real bound wsi */ - vhost->protocols[0].callback(wsi, + vhost->protocols[0].callback((struct lws *)plwsa, LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS, vhost->tls.ssl_client_ctx, NULL, 0); diff -Nru libwebsockets-4.0.20/lib/tls/tls-network.c libwebsockets-4.1.6/lib/tls/tls-network.c --- libwebsockets-4.0.20/lib/tls/tls-network.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/tls/tls-network.c 2020-12-01 17:40:26.000000000 +0000 @@ -61,7 +61,7 @@ void lws_ssl_remove_wsi_from_buffered_list(struct lws *wsi) { - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; lws_pt_lock(pt, __func__); __lws_ssl_remove_wsi_from_buffered_list(wsi); @@ -175,10 +175,10 @@ { struct lws wsi; - wsi.context = context; + wsi.a.context = context; lws_start_foreach_ll(struct lws_vhost *, v, context->vhost_list) { - wsi.vhost = v; /* not a real bound wsi */ + wsi.a.vhost = v; /* not a real bound wsi */ if (v->tls.alloc_cert_path && v->tls.key_path && !strcmp(v->tls.alloc_cert_path, certpath) && !strcmp(v->tls.key_path, keypath)) { diff -Nru libwebsockets-4.0.20/lib/tls/tls-server.c libwebsockets-4.1.6/lib/tls/tls-server.c --- libwebsockets-4.0.20/lib/tls/tls-server.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lib/tls/tls-server.c 2020-12-01 17:40:26.000000000 +0000 @@ -34,8 +34,9 @@ lws_tls_check_all_cert_lifetimes(pt->context); - __lws_sul_insert(&pt->pt_sul_owner, &pt->sul_tls, - (lws_usec_t)24 * 3600 * LWS_US_PER_SEC); + __lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], + &pt->sul_tls, + (lws_usec_t)24 * 3600 * LWS_US_PER_SEC); } int @@ -43,7 +44,9 @@ struct lws_vhost *vhost) { struct lws_context *context = vhost->context; - struct lws *wsi = context->pt[0].fake_wsi; + lws_fakewsi_def_plwsa(&vhost->context->pt[0]); + + lws_fakewsi_prep_plwsa_ctx(vhost->context); if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT)) { @@ -80,9 +83,7 @@ * give him a fake wsi with context + vhost set, so he can use * lws_get_context() in the callback */ - wsi->vhost = vhost; /* not a real bound wsi */ - wsi->context = context; - wsi->protocol = NULL; + plwsa->vhost = vhost; /* not a real bound wsi */ /* * as a server, if we are requiring clients to identify themselves @@ -98,12 +99,12 @@ * allowing it to verify incoming client certs */ if (vhost->tls.use_ssl) { - if (lws_tls_server_vhost_backend_init(info, vhost, wsi)) + if (lws_tls_server_vhost_backend_init(info, vhost, (struct lws *)plwsa)) return -1; lws_tls_server_client_cert_verify_config(vhost); - if (vhost->protocols[0].callback(wsi, + if (vhost->protocols[0].callback((struct lws *)plwsa, LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS, vhost->tls.ssl_ctx, vhost, 0)) return -1; @@ -115,22 +116,23 @@ /* check certs once a day */ context->pt[0].sul_tls.cb = lws_sul_tls_cb; - __lws_sul_insert(&context->pt[0].pt_sul_owner, &context->pt[0].sul_tls, - (lws_usec_t)24 * 3600 * LWS_US_PER_SEC); + __lws_sul_insert_us(&context->pt[0].pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], + &context->pt[0].sul_tls, + (lws_usec_t)24 * 3600 * LWS_US_PER_SEC); return 0; } #endif int -lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd) +lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd, char from_pollin) { - struct lws_context *context = wsi->context; + struct lws_context *context = wsi->a.context; struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; struct lws_vhost *vh; int n; - if (!LWS_SSL_ENABLED(wsi->vhost)) + if (!LWS_SSL_ENABLED(wsi->a.vhost)) return 0; switch (lwsi_state(wsi)) { @@ -141,10 +143,13 @@ if (accept_fd == LWS_SOCK_INVALID) assert(0); - if (lws_tls_restrict_borrow(context)) + if (lws_tls_restrict_borrow(context)) { + lwsl_err("%s: failed on ssl restriction\n", __func__); return 1; + } if (lws_tls_server_new_nonblocking(wsi, accept_fd)) { + lwsl_err("%s: failed on lws_tls_server_new_nonblocking\n", __func__); if (accept_fd != LWS_SOCK_INVALID) compatible_close(accept_fd); lws_tls_restrict_return(context); @@ -182,7 +187,11 @@ goto fail; } - if (wsi->vhost->tls.allow_non_ssl_on_ssl_port && !wsi->skip_fallback) { + if (wsi->a.vhost->tls.allow_non_ssl_on_ssl_port && !wsi->skip_fallback) { + /* + * We came here by POLLIN, so there is supposed to be + * something to read... + */ n = recv(wsi->desc.sockfd, (char *)pt->serv_buf, context->pt_serv_buf_size, MSG_PEEK); @@ -231,7 +240,7 @@ */ wsi->tls.ssl = NULL; - if (lws_check_opt(wsi->vhost->options, + if (lws_check_opt(wsi->a.vhost->options, LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS)) { lwsl_info("%s: redirecting from http " "to https\n", __func__); @@ -239,7 +248,7 @@ goto notls_accepted; } - if (lws_check_opt(wsi->vhost->options, + if (lws_check_opt(wsi->a.vhost->options, LWS_SERVER_OPTION_ALLOW_HTTP_ON_HTTPS_LISTENER)) { lwsl_info("%s: allowing unencrypted " "http service on tls port\n", @@ -247,7 +256,7 @@ goto notls_accepted; } - if (lws_check_opt(wsi->vhost->options, + if (lws_check_opt(wsi->a.vhost->options, LWS_SERVER_OPTION_FALLBACK_TO_APPLY_LISTEN_ACCEPT_CONFIG)) { if (lws_http_to_fallback(wsi, NULL, 0)) goto fail; @@ -258,18 +267,37 @@ lwsl_notice("%s: client did not send a valid " "tls hello (default vhost %s)\n", - __func__, wsi->vhost->name); + __func__, wsi->a.vhost->name); goto fail; } if (!n) { /* - * connection is gone, fail out + * POLLIN but nothing to read is supposed to + * mean the connection is gone, we should + * fail out... + * + */ + lwsl_debug("%s: PEEKed 0 (from_pollin %d)\n", + __func__, from_pollin); + if (!from_pollin) + /* + * If this wasn't actually info from a + * pollin let it go around again until + * either data came or we still get told + * zero length peek AND POLLIN + */ + goto punt; + + /* + * treat as remote closed */ - lwsl_debug("PEEKed 0\n"); + goto fail; } if (n < 0 && (LWS_ERRNO == LWS_EAGAIN || LWS_ERRNO == LWS_EWOULDBLOCK)) { + +punt: /* * well, we get no way to know ssl or not * so go around again waiting for something @@ -277,7 +305,7 @@ * connection. */ if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) { - lwsl_info("%s: change_pollfd failed\n", + lwsl_err("%s: change_pollfd failed\n", __func__); return -1; } @@ -303,8 +331,8 @@ break; case LWS_SSL_CAPABLE_ERROR: lws_stats_bump(pt, LWSSTATS_C_SSL_CONNECTIONS_FAILED, 1); - lwsl_info("SSL_accept failed socket %u: %d\n", - wsi->desc.sockfd, n); + lwsl_info("%s: SSL_accept failed socket %u: %d\n", + __func__, wsi->desc.sockfd, n); wsi->socket_is_permanently_unusable = 1; goto fail; @@ -328,7 +356,7 @@ lws_now_usecs() - wsi->detlat.earliest_write_req_pre_write; wsi->detlat.latencies[LAT_DUR_USERCB] = 0; - lws_det_lat_cb(wsi->context, &wsi->detlat); + lws_det_lat_cb(wsi->a.context, &wsi->detlat); } #endif @@ -349,8 +377,10 @@ context->timeout_secs); lwsi_set_state(wsi, LRS_ESTABLISHED); - if (lws_tls_server_conn_alpn(wsi)) + if (lws_tls_server_conn_alpn(wsi)) { + lwsl_warn("%s: fail on alpn\n", __func__); goto fail; + } lwsl_debug("accepted new SSL conn\n"); break; diff -Nru libwebsockets-4.0.20/libwebsockets.dox libwebsockets-4.1.6/libwebsockets.dox --- libwebsockets-4.0.20/libwebsockets.dox 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/libwebsockets.dox 2020-12-01 17:40:26.000000000 +0000 @@ -104,6 +104,9 @@ INPUT = include/libwebsockets.h \ include/libwebsockets/lws-adopt.h \ include/libwebsockets/lws-async-dns.h \ + include/libwebsockets/lws-bb-i2c.h \ + include/libwebsockets/lws-bb-spi.h \ + include/libwebsockets/lws-button.h \ include/libwebsockets/lws-callbacks.h \ include/libwebsockets/lws-cgi.h \ include/libwebsockets/lws-client.h \ @@ -111,8 +114,11 @@ include/libwebsockets/lws-dbus.h \ include/libwebsockets/lws-detailed-latency.h \ include/libwebsockets/lws-diskcache.h \ + include/libwebsockets/lws-display.h \ + include/libwebsockets/lws-dll2.h \ include/libwebsockets/lws-dsh.h \ include/libwebsockets/lws-esp32.h \ + include/libwebsockets/lws-eventlib-exports.h \ include/libwebsockets/lws-freertos.h \ include/libwebsockets/lws-fts.h \ include/libwebsockets/lws-genaes.h \ @@ -120,25 +126,39 @@ include/libwebsockets/lws-genec.h \ include/libwebsockets/lws-genhash.h \ include/libwebsockets/lws-genrsa.h \ + include/libwebsockets/lws-gpio.h \ include/libwebsockets/lws-http.h \ + include/libwebsockets/lws-i2c.h \ + include/libwebsockets/lws-ili9341-spi.h \ include/libwebsockets/lws-jose.h \ include/libwebsockets/lws-jwe.h \ include/libwebsockets/lws-jwk.h \ include/libwebsockets/lws-jws.h \ + include/libwebsockets/lws-led.h \ include/libwebsockets/lws-lejp.h \ include/libwebsockets/lws-logs.h \ include/libwebsockets/lws-lwsac.h \ include/libwebsockets/lws-misc.h \ + include/libwebsockets/lws-mqtt.h \ + include/libwebsockets/lws-netdev.h \ include/libwebsockets/lws-network-helper.h \ - include/libwebsockets/lws-plugin-generic-sessions.h \ include/libwebsockets/lws-protocols-plugins.h \ include/libwebsockets/lws-purify.h \ + include/libwebsockets/lws-pwm.h \ include/libwebsockets/lws-retry.h \ include/libwebsockets/lws-ring.h \ + include/libwebsockets/lws-secure-streams-client.h \ + include/libwebsockets/lws-secure-streams.h \ + include/libwebsockets/lws-secure-streams-policy.h \ include/libwebsockets/lws-sequencer.h \ include/libwebsockets/lws-service.h \ + include/libwebsockets/lws-settings.h \ include/libwebsockets/lws-sha1-base64.h \ + include/libwebsockets/lws-smd.h \ include/libwebsockets/lws-spa.h \ + include/libwebsockets/lws-spi.h \ + include/libwebsockets/lws-ssd1306-i2c.h \ + include/libwebsockets/lws-state.h \ include/libwebsockets/lws-stats.h \ include/libwebsockets/lws-struct.h \ include/libwebsockets/lws-system.h \ diff -Nru libwebsockets-4.0.20/lwsws/CMakeLists.txt libwebsockets-4.1.6/lwsws/CMakeLists.txt --- libwebsockets-4.0.20/lwsws/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/lwsws/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,66 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# + +if (LWS_WITH_LWSWS) + list(APPEND LWSWS_SRCS + "main.c" + ) + + if (WIN32) + list(APPEND LWSWS_SRCS + ${WIN32_HELPERS_PATH}/getopt.c + ${WIN32_HELPERS_PATH}/getopt_long.c + ${WIN32_HELPERS_PATH}/gettimeofday.c + ) + + list(APPEND LWSWS_HDR + ${WIN32_HELPERS_PATH}/getopt.h + ${WIN32_HELPERS_PATH}/gettimeofday.h + ) + endif(WIN32) + + source_group("Headers Private" FILES ${LWSWS_HDR}) + source_group("Sources" FILES ${LWSWS_SRCS}) + add_executable("lwsws" ${LWSWS_SRCS} ${LWSWS_HDR}) + + if (LWS_WITH_SHARED) + target_link_libraries("lwsws" websockets_shared ${LIB_LIST_AT_END}) + add_dependencies("lwsws" websockets_shared) + else() + target_link_libraries("lwsws" websockets ${LIB_LIST_AT_END}) + add_dependencies("lwsws" websockets) + endif() + target_include_directories("lwsws" PRIVATE "${LWS_LIB_INCLUDES}" ${LWS_LIB_BUILD_INC_PATHS}) + + # Set test app specific defines. + set_property(TARGET "lwsws" + PROPERTY COMPILE_DEFINITIONS + INSTALL_DATADIR="${CMAKE_INSTALL_PREFIX}/share" + ) + + install(TARGETS lwsws + RUNTIME DESTINATION "${LWS_INSTALL_BIN_DIR}" COMPONENT lwsws ) +endif (LWS_WITH_LWSWS) + + diff -Nru libwebsockets-4.0.20/lwsws/main.c libwebsockets-4.1.6/lwsws/main.c --- libwebsockets-4.0.20/lwsws/main.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/lwsws/main.c 2020-12-01 17:40:26.000000000 +0000 @@ -57,7 +57,7 @@ static struct lws_context *context; static lws_sorted_usec_list_t sul_lwsws; -static char config_dir[128]; +static char config_dir[128], default_plugin_path = 1; static int opts = 0, do_reload = 1; static uv_loop_t loop; static uv_signal_t signal_outer[2]; @@ -77,16 +77,19 @@ { NULL, NULL, NULL /* terminator */ } }; +#if defined(LWS_WITH_PLUGINS) static const char * const plugin_dirs[] = { INSTALL_DATADIR"/libwebsockets-test-server/plugins/", NULL }; +#endif #if defined(LWS_HAS_GETOPT_LONG) || defined(WIN32) static struct option options[] = { { "help", no_argument, NULL, 'h' }, { "debug", required_argument, NULL, 'd' }, { "configdir", required_argument, NULL, 'c' }, + { "no-default-plugins", no_argument, NULL, 'n' }, { NULL, 0, 0, 0 } }; #endif @@ -150,7 +153,10 @@ LWS_SERVER_OPTION_EXPLICIT_VHOSTS | LWS_SERVER_OPTION_LIBUV; - info.plugin_dirs = plugin_dirs; +#if defined(LWS_WITH_PLUGINS) + if (default_plugin_path) + info.plugin_dirs = plugin_dirs; +#endif lwsl_notice("Using config dir: \"%s\"\n", config_dir); /* @@ -240,9 +246,9 @@ strcpy(config_dir, "/etc/lwsws"); while (n >= 0) { #if defined(LWS_HAS_GETOPT_LONG) || defined(WIN32) - n = getopt_long(argc, argv, "hd:c:", options, NULL); + n = getopt_long(argc, argv, "hd:c:n", options, NULL); #else - n = getopt(argc, argv, "hd:c:"); + n = getopt(argc, argv, "hd:c:n"); #endif if (n < 0) continue; @@ -250,12 +256,16 @@ case 'd': debug_level = atoi(optarg); break; + case 'n': + default_plugin_path = 0; + break; case 'c': lws_strncpy(config_dir, optarg, sizeof(config_dir)); break; case 'h': fprintf(stderr, "Usage: lwsws [-c ] " - "[-d ] [--help]\n"); + "[-d ] [--help] " + "[-n]\n"); exit(1); } } @@ -335,7 +345,7 @@ } /* cancel the per-minute sul */ - lws_sul_schedule(context, 0, &sul_lwsws, NULL, LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&sul_lwsws); lws_context_destroy(context); (void)budget; diff -Nru libwebsockets-4.0.20/minimal-examples/abstract/protocols/smtp-client/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/abstract/protocols/smtp-client/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/abstract/protocols/smtp-client/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/abstract/protocols/smtp-client/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,67 +1,13 @@ -project(lws-api-test-smtp_client) +project(lws-api-test-smtp_client C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-api-test-smtp_client) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_SMTP 1 requirements) @@ -69,9 +15,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-async-dns/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/api-tests/api-test-async-dns/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-async-dns/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-async-dns/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,67 +1,13 @@ -project(lws-api-test-async-dns) +project(lws-api-test-async-dns C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-api-test-async-dns) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) @@ -69,11 +15,16 @@ if (requirements) add_executable(${SAMP} ${SRCS}) + add_test(NAME api-test-async-dns COMMAND lws-api-test-async-dns) + set_tests_properties(api-test-async-dns + PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/api-tests/api-test-async-dns + TIMEOUT 60) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-async-dns/selftest.sh libwebsockets-4.1.6/minimal-examples/api-tests/api-test-async-dns/selftest.sh --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-async-dns/selftest.sh 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-async-dns/selftest.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -#!/bin/bash -# -# $1: path to minimal example binaries... -# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 -# that will be ./bin from your build dir -# -# $2: path for logs and results. The results will go -# in a subdir named after the directory this script -# is in -# -# $3: offset for test index count -# -# $4: total test count -# -# $5: path to ./minimal-examples dir in lws -# -# Test return code 0: OK, 254: timed out, other: error indication - -. $5/selftests-library.sh - -COUNT_TESTS=1 - -dotest $1 $2 apiselftest -exit $FAILS diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-dhcpc/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/api-tests/api-test-dhcpc/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-dhcpc/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-dhcpc/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,67 +1,13 @@ -project(lws-api-test-dhcpc) +project(lws-api-test-dhcpc C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-api-test-dhcpc) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_SYS_DHCP_CLIENT 1 requirements) @@ -69,9 +15,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-fts/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/api-tests/api-test-fts/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-fts/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-fts/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,67 +1,13 @@ -project(lws-api-test-fts) +project(lws-api-test-fts C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-api-test-fts) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_FTS 1 requirements) @@ -69,9 +15,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-fts/selftest.sh libwebsockets-4.1.6/minimal-examples/api-tests/api-test-fts/selftest.sh --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-fts/selftest.sh 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-fts/selftest.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,58 +0,0 @@ -#!/bin/bash -# -# $1: path to minimal example binaries... -# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 -# that will be ./bin from your build dir -# -# $2: path for logs and results. The results will go -# in a subdir named after the directory this script -# is in -# -# $3: offset for test index count -# -# $4: total test count -# -# $5: path to ./minimal-examples dir in lws -# -# Test return code 0: OK, 254: timed out, other: error indication - -. $5/selftests-library.sh - -COUNT_TESTS=4 - -FAILS=0 - -# -# let's make an index with just Dorian first -# -dotest $1 $2 apitest -c -i /tmp/lws-fts-dorian.index \ - "../minimal-examples/api-tests/api-test-fts/the-picture-of-dorian-gray.txt" - -# and let's hear about autocompletes for "b" - -dotest $1 $2 apitest -i /tmp/lws-fts-dorian.index b -cat $2/api-test-fts/apitest.log | cut -d' ' -f5- > /tmp/fts1 -diff -urN /tmp/fts1 "../minimal-examples/api-tests/api-test-fts/canned-1.txt" -if [ $? -ne 0 ] ; then - echo "Test 1 failed" - FAILS=$(( $FAILS + 1 )) -fi - -# -# let's make an index with Dorian + Les Mis in French (ie, UTF-8) as well -# -dotest $1 $2 apitest -c -i /tmp/lws-fts-both.index \ - "../minimal-examples/api-tests/api-test-fts/the-picture-of-dorian-gray.txt" \ - "../minimal-examples/api-tests/api-test-fts/les-mis-utf8.txt" - -# and let's hear about "help", which appears in both - -dotest $1 $2 apitest -i /tmp/lws-fts-both.index -f -l help -cat $2/api-test-fts/apitest.log | cut -d' ' -f5- > /tmp/fts2 -diff -urN /tmp/fts2 "../minimal-examples/api-tests/api-test-fts/canned-2.txt" -if [ $? -ne 0 ] ; then - echo "Test 1 failed" - FAILS=$(( $FAILS + 1 )) -fi - -exit $FAILS diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-gencrypto/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/api-tests/api-test-gencrypto/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-gencrypto/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-gencrypto/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,67 +1,13 @@ -project(lws-api-test-gencrypto) +project(lws-api-test-gencrypto C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-api-test-gencrypto) set(SRCS main.c lws-genaes.c lws-genec.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_GENCRYPTO 1 requirements) require_lws_config(LWS_WITH_JOSE 1 requirements) @@ -70,12 +16,13 @@ if (requirements) add_executable(${SAMP} ${SRCS}) + add_test(NAME api-test-gencrypto COMMAND lws-api-test-gencrypto) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-gencrypto/selftest.sh libwebsockets-4.1.6/minimal-examples/api-tests/api-test-gencrypto/selftest.sh --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-gencrypto/selftest.sh 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-gencrypto/selftest.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -#!/bin/bash -# -# $1: path to minimal example binaries... -# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 -# that will be ./bin from your build dir -# -# $2: path for logs and results. The results will go -# in a subdir named after the directory this script -# is in -# -# $3: offset for test index count -# -# $4: total test count -# -# $5: path to ./minimal-examples dir in lws -# -# Test return code 0: OK, 254: timed out, other: error indication - -. $5/selftests-library.sh - -COUNT_TESTS=1 - -dotest $1 $2 apiselftest -exit $FAILS diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-jose/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/api-tests/api-test-jose/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-jose/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-jose/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,67 +1,13 @@ -project(lws-api-test-jose) +project(lws-api-test-jose C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-api-test-jose) set(SRCS main.c jwk.c jws.c jwe.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_JOSE 1 requirements) @@ -69,10 +15,14 @@ add_executable(${SAMP} ${SRCS}) + if (NOT (LWS_WITH_MBEDTLS AND NOT LWS_HAVE_mbedtls_internal_aes_encrypt)) + add_test(NAME api-test-jose COMMAND lws-api-test-jose) + endif() + if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-jose/jwe.c libwebsockets-4.1.6/minimal-examples/api-tests/api-test-jose/jwe.c --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-jose/jwe.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-jose/jwe.c 2020-12-01 17:40:26.000000000 +0000 @@ -82,7 +82,7 @@ } /* converts a compact serialization to jws b64 + decoded maps */ - if (lws_jws_compact_decode(ex_a1_compact, strlen(ex_a1_compact), + if (lws_jws_compact_decode(ex_a1_compact, (int)strlen(ex_a1_compact), &jwe.jws.map, &jwe.jws.map_b64, temp, &temp_len) != 5) { lwsl_err("%s: lws_jws_compact_decode failed\n", __func__); @@ -100,7 +100,7 @@ /* allowing for trailing padding, confirm the plaintext */ if (jwe.jws.map.len[LJWE_CTXT] < strlen(ex_a1_ptext) || lws_timingsafe_bcmp(jwe.jws.map.buf[LJWE_CTXT], ex_a1_ptext, - strlen(ex_a1_ptext))) { + (uint32_t)strlen(ex_a1_ptext))) { lwsl_err("%s: plaintext AES decrypt wrong\n", __func__); lwsl_hexdump_notice(ex_a1_ptext, strlen(ex_a1_ptext)); lwsl_hexdump_notice(jwe.jws.map.buf[LJWE_CTXT], @@ -185,7 +185,7 @@ temp_len = sizeof(temp); /* converts a compact serialization to jws b64 + decoded maps */ - if (lws_jws_compact_decode(compact, strlen(compact), &jwe.jws.map, + if (lws_jws_compact_decode(compact, (int)strlen(compact), &jwe.jws.map, &jwe.jws.map_b64, temp, &temp_len) != 5) { lwsl_err("%s: lws_jws_compact_decode failed\n", __func__); goto bail; @@ -299,7 +299,7 @@ /* converts a compact serialization to jws b64 + decoded maps */ if (lws_jws_compact_decode((const char *)ex_a2_compact, - strlen((char *)ex_a2_compact), + (int)strlen((char *)ex_a2_compact), &jwe.jws.map, &jwe.jws.map_b64, (char *)temp, &temp_len) != 5) { lwsl_err("%s: lws_jws_compact_decode failed\n", __func__); @@ -527,7 +527,7 @@ } jwe.jws.map.buf[LJWE_JOSE] = rsa256a128_jose; - jwe.jws.map.len[LJWE_JOSE] = strlen(rsa256a128_jose); + jwe.jws.map.len[LJWE_JOSE] = (uint32_t)strlen(rsa256a128_jose); n = lws_jwe_parse_jose(&jwe.jose, jwe.jws.map.buf[LJWE_JOSE], jwe.jws.map.len[LJWE_JOSE], @@ -657,7 +657,7 @@ } jwe.jws.map.buf[LJWE_JOSE] = rsa256a192_jose; - jwe.jws.map.len[LJWE_JOSE] = strlen(rsa256a192_jose); + jwe.jws.map.len[LJWE_JOSE] = (uint32_t)strlen(rsa256a192_jose); n = lws_jwe_parse_jose(&jwe.jose, jwe.jws.map.buf[LJWE_JOSE], jwe.jws.map.len[LJWE_JOSE], @@ -789,9 +789,10 @@ } jwe.jws.map.buf[LJWE_JOSE] = rsa256a256_jose; - jwe.jws.map.len[LJWE_JOSE] = strlen(rsa256a256_jose); + jwe.jws.map.len[LJWE_JOSE] = (int)strlen(rsa256a256_jose); - n = lws_jwe_parse_jose(&jwe.jose, rsa256a256_jose, strlen(rsa256a256_jose), + n = lws_jwe_parse_jose(&jwe.jose, rsa256a256_jose, + (int)strlen(rsa256a256_jose), lws_concat_temp(temp, temp_len), &temp_len); if (n < 0) { lwsl_err("%s: JOSE parse failed\n", __func__); @@ -1058,7 +1059,7 @@ /* converts a compact serialization to jws b64 + decoded maps */ if (lws_jws_compact_decode((const char *)jwe_compact_rsa_cbc_openssl, - strlen((char *)jwe_compact_rsa_cbc_openssl), + (int)strlen((char *)jwe_compact_rsa_cbc_openssl), &jwe.jws.map, &jwe.jws.map_b64, temp, &temp_len) != 5) { lwsl_err("%s: lws_jws_compact_decode failed\n", __func__); @@ -1149,7 +1150,7 @@ /* converts a compact serialization to jws b64 + decoded maps */ if (lws_jws_compact_decode((const char *)jwe_compact_rsa_cbc_mbedtls, - strlen((char *)jwe_compact_rsa_cbc_mbedtls), + (int)strlen((char *)jwe_compact_rsa_cbc_mbedtls), &jwe.jws.map, &jwe.jws.map_b64, temp, &temp_len) != 5) { lwsl_err("%s: lws_jws_compact_decode failed\n", __func__); @@ -1240,7 +1241,7 @@ /* converts a compact serialization to jws b64 + decoded maps */ if (lws_jws_compact_decode((const char *)ex_a3_compact, - strlen((char *)ex_a3_compact), + (int)strlen((char *)ex_a3_compact), &jwe.jws.map, &jwe.jws.map_b64, temp, &temp_len) != 5) { lwsl_err("%s: lws_jws_compact_decode failed\n", __func__); @@ -1649,7 +1650,7 @@ * See test_jwe_a3 above for a more normal usage pattern. */ - if (lws_jwe_parse_jose(&jwe.jose, ex_jwa_c_jose, strlen(ex_jwa_c_jose), + if (lws_jwe_parse_jose(&jwe.jose, ex_jwa_c_jose, (int)strlen(ex_jwa_c_jose), temp, &temp_len) < 0) { lwsl_err("%s: JOSE parse failed\n", __func__); @@ -1797,7 +1798,7 @@ jose_hdr, strlen(jose_hdr), 0)) goto bail; - if (lws_jwe_parse_jose(&jwe.jose, jose_hdr, strlen(jose_hdr), + if (lws_jwe_parse_jose(&jwe.jose, jose_hdr, (int)strlen(jose_hdr), temp, &temp_len) < 0) { lwsl_err("%s: JOSE parse failed\n", __func__); @@ -1873,7 +1874,7 @@ } /* converts a compact serialization to jws b64 + decoded maps */ - if (lws_jws_compact_decode(compact, strlen(compact), &jwe.jws.map, + if (lws_jws_compact_decode(compact, (int)strlen(compact), &jwe.jws.map, &jwe.jws.map_b64, temp, &temp_len) != 5) { lwsl_err("%s: lws_jws_compact_decode failed\n", __func__); goto bail; @@ -1975,7 +1976,7 @@ } /* converts a compact serialization to jws b64 + decoded maps */ - if (lws_jws_compact_decode(ciphertext, strlen(ciphertext), + if (lws_jws_compact_decode(ciphertext, (int)strlen(ciphertext), &jwe.jws.map, &jwe.jws.map_b64, temp, &temp_len) != 5) { lwsl_err("%s: lws_jws_compact_decode failed\n", __func__); @@ -1992,7 +1993,7 @@ /* allowing for trailing padding, confirm the plaintext */ if (jwe.jws.map.len[LJWE_CTXT] < strlen(akw_ptext) || lws_timingsafe_bcmp(jwe.jws.map.buf[LJWE_CTXT], akw_ptext, - strlen(akw_ptext))) { + (int)strlen(akw_ptext))) { lwsl_err("%s: plaintext AES decrypt wrong\n", __func__); lwsl_hexdump_notice(akw_ptext, strlen(akw_ptext)); lwsl_hexdump_notice(jwe.jws.map.buf[LJWE_CTXT], @@ -2141,7 +2142,7 @@ lws_jwe_init(&jwe, context); - if (lws_jwe_parse_jose(&jwe.jose, complete, strlen(complete), + if (lws_jwe_parse_jose(&jwe.jose, complete, (int)strlen(complete), temp, &temp_len) < 0) { lwsl_err("%s: JOSE parse failed\n", __func__); @@ -2199,29 +2200,29 @@ n |= test_jwe_a2(context); n |= test_jwe_ra_ptext_1024(context, (char *)lws_jwe_ex_a2_jwk_json, - strlen((char *)lws_jwe_ex_a2_jwk_json)); + (int)strlen((char *)lws_jwe_ex_a2_jwk_json)); n |= test_jwe_r256a192_ptext(context, (char *)lws_jwe_ex_a2_jwk_json, - strlen((char *)lws_jwe_ex_a2_jwk_json)); + (int)strlen((char *)lws_jwe_ex_a2_jwk_json)); n |= test_jwe_r256a256_ptext(context, (char *)lws_jwe_ex_a2_jwk_json, - strlen((char *)lws_jwe_ex_a2_jwk_json)); + (int)strlen((char *)lws_jwe_ex_a2_jwk_json)); n |= test_jwe_ra_ptext_1024(context, (char *)rsa_key_2048, - strlen((char *)rsa_key_2048)); + (int)strlen((char *)rsa_key_2048)); n |= test_jwe_r256a192_ptext(context, (char *)rsa_key_2048, - strlen((char *)rsa_key_2048)); + (int)strlen((char *)rsa_key_2048)); n |= test_jwe_r256a256_ptext(context, (char *)rsa_key_2048, - strlen((char *)rsa_key_2048)); + (int)strlen((char *)rsa_key_2048)); n |= test_jwe_ra_ptext_1024(context, (char *)rsa_key_4096, - strlen((char *)rsa_key_4096)); + (int)strlen((char *)rsa_key_4096)); n |= test_jwe_r256a192_ptext(context, (char *)rsa_key_4096, - strlen((char *)rsa_key_4096)); + (int)strlen((char *)rsa_key_4096)); n |= test_jwe_r256a256_ptext(context, (char *)rsa_key_4096, - strlen((char *)rsa_key_4096)); + (int)strlen((char *)rsa_key_4096)); n |= test_jwe_ra_ptext_1024(context, (char *)rsa_key_4096_no_optional, - strlen((char *)rsa_key_4096_no_optional)); + (int)strlen((char *)rsa_key_4096_no_optional)); n |= test_jwe_r256a192_ptext(context, (char *)rsa_key_4096_no_optional, - strlen((char *)rsa_key_4096_no_optional)); + (int)strlen((char *)rsa_key_4096_no_optional)); n |= test_jwe_r256a256_ptext(context, (char *)rsa_key_4096_no_optional, - strlen((char *)rsa_key_4096_no_optional)); + (int)strlen((char *)rsa_key_4096_no_optional)); /* AESKW decrypt all variations */ diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-jose/jws.c libwebsockets-4.1.6/minimal-examples/api-tests/api-test-jose/jws.c --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-jose/jws.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-jose/jws.c 2020-12-01 17:40:26.000000000 +0000 @@ -46,7 +46,7 @@ /* A.5 Unsecured JSON "none" RFC7515 worked example */ /* decode the b64.b64[.b64] compact serialization blocks */ - n = lws_jws_compact_decode(none_cser, strlen(none_cser), &map, NULL, + n = lws_jws_compact_decode(none_cser, (int)strlen(none_cser), &map, NULL, temp, &temp_len); if (n != 2) { lwsl_err("%s: concat_map failed\n", __func__); @@ -131,8 +131,8 @@ /* parse the JOSE header */ - if (lws_jws_parse_jose(&jose, test1, strlen(test1), temp, &temp_len) < 0 || - !jose.alg) { + if (lws_jws_parse_jose(&jose, test1, (int)strlen(test1), temp, + &temp_len) < 0 || !jose.alg) { lwsl_err("%s: JOSE parse failed\n", __func__); goto bail; } @@ -314,7 +314,7 @@ goto bail; } - if (lws_jws_b64_compact_map(rfc7515_rsa_a1, strlen(rfc7515_rsa_a1), + if (lws_jws_b64_compact_map(rfc7515_rsa_a1, (int)strlen(rfc7515_rsa_a1), &jws.map_b64) != 3) { lwsl_notice("%s: lws_jws_b64_compact_map failed\n", __func__); goto bail; @@ -323,7 +323,7 @@ /* 2.3: generate our own signature for a copy of the test packet */ in = lws_concat_temp(temp, temp_len); - l = strlen(rfc7515_rsa_a1); + l = (int)strlen(rfc7515_rsa_a1); if (temp_len < l + 1) goto bail; memcpy(in, rfc7515_rsa_a1, l + 1); @@ -421,7 +421,7 @@ lws_jose_init(&jose); /* decode the b64.b64[.b64] compact serialization blocks */ - if (lws_jws_compact_decode(es256_cser, strlen(es256_cser), + if (lws_jws_compact_decode(es256_cser, (int)strlen(es256_cser), &jws.map, &jws.map_b64, temp, &temp_len) != 3) { lwsl_err("%s: concat_map failed\n", __func__); @@ -481,7 +481,7 @@ /* A.3 "ES256" RFC7515 worked example - sign */ - l = strlen(es256_cser); + l = (int)strlen(es256_cser); if (temp_len < l + 1) goto bail1; p = lws_concat_temp(temp, temp_len); @@ -582,7 +582,7 @@ lws_jose_init(&jose); /* decode the b64.b64[.b64] compact serialization blocks */ - if (lws_jws_compact_decode(es512_cser, strlen(es512_cser), + if (lws_jws_compact_decode(es512_cser, (int)strlen(es512_cser), &jws.map, &jws.map_b64, temp, &temp_len) != 3) { lwsl_err("%s: concat_map failed\n", __func__); @@ -642,7 +642,7 @@ /* A.3 "es512" RFC7515 worked example - sign */ - l = strlen(es512_cser); + l = (int)strlen(es512_cser); if (temp_len < l) goto bail1; p = lws_concat_temp(temp, temp_len); @@ -685,6 +685,43 @@ goto bail1; } + /* jwt test */ + + { + unsigned long long ull = lws_now_secs(); + char buf[8192]; + size_t cml = 2048, cml2 = 2048; + + if (lws_jwt_sign_compact(context, &jwk, "ES512", + (char *)buf, &cml2, + (char *)buf + 2048, 4096, + "{\"iss\":\"warmcat.com\",\"aud\":" + "\"https://libwebsockets.org/sai\"," + "\"iat\":%llu," + "\"nbf\":%llu," + "\"exp\":%llu," + "\"sub\":\"manage\"}", ull, + ull - 60, ull + (30 * 24 * 3600) + )) { + lwsl_err("%s: failed to create JWT\n", __func__); + goto bail1; + } + + lwsl_notice("%s: jwt test '%s'\n", __func__, buf); + + if (lws_jwt_signed_validate(context, &jwk, "ES512", + (const char *)buf, cml2, + (char *)buf + 2048, 2048, + (char *)buf + 4096, &cml)) { + lwsl_err("%s: failed to parse JWT\n", __func__); + + goto bail1; + } + + lwsl_notice("%s: jwt valid, payload '%s'\n", + __func__, buf + 4096); + } + /* end */ ret = 0; diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-jose/selftest.sh libwebsockets-4.1.6/minimal-examples/api-tests/api-test-jose/selftest.sh --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-jose/selftest.sh 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-jose/selftest.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -#!/bin/bash -# -# $1: path to minimal example binaries... -# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 -# that will be ./bin from your build dir -# -# $2: path for logs and results. The results will go -# in a subdir named after the directory this script -# is in -# -# $3: offset for test index count -# -# $4: total test count -# -# $5: path to ./minimal-examples dir in lws -# -# Test return code 0: OK, 254: timed out, other: error indication - -. $5/selftests-library.sh - -COUNT_TESTS=1 - -dotest $1 $2 apiselftest -exit $FAILS diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lejp/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lejp/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lejp/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lejp/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,22 @@ +project(lws-api-test-lejp C) +cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) +include(CheckCSourceCompiles) +include(LwsCheckRequirements) + +set(requirements 1) +require_lws_config(LWS_WITH_LEJP 1 requirements) + +if (requirements) + + add_executable(${PROJECT_NAME} main.c) + add_test(NAME api-test-lejp COMMAND lws-api-test-lejp) + + if (websockets_shared) + target_link_libraries(${PROJECT_NAME} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) + add_dependencies(${PROJECT_NAME} websockets_shared) + else() + target_link_libraries(${PROJECT_NAME} websockets ${LIBWEBSOCKETS_DEP_LIBS}) + endif() +endif() diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lejp/main.c libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lejp/main.c --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lejp/main.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lejp/main.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,219 @@ +/* + * lws-api-test-lejp + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * sanity tests for lejp + */ + +#include + +/* + * in this example, the JSON is for one "builder" object, which may specify + * a child list "targets" of zero or more "target" objects. + */ + +static const char * const json_tests[] = { + "{" /* test 1 */ + "\"schema\":\"com-warmcat-sai-builder\"," + + "\"hostname\":\"learn\"," + "\"nspawn_timeout\":1800," + "\"targets\":[" + "{" + "\"name\":\"target1\"," + "\"someflag\":true" + "}," + "{" + "\"name\":\"target2\"," + "\"someflag\":false" + "}" + "]" + "}", + "{" /* test 2 */ + "\"schema\":\"com-warmcat-sai-builder\"," + + "\"hostname\":\"learn\"," + "\"targets\":[" + "{" + "\"name\":\"target1\"" + "}," + "{" + "\"name\":\"target2\"" + "}," + "{" + "\"name\":\"target3\"" + "}" + "]" + "}", "{" /* test 3 */ + "\"schema\":\"com-warmcat-sai-builder\"," + + "\"hostname\":\"learn\"," + "\"nspawn_timeout\":1800," + "\"targets\":[" + "{" + "\"name\":\"target1\"," + "\"unrecognized\":\"xyz\"," + "\"child\": {" + "\"somename\": \"abc\"," + "\"junk\": { \"x\": \"y\" }" + "}" + "}," + "{" + "\"name\":\"target2\"" + "}" + "]" + "}", + "{" /* test 4 */ + "\"schema\":\"com-warmcat-sai-builder\"," + + "\"hostname\":\"learn\"," + "\"nspawn_timeout\":1800" + "}", + "{" /* test 5 */ + "\"schema\":\"com-warmcat-sai-builder\"" + "}", + "{" /* test 6 ... check huge strings into smaller fixed char array */ + "\"schema\":\"com-warmcat-sai-builder\"," + "\"hostname\":\"" + "PYvtan6kqppjnS0KpYTCaiOLsJkc7XecAr1kcE0aCIciewYB+JcLG82mO1Vb1mJtjDwUjBxy2I6A" + "zefzoWUWmqZbsv4MXR55j9bKlyz1liiSX63iO0x6JAwACMtE2MkgcLwR86TSWAD9D1QKIWqg5RJ/" + "CRuVsW0DKAUMD52ql4JmPFuJpJgTq28z6PhYNzN3yI3bmQt6bzhA+A/xAsFzSBnb3MHYWzGMprr5" + "3FAP1ISo5Ec9i+2ehV40sG6Q470sH3PGQZ0YRPO7Sh/SyrSQ/scONmxRc3AcXl7X/CSs417ii+CV" + "8sq3ZgcxKNB7tNfN7idNx3upZ00G2BZy9jSy03cLKKLNaNUt0TQsxXbH55uDHzSEeZWvxJgT6zB1" + "NoMhdC02w+oXim94M6z6COCnqT3rgkGk8PHMry9Bkh4yVpRmzIRfMmln/lEhdZgxky2+g5hhlSIG" + "JYDCrdynD9kCfvfy6KGOpNIi1X+mhbbWn4lnL9ZKihL/RrfOV+oV4R26IDq+KqUiJBENeo8/GXkG" + "LUH/87iPyzXKEMavr6fkrK0vTGto8yEYxmOyaVz8phG5rwf4jJgmYNoMbGo8gWvhqO7UAGy2g7MW" + "v+B/t1eZZ+1euLsNrWAsFJiFbQKgdFfQT3RjB14iU8knlQ8usoy+pXssY2ddGJGVcGC21oZvstK9" + "eu1eRZftda/wP+N5unT1Hw7kCoVzqxHieiYt47EGIOaaQ7XjZDK6qPN6O/grHnvJZm2vBkxuXgsY" + "VkRQ7AuTWIecphqFsq7Wbc1YNbMW47SVU5zMD0WaCqbaaI0t4uIzRvPlD8cpiiTzFTrEHlIBTf8/" + "uZjjEGGLhJR1jPqA9D1Ej3ChV+ye6F9JTUMlozRMsGuF8U4btDzH5xdnmvRS4Ar6LKEtAXGkj2yu" + "yJln+v4RIWj2xOGPJovOqiXwi0FyM61f8U8gj0OiNA2/QlvrqQVDF7sMXgjvaE7iQt5vMETteZlx" + "+z3f+jTFM/aon511W4+ZkRD+6AHwucvM9BEC\"" + "}", + "{" /* test 7 ... check huge strings into char * */ + "\"schema\":\"com-warmcat-sai-builder\"," + "\"targets\":[" + "{" + "\"name\":\"" + "PYvtan6kqppjnS0KpYTCaiOLsJkc7XecAr1kcE0aCIciewYB+JcLG82mO1Vb1mJtjDwUjBxy2I6A" + "zefzoWUWmqZbsv4MXR55j9bKlyz1liiSX63iO0x6JAwACMtE2MkgcLwR86TSWAD9D1QKIWqg5RJ/" + "CRuVsW0DKAUMD52ql4JmPFuJpJgTq28z6PhYNzN3yI3bmQt6bzhA+A/xAsFzSBnb3MHYWzGMprr5" + "3FAP1ISo5Ec9i+2ehV40sG6Q470sH3PGQZ0YRPO7Sh/SyrSQ/scONmxRc3AcXl7X/CSs417ii+CV" + "8sq3ZgcxKNB7tNfN7idNx3upZ00G2BZy9jSy03cLKKLNaNUt0TQsxXbH55uDHzSEeZWvxJgT6zB1" + "NoMhdC02w+oXim94M6z6COCnqT3rgkGk8PHMry9Bkh4yVpRmzIRfMmln/lEhdZgxky2+g5hhlSIG" + "JYDCrdynD9kCfvfy6KGOpNIi1X+mhbbWn4lnL9ZKihL/RrfOV+oV4R26IDq+KqUiJBENeo8/GXkG" + "LUH/87iPyzXKEMavr6fkrK0vTGto8yEYxmOyaVz8phG5rwf4jJgmYNoMbGo8gWvhqO7UAGy2g7MW" + "v+B/t1eZZ+1euLsNrWAsFJiFbQKgdFfQT3RjB14iU8knlQ8usoy+pXssY2ddGJGVcGC21oZvstK9" + "eu1eRZftda/wP+N5unT1Hw7kCoVzqxHieiYt47EGIOaaQ7XjZDK6qPN6O/grHnvJZm2vBkxuXgsY" + "VkRQ7AuTWIecphqFsq7Wbc1YNbMW47SVU5zMD0WaCqbaaI0t4uIzRvPlD8cpiiTzFTrEHlIBTf8/" + "uZjjEGGLhJR1jPqA9D1Ej3ChV+ye6F9JTUMlozRMsGuF8U4btDzH5xdnmvRS4Ar6LKEtAXGkj2yu" + "yJln+v4RIWj2xOGPJovOqiXwi0FyM61f8U8gj0OiNA2/QlvrqQVDF7sMXgjvaE7iQt5vMETteZlx" + "+z3f+jTFM/aon511W4+ZkRD+6AHwucvM9BEC\"}]}" + "}", + "{" /* test 8 the "other" schema */ + "\"schema\":\"com-warmcat-sai-logs\"," + "\"task_uuid\":\"97fc90052506af8b3eb43b87aaa6fb76feab32bc128ede479a8a6b961e801f06\"," + "\"timestamp\": 170366786103,\"channel\":3, \"len\":20, " + "\"log\": \"PnNhaWI+IE5TU1RBVEVfSU5JVAo=\"}\x0a" + "ntu-xenial-amd64\"},{\"name\":\"linux-ubuntu-bionic-amd64\"},{\"name\":\"linux-fedora-32-x86_64\"}]}\",", + + "{" /* test 9, empty object */ + "\"a\":123,\"b\":{}" + "}", + + "{" /* SHOULD_FAIL: test 10, missing open */ + "\"a\":123,\"b\":}" + "}" +}; + +static const char * const tok[] = { + "something", +}; + +static signed char +test_cb(struct lejp_ctx *ctx, char reason) +{ + lwsl_info("%s: ctx->path %s, buf %s\n", __func__, ctx->path, ctx->buf); + return 0; +} + +/* authz JSON parsing */ + + +int main(int argc, const char **argv) +{ + int n, m, e = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE; + struct lejp_ctx ctx; + const char *p; + + if ((p = lws_cmdline_option(argc, argv, "-d"))) + logs = atoi(p); + + lws_set_log_level(logs, NULL); + lwsl_user("LWS API selftest: lws_struct JSON\n"); + + for (m = 0; m < (int)LWS_ARRAY_SIZE(json_tests); m++) { + + lwsl_info("%s: ++++++++++++++++ test %d\n", __func__, m + 1); + + lejp_construct(&ctx, test_cb, NULL, tok, LWS_ARRAY_SIZE(tok)); + + lwsl_hexdump_info(json_tests[m], strlen(json_tests[m])); + + if (m == 7) + n = lejp_parse(&ctx, (uint8_t *)json_tests[m], + 0xc8); + else + n = lejp_parse(&ctx, (uint8_t *)json_tests[m], + (int)strlen(json_tests[m])); + + lwsl_info("n = %d\n", n); + if (n < 0 && m != 9) { + lwsl_err("%s: test %d: JSON decode failed '%s'\n", + __func__, m + 1, lejp_error_to_string(n)); + e++; + } + if (n >= 0 && m == 9) { + lwsl_err("%s: test %d: JSON decode should have failed '%s'\n", + __func__, m + 1, lejp_error_to_string(n)); + e++; + } + } + + { + const char *cs; + size_t cslen; + cs = lws_json_simple_find("{\"blah\":123,\"ext\":{\"authorized\":1}}", 35, + "\"ext\":", &cslen); + if (!cs) { + lwsl_err("%s: simple_find failed\n", __func__); + e++; + } else { + if (lws_json_simple_strcmp(cs, cslen, + "\"authorized\":", "1")) + e++; + } + cs = lws_json_simple_find("{\"blah\":123,\"auth_user\":\"andy@warmcat.com\",\"thing\":\"yeah\"}", 57, + "\"auth_user\":", &cslen); + if (cslen != 16) { + lwsl_err("%s: wrong string len %d isolated\n", __func__, (int)cslen); + e++; + } + } + + if (e) + goto bail; + + lwsl_user("Completed: PASS\n"); + + return 0; + +bail: + lwsl_user("Completed: FAIL\n"); + + return 1; +} diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lwsac/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lwsac/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lwsac/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lwsac/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,74 +1,19 @@ -project(lws-api-test-lwsac) +project(lws-api-test-lwsac C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-api-test-lwsac) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) +add_executable(${SAMP} ${SRCS}) +add_test(NAME api-test-lwsac COMMAND lws-api-test-lwsac) - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - - - - add_executable(${SAMP} ${SRCS}) - - if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) - add_dependencies(${SAMP} websockets_shared) - else() - target_link_libraries(${SAMP} websockets) - endif() +if (websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) + add_dependencies(${SAMP} websockets_shared) +else() + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) +endif() diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lwsac/selftest.sh libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lwsac/selftest.sh --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lwsac/selftest.sh 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lwsac/selftest.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -#!/bin/bash -# -# $1: path to minimal example binaries... -# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 -# that will be ./bin from your build dir -# -# $2: path for logs and results. The results will go -# in a subdir named after the directory this script -# is in -# -# $3: offset for test index count -# -# $4: total test count -# -# $5: path to ./minimal-examples dir in lws -# -# Test return code 0: OK, 254: timed out, other: error indication - -. $5/selftests-library.sh - -COUNT_TESTS=1 - -dotest $1 $2 apiselftest -exit $FAILS diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_dsh/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_dsh/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_dsh/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_dsh/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,67 +1,13 @@ -project(lws-api-test-lws_dsh) +project(lws-api-test-lws_dsh C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-api-test-lws_dsh) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_NETWORK 1 requirements) require_lws_config(LWS_WITH_LWS_DSH 1 requirements) @@ -69,11 +15,12 @@ if (requirements) add_executable(${SAMP} ${SRCS}) + add_test(NAME api-test-lws_dsh COMMAND lws-api-test-lws_dsh) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_dsh/selftest.sh libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_dsh/selftest.sh --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_dsh/selftest.sh 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_dsh/selftest.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -#!/bin/bash -# -# $1: path to minimal example binaries... -# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 -# that will be ./bin from your build dir -# -# $2: path for logs and results. The results will go -# in a subdir named after the directory this script -# is in -# -# $3: offset for test index count -# -# $4: total test count -# -# $5: path to ./minimal-examples dir in lws -# -# Test return code 0: OK, 254: timed out, other: error indication - -. $5/selftests-library.sh - -COUNT_TESTS=1 - -dotest $1 $2 apiselftest -exit $FAILS diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_sequencer/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_sequencer/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_sequencer/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_sequencer/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,67 +1,13 @@ -project(lws-api-test-lws_sequencer) +project(lws-api-test-lws_sequencer C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-api-test-lws_sequencer) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) @@ -71,9 +17,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_sequencer/libwebsockets.org.cer libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_sequencer/libwebsockets.org.cer --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_sequencer/libwebsockets.org.cer 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_sequencer/libwebsockets.org.cer 2020-12-01 17:40:26.000000000 +0000 @@ -56,3 +56,24 @@ PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6 KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg== -----END CERTIFICATE----- + -----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow +PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD +Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O +rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq +OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b +xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw +7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD +aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG +SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 +ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr +AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz +R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 +JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo +Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +-----END CERTIFICATE----- + diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_sequencer/main.c libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_sequencer/main.c --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_sequencer/main.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_sequencer/main.c 2020-12-01 17:40:26.000000000 +0000 @@ -346,7 +346,7 @@ LWS_SERVER_OPTION_EXPLICIT_VHOSTS; info.protocols = protocols; -#if defined(LWS_WITH_MBEDTLS) +#if defined(LWS_WITH_MBEDTLS) || defined(USE_WOLFSSL) /* * OpenSSL uses the system trust store. mbedTLS has to be told which * CA to trust explicitly. diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_smd/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_smd/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_smd/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_smd/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,27 @@ +project(lws-api-test-lws_smd C) +cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) +include(CheckCSourceCompiles) +include(LwsCheckRequirements) + +set(requirements 1) +require_pthreads(requirements) +require_lws_config(LWS_WITH_SYS_SMD 1 requirements) + +if (requirements) + add_executable(${PROJECT_NAME} main.c) + add_test(NAME api-test-lws_smd COMMAND lws-api-test-lws_smd -d1039) + set_tests_properties(api-test-lws_smd + PROPERTIES + RUN_SERIAL TRUE + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/api-tests/api-test-lws_smd + TIMEOUT 60) + + if (websockets_shared) + target_link_libraries(${PROJECT_NAME} websockets_shared ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) + add_dependencies(${PROJECT_NAME} websockets_shared) + else() + target_link_libraries(${PROJECT_NAME} websockets ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) + endif() +endif() diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_smd/main.c libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_smd/main.c --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_smd/main.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_smd/main.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,202 @@ +/* + * lws-api-test-lws_smd + * + * Written in 2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * This api test confirms lws_smd System Message Distribution + */ + +#include +#define HAVE_STRUCT_TIMESPEC +#include +#include + +static int interrupted, ok, fail, _exp = 111; +static lws_sorted_usec_list_t sul; +struct lws_context *context; +static pthread_t thread_spam; + +static void +timeout_cb(lws_sorted_usec_list_t *sul) +{ + /* We should have completed the test before this fires */ + interrupted = 1; + lws_cancel_service(context); +} + +static int +smd_cb1int(void *opaque, lws_smd_class_t _class, lws_usec_t timestamp, + void *buf, size_t len) +{ +#if 0 + lwsl_notice("%s: ts %llu, len %d\n", __func__, + (unsigned long long)timestamp, (int)len); + lwsl_hexdump_notice(buf, len); +#endif + ok++; + + return 0; +} + +static int +smd_cb2int(void *opaque, lws_smd_class_t _class, lws_usec_t timestamp, + void *buf, size_t len) +{ +#if 0 + lwsl_notice("%s: ts %llu, len %d\n", __func__, + (unsigned long long)timestamp, (int)len); + lwsl_hexdump_notice(buf, len); +#endif + ok++; + + return 0; +} + +static void * +_thread_spam(void *d) +{ + int n; + + n = 0; + while (n++ < 100) { + + if (lws_smd_msg_printf(context, LWSSMDCL_SYSTEM_STATE, + "{\"s\":\"state\",\"msg\":%d}", + (unsigned int)n)) { + lwsl_info("%s: send failed\n", __func__); + n--; + } +#if defined(WIN32) + Sleep(3); +#else + usleep(3000); +#endif + } +#if !defined(WIN32) + pthread_exit(NULL); +#endif + + return NULL; +} + +void sigint_handler(int sig) +{ + interrupted = 1; +} + +static int +system_notify_cb(lws_state_manager_t *mgr, lws_state_notify_link_t *link, + int current, int target) +{ + // struct lws_context *context = mgr->parent; + + if (current != LWS_SYSTATE_OPERATIONAL || target != LWS_SYSTATE_OPERATIONAL) + return 0; + + lwsl_info("%s: operational\n", __func__); + + /* + * spawn the test thread, it's going to spam 100 messages at 20ms + * intervals... check we got everything + */ + + if (pthread_create(&thread_spam, NULL, _thread_spam, NULL)) + lwsl_err("%s: failed to create the spamming thread\n", __func__); + + return 0; +} + +int +main(int argc, const char **argv) +{ + lws_state_notify_link_t notifier = { {0}, system_notify_cb, "app" }; + lws_state_notify_link_t *na[] = { ¬ifier, NULL }; + int logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE; + struct lws_context_creation_info info; + const char *p; + void *retval; + + /* the normal lws init */ + + signal(SIGINT, sigint_handler); + + if ((p = lws_cmdline_option(argc, argv, "-d"))) + logs = atoi(p); + + lws_set_log_level(logs, NULL); + lwsl_user("LWS API selftest: lws_smd\n"); + + memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ + info.port = CONTEXT_PORT_NO_LISTEN; + info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + info.register_notifier_list = na; + + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + return 1; + } + + lws_sul_schedule(context, 0, &sul, timeout_cb, 5 * LWS_US_PER_SEC); + + /* register a messaging participant to hear INTERACTION class */ + + if (!lws_smd_register(context, NULL, 0, LWSSMDCL_INTERACTION, + smd_cb1int)) { + lwsl_err("%s: smd register 1 failed\n", __func__); + goto bail; + } + + /* register a messaging participant to hear SYSTEM_STATE class */ + + if (!lws_smd_register(context, NULL, 0, LWSSMDCL_SYSTEM_STATE, + smd_cb2int)) { + lwsl_err("%s: smd register 2 failed\n", __func__); + goto bail; + } + + + /* generate an INTERACTION class message */ + + if (lws_smd_msg_printf(context, LWSSMDCL_INTERACTION, + "{\"s\":\"interaction\"}")) { + lwsl_err("%s: problem sending smd\n", __func__); + goto bail; + } + + /* generate a SYSTEM_STATE class message */ + + if (lws_smd_msg_printf(context, LWSSMDCL_SYSTEM_STATE, + "{\"s\":\"state\"}")) { + lwsl_err("%s: problem sending smd\n", __func__); + goto bail; + } + + /* no participant listens for this class, so it should be skipped */ + + if (lws_smd_msg_printf(context, LWSSMDCL_NETWORK, "{\"s\":\"network\"}")) { + lwsl_err("%s: problem sending smd\n", __func__); + goto bail; + } + + /* the usual lws event loop */ + + while (!interrupted && lws_service(context, 0) >= 0) + ; + + pthread_join(thread_spam, &retval); + +bail: + lws_context_destroy(context); + + if (fail || ok >= _exp) + lwsl_user("Completed: PASS: %d / %d, FAIL: %d\n", ok, _exp, + fail); + else + lwsl_user("Completed: ALL PASS: %d / %d\n", ok, _exp); + + return !(ok >= _exp && !fail); +} diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_struct-json/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_struct-json/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_struct-json/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_struct-json/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,66 +1,12 @@ -project(lws-api-test-lws_struct-json) +project(lws-api-test-lws_struct-json C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-api-test-lws_struct-json) -set(SRCS main.c) - -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() +set(SRCS main.c test2.c) set(requirements 1) require_lws_config(LWS_WITH_STRUCT_JSON 1 requirements) @@ -68,11 +14,12 @@ if (requirements) add_executable(${SAMP} ${SRCS}) + add_test(NAME api-test-lws_struct-json COMMAND lws-api-test-lws_struct-json) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_struct-json/main.c libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_struct-json/main.c --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_struct-json/main.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_struct-json/main.c 2020-12-01 17:40:26.000000000 +0000 @@ -1,7 +1,7 @@ /* * lws-api-test-lws_struct-json * - * Written in 2010-2019 by Andy Green + * Written in 2010-2020 by Andy Green * * This file is made available under the Creative Commons CC0 1.0 * Universal Public Domain Dedication. @@ -16,6 +16,147 @@ #include +typedef struct { + lws_dll2_t list; + + struct gpiod_line *line; + + const char *name; + const char *wire; + + int chip_idx; + int offset; + int safe; +} sai_jig_gpio_t; + +typedef struct { + lws_dll2_t list; + sai_jig_gpio_t *gpio; /* null = wait ms */ + const char *gpio_name; + int value; +} sai_jig_seq_item_t; + +typedef struct { + lws_dll2_t list; + lws_dll2_owner_t seq_owner; + const char *name; +} sai_jig_sequence_t; + +typedef struct { + lws_dll2_t list; + lws_dll2_owner_t gpio_owner; + lws_dll2_owner_t seq_owner; + + lws_sorted_usec_list_t sul; /* next step in ongoing seq */ + sai_jig_seq_item_t *current; /* next seq step */ + + const char *name; + + struct lws *wsi; +} sai_jig_target_t; + +typedef struct { + lws_dll2_owner_t target_owner; + struct gpiod_chip *chip[16]; + struct lwsac *ac_conf; + int port; + const char *iface; + struct lws_context *ctx; +} sai_jig_t; + +/* + * We read the JSON config using lws_struct... instrument the related structures + */ + +static const lws_struct_map_t lsm_sai_jig_gpio[] = { + LSM_UNSIGNED (sai_jig_gpio_t, chip_idx, "chip_idx"), + LSM_UNSIGNED (sai_jig_gpio_t, offset, "offset"), + LSM_UNSIGNED (sai_jig_gpio_t, safe, "safe"), + LSM_STRING_PTR (sai_jig_gpio_t, name, "name"), + LSM_STRING_PTR (sai_jig_gpio_t, wire, "wire"), +}; + +static const lws_struct_map_t lsm_sai_jig_seq_item[] = { + LSM_STRING_PTR (sai_jig_seq_item_t, gpio_name, "gpio_name"), + LSM_UNSIGNED (sai_jig_seq_item_t, value, "value"), +}; + +static const lws_struct_map_t lsm_sai_jig_sequence[] = { + LSM_STRING_PTR (sai_jig_sequence_t, name, "name"), + LSM_LIST (sai_jig_sequence_t, seq_owner, + sai_jig_seq_item_t, list, + NULL, lsm_sai_jig_seq_item, "seq"), +}; + +static const lws_struct_map_t lsm_sai_jig_target[] = { + LSM_STRING_PTR (sai_jig_target_t, name, "name"), + LSM_LIST (sai_jig_target_t, gpio_owner, sai_jig_gpio_t, list, + NULL, lsm_sai_jig_gpio, "gpios"), + LSM_LIST (sai_jig_target_t, seq_owner, sai_jig_sequence_t, list, + NULL, lsm_sai_jig_sequence, "sequences"), +}; + +static const lws_struct_map_t lsm_sai_jig[] = { + LSM_STRING_PTR (sai_jig_t, iface, "iface"), + LSM_UNSIGNED (sai_jig_t, port, "port"), + LSM_LIST (sai_jig_t, target_owner, sai_jig_target_t, list, + NULL, lsm_sai_jig_target, "targets"), +}; + +static const lws_struct_map_t lsm_jig_schema[] = { + LSM_SCHEMA (sai_jig_t, NULL, lsm_sai_jig, "sai-jig"), +}; + +static const char * const jig_conf = +"{" + "\"schema\": \"sai-jig\"," + "\"port\": 44000," + "\"targets\": [" + "{" + "\"name\": \"linkit-7697-1\"," + "\"gpios\": [" + "{" + "\"chip_index\": 0," + "\"name\": \"nReset\"," + "\"offset\": 17," + "\"wire\": \"RST\"," + "\"safe\": 0" + "}, {" + "\"name\": \"usr\"," + "\"chip_index\": 0," + "\"offset\": 22," + "\"wire\": \"P6\"," + "\"safe\": 0" + "}" + "], \"sequences\": [" + "{" + "\"name\": \"reset\"," + "\"seq\": [" + "{ \"gpio_name\": \"nReset\", \"value\": 0 }," + "{ \"gpio_name\": \"usr\", \"value\": 0 }," + "{ \"value\": 300 }," + "{ \"gpio_name\": \"nReset\", \"value\": 1 }" + "]" + "}, {" + "\"name\": \"flash\"," + "\"seq\": [" + "{ \"gpio_name\": \"nReset\", \"value\": 0 }," + "{ \"gpio_name\": \"usr\", \"value\": 1 }," + "{ \"value\": 300 }," + "{ \"gpio_name\": \"nReset\", \"value\": 1 }," + "{ \"value\": 100 }," + "{ \"gpio_name\": \"usr\", \"value\": 0 }" + "]" + "}" + "]" + "}" + "]" +"}"; + + + +extern int test2(void); + /* * in this example, the JSON is for one "builder" object, which may specify * a child list "targets" of zero or more "target" objects. @@ -296,6 +437,63 @@ lsm_other, "com-warmcat-sai-other"), }; +typedef struct sai_cancel { + char task_uuid[65]; +} sai_cancel_t; + +const lws_struct_map_t lsm_task_cancel[] = { + LSM_CARRAY (sai_cancel_t, task_uuid, "uuid"), +}; + +static const lws_struct_map_t t2_map[] = { + LSM_SCHEMA (sai_cancel_t, NULL, lsm_task_cancel, + "com.warmcat.sai.taskinfo"), + LSM_SCHEMA (sai_cancel_t, NULL, lsm_task_cancel, + "com.warmcat.sai.eventinfo"), + LSM_SCHEMA (sai_cancel_t, NULL, lsm_task_cancel, + /* shares struct */ "com.warmcat.sai.taskreset"), + LSM_SCHEMA (sai_cancel_t, NULL, lsm_task_cancel, + /* shares struct */ "com.warmcat.sai.eventreset"), + LSM_SCHEMA (sai_cancel_t, NULL, lsm_task_cancel, + /* shares struct */ "com.warmcat.sai.eventdelete"), + LSM_SCHEMA (sai_cancel_t, NULL, lsm_task_cancel, + "com.warmcat.sai.taskcan"), +}; + +static const char *t2 = + "{\"schema\":\"com.warmcat.sai.taskcan\"," + "\"uuid\": \"071ab46ab4296e5de674c628fec17c55088254679f7714ad991f8c4873dca\"}\x01\x02\xff\xff\xff\xff"; + +typedef struct xlws_wifi_creds { + lws_dll2_t list; + char ssid[33]; + char passphrase[64]; + int alg; + char bssid[6]; +} xlws_wifi_creds_t; + +typedef struct xlws_netdevs { + lws_dll2_owner_t owner_creds; +} xlws_netdevs_t; + +static const lws_struct_map_t lsm_wifi_creds[] = { + LSM_CARRAY (xlws_wifi_creds_t, ssid, "ssid"), + LSM_CARRAY (xlws_wifi_creds_t, passphrase, "passphrase"), + LSM_UNSIGNED (xlws_wifi_creds_t, alg, "alg"), + LSM_STRING_PTR (xlws_wifi_creds_t, bssid, "bssid"), +}; + +static const lws_struct_map_t lsm_netdev_credentials[] = { + LSM_LIST (xlws_netdevs_t, owner_creds, xlws_wifi_creds_t, list, + NULL, lsm_wifi_creds, "credentials"), +}; + +static const lws_struct_map_t lsm_netdev_schema[] = { + LSM_SCHEMA (xlws_netdevs_t, NULL, lsm_netdev_credentials, + "com.warmcat.sai.taskinfo"), +}; + + static int show_target(struct lws_dll2 *d, void *user) { @@ -345,8 +543,8 @@ a.ac_block_size = 512; lws_struct_json_init_parse(&ctx, NULL, &a); - n = (int)(signed char)lejp_parse(&ctx, (uint8_t *)json_tests[m], - strlen(json_tests[m])); + n = lejp_parse(&ctx, (uint8_t *)json_tests[m], + (int)strlen(json_tests[m])); if (n < 0) { lwsl_err("%s: notification JSON decode failed '%s'\n", __func__, lejp_error_to_string(n)); @@ -482,12 +680,122 @@ lws_struct_json_serialize_destroy(&ser); + lwsl_notice("Test set 2\n"); + + memset(&a, 0, sizeof(a)); + a.map_st[0] = t2_map; + a.map_entries_st[0] = LWS_ARRAY_SIZE(t2_map); + a.ac_block_size = 128; + + lws_struct_json_init_parse(&ctx, NULL, &a); + m = lejp_parse(&ctx, (uint8_t *)t2, (int)strlen(t2)); + if (m < 0 || !a.dest) { + lwsl_notice("%s: notification JSON decode failed '%s'\n", + __func__, lejp_error_to_string(m)); + goto bail; + } + + lwsl_notice("Test set 2: %d: %s\n", m, + ((sai_cancel_t *)a.dest)->task_uuid); + + lwsac_free(&a.ac); + + if (test2()) + goto bail; + + { + lws_struct_serialize_t *js; + xlws_wifi_creds_t creds; + xlws_netdevs_t netdevs; + unsigned char *buf; + size_t w; + int n; + + memset(&creds, 0, sizeof(creds)); + memset(&netdevs, 0, sizeof(netdevs)); + + lws_strncpy(creds.ssid, "xxx", sizeof(creds.ssid)); + lws_strncpy(creds.passphrase, "yyy", sizeof(creds.passphrase)); + lws_dll2_add_tail(&creds.list, &netdevs.owner_creds); + + buf = malloc(2048); /* length should be computed */ + + js = lws_struct_json_serialize_create(lsm_netdev_schema, + LWS_ARRAY_SIZE(lsm_netdev_schema), 0, &netdevs); + if (!js) + goto bail; + + n = lws_struct_json_serialize(js, buf, 2048, &w); + lws_struct_json_serialize_destroy(&js); + if (n != LSJS_RESULT_FINISH) + goto bail; + if (strcmp("{\"schema\":\"com.warmcat.sai.taskinfo\",\"credentials\":[{\"ssid\":\"xxx\",\"passphrase\":\"yyy\",\"alg\":0}]}", (const char *)buf)) { + puts((const char *)buf); + goto bail; + } + free(buf); + } + + { + struct x { lws_dll2_t list; const char *sz; }; + struct x x1, x2, *xp; + lws_dll2_owner_t o; + + lws_dll2_owner_clear(&o); + memset(&x1, 0, sizeof(x1)); + memset(&x2, 0, sizeof(x2)); + + x1.sz = "nope"; + x2.sz = "yes"; + + lws_dll2_add_tail(&x1.list, &o); + lws_dll2_add_tail(&x2.list, &o); + + xp = lws_dll2_search_sz_pl(&o, "yes", 3, struct x, list, sz); + if (xp != &x2) { + lwsl_err("%s: 1 xp %p\n", __func__, xp); + goto bail; + } + xp = lws_dll2_search_sz_pl(&o, "nope", 4, struct x, list, sz); + if (xp != &x1) { + lwsl_err("%s: 2 xp %p\n", __func__, xp); + goto bail; + } + xp = lws_dll2_search_sz_pl(&o, "wrong", 4, struct x, list, sz); + if (xp) { + lwsl_err("%s: 3 xp %p\n", __func__, xp); + goto bail; + } + } + + { + lws_struct_args_t a; + struct lejp_ctx ctx; + int m; + + memset(&a, 0, sizeof(a)); + a.map_st[0] = lsm_jig_schema; + a.map_entries_st[0] = LWS_ARRAY_SIZE(lsm_jig_schema); + a.ac_block_size = 512; + + lws_struct_json_init_parse(&ctx, NULL, &a); + + m = lejp_parse(&ctx, (uint8_t *)jig_conf, (int)strlen(jig_conf)); + + if (m < 0 || !a.dest) { + lwsl_err("%s: line %d: JSON decode failed '%s'\n", + __func__, ctx.line, lejp_error_to_string(m)); + goto bail; + } + } lwsl_user("Completed: PASS\n"); return 0; bail: +if (test2()) + return 1; lwsl_user("Completed: FAIL\n"); return 1; diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_struct-json/README.md libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_struct-json/README.md --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_struct-json/README.md 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_struct-json/README.md 2020-12-01 17:40:26.000000000 +0000 @@ -17,40 +17,92 @@ ``` $ ./lws-api-test-lws_struct-json -[2019/03/30 22:09:09:2529] USER: LWS API selftest: lws_struct JSON -[2019/03/30 22:09:09:2625] NOTICE: main: ++++++++++++++++ test 1 -[2019/03/30 22:09:09:2812] NOTICE: builder.hostname = 'learn', timeout = 1800, targets (2) -[2019/03/30 22:09:09:2822] NOTICE: target.name 'target1' (target 0x543a830) -[2019/03/30 22:09:09:2824] NOTICE: target.name 'target2' (target 0x543a860) -[2019/03/30 22:09:09:2826] NOTICE: main: .... strarting serialization of test 1 -[2019/03/30 22:09:09:2899] NOTICE: ser says 1 -{"schema":"com-warmcat-sai-builder","hostname":"learn","nspawn_timeout":1800,"targets":[{"name":"target1"},{"name":"target2"}]} -[2019/03/30 22:09:09:2929] NOTICE: main: ++++++++++++++++ test 2 -[2019/03/30 22:09:09:2932] NOTICE: builder.hostname = 'learn', timeout = 0, targets (3) -[2019/03/30 22:09:09:2932] NOTICE: target.name 'target1' (target 0x543b060) -[2019/03/30 22:09:09:2933] NOTICE: target.name 'target2' (target 0x543b090) -[2019/03/30 22:09:09:2933] NOTICE: target.name 'target3' (target 0x543b0c0) -[2019/03/30 22:09:09:2934] NOTICE: main: .... strarting serialization of test 2 -[2019/03/30 22:09:09:2935] NOTICE: ser says 1 -{"schema":"com-warmcat-sai-builder","hostname":"learn","nspawn_timeout":0,"targets":[{"name":"target1"},{"name":"target2"},{"name":"target3"}]} -[2019/03/30 22:09:09:2940] NOTICE: main: ++++++++++++++++ test 3 -[2019/03/30 22:09:09:2959] NOTICE: builder.hostname = 'learn', timeout = 1800, targets (2) -[2019/03/30 22:09:09:2960] NOTICE: target.name 'target1' (target 0x543b450) -[2019/03/30 22:09:09:2961] NOTICE: child 0x543b480, target.child.somename 'abc' -[2019/03/30 22:09:09:2961] NOTICE: target.name 'target2' (target 0x543b490) -[2019/03/30 22:09:09:2962] NOTICE: main: .... strarting serialization of test 3 -[2019/03/30 22:09:09:2969] NOTICE: ser says 1 -{"schema":"com-warmcat-sai-builder","hostname":"learn","nspawn_timeout":1800,"targets":[{"name":"target1","child":{"somename":"abc"}},{"name":"target2"}]} -[2019/03/30 22:09:09:2970] NOTICE: main: ++++++++++++++++ test 4 -[2019/03/30 22:09:09:2971] NOTICE: builder.hostname = 'learn', timeout = 1800, targets (0) -[2019/03/30 22:09:09:2971] NOTICE: main: .... strarting serialization of test 4 -[2019/03/30 22:09:09:2973] NOTICE: ser says 1 +[2020/05/21 16:36:57:0808] U: LWS API selftest: lws_struct JSON +[2020/05/21 16:36:57:1188] N: main: ++++++++++++++++ test 1 +[2020/05/21 16:36:57:1291] N: lws_struct_schema_only_lejp_cb: child map ofs_clist 0 +[2020/05/21 16:36:57:1387] N: lws_struct_default_lejp_cb: created 'targets' object size 48 +[2020/05/21 16:36:57:1429] N: lws_struct_default_lejp_cb: created 'targets' object size 48 +[2020/05/21 16:36:57:1467] N: builder.hostname = 'learn', timeout = 1800, targets (2) +[2020/05/21 16:36:57:1490] N: target.name 'target1' (target 0x509fe30) +[2020/05/21 16:36:57:1495] N: target.name 'target2' (target 0x509fe68) +[2020/05/21 16:36:57:1500] N: main: .... strarting serialization of test 1 +{"schema":"com-warmcat-sai-builder","hostname":"learn","nspawn_timeout":1800,"targets":[{"name":"target1","someflag":true},{"name":"target2","someflag":false}]} +[2020/05/21 16:36:57:1648] N: main: ++++++++++++++++ test 2 +[2020/05/21 16:36:57:1649] N: lws_struct_schema_only_lejp_cb: child map ofs_clist 0 +[2020/05/21 16:36:57:1650] N: lws_struct_default_lejp_cb: created 'targets' object size 48 +[2020/05/21 16:36:57:1651] N: lws_struct_default_lejp_cb: created 'targets' object size 48 +[2020/05/21 16:36:57:1652] N: lws_struct_default_lejp_cb: created 'targets' object size 48 +[2020/05/21 16:36:57:1653] N: builder.hostname = 'learn', timeout = 0, targets (3) +[2020/05/21 16:36:57:1653] N: target.name 'target1' (target 0x50a0660) +[2020/05/21 16:36:57:1654] N: target.name 'target2' (target 0x50a0698) +[2020/05/21 16:36:57:1655] N: target.name 'target3' (target 0x50a06d0) +[2020/05/21 16:36:57:1655] N: main: .... strarting serialization of test 2 +{"schema":"com-warmcat-sai-builder","hostname":"learn","nspawn_timeout":0,"targets":[{"name":"target1","someflag":false},{"name":"target2","someflag":false},{"name":"target3","someflag":false}]} +[2020/05/21 16:36:57:1662] N: main: ++++++++++++++++ test 3 +[2020/05/21 16:36:57:1663] N: lws_struct_schema_only_lejp_cb: child map ofs_clist 0 +[2020/05/21 16:36:57:1664] N: lws_struct_default_lejp_cb: created 'targets' object size 48 +[2020/05/21 16:36:57:1671] N: lws_struct_default_lejp_cb: created 'child' object size 8 +[2020/05/21 16:36:57:1685] N: lws_struct_default_lejp_cb: created 'targets' object size 48 +[2020/05/21 16:36:57:1685] N: builder.hostname = 'learn', timeout = 1800, targets (2) +[2020/05/21 16:36:57:1686] N: target.name 'target1' (target 0x50a0a50) +[2020/05/21 16:36:57:1687] N: child 0x50a0a88, target.child.somename 'abc' +[2020/05/21 16:36:57:1688] N: target.name 'target2' (target 0x50a0a98) +[2020/05/21 16:36:57:1688] N: main: .... strarting serialization of test 3 +{"schema":"com-warmcat-sai-builder","hostname":"learn","nspawn_timeout":1800,"targets":[{"name":"target1","someflag":false,"child":{"somename":"abc"}},{"name":"target2","someflag":false}]} +[2020/05/21 16:36:57:1697] N: main: ++++++++++++++++ test 4 +[2020/05/21 16:36:57:1698] N: lws_struct_schema_only_lejp_cb: child map ofs_clist 0 +[2020/05/21 16:36:57:1699] N: builder.hostname = 'learn', timeout = 1800, targets (0) +[2020/05/21 16:36:57:1699] N: main: .... strarting serialization of test 4 {"schema":"com-warmcat-sai-builder","hostname":"learn","nspawn_timeout":1800} -[2019/03/30 22:09:09:2974] NOTICE: main: ++++++++++++++++ test 5 -[2019/03/30 22:09:09:2978] NOTICE: builder.hostname = '', timeout = 0, targets (0) -[2019/03/30 22:09:09:2979] NOTICE: main: .... strarting serialization of test 5 -[2019/03/30 22:09:09:2980] NOTICE: ser says 1 +[2020/05/21 16:36:57:1701] N: main: ++++++++++++++++ test 5 +[2020/05/21 16:36:57:1702] N: lws_struct_schema_only_lejp_cb: child map ofs_clist 0 +[2020/05/21 16:36:57:1707] N: builder.hostname = '', timeout = 0, targets (0) +[2020/05/21 16:36:57:1708] N: main: .... strarting serialization of test 5 {"schema":"com-warmcat-sai-builder","hostname":"","nspawn_timeout":0} -[2019/03/30 22:09:09:2982] USER: Completed: PASS +[2020/05/21 16:36:57:1709] N: main: ++++++++++++++++ test 6 +[2020/05/21 16:36:57:1710] N: lws_struct_schema_only_lejp_cb: child map ofs_clist 0 +[2020/05/21 16:36:57:1730] N: builder.hostname = 'PYvtan6kqppjnS0KpYTCaiOLsJkc7Xe', timeout = 0, targets (0) +[2020/05/21 16:36:57:1731] N: main: .... strarting serialization of test 6 +{"schema":"com-warmcat-sai-builder","hostname":"PYvtan6kqppjnS0KpYTCaiOLsJkc7Xe","nspawn_timeout":0} +[2020/05/21 16:36:57:1732] N: main: ++++++++++++++++ test 7 +[2020/05/21 16:36:57:1732] N: lws_struct_schema_only_lejp_cb: child map ofs_clist 0 +[2020/05/21 16:36:57:1733] N: lws_struct_default_lejp_cb: created 'targets' object size 48 +[2020/05/21 16:36:57:1739] N: builder.hostname = '', timeout = 0, targets (1) +[2020/05/21 16:36:57:1751] N: target.name 'PYvtan6kqppjnS0KpYTCaiOLsJkc7XecAr1kcE0aCIciewYB+JcLG82mO1Vb1mJtjDwUjBxy2I6AzefzoWUWmqZbsv4MXR55j9bKlyz1liiSX63iO0x6JAwACMtE2MkgcLwR86TSWAD9D1QKIWqg5RJ/CRuVsW0DKAUMD52ql4JmPFuJpJgTq28z6PhYNzN3yI3bmQt6bzhA+A/xAsFzSBnb3MHYWzGMprr53FAP1ISo5Ec9i+2ehV40sG6Q470sH3PGQZ0YRPO7Sh/SyrSQ/scONmxRc3AcXl7X/CSs417ii+CV8sq3ZgcxKNB7tNfN7idNx3upZ00G2BZy9jSy03cLKKLNaNUt0TQsxXbH55uDHzSEeZWvxJgT6zB1NoMhdC02w+oXim94M6z6COCnqT3rgkGk8PHMry9Bkh4yVpRmzIRfMmln/lEhdZgxky2+g5hhlSIGJYDCrdynD9kCfvfy6KGOpNIi1X+mhbbWn4lnL9ZKihL/RrfOV+oV4R26IDq+KqUiJBENeo8/GXkGLUH/87iPyzXKEMavr6fkrK0vTGto8yEYxmOyaVz8phG5rwf4jJgmYNoMbGo8gWvhqO7UAGy2g7MWv+B/t1eZZ+1euLsNrWAsFJiFbQKgdFfQT3RjB14iU8knlQ8usoy+pXssY2ddGJGVcGC21oZvstK9eu1eRZftda/wP+N5unT1Hw7kCoVzqxHieiYt47EGIOaaQ7XjZDK6qPN6O/grHnvJZm2vBkxuXgsYVkRQ7AuTWIecphqFsq7Wbc1YNbMW47SVU5zMD0WaCqbaaI0t4uIzRvPlD8cpiiTzFTrEHlIBTf8/uZjjEGGLhJR1jPqA9D1Ej3ChV+ye6F9JTUMlozRMsGuF8U4btDzH5xdnmvRS4Ar6LKEtAXGkj2yuyJln+v4RIWj2xOGPJovOqiXwi0FyM61f8U8gj0OiNA2/QlvrqQVDF7sMXgjvaE7iQt5vMETteZlx+z3f+jTFM/aon5... +[2020/05/21 16:36:57:1752] N: main: .... strarting serialization of test 7 +{"schema":"com-warmcat-sai-builder","hostname":"","nspawn_timeout":0,"targets":[{"name":"PYvtan6kqppjnS0KpYTCaiOLsJkc7XecAr1kcE0aCIciewYB+JcLG82mO1Vb1mJtjDwUjBxy2I6AzefzoWUWmqZbsv4MXR55j9bKlyz1liiSX63iO0x6JAwACMtE2MkgcLwR86TSWAD9D1QKIWqg5RJ/CRuVsW0DKAUMD52ql4JmPFuJpJgTq28z6PhYNzN3yI3bmQt6bzhA+A/xAsFzSBnb3MHYWzGMprr53FAP1ISo5Ec9i+2ehV40sG6Q470sH3PGQZ0YRPO7Sh/SyrSQ/scONmxRc3AcXl7X/CSs417ii+CV8sq3ZgcxKNB7tNfN7idNx3upZ00G2BZy9jSy03cLKKLNaNUt0TQsxXbH55uDHzSEeZWvxJgT6zB1NoMhdC02w+oXim94M6z6COCnqT3rgkGk8PHMry9Bkh4yVpRmzIRfMmln/lEhdZgxky2+g5hhlSIGJYDCrdynD9kCfvfy6KGOpNIi1X+mhbbWn4lnL9ZKihL/RrfOV+oV4R26IDq+KqUiJBENeo8/GXkGLUH/87iPyzXKEMavr6fkrK0vTGto8yEYxmOyaVz8phG5rwf4jJgmYNoMbGo8gWvhqO7UAGy2g7MWv+B/t1eZZ+1euLsNrWAsFJiFbQKgdFfQT3RjB14iU8knlQ8usoy+pXssY2ddGJGVcGC21oZvstK9eu1eRZftda/wP+N5unT1Hw7kCoVzqxHieiYt47EGIOaaQ7XjZDK6qPN6O/grHnvJZm2vBkxuXgsYVkRQ7AuTWIecphqFsq7Wbc1YNbMW47SVU5zMD0WaCqbaaI0t4uIzRvPlD8cpiiTzFTrEHlIBTf8/uZjjEGGLhJR1jPqA9D1Ej3ChV+ye6F9JTUMlozRMsGuF8U4btDzH5xdnmvRS4Ar6LKEtAXGkj2yuyJln+v4RIWj2xOGPJovOqiXwi0FyM61f8U8gj0OiNA2/QlvrqQVDF7sMXgjvaE7iQt5vMETteZlx+z3f+jTFM/aon511W4+ZkRD+6AHwucvM9BEC","someflag":false}]} +[2020/05/21 16:36:57:1756] N: main: ++++++++++++++++ test 8 +[2020/05/21 16:36:57:1758] N: lws_struct_schema_only_lejp_cb: child map ofs_clist 0 +[2020/05/21 16:36:57:1761] N: other.name = 'somename' +[2020/05/21 16:36:57:1763] N: main: .... strarting serialization of test 8 +{"schema":"com-warmcat-sai-other","name":"somename"} +{"schema":"meta.schema","t":{"name":"mytargetname","someflag":false},"e":{"hostname":"myhostname","nspawn_timeout":0}} +[2020/05/21 16:36:57:1785] N: Test set 2 +[2020/05/21 16:36:57:1791] N: lws_struct_schema_only_lejp_cb: child map ofs_clist 0 +[2020/05/21 16:36:57:1795] N: Test set 2: 6: 071ab46ab4296e5de674c628fec17c55088254679f7714ad991f8c4873dca +[2020/05/21 16:36:57:1801] N: test2: start +[2020/05/21 16:36:57:1811] N: lws_struct_schema_only_lejp_cb: child map ofs_clist 0 +[2020/05/21 16:36:57:1815] N: lws_struct_default_lejp_cb: created 'config' object size 80 +[2020/05/21 16:36:57:1819] N: lws_struct_default_lejp_cb: created 'creds' object size 16 +[2020/05/21 16:36:57:1833] N: lws_struct_default_lejp_cb: created 'config' object size 80 +[2020/05/21 16:36:57:1834] N: lws_struct_default_lejp_cb: created 'creds' object size 16 +[2020/05/21 16:36:57:1837] N: test2: lejp_parse 0 +[2020/05/21 16:36:57:1841] N: t2_configs_dump: number of configs: 2 +[2020/05/21 16:36:57:1844] N: t2_config_dump: id1 '(null)' +[2020/05/21 16:36:57:1846] N: t2_config_dump: arg1 'val1' +[2020/05/21 16:36:57:1848] N: t2_config_dump: ssid '"nw2"' +[2020/05/21 16:36:57:1850] N: t2_config_dump: freq 0 +[2020/05/21 16:36:57:1852] N: t2_config_dump: arg2 0 +[2020/05/21 16:36:57:1854] N: t2_config_dump: priority 1 +[2020/05/21 16:36:57:1856] N: t2_config_dump: key1: "xxxxxxxxx", key2: (null) +[2020/05/21 16:36:57:1857] N: t2_config_dump: id1 '(null)' +[2020/05/21 16:36:57:1858] N: t2_config_dump: arg1 'val2' +[2020/05/21 16:36:57:1858] N: t2_config_dump: ssid '"nw1"' +[2020/05/21 16:36:57:1859] N: t2_config_dump: freq 11 +[2020/05/21 16:36:57:1859] N: t2_config_dump: arg2 1420887242594 +[2020/05/21 16:36:57:1860] N: t2_config_dump: priority 3 +[2020/05/21 16:36:57:1860] N: t2_config_dump: key1: "xxxxxxxxxxxxx", key2: (null) +{"config":[{"creds":{"key1":"\u0022xxxxxxxxx\u0022"},"arg1":"val1","ssid":"\u0022nw2\u0022","frequency":0,"arg2":0,"priority":1},{"creds":{"key1":"\u0022xxxxxxxxxxxxx\u0022"},"arg1":"val2","ssid":"\u0022nw1\u0022","frequency":11,"arg2":1420887242594,"priority":3}]} +[2020/05/21 16:36:57:1880] U: Completed: PASS ``` diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_struct-json/selftest.sh libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_struct-json/selftest.sh --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_struct-json/selftest.sh 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_struct-json/selftest.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -#!/bin/bash -# -# $1: path to minimal example binaries... -# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 -# that will be ./bin from your build dir -# -# $2: path for logs and results. The results will go -# in a subdir named after the directory this script -# is in -# -# $3: offset for test index count -# -# $4: total test count -# -# $5: path to ./minimal-examples dir in lws -# -# Test return code 0: OK, 254: timed out, other: error indication - -. $5/selftests-library.sh - -COUNT_TESTS=1 - -dotest $1 $2 apiselftest -exit $FAILS diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_struct-json/test2.c libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_struct-json/test2.c --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_struct-json/test2.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_struct-json/test2.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,242 @@ +/* + * lws-api-test-lws_struct-json + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * lws_struct apis are used to serialize and deserialize your C structs and + * linked-lists in a standardized way that's very modest on memory but + * convenient and easy to maintain. + * + * This second test file shows a worked example for how to express a schema + * and both consume JSON -> struct and struct -> JSON for it. + */ + +#include + +static const char * const test2_json = +"{" + "\"config\":[" + "{" + "\"id1\":" "null," + "\"creds\":{" + "\"key1\":" "\"\\\"xxxxxxxxx\\\"\"," + "\"key2\":" "null" + "}," + "\"frequency\":" "0," + "\"arg1\":" "\"val1\"," + "\"arg2\":" "0," + "\"priority\":" "1," + "\"ssid\":" "\"\\\"nw2\\\"\"" + "}, {" + "\"id2\":" "null," + "\"creds\": {" + "\"key1\":" "\"\\\"xxxxxxxxxxxxx\\\"\"," + "\"key2\":" "null" + "}," + "\"frequency\":" "11," + "\"arg1\":" "\"val2\"," +#if defined(_WIN32) + "\"arg2\":" "2147483647," +#else + "\"arg2\":" "1420887242594," +#endif + "\"priority\":" "3," + "\"ssid\":" "\"\\\"nw1\\\"\"" + "}" + "]" +"}"; + +static const char * const test2_json_expected = + "{\"config\":[{\"creds\":{\"key1\":\"\\u0022xxxxxxxxx\\u0022\"}," + "\"arg1\":\"val1\",\"ssid\":\"\\u0022nw2\\u0022\"," + "\"frequency\":0,\"arg2\":0,\"priority\":1}," + "{\"creds\":{\"key1\":\"\\u0022xxxxxxxxxxxxx\\u0022\"}," + "\"arg1\":\"val2\",\"ssid\":\"\\u0022nw1\\u0022\"," +#if defined(_WIN32) + "\"frequency\":11,\"arg2\":2147483647,\"priority\":3}]}" +#else + "\"frequency\":11,\"arg2\":1420887242594,\"priority\":3}]}" +#endif +; + +/* + * level 3: Credentials object + */ + +typedef struct t2_cred { + const char *key1; + const char *key2; +} t2_cred_t; + +static const lws_struct_map_t lsm_t2_cred[] = { + LSM_STRING_PTR (t2_cred_t, key1, "key1"), + LSM_STRING_PTR (t2_cred_t, key2, "key2"), +}; + +/* + * level 2: Configuration object, containing a child credentials object + */ + +typedef struct t2_config { + lws_dll2_t list; + t2_cred_t *creds; + const char *id1; + const char *arg1; + const char *ssid; + unsigned int frequency; + unsigned long arg2; + unsigned int priority; +} t2_config_t; + +static const lws_struct_map_t lsm_t2_config[] = { + LSM_CHILD_PTR (t2_config_t, + creds, /* the child pointer member */ + t2_cred_t, /* the child type */ + NULL, lsm_t2_cred, /* map object for item type */ + "creds"), /* outer json object name */ + LSM_STRING_PTR (t2_config_t, id1, "id1"), + LSM_STRING_PTR (t2_config_t, arg1, "arg1"), + LSM_STRING_PTR (t2_config_t, ssid, "ssid"), + + LSM_UNSIGNED (t2_config_t, frequency, "frequency"), + LSM_UNSIGNED (t2_config_t, arg2, "arg2"), + LSM_UNSIGNED (t2_config_t, priority, "priority"), +}; + +/* + * level 1: list-of-configurations object + */ + +typedef struct t2_configs { + lws_dll2_owner_t configs; +} t2_configs_t; + +static const lws_struct_map_t lsm_t2_configs[] = { + LSM_LIST (t2_configs_t, configs, /* the list owner type/member */ + t2_config_t, list, /* the list item type/member */ + NULL, lsm_t2_config, /* map object for item type */ + "config"), /* outer json object name */ +}; + +/* + * For parsing, this lists the kind of object we expect to parse so the struct + * can be allocated polymorphically. + * + * Lws uses an explicit "schema" member so the type is known unambiguously. If + * in the incoming JSON the first member is not "schema", it will scan the + * maps listed here and instantiate the first object that has a member of that + * name. + */ + +static const lws_struct_map_t lsm_schema[] = { + LSM_SCHEMA (t2_configs_t, NULL, lsm_t2_configs, "t2"), + /* other schemata that might need parsing... */ +}; + + + +static int +t2_config_dump(struct lws_dll2 *d, void *user) +{ + t2_config_t *c = lws_container_of(d, t2_config_t, list); + + lwsl_notice("%s: id1 '%s'\n", __func__, c->id1); + lwsl_notice("%s: arg1 '%s'\n", __func__, c->arg1); + lwsl_notice("%s: ssid '%s'\n", __func__, c->ssid); + + lwsl_notice("%s: freq %d\n", __func__, c->frequency); + lwsl_notice("%s: arg2 %lu\n", __func__, c->arg2); + lwsl_notice("%s: priority %d\n", __func__, c->priority); + + lwsl_notice("%s: key1: %s, key2: %s\n", __func__, + c->creds->key1, c->creds->key2); + + return 0; +} + +static int +t2_configs_dump(t2_configs_t *t2cs) +{ + lwsl_notice("%s: number of configs: %d\n", __func__, + t2cs->configs.count); + + lws_dll2_foreach_safe(&t2cs->configs, NULL, t2_config_dump); + + return 0; +} + + +int +test2(void) +{ + lws_struct_serialize_t *ser; + struct lejp_ctx ctx; + lws_struct_args_t a; + t2_configs_t *top; + uint8_t buf[4096]; + size_t written; + int n, bad = 1; + + lwsl_notice("%s: start \n", __func__); + + memset(&a, 0, sizeof(a)); + a.map_st[0] = lsm_schema; + a.map_entries_st[0] = LWS_ARRAY_SIZE(lsm_schema); + a.ac_block_size = 512; + lws_struct_json_init_parse(&ctx, NULL, &a); + + n = lejp_parse(&ctx, (uint8_t *)test2_json, (int)strlen(test2_json)); + lwsl_notice("%s: lejp_parse %d\n", __func__, n); + if (n < 0) { + lwsl_err("%s: test2 JSON decode failed '%s'\n", + __func__, lejp_error_to_string(n)); + goto bail; + } + lwsac_info(a.ac); + + top = (t2_configs_t *)a.dest; /* the top level object */ + + if (!top) { + lwsl_err("%s: no top level object\n", __func__); + goto bail; + } + t2_configs_dump(top); + + /* 2. Let's reserialize the top level object and see what comes out */ + + ser = lws_struct_json_serialize_create(&lsm_schema[0], 1, + LSSERJ_FLAG_OMIT_SCHEMA, top); + if (!ser) { + lwsl_err("%s: unable to init serialization\n", __func__); + goto bail; + } + + do { + n = lws_struct_json_serialize(ser, buf, sizeof(buf), &written); + switch (n) { + case LSJS_RESULT_FINISH: + puts((const char *)buf); + break; + case LSJS_RESULT_CONTINUE: + case LSJS_RESULT_ERROR: + goto bail; + } + } while (n == LSJS_RESULT_CONTINUE); + + if (strcmp(test2_json_expected, (char *)buf)) { + lwsl_err("%s: expected %s\n", __func__, test2_json_expected); + goto bail; + } + + lws_struct_json_serialize_destroy(&ser); + + bad = 0; + +bail: + lwsac_free(&a.ac); + + return bad; +} diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_struct_sqlite/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_struct_sqlite/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_struct_sqlite/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_struct_sqlite/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,78 +1,25 @@ -project(lws-api-test-lws_struct-sqlite) +project(lws-api-test-lws_struct-sqlite C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-api-test-lws_struct-sqlite) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) -require_lws_config(LWS_WITH_STRUCT_SQLITE 1 requirements) +require_lws_config(LWS_WITH_STRUCT_SQLITE3 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) + add_test(NAME api-test-lws_struct_sqlite COMMAND lws-api-test-lws_struct-sqlite) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared sqlite3) + target_link_libraries(${SAMP} websockets_shared sqlite3 ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets sqlite3) + target_link_libraries(${SAMP} websockets sqlite3 ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_struct_sqlite/main.c libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_struct_sqlite/main.c --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_struct_sqlite/main.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_struct_sqlite/main.c 2020-12-01 17:40:26.000000000 +0000 @@ -97,7 +97,7 @@ unlink("_lws_apitest.sq3"); - if (lws_struct_sq3_open(context, "_lws_apitest.sq3", &db)) { + if (lws_struct_sq3_open(context, "_lws_apitest.sq3", 1, &db)) { lwsl_err("%s: failed to open table\n", __func__); goto bail; } diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_struct_sqlite/selftest.sh libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_struct_sqlite/selftest.sh --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_struct_sqlite/selftest.sh 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_struct_sqlite/selftest.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -#!/bin/bash -# -# $1: path to minimal example binaries... -# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 -# that will be ./bin from your build dir -# -# $2: path for logs and results. The results will go -# in a subdir named after the directory this script -# is in -# -# $3: offset for test index count -# -# $4: total test count -# -# $5: path to ./minimal-examples dir in lws -# -# Test return code 0: OK, 254: timed out, other: error indication - -. $5/selftests-library.sh - -COUNT_TESTS=1 - -dotest $1 $2 apiselftest -exit $FAILS diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_tokenize/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_tokenize/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_tokenize/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_tokenize/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,74 +1,19 @@ -project(lws-api-test-lws_tokenize) +project(lws-api-test-lws_tokenize C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-api-test-lws_tokenize) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - - - add_executable(${SAMP} ${SRCS}) + add_test(NAME api-test-lws_tokenize COMMAND lws-api-test-lws_tokenize) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_tokenize/main.c libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_tokenize/main.c --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_tokenize/main.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_tokenize/main.c 2020-12-01 17:40:26.000000000 +0000 @@ -299,7 +299,8 @@ if (total < budget) budget = total; - memcpy(out + *pos, replace + (*exp_ofs), budget); + if (out) + memcpy(out + *pos, replace + (*exp_ofs), budget); *exp_ofs += budget; *pos += budget; @@ -354,6 +355,17 @@ return 1; } + /* as above, but don't generate output, just find the length */ + + lws_strexp_init(&exp, NULL, exp_cb1, NULL, (size_t)-1); + n = lws_strexp_expand(&exp, exp_inp1, 28, &used_in, &used_out); + if (n != LSTRX_DONE || used_in != 28 || used_out != 39) { + lwsl_err("%s: lws_strexp test 2 failed: %d, used_out: %d\n", + __func__, n, (int)used_out); + + return 1; + } + p = exp_inp1; in_len = strlen(p); memset(obuf, 0, sizeof(obuf)); @@ -405,6 +417,74 @@ return 1; } + /* sanity check lws_nstrstr() */ + + { + static const char *t1 = "abc123456"; + const char *mcp; + + mcp = lws_nstrstr(t1, strlen(t1), "abc", 3); + if (mcp != t1) { + lwsl_err("%s: lws_nstrstr 1 failed\n", __func__); + return 1; + } + mcp = lws_nstrstr(t1, strlen(t1), "def", 3); + if (mcp != NULL) { + lwsl_err("%s: lws_nstrstr 2 failed\n", __func__); + return 1; + } + mcp = lws_nstrstr(t1, strlen(t1), "456", 3); + if (mcp != t1 + 6) { + lwsl_err("%s: lws_nstrstr 3 failed: %p\n", __func__, mcp); + return 1; + } + mcp = lws_nstrstr(t1, strlen(t1), "1", 1); + if (mcp != t1 + 3) { + lwsl_err("%s: lws_nstrstr 4 failed\n", __func__); + return 1; + } + mcp = lws_nstrstr(t1, strlen(t1), "abc1234567", 10); + if (mcp != NULL) { + lwsl_err("%s: lws_nstrstr 5 failed\n", __func__); + return 1; + } + } + + /* sanity check lws_json_simple_find() */ + + { + static const char *t1 = "{\"myname1\":true," + "\"myname2\":\"string\", " + "\"myname3\": 123}"; + size_t alen; + const char *mcp; + + mcp = lws_json_simple_find(t1, strlen(t1), "\"myname1\":", &alen); + if (mcp != t1 + 11 || alen != 4) { + lwsl_err("%s: lws_json_simple_find 1 failed: (%d) %s\n", + __func__, (int)alen, mcp); + return 1; + } + + mcp = lws_json_simple_find(t1, strlen(t1), "\"myname2\":", &alen); + if (mcp != t1 + 27 || alen != 6) { + lwsl_err("%s: lws_json_simple_find 2 failed\n", __func__); + return 1; + } + + mcp = lws_json_simple_find(t1, strlen(t1), "\"myname3\":", &alen); + if (mcp != t1 + 47 || alen != 3) { + lwsl_err("%s: lws_json_simple_find 3 failed\n", __func__); + return 1; + } + + mcp = lws_json_simple_find(t1, strlen(t1), "\"nope\":", &alen); + if (mcp != NULL) { + lwsl_err("%s: lws_json_simple_find 4 failed\n", __func__); + return 1; + } + } + p = lws_cmdline_option(argc, argv, "-s"); for (n = 0; n < (int)LWS_ARRAY_SIZE(tests); n++) { diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_tokenize/selftest.sh libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_tokenize/selftest.sh --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-lws_tokenize/selftest.sh 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-lws_tokenize/selftest.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -#!/bin/bash -# -# $1: path to minimal example binaries... -# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 -# that will be ./bin from your build dir -# -# $2: path for logs and results. The results will go -# in a subdir named after the directory this script -# is in -# -# $3: offset for test index count -# -# $4: total test count -# -# $5: path to ./minimal-examples dir in lws -# -# Test return code 0: OK, 254: timed out, other: error indication - -. $5/selftests-library.sh - -COUNT_TESTS=1 - -dotest $1 $2 apiselftest -exit $FAILS diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-secure-streams/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/api-tests/api-test-secure-streams/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-secure-streams/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-secure-streams/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,77 +1,31 @@ -project(lws-api-test-secure-streams) +project(lws-api-test-secure-streams C) cmake_minimum_required(VERSION 2.8) include(CheckCSourceCompiles) - -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - +include(LwsCheckRequirements) set(requirements 1) require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) +require_lws_config(LWS_WITH_TLS 1 requirements) +require_lws_config(LWS_WITH_SYS_STATE 1 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 requirements) if (requirements) add_executable(${PROJECT_NAME} main.c) + if (LWS_CTEST_INTERNET_AVAILABLE) + add_test(NAME api-test-secure-streams COMMAND ${PROJECT_NAME}) + set_tests_properties(api-test-secure-streams + PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/api-tests/api-test-secure-streams + TIMEOUT 20) + endif() + if (websockets_shared) - target_link_libraries(${PROJECT_NAME} websockets_shared) + target_link_libraries(${PROJECT_NAME} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${PROJECT_NAME} websockets_shared) else() - target_link_libraries(${PROJECT_NAME} websockets) + target_link_libraries(${PROJECT_NAME} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-secure-streams/README.md libwebsockets-4.1.6/minimal-examples/api-tests/api-test-secure-streams/README.md --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-secure-streams/README.md 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-secure-streams/README.md 2020-12-01 17:40:26.000000000 +0000 @@ -1,7 +1,7 @@ -# lws api test lws_struct JSON +# lws api test Secure Streams -Demonstrates how to use and performs selftests for lws_struct -JSON serialization and deserialization +Performs some tests against httpbin.org server +to check Secure Streams client performance ## build @@ -16,41 +16,6 @@ -d |Debug verbosity in decimal, eg, -d15 ``` - $ ./lws-api-test-lws_struct-json -[2019/03/30 22:09:09:2529] USER: LWS API selftest: lws_struct JSON -[2019/03/30 22:09:09:2625] NOTICE: main: ++++++++++++++++ test 1 -[2019/03/30 22:09:09:2812] NOTICE: builder.hostname = 'learn', timeout = 1800, targets (2) -[2019/03/30 22:09:09:2822] NOTICE: target.name 'target1' (target 0x543a830) -[2019/03/30 22:09:09:2824] NOTICE: target.name 'target2' (target 0x543a860) -[2019/03/30 22:09:09:2826] NOTICE: main: .... strarting serialization of test 1 -[2019/03/30 22:09:09:2899] NOTICE: ser says 1 -{"schema":"com-warmcat-sai-builder","hostname":"learn","nspawn_timeout":1800,"targets":[{"name":"target1"},{"name":"target2"}]} -[2019/03/30 22:09:09:2929] NOTICE: main: ++++++++++++++++ test 2 -[2019/03/30 22:09:09:2932] NOTICE: builder.hostname = 'learn', timeout = 0, targets (3) -[2019/03/30 22:09:09:2932] NOTICE: target.name 'target1' (target 0x543b060) -[2019/03/30 22:09:09:2933] NOTICE: target.name 'target2' (target 0x543b090) -[2019/03/30 22:09:09:2933] NOTICE: target.name 'target3' (target 0x543b0c0) -[2019/03/30 22:09:09:2934] NOTICE: main: .... strarting serialization of test 2 -[2019/03/30 22:09:09:2935] NOTICE: ser says 1 -{"schema":"com-warmcat-sai-builder","hostname":"learn","nspawn_timeout":0,"targets":[{"name":"target1"},{"name":"target2"},{"name":"target3"}]} -[2019/03/30 22:09:09:2940] NOTICE: main: ++++++++++++++++ test 3 -[2019/03/30 22:09:09:2959] NOTICE: builder.hostname = 'learn', timeout = 1800, targets (2) -[2019/03/30 22:09:09:2960] NOTICE: target.name 'target1' (target 0x543b450) -[2019/03/30 22:09:09:2961] NOTICE: child 0x543b480, target.child.somename 'abc' -[2019/03/30 22:09:09:2961] NOTICE: target.name 'target2' (target 0x543b490) -[2019/03/30 22:09:09:2962] NOTICE: main: .... strarting serialization of test 3 -[2019/03/30 22:09:09:2969] NOTICE: ser says 1 -{"schema":"com-warmcat-sai-builder","hostname":"learn","nspawn_timeout":1800,"targets":[{"name":"target1","child":{"somename":"abc"}},{"name":"target2"}]} -[2019/03/30 22:09:09:2970] NOTICE: main: ++++++++++++++++ test 4 -[2019/03/30 22:09:09:2971] NOTICE: builder.hostname = 'learn', timeout = 1800, targets (0) -[2019/03/30 22:09:09:2971] NOTICE: main: .... strarting serialization of test 4 -[2019/03/30 22:09:09:2973] NOTICE: ser says 1 -{"schema":"com-warmcat-sai-builder","hostname":"learn","nspawn_timeout":1800} -[2019/03/30 22:09:09:2974] NOTICE: main: ++++++++++++++++ test 5 -[2019/03/30 22:09:09:2978] NOTICE: builder.hostname = '', timeout = 0, targets (0) -[2019/03/30 22:09:09:2979] NOTICE: main: .... strarting serialization of test 5 -[2019/03/30 22:09:09:2980] NOTICE: ser says 1 -{"schema":"com-warmcat-sai-builder","hostname":"","nspawn_timeout":0} -[2019/03/30 22:09:09:2982] USER: Completed: PASS + $ ./lws-api-test-secure-streams ``` diff -Nru libwebsockets-4.0.20/minimal-examples/api-tests/api-test-smtp_client/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/api-tests/api-test-smtp_client/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/api-tests/api-test-smtp_client/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/api-tests/api-test-smtp_client/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,67 +1,13 @@ -project(lws-unit-tests-smtp-client) +project(lws-unit-tests-smtp-client C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-unit-tests-smtp-client) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_SMTP 1 requirements) @@ -69,9 +15,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/client-server/minimal-ws-proxy/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/client-server/minimal-ws-proxy/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/client-server/minimal-ws-proxy/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/client-server/minimal-ws-proxy/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,68 +1,13 @@ -project(lws-minimal-ws-proxy) +project(lws-minimal-ws-proxy C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-proxy) set(SRCS minimal-ws-proxy.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_WS 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) @@ -72,9 +17,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() \ No newline at end of file diff -Nru libwebsockets-4.0.20/minimal-examples/client-server/minimal-ws-proxy/protocol_lws_minimal.c libwebsockets-4.1.6/minimal-examples/client-server/minimal-ws-proxy/protocol_lws_minimal.c --- libwebsockets-4.0.20/minimal-examples/client-server/minimal-ws-proxy/protocol_lws_minimal.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/client-server/minimal-ws-proxy/protocol_lws_minimal.c 2020-12-01 17:40:26.000000000 +0000 @@ -41,6 +41,8 @@ struct lws_vhost *vhost; const struct lws_protocols *protocol; + lws_sorted_usec_list_t sul; + struct per_session_data__minimal *pss_list; /* linked-list of live pss*/ struct lws_ring *ring; /* ringbuffer holding unsent messages */ @@ -60,9 +62,12 @@ msg->len = 0; } -static int -connect_client(struct per_vhost_data__minimal *vhd) +static void +sul_connect_attempt(struct lws_sorted_usec_list *sul) { + struct per_vhost_data__minimal *vhd = + lws_container_of(sul, struct per_vhost_data__minimal, sul); + vhd->i.context = vhd->context; vhd->i.port = 443; vhd->i.address = "libwebsockets.org"; @@ -75,7 +80,9 @@ vhd->i.local_protocol_name = "lws-minimal-proxy"; vhd->i.pwsi = &vhd->client_wsi; - return !lws_client_connect_via_info(&vhd->i); + if (!lws_client_connect_via_info(&vhd->i)) + lws_sul_schedule(vhd->context, 0, &vhd->sul, + sul_connect_attempt, 10 * LWS_US_PER_SEC); } static int @@ -109,14 +116,12 @@ if (!vhd->ring) return 1; - if (connect_client(vhd)) - lws_timed_callback_vh_protocol(vhd->vhost, - vhd->protocol, - LWS_CALLBACK_USER, 1); + sul_connect_attempt(&vhd->sul); break; case LWS_CALLBACK_PROTOCOL_DESTROY: lws_ring_destroy(vhd->ring); + lws_sul_cancel(&vhd->sul); break; /* --- serving callbacks --- */ @@ -169,8 +174,8 @@ lwsl_err("CLIENT_CONNECTION_ERROR: %s\n", in ? (char *)in : "(null)"); vhd->client_wsi = NULL; - lws_timed_callback_vh_protocol(vhd->vhost, vhd->protocol, - LWS_CALLBACK_USER, 1); + lws_sul_schedule(vhd->context, 0, &vhd->sul, + sul_connect_attempt, LWS_US_PER_SEC); break; case LWS_CALLBACK_CLIENT_ESTABLISHED: @@ -214,18 +219,8 @@ case LWS_CALLBACK_CLIENT_CLOSED: vhd->client_wsi = NULL; - lws_timed_callback_vh_protocol(vhd->vhost, vhd->protocol, - LWS_CALLBACK_USER, 1); - break; - - /* rate-limited client connect retries */ - - case LWS_CALLBACK_USER: - lwsl_notice("%s: LWS_CALLBACK_USER\n", __func__); - if (connect_client(vhd)) - lws_timed_callback_vh_protocol(vhd->vhost, - vhd->protocol, - LWS_CALLBACK_USER, 1); + lws_sul_schedule(vhd->context, 0, &vhd->sul, + sul_connect_attempt, LWS_US_PER_SEC); break; default: @@ -243,37 +238,3 @@ 128, \ 0, NULL, 0 \ } - - -#if !defined (LWS_PLUGIN_STATIC) - -/* boilerplate needed if we are built as a dynamic plugin */ - -static const struct lws_protocols protocols[] = { - LWS_PLUGIN_PROTOCOL_MINIMAL -}; - -int -init_protocol_minimal(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } - - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} - -int -destroy_protocol_minimal(struct lws_context *context) -{ - return 0; -} -#endif diff -Nru libwebsockets-4.0.20/minimal-examples/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,50 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. + +MACRO(SUBDIRLIST result curdir) + FILE(GLOB children RELATIVE ${curdir} ${curdir}/*) + SET(dirlist "") + + FOREACH(child ${children}) + IF (IS_DIRECTORY ${curdir}/${child}) + LIST(APPEND dirlist ${child}) + ENDIF() + ENDFOREACH() + + SET(${result} ${dirlist}) +ENDMACRO() + +include_directories(${LWS_LIB_BUILD_INC_PATHS}) +link_libraries(${LIB_LIST_AT_END}) + +SUBDIRLIST(SUBDIRS "${PROJECT_SOURCE_DIR}/minimal-examples") +FOREACH(subdir ${SUBDIRS}) + + SUBDIRLIST(SUBDIRS2 "${PROJECT_SOURCE_DIR}/minimal-examples/${subdir}") + FOREACH(subdir2 ${SUBDIRS2}) + if (EXISTS "${PROJECT_SOURCE_DIR}/minimal-examples/${subdir}/${subdir2}/CMakeLists.txt") + message("Processing ${PROJECT_SOURCE_DIR}/minimal-examples/${subdir}/${subdir2}") + add_subdirectory("${PROJECT_SOURCE_DIR}/minimal-examples/${subdir}/${subdir2}") + endif() + ENDFOREACH() +ENDFOREACH() diff -Nru libwebsockets-4.0.20/minimal-examples/crypto/minimal-crypto-jwe/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/crypto/minimal-crypto-jwe/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/crypto/minimal-crypto-jwe/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/crypto/minimal-crypto-jwe/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,78 +1,23 @@ -project(lws-crypto-jwe) +project(lws-crypto-jwe C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-crypto-jwe) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_JOSE 1 requirements) if (requirements) - add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/crypto/minimal-crypto-jwe/main.c libwebsockets-4.1.6/minimal-examples/crypto/minimal-crypto-jwe/main.c --- libwebsockets-4.0.20/minimal-examples/crypto/minimal-crypto-jwe/main.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/crypto/minimal-crypto-jwe/main.c 2020-12-01 17:40:26.000000000 +0000 @@ -156,7 +156,7 @@ /* account for padding as well */ - temp_len -= lws_gencrypto_padded_length(LWS_AES_CBC_BLOCKLEN, n); + temp_len -= (int)lws_gencrypto_padded_length(LWS_AES_CBC_BLOCKLEN, n); /* grab the key */ @@ -219,7 +219,11 @@ if (lws_cmdline_option(argc, argv, "-c")) format_c(compact); else - if (write(1, compact, strlen(compact)) < 0) { + if (write(1, compact, +#if defined(WIN32) + (unsigned int) +#endif + strlen(compact)) < 0) { lwsl_err("Write stdout failed\n"); goto bail1; } diff -Nru libwebsockets-4.0.20/minimal-examples/crypto/minimal-crypto-jwk/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/crypto/minimal-crypto-jwk/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/crypto/minimal-crypto-jwk/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/crypto/minimal-crypto-jwk/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,78 +1,23 @@ -project(lws-crypto-jwk) +project(lws-crypto-jwk C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-crypto-jwk) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_JOSE 1 requirements) if (requirements) - add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/crypto/minimal-crypto-jwk/main.c libwebsockets-4.1.6/minimal-examples/crypto/minimal-crypto-jwk/main.c --- libwebsockets-4.0.20/minimal-examples/crypto/minimal-crypto-jwk/main.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/crypto/minimal-crypto-jwk/main.c 2020-12-01 17:40:26.000000000 +0000 @@ -123,16 +123,16 @@ } if ((p = lws_cmdline_option(argc, argv, "--kid"))) - lws_jwk_strdup_meta(&jwk, JWK_META_KID, p, strlen(p)); + lws_jwk_strdup_meta(&jwk, JWK_META_KID, p, (int)strlen(p)); if ((p = lws_cmdline_option(argc, argv, "--use"))) - lws_jwk_strdup_meta(&jwk, JWK_META_USE, p, strlen(p)); + lws_jwk_strdup_meta(&jwk, JWK_META_USE, p, (int)strlen(p)); if ((p = lws_cmdline_option(argc, argv, "--alg"))) - lws_jwk_strdup_meta(&jwk, JWK_META_ALG, p, strlen(p)); + lws_jwk_strdup_meta(&jwk, JWK_META_ALG, p, (int)strlen(p)); if ((p = lws_cmdline_option(argc, argv, "--key-ops"))) - lws_jwk_strdup_meta(&jwk, JWK_META_KEY_OPS, p, strlen(p)); + lws_jwk_strdup_meta(&jwk, JWK_META_KEY_OPS, p, (int)strlen(p)); if ((p = lws_cmdline_option(argc, argv, "--public")) && kty != LWS_GENCRYPTO_KTY_OCT) { @@ -156,7 +156,11 @@ if (lws_cmdline_option(argc, argv, "-c")) format_c(fd, key); else { - if (write(fd, key, strlen(key)) < 0) { + if (write(fd, key, +#if defined(WIN32) + (unsigned int) +#endif + strlen(key)) < 0) { lwsl_err("Write public failed\n"); return 1; } @@ -177,7 +181,11 @@ if (format_c(1, key) < 0) return 1; } else - if (write(1, key, strlen(key)) < 0) { + if (write(1, key, +#if defined(WIN32) + (unsigned int) +#endif + strlen(key)) < 0) { lwsl_err("Write stdout failed\n"); return 1; } diff -Nru libwebsockets-4.0.20/minimal-examples/crypto/minimal-crypto-jws/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/crypto/minimal-crypto-jws/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/crypto/minimal-crypto-jws/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/crypto/minimal-crypto-jws/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,67 +1,13 @@ -project(lws-crypto-jws) +project(lws-crypto-jws C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-crypto-jws) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_JOSE 1 requirements) @@ -70,9 +16,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/crypto/minimal-crypto-jws/main.c libwebsockets-4.1.6/minimal-examples/crypto/minimal-crypto-jws/main.c --- libwebsockets-4.0.20/minimal-examples/crypto/minimal-crypto-jws/main.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/crypto/minimal-crypto-jws/main.c 2020-12-01 17:40:26.000000000 +0000 @@ -152,7 +152,11 @@ /* dump the compact JWS representation on stdout */ - if (write(1, compact, strlen(compact)) < 0) { + if (write(1, compact, +#if defined(WIN32) + (unsigned int) +#endif + strlen(compact)) < 0) { lwsl_err("Write stdout failed\n"); goto bail1; } diff -Nru libwebsockets-4.0.20/minimal-examples/crypto/minimal-crypto-x509/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/crypto/minimal-crypto-x509/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/crypto/minimal-crypto-x509/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/crypto/minimal-crypto-x509/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,67 +1,13 @@ -project(lws-crypto-x509) +project(lws-crypto-x509 C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-crypto-x509) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_JOSE 1 requirements) @@ -70,9 +16,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/crypto/minimal-crypto-x509/main.c libwebsockets-4.1.6/minimal-examples/crypto/minimal-crypto-x509/main.c --- libwebsockets-4.0.20/minimal-examples/crypto/minimal-crypto-x509/main.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/crypto/minimal-crypto-x509/main.c 2020-12-01 17:40:26.000000000 +0000 @@ -126,7 +126,7 @@ } if ((p = lws_cmdline_option(argc, argv, "--alg"))) - lws_jwk_strdup_meta(&jwk, JWK_META_ALG, p, strlen(p)); + lws_jwk_strdup_meta(&jwk, JWK_META_ALG, p, (int)strlen(p)); lwsl_info("JWK version of trusted cert:\n"); lws_jwk_dump(&jwk); @@ -143,7 +143,7 @@ lwsl_info("JWK version of cert:\n"); if ((p = lws_cmdline_option(argc, argv, "--alg"))) - lws_jwk_strdup_meta(&jwk, JWK_META_ALG, p, strlen(p)); + lws_jwk_strdup_meta(&jwk, JWK_META_ALG, p, (int)strlen(p)); lws_jwk_dump(&jwk); /* only print public if he doesn't provide private */ @@ -172,7 +172,7 @@ } if ((p = lws_cmdline_option(argc, argv, "--alg"))) - lws_jwk_strdup_meta(&jwk, JWK_META_ALG, p, strlen(p)); + lws_jwk_strdup_meta(&jwk, JWK_META_ALG, p, (int)strlen(p)); lwsl_info("JWK version of cert + privkey:\n"); lws_jwk_dump(&jwk); diff -Nru libwebsockets-4.0.20/minimal-examples/dbus-client/minimal-dbus-client/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/dbus-client/minimal-dbus-client/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/dbus-client/minimal-dbus-client/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/dbus-client/minimal-dbus-client/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,121 +1,34 @@ -project(lws-minimal-dbus-client) +project(lws-minimal-dbus-client C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) include(CheckLibraryExists) +include(LwsCheckRequirements) set(SAMP lws-minimal-dbus-client) set(SRCS minimal-dbus-client.c) -if (NOT LWS_WITH_MINIMAL_EXAMPLES) - CHECK_LIBRARY_EXISTS(dbus-1 dbus_connection_set_watch_functions "" LWS_HAVE_LIBDBUS) - if (NOT LWS_HAVE_LIBDBUS) - message(FATAL_ERROR "Install dbus-devel, or libdbus-1-dev etc") - endif() - - if (NOT LWS_DBUS_LIB) - set(LWS_DBUS_LIB "dbus-1") - endif() - - if (NOT LWS_DBUS_INCLUDE1) - # look in fedora and debian / ubuntu place - if (EXISTS "/usr/include/dbus-1.0") - set(LWS_DBUS_INCLUDE1 "/usr/include/dbus-1.0") - else() - message(FATAL_ERROR "Set LWS_DBUS_INCLUDE1 to /usr/include/dbus-1.0 or wherever the main dbus includes are") - endif() - endif() - - if (NOT LWS_DBUS_INCLUDE2) - # look in fedora... debian / ubuntu has the ARCH in the path... - if (EXISTS "/usr/lib64/dbus-1.0/include") - set(LWS_DBUS_INCLUDE2 "/usr/lib64/dbus-1.0/include") - else() - message(FATAL_ERROR "Set LWS_DBUS_INCLUDE2 to /usr/lib/ARCH-linux-gnu/dbus-1.0/include or wherever dbus-arch-deps.h is on your system") - endif() - endif() - - set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES};${LWS_DBUS_INCLUDE1};${LWS_DBUS_INCLUDE2}) - - if (NOT LWS_DBUS_INCLUDE1 OR NOT LWS_DBUS_INCLUDE2) - message(FATAL_ERROR "To build with libdbus, LWS_DBUS_INCLUDE1/2 must be given. See lib/roles/dbus/README.md") - endif() - -endif() - -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_DBUS 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) -if (requirements) +if (NOT MSVC AND NOT WIN32 AND requirements) add_executable(${SAMP} ${SRCS}) - + + if (NOT LWS_PLAT_FREERTOS) + find_package(PkgConfig QUIET) + pkg_check_modules(PC_DBUS1 dbus-1 QUIET) + list(APPEND LWS_DBUS_INCLUDE1 ${PC_DBUS1_INCLUDE_DIRS}) + list(APPEND LWS_DBUS_LIB "${PC_DBUS1_LIBRARIES};dl") + endif() + include_directories("${LWS_DBUS_INCLUDE1}") - include_directories("${LWS_DBUS_INCLUDE2}") - list(APPEND LIB_LIST dbus-1) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared ${LWS_DBUS_LIB}) else() - target_link_libraries(${SAMP} websockets ${LWS_DBUS_LIB}) + target_link_libraries(${SAMP} websockets ${LWS_DBUS_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,121 +1,31 @@ -project(lws-minimal-dbus-ws-proxy-testclient) +project(lws-minimal-dbus-ws-proxy-testclient C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) include(CheckLibraryExists) - -set(SAMP lws-minimal-dbus-ws-proxy-testclient) -set(SRCS minimal-dbus-ws-proxy-testclient.c) - -if (NOT LWS_WITH_MINIMAL_EXAMPLES) - CHECK_LIBRARY_EXISTS(dbus-1 dbus_connection_set_watch_functions "" LWS_HAVE_LIBDBUS) - if (NOT LWS_HAVE_LIBDBUS) - message(FATAL_ERROR "Install dbus-devel, or libdbus-1-dev etc") - endif() - - if (NOT LWS_DBUS_LIB) - set(LWS_DBUS_LIB "dbus-1") - endif() - - if (NOT LWS_DBUS_INCLUDE1) - # look in fedora and debian / ubuntu place - if (EXISTS "/usr/include/dbus-1.0") - set(LWS_DBUS_INCLUDE1 "/usr/include/dbus-1.0") - else() - message(FATAL_ERROR "Set LWS_DBUS_INCLUDE1 to /usr/include/dbus-1.0 or wherever the main dbus includes are") - endif() - endif() - - if (NOT LWS_DBUS_INCLUDE2) - # look in fedora... debian / ubuntu has the ARCH in the path... - if (EXISTS "/usr/lib64/dbus-1.0/include") - set(LWS_DBUS_INCLUDE2 "/usr/lib64/dbus-1.0/include") - else() - message(FATAL_ERROR "Set LWS_DBUS_INCLUDE2 to /usr/lib/ARCH-linux-gnu/dbus-1.0/include or wherever dbus-arch-deps.h is on your system") - endif() - endif() - - set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES};${LWS_DBUS_INCLUDE1};${LWS_DBUS_INCLUDE2}) - - if (NOT LWS_DBUS_INCLUDE1 OR NOT LWS_DBUS_INCLUDE2) - message(FATAL_ERROR "To build with libdbus, LWS_DBUS_INCLUDE1/2 must be given. See lib/roles/dbus/README.md") - endif() - -endif() - -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - +include(LwsCheckRequirements) set(requirements 1) require_lws_config(LWS_ROLE_DBUS 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) -if (requirements) - add_executable(${SAMP} ${SRCS}) - - include_directories("${LWS_DBUS_INCLUDE1}") - include_directories("${LWS_DBUS_INCLUDE2}") - list(APPEND LIB_LIST dbus-1) +if (NOT MSVC AND NOT WIN32 AND requirements) + add_executable(${PROJECT_NAME} minimal-dbus-ws-proxy-testclient.c) + + if (NOT LWS_PLAT_FREERTOS) + find_package(PkgConfig QUIET) + pkg_check_modules(PC_DBUS1 dbus-1 QUIET) + list(APPEND LWS_DBUS_INCLUDE1 ${PC_DBUS1_INCLUDE_DIRS}) + list(APPEND LWS_DBUS_LIB "${PC_DBUS1_LIBRARIES};dl") + endif() + include_directories("${LWS_DBUS_INCLUDE1}") + message("project ${PROJECT_NAME}") if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) - add_dependencies(${SAMP} websockets_shared ${LWS_DBUS_LIB}) + target_link_libraries(${PROJECT_NAME} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) + add_dependencies(${PROJECT_NAME} websockets_shared ${LWS_DBUS_LIB}) else() - target_link_libraries(${SAMP} websockets ${LWS_DBUS_LIB}) + target_link_libraries(${PROJECT_NAME} websockets ${LWS_DBUS_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/minimal-dbus-ws-proxy-testclient.c libwebsockets-4.1.6/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/minimal-dbus-ws-proxy-testclient.c --- libwebsockets-4.0.20/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/minimal-dbus-ws-proxy-testclient.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/minimal-dbus-ws-proxy-testclient.c 2020-12-01 17:40:26.000000000 +0000 @@ -43,6 +43,8 @@ struct lws_dbus_ctx_wsproxy_client { struct lws_dbus_ctx ctx; + lws_sorted_usec_list_t sul; + enum lws_dbus_client_state state; }; @@ -309,83 +311,56 @@ return ret; } -/* - * Stub lws protocol, just so we can get synchronous timers conveniently. - * - * Set up a 1Hz timer and if our connection state is suitable, use that - * to write mirror protocol drawing packets to the proxied ws connection - */ - -static int -callback_just_timer(struct lws *wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len) +static void +sul_timer(struct lws_sorted_usec_list *sul) { char payload[64]; const char *ws_pkt = payload; DBusMessage *msg; - switch (reason) { - case LWS_CALLBACK_PROTOCOL_INIT: - case LWS_CALLBACK_USER: - lwsl_info("%s: LWS_CALLBACK_USER\n", __func__); - - if (!dbus_ctx || dbus_ctx->state != LDCS_CONN_ONWARD) - goto again; - - if (autoexit_budget > 0) { - if (!--autoexit_budget) { - lwsl_notice("reached autoexit budget\n"); - interrupted = 1; - break; - } - } + if (!dbus_ctx || dbus_ctx->state != LDCS_CONN_ONWARD) + goto again; - msg = dbus_message_new_method_call(THIS_BUSNAME, THIS_OBJECT, - THIS_INTERFACE, "Send"); - if (!msg) - break; - - lws_snprintf(payload, sizeof(payload), "d #%06X %d %d %d %d;", - rand() & 0xffffff, rand() % 480, rand() % 300, - rand() % 480, rand() % 300); - - if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &ws_pkt, - DBUS_TYPE_INVALID)) { - dbus_message_unref(msg); - break; + if (autoexit_budget > 0) { + if (!--autoexit_budget) { + lwsl_notice("reached autoexit budget\n"); + interrupted = 1; + return; } + } - if (!dbus_connection_send_with_reply(dbus_ctx->ctx.conn, msg, - &dbus_ctx->ctx.pc, - DBUS_TIMEOUT_USE_DEFAULT)) { - lwsl_err("%s: unable to send\n", __func__); - dbus_message_unref(msg); - break; - } + msg = dbus_message_new_method_call(THIS_BUSNAME, THIS_OBJECT, + THIS_INTERFACE, "Send"); + if (!msg) + goto again; - dbus_message_unref(msg); - dbus_pending_call_set_notify(dbus_ctx->ctx.pc, - pending_call_notify, - &dbus_ctx->ctx, NULL); - count_tx++; + lws_snprintf(payload, sizeof(payload), "d #%06X %d %d %d %d;", + rand() & 0xffffff, rand() % 480, rand() % 300, + rand() % 480, rand() % 300); -again: - lws_timed_callback_vh_protocol(lws_get_vhost(wsi), - lws_get_protocol(wsi), - LWS_CALLBACK_USER, 2); - break; - default: - break; + if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &ws_pkt, + DBUS_TYPE_INVALID)) { + dbus_message_unref(msg); + goto again; } - return 0; -} + if (!dbus_connection_send_with_reply(dbus_ctx->ctx.conn, msg, + &dbus_ctx->ctx.pc, + DBUS_TIMEOUT_USE_DEFAULT)) { + lwsl_err("%s: unable to send\n", __func__); + dbus_message_unref(msg); + goto again; + } -static struct lws_protocols protocols[] = { - { "_just_timer", callback_just_timer, 0, 10, 0, NULL, 0 }, - { } -}; + dbus_message_unref(msg); + dbus_pending_call_set_notify(dbus_ctx->ctx.pc, + pending_call_notify, + &dbus_ctx->ctx, NULL); + count_tx++; +again: + lws_sul_schedule(context, 0, &dbus_ctx->sul, sul_timer, 2 * LWS_US_PER_SEC); +} int main(int argc, const char **argv) { @@ -413,7 +388,6 @@ memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS; - info.protocols = protocols; context = lws_create_context(&info); if (!context) { lwsl_err("lws init failed\n"); @@ -431,6 +405,9 @@ if (!dbus_ctx) goto bail1; + lws_sul_schedule(context, 0, &dbus_ctx->sul, sul_timer, LWS_US_PER_SEC); + + if (remote_method_call(dbus_ctx)) goto bail2; diff -Nru libwebsockets-4.0.20/minimal-examples/dbus-server/minimal-dbus-server/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/dbus-server/minimal-dbus-server/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/dbus-server/minimal-dbus-server/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/dbus-server/minimal-dbus-server/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,121 +1,34 @@ -project(lws-minimal-dbus-server) +project(lws-minimal-dbus-server C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) include(CheckLibraryExists) +include(LwsCheckRequirements) set(SAMP lws-minimal-dbus-server) set(SRCS main.c) -if (NOT LWS_WITH_MINIMAL_EXAMPLES) - CHECK_LIBRARY_EXISTS(dbus-1 dbus_connection_set_watch_functions "" LWS_HAVE_LIBDBUS) - if (NOT LWS_HAVE_LIBDBUS) - message(FATAL_ERROR "Install dbus-devel, or libdbus-1-dev etc") - endif() - - if (NOT LWS_DBUS_LIB) - set(LWS_DBUS_LIB "dbus-1") - endif() - - if (NOT LWS_DBUS_INCLUDE1) - # look in fedora and debian / ubuntu place - if (EXISTS "/usr/include/dbus-1.0") - set(LWS_DBUS_INCLUDE1 "/usr/include/dbus-1.0") - else() - message(FATAL_ERROR "Set LWS_DBUS_INCLUDE1 to /usr/include/dbus-1.0 or wherever the main dbus includes are") - endif() - endif() - - if (NOT LWS_DBUS_INCLUDE2) - # look in fedora... debian / ubuntu has the ARCH in the path... - if (EXISTS "/usr/lib64/dbus-1.0/include") - set(LWS_DBUS_INCLUDE2 "/usr/lib64/dbus-1.0/include") - else() - message(FATAL_ERROR "Set LWS_DBUS_INCLUDE2 to /usr/lib/ARCH-linux-gnu/dbus-1.0/include or wherever dbus-arch-deps.h is on your system") - endif() - endif() - - set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES};${LWS_DBUS_INCLUDE1};${LWS_DBUS_INCLUDE2}) - - if (NOT LWS_DBUS_INCLUDE1 OR NOT LWS_DBUS_INCLUDE2) - message(FATAL_ERROR "To build with libdbus, LWS_DBUS_INCLUDE1/2 must be given. See lib/roles/dbus/README.md") - endif() - -endif() - -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_DBUS 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) -if (requirements) +if (NOT MSVC AND NOT WIN32 AND requirements) add_executable(${SAMP} ${SRCS}) - + + if (NOT LWS_PLAT_FREERTOS) + find_package(PkgConfig QUIET) + pkg_check_modules(PC_DBUS1 dbus-1 QUIET) + list(APPEND LWS_DBUS_INCLUDE1 ${PC_DBUS1_INCLUDE_DIRS}) + list(APPEND LWS_DBUS_LIB "${PC_DBUS1_LIBRARIES};dl") + endif() + include_directories("${LWS_DBUS_INCLUDE1}") - include_directories("${LWS_DBUS_INCLUDE2}") - list(APPEND LIB_LIST dbus-1) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared ${LWS_DBUS_LIB}) else() - target_link_libraries(${SAMP} websockets ${LWS_DBUS_LIB}) + target_link_libraries(${SAMP} websockets ${LWS_DBUS_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/dbus-server/minimal-dbus-ws-proxy/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/dbus-server/minimal-dbus-ws-proxy/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/dbus-server/minimal-dbus-ws-proxy/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/dbus-server/minimal-dbus-ws-proxy/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,123 +1,36 @@ -project(lws-minimal-dbus-ws-proxy) +project(lws-minimal-dbus-ws-proxy C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) include(CheckLibraryExists) +include(LwsCheckRequirements) set(SAMP lws-minimal-dbus-ws-proxy) set(SRCS main.c) -if (NOT LWS_WITH_MINIMAL_EXAMPLES) - CHECK_LIBRARY_EXISTS(dbus-1 dbus_connection_set_watch_functions "" LWS_HAVE_LIBDBUS) - if (NOT LWS_HAVE_LIBDBUS) - message(FATAL_ERROR "Install dbus-devel, or libdbus-1-dev etc") - endif() - - if (NOT LWS_DBUS_LIB) - set(LWS_DBUS_LIB "dbus-1") - endif() - - if (NOT LWS_DBUS_INCLUDE1) - # look in fedora and debian / ubuntu place - if (EXISTS "/usr/include/dbus-1.0") - set(LWS_DBUS_INCLUDE1 "/usr/include/dbus-1.0") - else() - message(FATAL_ERROR "Set LWS_DBUS_INCLUDE1 to /usr/include/dbus-1.0 or wherever the main dbus includes are") - endif() - endif() - - if (NOT LWS_DBUS_INCLUDE2) - # look in fedora... debian / ubuntu has the ARCH in the path... - if (EXISTS "/usr/lib64/dbus-1.0/include") - set(LWS_DBUS_INCLUDE2 "/usr/lib64/dbus-1.0/include") - else() - message(FATAL_ERROR "Set LWS_DBUS_INCLUDE2 to /usr/lib/ARCH-linux-gnu/dbus-1.0/include or wherever dbus-arch-deps.h is on your system") - endif() - endif() - - set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES};${LWS_DBUS_INCLUDE1};${LWS_DBUS_INCLUDE2}) - - if (NOT LWS_DBUS_INCLUDE1 OR NOT LWS_DBUS_INCLUDE2) - message(FATAL_ERROR "To build with libdbus, LWS_DBUS_INCLUDE1/2 must be given. See lib/roles/dbus/README.md") - endif() - -endif() - -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_DBUS 1 requirements) require_lws_config(LWS_ROLE_WS 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) -if (requirements) +if (NOT MSVC AND NOT WIN32 AND requirements) add_executable(${SAMP} ${SRCS}) + if (NOT LWS_PLAT_FREERTOS) + find_package(PkgConfig QUIET) + pkg_check_modules(PC_DBUS1 dbus-1 QUIET) + list(APPEND LWS_DBUS_INCLUDE1 ${PC_DBUS1_INCLUDE_DIRS}) + list(APPEND LWS_DBUS_LIB "${PC_DBUS1_LIBRARIES};dl") + endif() + include_directories("${LWS_DBUS_INCLUDE1}") - include_directories("${LWS_DBUS_INCLUDE2}") - list(APPEND LIB_LIST dbus-1) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared ${LWS_DBUS_LIB}) else() - target_link_libraries(${SAMP} websockets ${LWS_DBUS_LIB}) + target_link_libraries(${SAMP} websockets ${LWS_DBUS_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/dbus-server/minimal-dbus-ws-proxy/main.c libwebsockets-4.1.6/minimal-examples/dbus-server/minimal-dbus-ws-proxy/main.c --- libwebsockets-4.0.20/minimal-examples/dbus-server/minimal-dbus-ws-proxy/main.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/dbus-server/minimal-dbus-ws-proxy/main.c 2020-12-01 17:40:26.000000000 +0000 @@ -79,7 +79,6 @@ info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT | LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; info.port = CONTEXT_PORT_NO_LISTEN; - info.ws_ping_pong_interval = 30; info.protocols = protocols; info.pvo = &pvo; diff -Nru libwebsockets-4.0.20/minimal-examples/dbus-server/minimal-dbus-ws-proxy/protocol_lws_minimal_dbus_ws_proxy.c libwebsockets-4.1.6/minimal-examples/dbus-server/minimal-dbus-ws-proxy/protocol_lws_minimal_dbus_ws_proxy.c --- libwebsockets-4.0.20/minimal-examples/dbus-server/minimal-dbus-ws-proxy/protocol_lws_minimal_dbus_ws_proxy.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/dbus-server/minimal-dbus-ws-proxy/protocol_lws_minimal_dbus_ws_proxy.c 2020-12-01 17:40:26.000000000 +0000 @@ -793,36 +793,3 @@ 1024, \ 0, NULL, 0 \ } - -#if !defined (LWS_PLUGIN_STATIC) - -/* boilerplate needed if we are built as a dynamic plugin */ - -static const struct lws_protocols protocols[] = { - LWS_PLUGIN_PROTOCOL_MINIMAL_DBUS_WSPROXY -}; - -int -init_protocol_minimal_dbus_wsproxy(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } - - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} - -int -destroy_protocol_minimal_dbus_wsproxy(struct lws_context *context) -{ - return 0; -} -#endif diff -Nru libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-heltec-wb32/banded-img.h libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-heltec-wb32/banded-img.h --- libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-heltec-wb32/banded-img.h 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-heltec-wb32/banded-img.h 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,64 @@ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xE0, 0x40, 0x20, 0x20, 0x20, 0x20, 0x00, 0x40, 0xE0, 0x00, 0x80, 0xE0, 0x20, 0x20, +0x20, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0xE0, 0x00, 0x00, 0xE0, 0xE0, 0x00, 0x00, 0x80, 0x40, 0x20, +0x20, 0x20, 0x60, 0x80, 0x00, 0xE0, 0x40, 0x20, 0x20, 0x60, 0xC0, 0x00, 0x80, 0x40, 0x20, 0x20, +0x20, 0x60, 0x80, 0x00, 0xC0, 0x60, 0x20, 0x20, 0x20, 0xC0, 0x00, 0x80, 0xC0, 0x20, 0x20, 0x20, +0x40, 0xC0, 0x00, 0xE0, 0x00, 0x80, 0x80, 0x60, 0x00, 0x80, 0xC0, 0x20, 0x20, 0x20, 0x60, 0x80, +0x00, 0x00, 0x40, 0x60, 0x20, 0x00, 0xC0, 0x40, 0x20, 0x20, 0x20, 0xC0, 0x40, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7F, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x6F, 0x00, 0x34, 0x2F, 0x08, 0x08, +0x08, 0x0D, 0x07, 0x00, 0x0F, 0x00, 0x01, 0x0E, 0x0E, 0x01, 0x00, 0x0F, 0x08, 0x02, 0x0F, 0x09, +0x09, 0x19, 0x0F, 0x02, 0x00, 0x7F, 0x19, 0x08, 0x18, 0x08, 0x07, 0x01, 0x00, 0x0E, 0x09, 0x0B, +0x09, 0x0D, 0x04, 0x00, 0x07, 0x08, 0x08, 0x08, 0x08, 0x0F, 0x00, 0x03, 0x0E, 0x08, 0x18, 0x08, +0x0C, 0x04, 0x00, 0x7F, 0x02, 0x07, 0x08, 0x08, 0x00, 0x05, 0x0F, 0x0A, 0x11, 0x09, 0x0D, 0x06, +0x00, 0x08, 0x3F, 0x19, 0x08, 0x00, 0x06, 0x0A, 0x09, 0x09, 0x09, 0x0D, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xE0, 0xC0, 0x80, 0x00, +0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0xC0, +0xE0, 0xE0, 0xF0, 0xF0, 0xE0, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0xE0, +0xF0, 0xF0, 0xE0, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x80, 0xC0, 0xC0, 0xC1, 0x87, 0x8F, 0x0F, 0x0F, 0x0F, 0x07, 0x07, 0x00, 0x00, +0x00, 0x80, 0x80, 0xC0, 0x83, 0x87, 0x0F, 0x0F, 0x0F, 0x0F, 0x07, 0x83, 0x80, 0x80, 0x80, 0x83, +0x07, 0x0F, 0x1F, 0x0F, 0x0F, 0x0F, 0x83, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x03, 0x07, 0x0F, +0x0F, 0x0F, 0x0F, 0x8F, 0x87, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x10, 0x00, 0xBC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xF8, 0x00, 0x28, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, +0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, +0x3F, 0x7F, 0x7F, 0x7F, 0x7F, 0x3F, 0x3F, 0x00, 0x00, 0x1F, 0x3F, 0x7F, 0x7F, 0xFF, 0x7F, 0x7F, +0x3F, 0x0E, 0x00, 0x05, 0x3F, 0x7F, 0x7F, 0xFF, 0x7F, 0x7F, 0x7F, 0x1F, 0x00, 0x00, 0x00, 0x00, +0x00, 0x0E, 0x3F, 0x7F, 0xFF, 0xFF, 0x7F, 0x7F, 0x3F, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x3B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xF8, 0xF8, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0x20, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, diff -Nru libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-heltec-wb32/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-heltec-wb32/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-heltec-wb32/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-heltec-wb32/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,35 @@ +cmake_minimum_required(VERSION 3.5) + +if (ESP_PLATFORM) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) + project(lws-minimal-esp32 C) + enable_testing() + + target_link_libraries(lws-minimal-esp32.elf websockets) + + option(LWS_WITH_DRIVERS "With generic drivers for gpio, i2c, display etc" ON) + set(LWS_WITH_DRIVERS ON) + option(LWS_WITH_SECURE_STREAMS "With secure streams" ON) + set(LWS_WITH_SECURE_STREAMS ON) + option(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY "static ssp" OFF) + set(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY OFF) + option(LWS_WITH_LWSAC "With lwsac" ON) + set(LWS_WITH_LWSAC ON) + option(LWS_WITH_STRUCT_JSON "With lws_struct JSON" ON) + set(LWS_WITH_STRUCT_JSON ON) + option(LWS_WITH_SYS_NTPCLIENT "With ntpclient" ON) + set(LWS_WITH_SYS_NTPCLIENT ON) + + add_subdirectory(libwebsockets) + + add_test(NAME flashing COMMAND idf.py flash) + set_tests_properties(flashing PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + TIMEOUT 120) + + add_test(NAME boot COMMAND /usr/local/bin/sai-expect) + set_tests_properties(boot PROPERTIES + DEPENDS flashing + TIMEOUT 60) + +endif() diff -Nru libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-heltec-wb32/main/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-heltec-wb32/main/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-heltec-wb32/main/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-heltec-wb32/main/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,6 @@ +idf_component_register(SRCS + lws-minimal-esp32.c devices.c + INCLUDE_DIRS "../libwebsockets/include;${IDF_PATH}/components/spi_flash/include;${IDF_PATH}/components/nvs_flash/include;${IDF_PATH}/components/mdns/include") + +target_link_libraries(${COMPONENT_LIB} websockets) +include_directories(../build/libwebsockets) diff -Nru libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-heltec-wb32/main/devices.c libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-heltec-wb32/main/devices.c --- libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-heltec-wb32/main/devices.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-heltec-wb32/main/devices.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,207 @@ +/* + * devices for ESP32 Heltec WB32 + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + */ + +#define LWIP_PROVIDE_ERRNO 1 +#define _ESP_PLATFORM_ERRNO_H_ + +#include +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#include + +#include + +struct lws_led_state *lls; +lws_display_state_t lds; +struct lws_button_state *bcs; +lws_netdev_instance_wifi_t *wnd; + +/* + * Hook up bitbang i2c, display driver and display + */ + +static void +esp32_i2c_delay(void) +{ + ets_delay_us(1); +} + +static const lws_bb_i2c_t li2c = { + .bb_ops = lws_bb_i2c_ops, + .scl = GPIO_NUM_15, + .sda = GPIO_NUM_4, + .gpio = &lws_gpio_plat, + .delay = esp32_i2c_delay +}; + +/* + * Button controller + */ + +static const lws_button_map_t bcm[] = { + { + .gpio = GPIO_NUM_0, + .smd_interaction_name = "user" + }, +}; + +static const lws_button_controller_t bc = { + .smd_bc_name = "bc", + .gpio_ops = &lws_gpio_plat, + .button_map = &bcm[0], + .active_state_bitmap = 0, + .count_buttons = LWS_ARRAY_SIZE(bcm), +}; + +/* + * pwm controller + */ + +static const lws_pwm_map_t pwm_map[] = { + { .gpio = GPIO_NUM_25, .index = 0, .active_level = 1 } +}; + +static const lws_pwm_ops_t pwm_ops = { + lws_pwm_plat_ops, + .pwm_map = &pwm_map[0], + .count_pwm_map = LWS_ARRAY_SIZE(pwm_map) +}; + +static const lws_display_ssd1306_t disp = { + .disp = { + lws_display_ssd1306_ops, + .w = 128, + .h = 64 + }, + .i2c = (lws_i2c_ops_t *)&li2c, + .gpio = &lws_gpio_plat, + .reset_gpio = GPIO_NUM_16, + .i2c7_address = SSD1306_I2C7_ADS1 +}; + +/* + * led controller + */ + +static const lws_led_gpio_map_t lgm[] = { + { + .name = "alert", + .gpio = GPIO_NUM_25, + .pwm_ops = &pwm_ops, /* managed by pwm */ + .active_level = 1, + }, +}; + +static const lws_led_gpio_controller_t lgc = { + .led_ops = lws_led_gpio_ops, + .gpio_ops = &lws_gpio_plat, + .led_map = &lgm[0], + .count_leds = LWS_ARRAY_SIZE(lgm) +}; + +/* + * Settings stored in platform nv + */ + +static const lws_settings_ops_t sett = { + lws_settings_ops_plat +}; + +/* + * Wifi + */ + +static const lws_netdev_ops_t wifi_ops = { + lws_netdev_wifi_plat_ops +}; + +int +init_plat_devices(struct lws_context *ctx) +{ + lws_settings_instance_t *si; + lws_netdevs_t *netdevs = lws_netdevs_from_ctx(ctx); + + si = lws_settings_init(&sett, (void *)"nvs"); + if (!si) { + lwsl_err("%s: failed to create settings instance\n", __func__); + return 1; + } + netdevs->si = si; + +#if 0 + /* + * This is a temp hack to bootstrap the settings to contain the test + * AP ssid and passphrase for one time, so the settings can be stored + * while there's no UI atm + */ + { + lws_wifi_creds_t creds; + + memset(&creds, 0, sizeof(creds)); + + lws_strncpy(creds.ssid, "xxx", sizeof(creds.ssid)); + lws_strncpy(creds.passphrase, "yyy", sizeof(creds.passphrase)); + lws_dll2_add_tail(&creds.list, &netdevs->owner_creds); + + if (lws_netdev_credentials_settings_set(netdevs)) { + lwsl_err("%s: failed to write bootstrap creds\n", + __func__); + return 1; + } + } +#endif + + /* create the wifi network device and configure it */ + + wnd = (lws_netdev_instance_wifi_t *) + wifi_ops.create(ctx, &wifi_ops, "wl0", NULL); + if (!wnd) { + lwsl_err("%s: failed to create wifi object\n", __func__); + return 1; + } + + wnd->flags |= LNDIW_MODE_STA; + + if (wifi_ops.configure(&wnd->inst, NULL)) { + lwsl_err("%s: failed to configure wifi object\n", __func__); + return 1; + } + + wifi_ops.up(&wnd->inst); + + lls = lgc.led_ops.create(&lgc.led_ops); + if (!lls) { + lwsl_err("%s: could not create led\n", __func__); + return 1; + } + + /* pwm init must go after the led controller init */ + + pwm_ops.init(&pwm_ops); + + bcs = lws_button_controller_create(ctx, &bc); + if (!bcs) { + lwsl_err("%s: could not create buttons\n", __func__); + return 1; + } + + /* + * Show the lws logo on the display + */ + + lws_display_state_init(&lds, ctx, 10000, 20000, lls, &disp.disp); + + lws_button_enable(bcs, 0, lws_button_get_bit(bcs, "user")); + lws_led_transition(lls, "alert", &lws_pwmseq_static_off, + &lws_pwmseq_static_on); + + return 0; +} diff -Nru libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-heltec-wb32/main/lws-minimal-esp32.c libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-heltec-wb32/main/lws-minimal-esp32.c --- libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-heltec-wb32/main/lws-minimal-esp32.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-heltec-wb32/main/lws-minimal-esp32.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,213 @@ +/* + * lws-minimal-esp32 + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * Based on espressif Public Domain sample + */ + +#define LWIP_PROVIDE_ERRNO 1 +#define _ESP_PLATFORM_ERRNO_H_ + +#include +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#include + +#include + +struct lws_context *context; +extern struct lws_led_state *lls; +extern lws_display_state_t lds; +extern lws_netdev_instance_wifi_t *wnd; + +extern int init_plat_devices(struct lws_context *); + +static const uint8_t img[] = { +#include "../banded-img.h" +}; + +#include "policy.h" + +static uint8_t flip; + +typedef struct myss { + struct lws_ss_handle *ss; + void *opaque_data; + /* ... application specific state ... */ + + size_t amount; + +} myss_t; + +static int +myss_rx(void *userobj, const uint8_t *buf, size_t len, int flags) +{ + myss_t *m = (myss_t *)userobj; + + lwsl_user("%s: len %d, flags: %d\n", __func__, (int)len, flags); +// lwsl_hexdump_info(buf, len); + m->amount += len; + + if (flags & LWSSS_FLAG_EOM) { + + /* + * If we received the whole message, for our example it means + * we are done. + */ + + lwsl_notice("%s: received %u bytes\n", __func__, + (unsigned int)m->amount); + + /* + * In CI, we use sai-expect to look for this + * string for success + */ + + lwsl_notice("Completed: PASS\n"); + } + + return 0; +} + +static int +myss_state(void *userobj, void *sh, lws_ss_constate_t state, + lws_ss_tx_ordinal_t ack) +{ + myss_t *m = (myss_t *)userobj; + + lwsl_user("%s: %s, ord 0x%x\n", __func__, lws_ss_state_name(state), + (unsigned int)ack); + + switch (state) { + case LWSSSCS_CREATING: + lws_ss_client_connect(m->ss); + break; + default: + break; + } + + return 0; +} + +static const lws_ss_info_t ssi = { + .handle_offset = offsetof(myss_t, ss), + .opaque_user_data_offset = offsetof(myss_t, opaque_data), + .rx = myss_rx, + .state = myss_state, + .user_alloc = sizeof(myss_t), + .streamtype = "test_stream", +}; + +static const lws_led_sequence_def_t *seqs[] = { + &lws_pwmseq_static_on, + &lws_pwmseq_static_off, + &lws_pwmseq_sine_endless_slow, + &lws_pwmseq_sine_endless_fast, +}; + +static int +smd_cb(void *opaque, lws_smd_class_t _class, lws_usec_t timestamp, void *buf, + size_t len) +{ + + if (!lws_json_simple_strcmp(buf, len, "\"src\":", "bc/user") && + !lws_json_simple_strcmp(buf, len, "\"event\":", "click")) { + lws_led_transition(lls, "alert", seqs[flip & 3], + &lws_pwmseq_linear_wipe); + flip++; + } + + lwsl_hexdump_notice(buf, len); + + if ((_class & LWSSMDCL_SYSTEM_STATE) && + !lws_json_simple_strcmp(buf, len, "\"state\":", "OPERATIONAL")) { + + /* create the secure stream */ + + lwsl_notice("%s: creating test secure stream\n", __func__); + + if (lws_ss_create(context, 0, &ssi, NULL, NULL, NULL, NULL)) { + lwsl_err("%s: failed to create secure stream\n", + __func__); + return -1; + } + } + + if (_class & LWSSMDCL_INTERACTION) + /* + * Any kind of user interaction brings the display back up and + * resets the dimming / blanking timers + */ + lws_display_state_active(&lds); + + return 0; +} + +void +app_main(void) +{ + struct lws_context_creation_info *info; + + lws_set_log_level(1024 | 15, NULL); + + lws_netdev_plat_init(); + lws_netdev_plat_wifi_init(); + + info = malloc(sizeof(*info)); + if (!info) + goto spin; + + memset(info, 0, sizeof(*info)); + + lwsl_notice("LWS test for Heltec WB32 ESP32 board\n"); + + info->pss_policies_json = ss_policy; + info->options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | + LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + info->port = CONTEXT_PORT_NO_LISTEN; + info->early_smd_cb = smd_cb; + info->early_smd_class_filter = LWSSMDCL_INTERACTION | + LWSSMDCL_SYSTEM_STATE | + LWSSMDCL_NETWORK; + + context = lws_create_context(info); + if (!context) { + lwsl_err("lws init failed\n"); + return; + } + + /* + * We don't need this after context creation... things it pointed to + * still need to exist though since the context copied the pointers. + */ + + free(info); + + /* devices and init are in devices.c */ + + if (init_plat_devices(context)) + goto spin; + + /* put the logo on the OLED display */ + + lds.disp->blit(lds.disp, img, 0, 0, 128, 64); + lws_display_state_active(&lds); + + /* the lws event loop */ + + do { + taskYIELD(); + } while (lws_service(context, 0) >= 0); + + +spin: + vTaskDelay(10); + taskYIELD(); + goto spin; +} diff -Nru libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-heltec-wb32/main/policy.h libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-heltec-wb32/main/policy.h --- libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-heltec-wb32/main/policy.h 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-heltec-wb32/main/policy.h 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,134 @@ + +static const char * const ss_policy = + "{" + "\"release\":" "\"01234567\"," + "\"product\":" "\"myproduct\"," + "\"schema-version\":" "1," + + "\"retry\": [" /* named backoff / retry strategies */ + "{\"default\": {" + "\"backoff\": [" "1000," + "2000," + "3000," + "5000," + "10000" + "]," + "\"conceal\":" "25," + "\"jitterpc\":" "20," + "\"svalidping\":" "30," + "\"svalidhup\":" "35" + "}}" + "]," + "\"certs\": [" /* named individual certificates in BASE64 DER */ + /* + * Let's Encrypt certs for warmcat.com / libwebsockets.org + * + * We fetch the real policy from there using SS and switch to + * using that. + */ + "{\"isrg_root_x1\": \"" /* ISRG ROOT X1 */ + "MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw" + "TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh" + "cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4" + "WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu" + "ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY" + "MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc" + "h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+" + "0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U" + "A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW" + "T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH" + "B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC" + "B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv" + "KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn" + "OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn" + "jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw" + "qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI" + "rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV" + "HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq" + "hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL" + "ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ" + "3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK" + "NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5" + "ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur" + "TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC" + "jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc" + "oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq" + "4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA" + "mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d" + "emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=" + "\"}," + "{\"LEX3_isrg_root_x1\": \"" /* LE X3 signed by ISRG X1 root */ + "MIIFjTCCA3WgAwIBAgIRANOxciY0IzLc9AUoUSrsnGowDQYJKoZIhvcNAQELBQAw" + "TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh" + "cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTYxMDA2MTU0MzU1" + "WhcNMjExMDA2MTU0MzU1WjBKMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg" + "RW5jcnlwdDEjMCEGA1UEAxMaTGV0J3MgRW5jcnlwdCBBdXRob3JpdHkgWDMwggEi" + "MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCc0wzwWuUuR7dyXTeDs2hjMOrX" + "NSYZJeG9vjXxcJIvt7hLQQWrqZ41CFjssSrEaIcLo+N15Obzp2JxunmBYB/XkZqf" + "89B4Z3HIaQ6Vkc/+5pnpYDxIzH7KTXcSJJ1HG1rrueweNwAcnKx7pwXqzkrrvUHl" + "Npi5y/1tPJZo3yMqQpAMhnRnyH+lmrhSYRQTP2XpgofL2/oOVvaGifOFP5eGr7Dc" + "Gu9rDZUWfcQroGWymQQ2dYBrrErzG5BJeC+ilk8qICUpBMZ0wNAxzY8xOJUWuqgz" + "uEPxsR/DMH+ieTETPS02+OP88jNquTkxxa/EjQ0dZBYzqvqEKbbUC8DYfcOTAgMB" + "AAGjggFnMIIBYzAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADBU" + "BgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEBATAwMC4GCCsGAQUFBwIB" + "FiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQub3JnMB0GA1UdDgQWBBSo" + "SmpjBH3duubRObemRWXv86jsoTAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8vY3Js" + "LnJvb3QteDEubGV0c2VuY3J5cHQub3JnMHIGCCsGAQUFBwEBBGYwZDAwBggrBgEF" + "BQcwAYYkaHR0cDovL29jc3Aucm9vdC14MS5sZXRzZW5jcnlwdC5vcmcvMDAGCCsG" + "AQUFBzAChiRodHRwOi8vY2VydC5yb290LXgxLmxldHNlbmNyeXB0Lm9yZy8wHwYD" + "VR0jBBgwFoAUebRZ5nu25eQBc4AIiMgaWPbpm24wDQYJKoZIhvcNAQELBQADggIB" + "ABnPdSA0LTqmRf/Q1eaM2jLonG4bQdEnqOJQ8nCqxOeTRrToEKtwT++36gTSlBGx" + "A/5dut82jJQ2jxN8RI8L9QFXrWi4xXnA2EqA10yjHiR6H9cj6MFiOnb5In1eWsRM" + "UM2v3e9tNsCAgBukPHAg1lQh07rvFKm/Bz9BCjaxorALINUfZ9DD64j2igLIxle2" + "DPxW8dI/F2loHMjXZjqG8RkqZUdoxtID5+90FgsGIfkMpqgRS05f4zPbCEHqCXl1" + "eO5HyELTgcVlLXXQDgAWnRzut1hFJeczY1tjQQno6f6s+nMydLN26WuU4s3UYvOu" + "OsUxRlJu7TSRHqDC3lSE5XggVkzdaPkuKGQbGpny+01/47hfXXNB7HntWNZ6N2Vw" + "p7G6OfY+YQrZwIaQmhrIqJZuigsrbe3W+gdn5ykE9+Ky0VgVUsfxo52mwFYs1JKY" + "2PGDuWx8M6DlS6qQkvHaRUo0FMd8TsSlbF0/v965qGFKhSDeQoMpYnwcmQilRh/0" + "ayLThlHLN81gSkJjVrPI0Y8xCVPB4twb1PFUd2fPM3sA1tJ83sZ5v8vgFv2yofKR" + "PB0t6JzUA81mSqM3kxl5e+IZwhYAyO0OTg3/fs8HqGTNKd9BqoUwSRBzp06JMg5b" + "rUCGwbCUDI0mxadJ3Bz4WxR6fyNpBK2yAinWEsikxqEt" + "\"}" + "]," + "\"trust_stores\": [" /* named cert chains */ + "{" + "\"name\": \"le_via_isrg\"," + "\"stack\": [" + "\"isrg_root_x1\"," + "\"LEX3_isrg_root_x1\"" + "]" + "}" + "]," + "\"s\": [" + + "{\"test_stream\": {" + "\"endpoint\":" "\"warmcat.com\"," + "\"port\":" "443," + "\"protocol\":" "\"h2\"," + "\"http_method\":" "\"GET\"," + "\"http_url\":" "\"index.html\"," + "\"tls\":" "true," + "\"opportunistic\":" "true," + "\"retry\":" "\"default\"," + "\"tls_trust_store\":" "\"le_via_isrg\"" + "}},{" + /* + * "captive_portal_detect" describes + * what to do in order to check if the path to + * the Internet is being interrupted by a + * captive portal. + */ + "\"captive_portal_detect\": {" + "\"endpoint\":" "\"connectivitycheck.android.com\"," + "\"http_url\":" "\"generate_204\"," + "\"port\":" "80," + "\"protocol\":" "\"h1\"," + "\"http_method\":" "\"GET\"," + "\"opportunistic\":" "true," + "\"http_expect\":" "204," + "\"http_fail_redirect\": true" + "}}" + "]}" +; + + diff -Nru libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-heltec-wb32/partitions.csv libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-heltec-wb32/partitions.csv --- libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-heltec-wb32/partitions.csv 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-heltec-wb32/partitions.csv 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,5 @@ +# ESP-IDF Partition Table +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x6000, +phy_init, data, phy, 0xf000, 0x1000, +factory, app, factory, 0x10000, 2M, Binary files /tmp/tmpmec97nsd/m0nuW2sR0N/libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-heltec-wb32/scan/output.bmp and /tmp/tmpmec97nsd/q8JCI83EXS/libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-heltec-wb32/scan/output.bmp differ diff -Nru libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-heltec-wb32/scan/pic.h libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-heltec-wb32/scan/pic.h --- libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-heltec-wb32/scan/pic.h 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-heltec-wb32/scan/pic.h 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,64 @@ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x2f, 0x27, 0xc6, 0x61, 0xe5, 0xc3, 0xc7, 0x87, 0x11, 0x1e, 0x18, 0xe0, 0x00, 0x00, +0x00, 0x00, 0x30, 0x64, 0x46, 0x62, 0x26, 0x64, 0x4c, 0x48, 0xd1, 0x22, 0x33, 0x18, 0x00, 0x00, +0x00, 0x00, 0x20, 0x2c, 0x46, 0x64, 0x14, 0x28, 0x28, 0x58, 0x56, 0x61, 0x02, 0x10, 0x00, 0x00, +0x00, 0x00, 0x20, 0x24, 0x6a, 0x53, 0xe6, 0x33, 0xc8, 0x50, 0x14, 0x6e, 0x30, 0xf0, 0x00, 0x00, +0x00, 0x00, 0x20, 0x24, 0x29, 0x96, 0x34, 0x25, 0x08, 0x58, 0x1c, 0x31, 0x23, 0x00, 0x00, 0x00, +0x00, 0x00, 0x30, 0x6c, 0x69, 0x92, 0x24, 0x24, 0x68, 0x48, 0xd4, 0x63, 0x22, 0x10, 0x00, 0x00, +0x00, 0x00, 0x20, 0x27, 0xc9, 0x9b, 0xe7, 0xc7, 0xc7, 0xcf, 0x93, 0x36, 0x79, 0xf0, 0x00, 0x00, +0x00, 0x00, 0x20, 0x08, 0x00, 0x00, 0x46, 0x80, 0x00, 0x02, 0x10, 0x08, 0x30, 0x00, 0x00, 0x00, +0x00, 0x00, 0x20, 0x2c, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00, 0x00, +0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03, 0xc0, 0x30, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x07, 0xe0, 0xfc, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x0f, 0xf1, 0xfe, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x03, 0xfe, 0x0f, 0xf1, 0xfe, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x03, 0xfc, 0x0f, 0xf1, 0xfe, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x0f, 0xf1, 0xfe, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x07, 0xe0, 0xfc, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03, 0xc0, 0x7c, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x7c, 0x1f, 0x03, 0xc0, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x3f, 0x80, 0xfe, 0x3f, 0x8f, 0xe0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc1, 0xfe, 0x3f, 0x8f, 0xe0, 0x3f, 0x80, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc1, 0xfe, 0x7f, 0x8f, 0xf0, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc1, 0xfe, 0x7f, 0xdf, 0xf0, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc1, 0xff, 0x7f, 0xcf, 0xf0, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc1, 0xfe, 0x7f, 0xdf, 0xf0, 0x7f, 0x80, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc1, 0xfe, 0x3f, 0xcf, 0xf0, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc1, 0xfe, 0x7f, 0xcf, 0xf0, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc1, 0xfe, 0x7f, 0x9f, 0xf0, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc1, 0xfe, 0x7f, 0xcf, 0xf0, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc1, 0xfe, 0x7f, 0xdf, 0xf0, 0x7f, 0x80, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc1, 0xfe, 0x7f, 0xcf, 0xf0, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc1, 0xfe, 0x7f, 0x8f, 0xf0, 0x3f, 0x80, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc0, 0xfe, 0x3f, 0x8f, 0xe0, 0x3f, 0x80, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x3f, 0xc0, 0x78, 0x1f, 0x07, 0xe0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc0, 0x00, 0x04, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, diff -Nru libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-heltec-wb32/scan/pic.h.1 libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-heltec-wb32/scan/pic.h.1 --- libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-heltec-wb32/scan/pic.h.1 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-heltec-wb32/scan/pic.h.1 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,64 @@ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x2f, 0x27, 0xc6, 0x61, 0xe5, 0xc3, 0xc7, 0x87, 0x11, 0x1e, 0x18, 0xe0, 0x00, 0x00 +0x00, 0x00, 0x30, 0x64, 0x46, 0x62, 0x26, 0x64, 0x4c, 0x48, 0xd1, 0x22, 0x33, 0x18, 0x00, 0x00 +0x00, 0x00, 0x20, 0x2c, 0x46, 0x64, 0x14, 0x28, 0x28, 0x58, 0x56, 0x61, 0x02, 0x10, 0x00, 0x00 +0x00, 0x00, 0x20, 0x24, 0x6a, 0x53, 0xe6, 0x33, 0xc8, 0x50, 0x14, 0x6e, 0x30, 0xf0, 0x00, 0x00 +0x00, 0x00, 0x20, 0x24, 0x29, 0x96, 0x34, 0x25, 0x08, 0x58, 0x1c, 0x31, 0x23, 0x00, 0x00, 0x00 +0x00, 0x00, 0x30, 0x6c, 0x69, 0x92, 0x24, 0x24, 0x68, 0x48, 0xd4, 0x63, 0x22, 0x10, 0x00, 0x00 +0x00, 0x00, 0x20, 0x27, 0xc9, 0x9b, 0xe7, 0xc7, 0xc7, 0xcf, 0x93, 0x36, 0x79, 0xf0, 0x00, 0x00 +0x00, 0x00, 0x20, 0x08, 0x00, 0x00, 0x46, 0x80, 0x00, 0x02, 0x10, 0x08, 0x30, 0x00, 0x00, 0x00 +0x00, 0x00, 0x20, 0x2c, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00, 0x00 +0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03, 0xc0, 0x30, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x07, 0xe0, 0xfc, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x0f, 0xf1, 0xfe, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x03, 0xfe, 0x0f, 0xf1, 0xfe, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x03, 0xfc, 0x0f, 0xf1, 0xfe, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x0f, 0xf1, 0xfe, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x07, 0xe0, 0xfc, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03, 0xc0, 0x7c, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x7c, 0x1f, 0x03, 0xc0, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x3f, 0x80, 0xfe, 0x3f, 0x8f, 0xe0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc1, 0xfe, 0x3f, 0x8f, 0xe0, 0x3f, 0x80, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc1, 0xfe, 0x7f, 0x8f, 0xf0, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc1, 0xfe, 0x7f, 0xdf, 0xf0, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc1, 0xff, 0x7f, 0xcf, 0xf0, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc1, 0xfe, 0x7f, 0xdf, 0xf0, 0x7f, 0x80, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc1, 0xfe, 0x3f, 0xcf, 0xf0, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc1, 0xfe, 0x7f, 0xcf, 0xf0, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc1, 0xfe, 0x7f, 0x9f, 0xf0, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc1, 0xfe, 0x7f, 0xcf, 0xf0, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc1, 0xfe, 0x7f, 0xdf, 0xf0, 0x7f, 0x80, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc1, 0xfe, 0x7f, 0xcf, 0xf0, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc1, 0xfe, 0x7f, 0x8f, 0xf0, 0x3f, 0x80, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc0, 0xfe, 0x3f, 0x8f, 0xe0, 0x3f, 0x80, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x3f, 0xc0, 0x78, 0x1f, 0x07, 0xe0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc0, 0x00, 0x04, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 Binary files /tmp/tmpmec97nsd/m0nuW2sR0N/libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-heltec-wb32/scan/scan and /tmp/tmpmec97nsd/q8JCI83EXS/libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-heltec-wb32/scan/scan differ diff -Nru libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-heltec-wb32/scan/scan.c libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-heltec-wb32/scan/scan.c --- libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-heltec-wb32/scan/scan.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-heltec-wb32/scan/scan.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,70 @@ +#include +#include +#include +#include +/* + * The bitmap mapping for the framebuffer is from top left to right, a strip of 8 vertical + * bits from each byte, so there is a block of 128 x 8 px on a stride of 128 bytes. + * + * The 8 bits from the first byte in the fb are the leftmost vertical strip of 8, then the + * next byte is the 8 pixels one to the right, until the 127th byte if the vertical strip + * of 8 on the rhs. + * + * +----------------------------------+ + * |0 | + * |1 | + * |2 | + * |3 | + * |4 | + * |5 | + * |6 | + * |7 | + * + * In this way the fb is more like (8 x vertical (128 x 8)) + * + */ + + +static const uint8_t scan[] = { + +#include "pic.h" +}; + +/* + * input byte 0 is like ABCDEFGH, one bit per horizontal pixel for one line + * on an hstride of 16 bytes + * + * output byte 0 = b0 = byte 0 b0, b1 = byte16 b0, b2 = byte24 b0 etc + * + * px(0,0) --> byte0 b0 + * px(0,1) --> byte0 b1 + */ + +int +main(void) +{ + const uint8_t *p = scan; + uint8_t r[1024]; + int x, y, t = 0; + + memset(&r, 0, sizeof(r)); + + while (t < 1024) { + + for (x = 0; x < 128; x++) { + for (y = 0; y < 8; y++) { + if (p[t + (16 * y) + (x / 8)] & (1 << (7 - (x & 7)))) + r[t + x] |= 1 << y; + } + } + + t += 128; + } + + for (x = 0; x < 1024; x++) { + printf("0x%02X, ", r[x]); + if ((x & 0xf) == 0xf) + printf("\n"); + } +} + diff -Nru libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-heltec-wb32/scan/scan.sh libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-heltec-wb32/scan/scan.sh --- libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-heltec-wb32/scan/scan.sh 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-heltec-wb32/scan/scan.sh 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,8 @@ +#!/bin/bash + +convert -size 128x64 /tmp/128x64.png -monochrome output.bmp +dd if=output.bmp bs=1 skip=130 | hexdump -Cv | tr -s ' ' | cut -d' ' -f2-17 | grep ' ' | sed "s/^/0x/g" | sed "s/\ /,\ 0x/g" > pic.h.1 +cat pic.h.1 | sed "s/\$/,/g" > pic.h + +gcc -o scan scan.c && ./scan > ../banded-img.h + diff -Nru libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-heltec-wb32/sdkconfig libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-heltec-wb32/sdkconfig --- libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-heltec-wb32/sdkconfig 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-heltec-wb32/sdkconfig 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,1152 @@ +# +# Automatically generated file. DO NOT EDIT. +# Espressif IoT Development Framework (ESP-IDF) Project Configuration +# +CONFIG_IDF_CMAKE=y +CONFIG_IDF_TARGET="esp32" +CONFIG_IDF_TARGET_ESP32=y +CONFIG_IDF_FIRMWARE_CHIP_ID=0x0000 + +# +# SDK tool configuration +# +CONFIG_SDK_TOOLPREFIX="xtensa-esp32-elf-" +# CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS is not set +# end of SDK tool configuration + +# +# Build type +# +CONFIG_APP_BUILD_TYPE_APP_2NDBOOT=y +# CONFIG_APP_BUILD_TYPE_ELF_RAM is not set +CONFIG_APP_BUILD_GENERATE_BINARIES=y +CONFIG_APP_BUILD_BOOTLOADER=y +CONFIG_APP_BUILD_USE_FLASH_SECTIONS=y +# end of Build type + +# +# Application manager +# +CONFIG_APP_COMPILE_TIME_DATE=y +# CONFIG_APP_EXCLUDE_PROJECT_VER_VAR is not set +# CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR is not set +# CONFIG_APP_PROJECT_VER_FROM_CONFIG is not set +CONFIG_APP_RETRIEVE_LEN_ELF_SHA=16 +# end of Application manager + +# +# Bootloader config +# +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_NONE is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_ERROR is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_WARN is not set +CONFIG_BOOTLOADER_LOG_LEVEL_INFO=y +# CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set +CONFIG_BOOTLOADER_LOG_LEVEL=3 +# CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_8V is not set +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y +# CONFIG_BOOTLOADER_FACTORY_RESET is not set +# CONFIG_BOOTLOADER_APP_TEST is not set +CONFIG_BOOTLOADER_WDT_ENABLE=y +# CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE is not set +CONFIG_BOOTLOADER_WDT_TIME_MS=9000 +# CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP is not set +CONFIG_BOOTLOADER_RESERVE_RTC_SIZE=0 +# CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC is not set +# end of Bootloader config + +# +# Security features +# +# CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT is not set +# CONFIG_SECURE_BOOT is not set +# CONFIG_SECURE_FLASH_ENC_ENABLED is not set +# end of Security features + +# +# Serial flasher config +# +CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 +# CONFIG_ESPTOOLPY_FLASHMODE_QIO is not set +# CONFIG_ESPTOOLPY_FLASHMODE_QOUT is not set +CONFIG_ESPTOOLPY_FLASHMODE_DIO=y +# CONFIG_ESPTOOLPY_FLASHMODE_DOUT is not set +CONFIG_ESPTOOLPY_FLASHMODE="dio" +# CONFIG_ESPTOOLPY_FLASHFREQ_80M is not set +# CONFIG_ESPTOOLPY_FLASHFREQ_40M is not set +CONFIG_ESPTOOLPY_FLASHFREQ_26M=y +# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set +CONFIG_ESPTOOLPY_FLASHFREQ="26m" +# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE="4MB" +CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y +CONFIG_ESPTOOLPY_BEFORE_RESET=y +# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set +CONFIG_ESPTOOLPY_BEFORE="default_reset" +CONFIG_ESPTOOLPY_AFTER_RESET=y +# CONFIG_ESPTOOLPY_AFTER_NORESET is not set +CONFIG_ESPTOOLPY_AFTER="hard_reset" +# CONFIG_ESPTOOLPY_MONITOR_BAUD_9600B is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_57600B is not set +CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B=y +# CONFIG_ESPTOOLPY_MONITOR_BAUD_230400B is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_921600B is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_2MB is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER is not set +CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER_VAL=115200 +CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 +# end of Serial flasher config + +# +# Partition Table +# +# CONFIG_PARTITION_TABLE_SINGLE_APP is not set +# CONFIG_PARTITION_TABLE_TWO_OTA is not set +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv" +CONFIG_PARTITION_TABLE_OFFSET=0x8000 +CONFIG_PARTITION_TABLE_MD5=y +# end of Partition Table + +# +# Compiler options +# +CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y +# CONFIG_COMPILER_OPTIMIZATION_SIZE is not set +# CONFIG_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_COMPILER_OPTIMIZATION_NONE is not set +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set +# CONFIG_COMPILER_CXX_EXCEPTIONS is not set +# CONFIG_COMPILER_CXX_RTTI is not set +CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y +# CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_STRONG is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_ALL is not set +# CONFIG_COMPILER_WARN_WRITE_STRINGS is not set +# CONFIG_COMPILER_DISABLE_GCC8_WARNINGS is not set +# end of Compiler options + +# +# Component config +# + +# +# Application Level Tracing +# +# CONFIG_APPTRACE_DEST_TRAX is not set +CONFIG_APPTRACE_DEST_NONE=y +CONFIG_APPTRACE_LOCK_ENABLE=y +# end of Application Level Tracing + +# +# Bluetooth +# +# CONFIG_BT_ENABLED is not set +CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 +CONFIG_BTDM_CTRL_BLE_MAX_CONN_EFF=0 +CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN_EFF=0 +CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF=0 +CONFIG_BTDM_CTRL_PINNED_TO_CORE=0 +CONFIG_BTDM_BLE_SLEEP_CLOCK_ACCURACY_INDEX_EFF=1 +CONFIG_BT_RESERVE_DRAM=0 +# end of Bluetooth + +# +# CoAP Configuration +# +CONFIG_COAP_MBEDTLS_PSK=y +# CONFIG_COAP_MBEDTLS_PKI is not set +# CONFIG_COAP_MBEDTLS_DEBUG is not set +CONFIG_COAP_LOG_DEFAULT_LEVEL=0 +# end of CoAP Configuration + +# +# Driver configurations +# + +# +# ADC configuration +# +# CONFIG_ADC_FORCE_XPD_FSM is not set +CONFIG_ADC_DISABLE_DAC=y +# end of ADC configuration + +# +# SPI configuration +# +# CONFIG_SPI_MASTER_IN_IRAM is not set +CONFIG_SPI_MASTER_ISR_IN_IRAM=y +# CONFIG_SPI_SLAVE_IN_IRAM is not set +CONFIG_SPI_SLAVE_ISR_IN_IRAM=y +# end of SPI configuration + +# +# UART configuration +# +# CONFIG_UART_ISR_IN_IRAM is not set +# end of UART configuration + +# +# RTCIO configuration +# +# CONFIG_RTCIO_SUPPORT_RTC_GPIO_DESC is not set +# end of RTCIO configuration +# end of Driver configurations + +# +# eFuse Bit Manager +# +# CONFIG_EFUSE_CUSTOM_TABLE is not set +# CONFIG_EFUSE_VIRTUAL is not set +# CONFIG_EFUSE_CODE_SCHEME_COMPAT_NONE is not set +CONFIG_EFUSE_CODE_SCHEME_COMPAT_3_4=y +# CONFIG_EFUSE_CODE_SCHEME_COMPAT_REPEAT is not set +CONFIG_EFUSE_MAX_BLK_LEN=192 +# end of eFuse Bit Manager + +# +# ESP-TLS +# +CONFIG_ESP_TLS_USING_MBEDTLS=y +# CONFIG_ESP_TLS_USE_SECURE_ELEMENT is not set +# CONFIG_ESP_TLS_SERVER is not set +# CONFIG_ESP_TLS_PSK_VERIFICATION is not set +# end of ESP-TLS + +# +# ESP32-specific +# +CONFIG_ESP32_REV_MIN_0=y +# CONFIG_ESP32_REV_MIN_1 is not set +# CONFIG_ESP32_REV_MIN_2 is not set +# CONFIG_ESP32_REV_MIN_3 is not set +CONFIG_ESP32_REV_MIN=0 +CONFIG_ESP32_DPORT_WORKAROUND=y +# CONFIG_ESP32_DEFAULT_CPU_FREQ_80 is not set +CONFIG_ESP32_DEFAULT_CPU_FREQ_160=y +# CONFIG_ESP32_DEFAULT_CPU_FREQ_240 is not set +CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=160 +# CONFIG_ESP32_SPIRAM_SUPPORT is not set +# CONFIG_ESP32_TRAX is not set +CONFIG_ESP32_TRACEMEM_RESERVE_DRAM=0x0 +# CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_TWO is not set +CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR=y +CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES=4 +# CONFIG_ESP32_ULP_COPROC_ENABLED is not set +CONFIG_ESP32_ULP_COPROC_RESERVE_MEM=0 +CONFIG_ESP32_DEBUG_OCDAWARE=y +CONFIG_ESP32_BROWNOUT_DET=y +CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_0=y +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_1 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_7 is not set +CONFIG_ESP32_BROWNOUT_DET_LVL=0 +CONFIG_ESP32_REDUCE_PHY_TX_POWER=y +CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1=y +# CONFIG_ESP32_TIME_SYSCALL_USE_RTC is not set +# CONFIG_ESP32_TIME_SYSCALL_USE_FRC1 is not set +# CONFIG_ESP32_TIME_SYSCALL_USE_NONE is not set +CONFIG_ESP32_RTC_CLK_SRC_INT_RC=y +# CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS is not set +# CONFIG_ESP32_RTC_CLK_SRC_EXT_OSC is not set +# CONFIG_ESP32_RTC_CLK_SRC_INT_8MD256 is not set +CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024 +CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=2000 +# CONFIG_ESP32_XTAL_FREQ_40 is not set +CONFIG_ESP32_XTAL_FREQ_26=y +# CONFIG_ESP32_XTAL_FREQ_AUTO is not set +CONFIG_ESP32_XTAL_FREQ=26 +# CONFIG_ESP32_DISABLE_BASIC_ROM_CONSOLE is not set +# CONFIG_ESP32_NO_BLOBS is not set +# CONFIG_ESP32_COMPATIBLE_PRE_V2_1_BOOTLOADERS is not set +# CONFIG_ESP32_USE_FIXED_STATIC_RAM_SIZE is not set +CONFIG_ESP32_DPORT_DIS_INTERRUPT_LVL=5 +# end of ESP32-specific + +# +# Power Management +# +# CONFIG_PM_ENABLE is not set +# end of Power Management + +# +# ADC-Calibration +# +CONFIG_ADC_CAL_EFUSE_TP_ENABLE=y +CONFIG_ADC_CAL_EFUSE_VREF_ENABLE=y +CONFIG_ADC_CAL_LUT_ENABLE=y +# end of ADC-Calibration + +# +# Common ESP-related +# +CONFIG_ESP_ERR_TO_NAME_LOOKUP=y +CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=4304 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=6584 +CONFIG_ESP_IPC_TASK_STACK_SIZE=3024 +CONFIG_ESP_IPC_USES_CALLERS_PRIORITY=y +CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048 +CONFIG_ESP_CONSOLE_UART_DEFAULT=y +# CONFIG_ESP_CONSOLE_UART_CUSTOM is not set +# CONFIG_ESP_CONSOLE_UART_NONE is not set +CONFIG_ESP_CONSOLE_UART_NUM=0 +CONFIG_ESP_CONSOLE_UART_TX_GPIO=1 +CONFIG_ESP_CONSOLE_UART_RX_GPIO=3 +CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 +CONFIG_ESP_INT_WDT=y +CONFIG_ESP_INT_WDT_TIMEOUT_MS=300 +CONFIG_ESP_INT_WDT_CHECK_CPU1=y +CONFIG_ESP_TASK_WDT=y +# CONFIG_ESP_TASK_WDT_PANIC is not set +CONFIG_ESP_TASK_WDT_TIMEOUT_S=5 +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +# CONFIG_ESP_PANIC_HANDLER_IRAM is not set +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_BT=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH=y +# end of Common ESP-related + +# +# Ethernet +# +CONFIG_ETH_ENABLED=y +CONFIG_ETH_USE_ESP32_EMAC=y +CONFIG_ETH_PHY_INTERFACE_RMII=y +# CONFIG_ETH_PHY_INTERFACE_MII is not set +CONFIG_ETH_RMII_CLK_INPUT=y +# CONFIG_ETH_RMII_CLK_OUTPUT is not set +CONFIG_ETH_RMII_CLK_IN_GPIO=0 +CONFIG_ETH_DMA_BUFFER_SIZE=512 +CONFIG_ETH_DMA_RX_BUFFER_NUM=10 +CONFIG_ETH_DMA_TX_BUFFER_NUM=10 +CONFIG_ETH_USE_SPI_ETHERNET=y +# CONFIG_ETH_SPI_ETHERNET_DM9051 is not set +# CONFIG_ETH_USE_OPENETH is not set +# end of Ethernet + +# +# Event Loop Library +# +# CONFIG_ESP_EVENT_LOOP_PROFILING is not set +CONFIG_ESP_EVENT_POST_FROM_ISR=y +CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR=y +# end of Event Loop Library + +# +# GDB Stub +# +# end of GDB Stub + +# +# ESP HTTP client +# +CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y +# CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH is not set +# end of ESP HTTP client + +# +# HTTP Server +# +CONFIG_HTTPD_MAX_REQ_HDR_LEN=512 +CONFIG_HTTPD_MAX_URI_LEN=512 +CONFIG_HTTPD_ERR_RESP_NO_DELAY=y +CONFIG_HTTPD_PURGE_BUF_LEN=32 +# CONFIG_HTTPD_LOG_PURGE_DATA is not set +# CONFIG_HTTPD_WS_SUPPORT is not set +# end of HTTP Server + +# +# ESP HTTPS OTA +# +# CONFIG_OTA_ALLOW_HTTP is not set +# end of ESP HTTPS OTA + +# +# ESP HTTPS server +# +# CONFIG_ESP_HTTPS_SERVER_ENABLE is not set +# end of ESP HTTPS server + +# +# ESP NETIF Adapter +# +CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL=120 +CONFIG_ESP_NETIF_TCPIP_LWIP=y +# CONFIG_ESP_NETIF_LOOPBACK is not set +CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER=y +# end of ESP NETIF Adapter + +# +# ESP System Settings +# +# CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT is not set +CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT=y +# CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set +# CONFIG_ESP_SYSTEM_PANIC_GDBSTUB is not set +# end of ESP System Settings + +# +# High resolution timer (esp_timer) +# +# CONFIG_ESP_TIMER_PROFILING is not set +CONFIG_ESP_TIMER_TASK_STACK_SIZE=6584 +# CONFIG_ESP_TIMER_IMPL_FRC2 is not set +CONFIG_ESP_TIMER_IMPL_TG0_LAC=y +# end of High resolution timer (esp_timer) + +# +# Wi-Fi +# +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 +# CONFIG_ESP32_WIFI_STATIC_TX_BUFFER is not set +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y +CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32 +# CONFIG_ESP32_WIFI_CSI_ENABLED is not set +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=6 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=6 +CONFIG_ESP32_WIFI_NVS_ENABLED=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y +# CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 is not set +CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752 +CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32 +# CONFIG_ESP32_WIFI_DEBUG_LOG_ENABLE is not set +CONFIG_ESP32_WIFI_IRAM_OPT=y +CONFIG_ESP32_WIFI_RX_IRAM_OPT=y +CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE=y +# end of Wi-Fi + +# +# PHY +# +CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP32_PHY_MAX_TX_POWER=20 +# end of PHY + +# +# Core dump +# +# CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set +# CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set +CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y +# end of Core dump + +# +# FAT Filesystem support +# +# CONFIG_FATFS_CODEPAGE_DYNAMIC is not set +CONFIG_FATFS_CODEPAGE_437=y +# CONFIG_FATFS_CODEPAGE_720 is not set +# CONFIG_FATFS_CODEPAGE_737 is not set +# CONFIG_FATFS_CODEPAGE_771 is not set +# CONFIG_FATFS_CODEPAGE_775 is not set +# CONFIG_FATFS_CODEPAGE_850 is not set +# CONFIG_FATFS_CODEPAGE_852 is not set +# CONFIG_FATFS_CODEPAGE_855 is not set +# CONFIG_FATFS_CODEPAGE_857 is not set +# CONFIG_FATFS_CODEPAGE_860 is not set +# CONFIG_FATFS_CODEPAGE_861 is not set +# CONFIG_FATFS_CODEPAGE_862 is not set +# CONFIG_FATFS_CODEPAGE_863 is not set +# CONFIG_FATFS_CODEPAGE_864 is not set +# CONFIG_FATFS_CODEPAGE_865 is not set +# CONFIG_FATFS_CODEPAGE_866 is not set +# CONFIG_FATFS_CODEPAGE_869 is not set +# CONFIG_FATFS_CODEPAGE_932 is not set +# CONFIG_FATFS_CODEPAGE_936 is not set +# CONFIG_FATFS_CODEPAGE_949 is not set +# CONFIG_FATFS_CODEPAGE_950 is not set +CONFIG_FATFS_CODEPAGE=437 +CONFIG_FATFS_LFN_NONE=y +# CONFIG_FATFS_LFN_HEAP is not set +# CONFIG_FATFS_LFN_STACK is not set +CONFIG_FATFS_FS_LOCK=0 +CONFIG_FATFS_TIMEOUT_MS=10000 +CONFIG_FATFS_PER_FILE_CACHE=y +# end of FAT Filesystem support + +# +# Modbus configuration +# +CONFIG_FMB_COMM_MODE_RTU_EN=y +CONFIG_FMB_COMM_MODE_ASCII_EN=y +CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND=150 +CONFIG_FMB_MASTER_DELAY_MS_CONVERT=200 +CONFIG_FMB_QUEUE_LENGTH=20 +CONFIG_FMB_SERIAL_TASK_STACK_SIZE=2048 +CONFIG_FMB_SERIAL_BUF_SIZE=256 +CONFIG_FMB_SERIAL_ASCII_BITS_PER_SYMB=8 +CONFIG_FMB_SERIAL_ASCII_TIMEOUT_RESPOND_MS=1000 +CONFIG_FMB_SERIAL_TASK_PRIO=10 +# CONFIG_FMB_CONTROLLER_SLAVE_ID_SUPPORT is not set +CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT=20 +CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE=20 +CONFIG_FMB_CONTROLLER_STACK_SIZE=4096 +CONFIG_FMB_EVENT_QUEUE_TIMEOUT=20 +CONFIG_FMB_TIMER_PORT_ENABLED=y +CONFIG_FMB_TIMER_GROUP=0 +CONFIG_FMB_TIMER_INDEX=0 +# CONFIG_FMB_TIMER_ISR_IN_IRAM is not set +# end of Modbus configuration + +# +# FreeRTOS +# +# CONFIG_FREERTOS_UNICORE is not set +CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF +CONFIG_FREERTOS_CORETIMER_0=y +# CONFIG_FREERTOS_CORETIMER_1 is not set +CONFIG_FREERTOS_HZ=100 +CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y +# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set +CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y +CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 +CONFIG_FREERTOS_ASSERT_FAIL_ABORT=y +# CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE is not set +# CONFIG_FREERTOS_ASSERT_DISABLE is not set +CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536 +CONFIG_FREERTOS_ISR_STACKSIZE=1536 +# CONFIG_FREERTOS_LEGACY_HOOKS is not set +CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 +# CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION is not set +CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1 +CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=5048 +CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10 +CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 +# CONFIG_FREERTOS_USE_TRACE_FACILITY is not set +# CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS is not set +CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y +CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y +# CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set +CONFIG_FREERTOS_DEBUG_OCDAWARE=y +# CONFIG_FREERTOS_FPU_IN_ISR is not set +# end of FreeRTOS + +# +# Heap memory debugging +# +CONFIG_HEAP_POISONING_DISABLED=y +# CONFIG_HEAP_POISONING_LIGHT is not set +# CONFIG_HEAP_POISONING_COMPREHENSIVE is not set +CONFIG_HEAP_TRACING_OFF=y +# CONFIG_HEAP_TRACING_STANDALONE is not set +# CONFIG_HEAP_TRACING_TOHOST is not set +# CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS is not set +# end of Heap memory debugging + +# +# jsmn +# +# CONFIG_JSMN_PARENT_LINKS is not set +# CONFIG_JSMN_STRICT is not set +# end of jsmn + +# +# libsodium +# +# end of libsodium + +# +# Log output +# +# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set +# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set +# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set +CONFIG_LOG_DEFAULT_LEVEL_INFO=y +# CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set +# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set +CONFIG_LOG_DEFAULT_LEVEL=3 +CONFIG_LOG_COLORS=y +CONFIG_LOG_TIMESTAMP_SOURCE_RTOS=y +# CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM is not set +# end of Log output + +# +# LWIP +# +CONFIG_LWIP_LOCAL_HOSTNAME="espressif" +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +# CONFIG_LWIP_L2_TO_L3_COPY is not set +# CONFIG_LWIP_IRAM_OPTIMIZATION is not set +CONFIG_LWIP_TIMERS_ONDEMAND=y +CONFIG_LWIP_MAX_SOCKETS=10 +# CONFIG_LWIP_USE_ONLY_LWIP_SELECT is not set +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +# CONFIG_LWIP_SO_RCVBUF is not set +# CONFIG_LWIP_NETBUF_RECVINFO is not set +CONFIG_LWIP_IP_FRAG=y +# CONFIG_LWIP_IP_REASSEMBLY is not set +# CONFIG_LWIP_IP_FORWARD is not set +# CONFIG_LWIP_STATS is not set +# CONFIG_LWIP_ETHARP_TRUST_IP_MAC is not set +CONFIG_LWIP_ESP_GRATUITOUS_ARP=y +CONFIG_LWIP_GARP_TMR_INTERVAL=60 +CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32 +CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set + +# +# DHCP server +# +CONFIG_LWIP_DHCPS_LEASE_UNIT=60 +CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8 +# end of DHCP server + +# CONFIG_LWIP_AUTOIP is not set +# CONFIG_LWIP_IPV6_AUTOCONFIG is not set +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 + +# +# TCP +# +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_LWIP_TCP_MAXRTX=12 +CONFIG_LWIP_TCP_SYNMAXRTX=6 +CONFIG_LWIP_TCP_MSS=1440 +CONFIG_LWIP_TCP_TMR_INTERVAL=250 +CONFIG_LWIP_TCP_MSL=60000 +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5744 +CONFIG_LWIP_TCP_WND_DEFAULT=5744 +CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 +CONFIG_LWIP_TCP_QUEUE_OOSEQ=y +# CONFIG_LWIP_TCP_SACK_OUT is not set +# CONFIG_LWIP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set +CONFIG_LWIP_TCP_OVERSIZE_MSS=y +# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set +# end of TCP + +# +# UDP +# +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 +# end of UDP + +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0 is not set +# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU1 is not set +CONFIG_LWIP_TCPIP_TASK_AFFINITY=0x7FFFFFFF +# CONFIG_LWIP_PPP_SUPPORT is not set + +# +# ICMP +# +# CONFIG_LWIP_MULTICAST_PING is not set +# CONFIG_LWIP_BROADCAST_PING is not set +# end of ICMP + +# +# LWIP RAW API +# +CONFIG_LWIP_MAX_RAW_PCBS=16 +# end of LWIP RAW API + +# +# SNTP +# +CONFIG_LWIP_DHCP_MAX_NTP_SERVERS=1 +CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000 +# end of SNTP + +CONFIG_LWIP_ESP_LWIP_ASSERT=y +# end of LWIP + +# +# mbedTLS +# +CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y +# CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set +# CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC is not set +CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y +CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=16384 +CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 +# CONFIG_MBEDTLS_DYNAMIC_BUFFER is not set +# CONFIG_MBEDTLS_DEBUG is not set + +# +# Certificate Bundle +# +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN is not set +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE is not set +# CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE is not set +# end of Certificate Bundle + +# CONFIG_MBEDTLS_ECP_RESTARTABLE is not set +# CONFIG_MBEDTLS_CMAC_C is not set +CONFIG_MBEDTLS_HARDWARE_AES=y +CONFIG_MBEDTLS_HARDWARE_MPI=y +CONFIG_MBEDTLS_HARDWARE_SHA=y +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN is not set +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY is not set +CONFIG_MBEDTLS_HAVE_TIME=y +# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set +CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y +CONFIG_MBEDTLS_SHA512_C=y +CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y +# CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set +# CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set +# CONFIG_MBEDTLS_TLS_DISABLED is not set +CONFIG_MBEDTLS_TLS_SERVER=y +CONFIG_MBEDTLS_TLS_CLIENT=y +CONFIG_MBEDTLS_TLS_ENABLED=y + +# +# TLS Key Exchange Methods +# +# CONFIG_MBEDTLS_PSK_MODES is not set +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y +# end of TLS Key Exchange Methods + +CONFIG_MBEDTLS_SSL_RENEGOTIATION=y +# CONFIG_MBEDTLS_SSL_PROTO_SSL3 is not set +CONFIG_MBEDTLS_SSL_PROTO_TLS1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +# CONFIG_MBEDTLS_SSL_PROTO_DTLS is not set +CONFIG_MBEDTLS_SSL_ALPN=y +CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS=y +CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS=y + +# +# Symmetric Ciphers +# +CONFIG_MBEDTLS_AES_C=y +# CONFIG_MBEDTLS_CAMELLIA_C is not set +# CONFIG_MBEDTLS_DES_C is not set +CONFIG_MBEDTLS_RC4_DISABLED=y +# CONFIG_MBEDTLS_RC4_ENABLED_NO_DEFAULT is not set +# CONFIG_MBEDTLS_RC4_ENABLED is not set +# CONFIG_MBEDTLS_BLOWFISH_C is not set +# CONFIG_MBEDTLS_XTEA_C is not set +CONFIG_MBEDTLS_CCM_C=y +CONFIG_MBEDTLS_GCM_C=y +# end of Symmetric Ciphers + +# CONFIG_MBEDTLS_RIPEMD160_C is not set + +# +# Certificates +# +CONFIG_MBEDTLS_PEM_PARSE_C=y +CONFIG_MBEDTLS_PEM_WRITE_C=y +CONFIG_MBEDTLS_X509_CRL_PARSE_C=y +CONFIG_MBEDTLS_X509_CSR_PARSE_C=y +# end of Certificates + +CONFIG_MBEDTLS_ECP_C=y +CONFIG_MBEDTLS_ECDH_C=y +CONFIG_MBEDTLS_ECDSA_C=y +# CONFIG_MBEDTLS_ECJPAKE_C is not set +CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y +CONFIG_MBEDTLS_ECP_NIST_OPTIM=y +# CONFIG_MBEDTLS_POLY1305_C is not set +# CONFIG_MBEDTLS_CHACHA20_C is not set +# CONFIG_MBEDTLS_HKDF_C is not set +# CONFIG_MBEDTLS_THREADING_C is not set +# CONFIG_MBEDTLS_SECURITY_RISKS is not set +# end of mbedTLS + +# +# mDNS +# +CONFIG_MDNS_MAX_SERVICES=10 +CONFIG_MDNS_TASK_PRIORITY=1 +CONFIG_MDNS_TASK_STACK_SIZE=4096 +# CONFIG_MDNS_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_MDNS_TASK_AFFINITY_CPU0=y +# CONFIG_MDNS_TASK_AFFINITY_CPU1 is not set +CONFIG_MDNS_TASK_AFFINITY=0x0 +CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS=2000 +CONFIG_MDNS_TIMER_PERIOD_MS=100 +# end of mDNS + +# +# ESP-MQTT Configurations +# +CONFIG_MQTT_PROTOCOL_311=y +CONFIG_MQTT_TRANSPORT_SSL=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y +# CONFIG_MQTT_USE_CUSTOM_CONFIG is not set +# CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED is not set +# CONFIG_MQTT_CUSTOM_OUTBOX is not set +# end of ESP-MQTT Configurations + +# +# Newlib +# +CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_LF is not set +CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y +# CONFIG_NEWLIB_NANO_FORMAT is not set +# end of Newlib + +# +# NVS +# +# end of NVS + +# +# OpenSSL +# +# CONFIG_OPENSSL_DEBUG is not set +# CONFIG_OPENSSL_ASSERT_DO_NOTHING is not set +CONFIG_OPENSSL_ASSERT_EXIT=y +# end of OpenSSL + +# +# PThreads +# +CONFIG_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_PTHREAD_STACK_MIN=768 +CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY=y +# CONFIG_PTHREAD_DEFAULT_CORE_0 is not set +# CONFIG_PTHREAD_DEFAULT_CORE_1 is not set +CONFIG_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_PTHREAD_TASK_NAME_DEFAULT="pthread" +# end of PThreads + +# +# SPI Flash driver +# +# CONFIG_SPI_FLASH_VERIFY_WRITE is not set +# CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set +CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y +CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS is not set +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set +# CONFIG_SPI_FLASH_USE_LEGACY_IMPL is not set +# CONFIG_SPI_FLASH_SHARE_SPI1_BUS is not set +# CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE is not set +CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y +CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS=20 +CONFIG_SPI_FLASH_ERASE_YIELD_TICKS=1 + +# +# Auto-detect flash chips +# +CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_GD_CHIP=y +# end of Auto-detect flash chips +# end of SPI Flash driver + +# +# SPIFFS Configuration +# +CONFIG_SPIFFS_MAX_PARTITIONS=3 + +# +# SPIFFS Cache Configuration +# +CONFIG_SPIFFS_CACHE=y +CONFIG_SPIFFS_CACHE_WR=y +# CONFIG_SPIFFS_CACHE_STATS is not set +# end of SPIFFS Cache Configuration + +CONFIG_SPIFFS_PAGE_CHECK=y +CONFIG_SPIFFS_GC_MAX_RUNS=10 +# CONFIG_SPIFFS_GC_STATS is not set +CONFIG_SPIFFS_PAGE_SIZE=256 +CONFIG_SPIFFS_OBJ_NAME_LEN=32 +# CONFIG_SPIFFS_FOLLOW_SYMLINKS is not set +CONFIG_SPIFFS_USE_MAGIC=y +CONFIG_SPIFFS_USE_MAGIC_LENGTH=y +CONFIG_SPIFFS_META_LENGTH=4 +CONFIG_SPIFFS_USE_MTIME=y + +# +# Debug Configuration +# +# CONFIG_SPIFFS_DBG is not set +# CONFIG_SPIFFS_API_DBG is not set +# CONFIG_SPIFFS_GC_DBG is not set +# CONFIG_SPIFFS_CACHE_DBG is not set +# CONFIG_SPIFFS_CHECK_DBG is not set +# CONFIG_SPIFFS_TEST_VISUALISATION is not set +# end of Debug Configuration +# end of SPIFFS Configuration + +# +# TinyUSB +# + +# +# Descriptor configuration +# +CONFIG_USB_DESC_CUSTOM_VID=0x1234 +CONFIG_USB_DESC_CUSTOM_PID=0x5678 +# end of Descriptor configuration +# end of TinyUSB + +# +# Unity unit testing library +# +CONFIG_UNITY_ENABLE_FLOAT=y +CONFIG_UNITY_ENABLE_DOUBLE=y +# CONFIG_UNITY_ENABLE_COLOR is not set +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y +# CONFIG_UNITY_ENABLE_FIXTURE is not set +# CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL is not set +# end of Unity unit testing library + +# +# Virtual file system +# +CONFIG_VFS_SUPPORT_IO=y +CONFIG_VFS_SUPPORT_DIR=y +CONFIG_VFS_SUPPORT_SELECT=y +CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_VFS_SUPPORT_TERMIOS=y + +# +# Host File System I/O (Semihosting) +# +CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +CONFIG_VFS_SEMIHOSTFS_HOST_PATH_MAX_LEN=128 +# end of Host File System I/O (Semihosting) +# end of Virtual file system + +# +# Wear Levelling +# +# CONFIG_WL_SECTOR_SIZE_512 is not set +CONFIG_WL_SECTOR_SIZE_4096=y +CONFIG_WL_SECTOR_SIZE=4096 +# end of Wear Levelling + +# +# Wi-Fi Provisioning Manager +# +CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16 +CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT=30 +# end of Wi-Fi Provisioning Manager + +# +# Supplicant +# +CONFIG_WPA_MBEDTLS_CRYPTO=y +# CONFIG_WPA_DEBUG_PRINT is not set +# CONFIG_WPA_TESTING_OPTIONS is not set +# CONFIG_WPA_TLS_V12 is not set +# CONFIG_WPA_WPS_WARS is not set +# end of Supplicant +# end of Component config + +# +# Compatibility options +# +# CONFIG_LEGACY_INCLUDE_COMMON_HEADERS is not set +# end of Compatibility options + +# Deprecated options for backward compatibility +CONFIG_TOOLPREFIX="xtensa-esp32-elf-" +# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set +CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y +# CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set +CONFIG_LOG_BOOTLOADER_LEVEL=3 +# CONFIG_APP_ROLLBACK_ENABLE is not set +# CONFIG_FLASH_ENCRYPTION_ENABLED is not set +# CONFIG_FLASHMODE_QIO is not set +# CONFIG_FLASHMODE_QOUT is not set +CONFIG_FLASHMODE_DIO=y +# CONFIG_FLASHMODE_DOUT is not set +# CONFIG_MONITOR_BAUD_9600B is not set +# CONFIG_MONITOR_BAUD_57600B is not set +CONFIG_MONITOR_BAUD_115200B=y +# CONFIG_MONITOR_BAUD_230400B is not set +# CONFIG_MONITOR_BAUD_921600B is not set +# CONFIG_MONITOR_BAUD_2MB is not set +# CONFIG_MONITOR_BAUD_OTHER is not set +CONFIG_MONITOR_BAUD_OTHER_VAL=115200 +CONFIG_MONITOR_BAUD=115200 +CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG=y +# CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE is not set +CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y +# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set +# CONFIG_CXX_EXCEPTIONS is not set +CONFIG_STACK_CHECK_NONE=y +# CONFIG_STACK_CHECK_NORM is not set +# CONFIG_STACK_CHECK_STRONG is not set +# CONFIG_STACK_CHECK_ALL is not set +# CONFIG_WARN_WRITE_STRINGS is not set +# CONFIG_DISABLE_GCC8_WARNINGS is not set +# CONFIG_ESP32_APPTRACE_DEST_TRAX is not set +CONFIG_ESP32_APPTRACE_DEST_NONE=y +CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y +CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN_EFF=0 +CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN_EFF=0 +CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN_EFF=0 +CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0 +CONFIG_ADC2_DISABLE_DAC=y +# CONFIG_SPIRAM_SUPPORT is not set +CONFIG_TRACEMEM_RESERVE_DRAM=0x0 +# CONFIG_TWO_UNIVERSAL_MAC_ADDRESS is not set +CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS=y +CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS=4 +# CONFIG_ULP_COPROC_ENABLED is not set +CONFIG_ULP_COPROC_RESERVE_MEM=0 +CONFIG_BROWNOUT_DET=y +CONFIG_BROWNOUT_DET_LVL_SEL_0=y +# CONFIG_BROWNOUT_DET_LVL_SEL_1 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_7 is not set +CONFIG_BROWNOUT_DET_LVL=0 +CONFIG_REDUCE_PHY_TX_POWER=y +CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y +# CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL is not set +# CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_OSC is not set +# CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_8MD256 is not set +# CONFIG_DISABLE_BASIC_ROM_CONSOLE is not set +# CONFIG_NO_BLOBS is not set +# CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS is not set +CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=4304 +CONFIG_MAIN_TASK_STACK_SIZE=6584 +CONFIG_IPC_TASK_STACK_SIZE=3024 +CONFIG_CONSOLE_UART_DEFAULT=y +# CONFIG_CONSOLE_UART_CUSTOM is not set +# CONFIG_CONSOLE_UART_NONE is not set +CONFIG_CONSOLE_UART_NUM=0 +CONFIG_CONSOLE_UART_TX_GPIO=1 +CONFIG_CONSOLE_UART_RX_GPIO=3 +CONFIG_CONSOLE_UART_BAUDRATE=115200 +CONFIG_INT_WDT=y +CONFIG_INT_WDT_TIMEOUT_MS=300 +CONFIG_INT_WDT_CHECK_CPU1=y +CONFIG_TASK_WDT=y +# CONFIG_TASK_WDT_PANIC is not set +CONFIG_TASK_WDT_TIMEOUT_S=5 +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +# CONFIG_EVENT_LOOP_PROFILING is not set +CONFIG_POST_EVENTS_FROM_ISR=y +CONFIG_POST_EVENTS_FROM_IRAM_ISR=y +# CONFIG_ESP32S2_PANIC_PRINT_HALT is not set +CONFIG_ESP32S2_PANIC_PRINT_REBOOT=y +# CONFIG_ESP32S2_PANIC_SILENT_REBOOT is not set +# CONFIG_ESP32S2_PANIC_GDBSTUB is not set +CONFIG_TIMER_TASK_STACK_SIZE=6584 +CONFIG_MB_MASTER_TIMEOUT_MS_RESPOND=150 +CONFIG_MB_MASTER_DELAY_MS_CONVERT=200 +CONFIG_MB_QUEUE_LENGTH=20 +CONFIG_MB_SERIAL_TASK_STACK_SIZE=2048 +CONFIG_MB_SERIAL_BUF_SIZE=256 +CONFIG_MB_SERIAL_TASK_PRIO=10 +# CONFIG_MB_CONTROLLER_SLAVE_ID_SUPPORT is not set +CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT=20 +CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE=20 +CONFIG_MB_CONTROLLER_STACK_SIZE=4096 +CONFIG_MB_EVENT_QUEUE_TIMEOUT=20 +CONFIG_MB_TIMER_PORT_ENABLED=y +CONFIG_MB_TIMER_GROUP=0 +CONFIG_MB_TIMER_INDEX=0 +# CONFIG_SUPPORT_STATIC_ALLOCATION is not set +CONFIG_TIMER_TASK_PRIORITY=1 +CONFIG_TIMER_TASK_STACK_DEPTH=5048 +CONFIG_TIMER_QUEUE_LENGTH=10 +# CONFIG_L2_TO_L3_COPY is not set +# CONFIG_USE_ONLY_LWIP_SELECT is not set +CONFIG_ESP_GRATUITOUS_ARP=y +CONFIG_GARP_TMR_INTERVAL=60 +CONFIG_TCPIP_RECVMBOX_SIZE=32 +CONFIG_TCP_MAXRTX=12 +CONFIG_TCP_SYNMAXRTX=6 +CONFIG_TCP_MSS=1440 +CONFIG_TCP_MSL=60000 +CONFIG_TCP_SND_BUF_DEFAULT=5744 +CONFIG_TCP_WND_DEFAULT=5744 +CONFIG_TCP_RECVMBOX_SIZE=6 +CONFIG_TCP_QUEUE_OOSEQ=y +# CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set +CONFIG_TCP_OVERSIZE_MSS=y +# CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_TCP_OVERSIZE_DISABLE is not set +CONFIG_UDP_RECVMBOX_SIZE=6 +CONFIG_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_TCPIP_TASK_AFFINITY_CPU0 is not set +# CONFIG_TCPIP_TASK_AFFINITY_CPU1 is not set +CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF +# CONFIG_PPP_SUPPORT is not set +CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_ESP32_PTHREAD_STACK_MIN=768 +CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY=y +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_0 is not set +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_1 is not set +CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread" +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS is not set +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is not set +CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_SUPPORT_TERMIOS=y +CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN=128 +# End of deprecated options + diff -Nru libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-heltec-wb32/sdkconfig.h libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-heltec-wb32/sdkconfig.h --- libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-heltec-wb32/sdkconfig.h 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-heltec-wb32/sdkconfig.h 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,426 @@ +/* + * Automatically generated file. DO NOT EDIT. + * Espressif IoT Development Framework (ESP-IDF) Configuration Header + */ +#pragma once +#define CONFIG_IDF_CMAKE 1 +#define CONFIG_IDF_TARGET "esp32" +#define CONFIG_IDF_TARGET_ESP32 1 +#define CONFIG_IDF_FIRMWARE_CHIP_ID 0x0000 +#define CONFIG_SDK_TOOLPREFIX "xtensa-esp32-elf-" +#define CONFIG_APP_BUILD_TYPE_APP_2NDBOOT 1 +#define CONFIG_APP_BUILD_GENERATE_BINARIES 1 +#define CONFIG_APP_BUILD_BOOTLOADER 1 +#define CONFIG_APP_BUILD_USE_FLASH_SECTIONS 1 +#define CONFIG_APP_COMPILE_TIME_DATE 1 +#define CONFIG_APP_RETRIEVE_LEN_ELF_SHA 16 +#define CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE 1 +#define CONFIG_BOOTLOADER_LOG_LEVEL_INFO 1 +#define CONFIG_BOOTLOADER_LOG_LEVEL 3 +#define CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V 1 +#define CONFIG_BOOTLOADER_WDT_ENABLE 1 +#define CONFIG_BOOTLOADER_WDT_TIME_MS 9000 +#define CONFIG_BOOTLOADER_RESERVE_RTC_SIZE 0x0 +#define CONFIG_ESPTOOLPY_BAUD_OTHER_VAL 115200 +#define CONFIG_ESPTOOLPY_FLASHMODE_DIO 1 +#define CONFIG_ESPTOOLPY_FLASHMODE "dio" +#define CONFIG_ESPTOOLPY_FLASHFREQ_26M 1 +#define CONFIG_ESPTOOLPY_FLASHFREQ "26m" +#define CONFIG_ESPTOOLPY_FLASHSIZE_2MB 1 +#define CONFIG_ESPTOOLPY_FLASHSIZE "2MB" +#define CONFIG_ESPTOOLPY_FLASHSIZE_DETECT 1 +#define CONFIG_ESPTOOLPY_BEFORE_RESET 1 +#define CONFIG_ESPTOOLPY_BEFORE "default_reset" +#define CONFIG_ESPTOOLPY_AFTER_RESET 1 +#define CONFIG_ESPTOOLPY_AFTER "hard_reset" +#define CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B 1 +#define CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER_VAL 115200 +#define CONFIG_ESPTOOLPY_MONITOR_BAUD 115200 +#define CONFIG_PARTITION_TABLE_CUSTOM 1 +#define CONFIG_PARTITION_TABLE_CUSTOM_FILENAME "partitions.csv" +#define CONFIG_PARTITION_TABLE_FILENAME "partitions_singleapp.csv" +#define CONFIG_PARTITION_TABLE_OFFSET 0x8000 +#define CONFIG_PARTITION_TABLE_MD5 1 +#define CONFIG_COMPILER_OPTIMIZATION_DEFAULT 1 +#define CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE 1 +#define CONFIG_COMPILER_STACK_CHECK_MODE_NONE 1 +#define CONFIG_APPTRACE_DEST_NONE 1 +#define CONFIG_APPTRACE_LOCK_ENABLE 1 +#define CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF 0 +#define CONFIG_BTDM_CTRL_BLE_MAX_CONN_EFF 0 +#define CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN_EFF 0 +#define CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF 0 +#define CONFIG_BTDM_CTRL_PINNED_TO_CORE 0 +#define CONFIG_BTDM_BLE_SLEEP_CLOCK_ACCURACY_INDEX_EFF 1 +#define CONFIG_BT_RESERVE_DRAM 0x0 +#define CONFIG_COAP_MBEDTLS_PSK 1 +#define CONFIG_COAP_LOG_DEFAULT_LEVEL 0 +#define CONFIG_ADC_DISABLE_DAC 1 +#define CONFIG_SPI_MASTER_ISR_IN_IRAM 1 +#define CONFIG_SPI_SLAVE_ISR_IN_IRAM 1 +#define CONFIG_EFUSE_CODE_SCHEME_COMPAT_3_4 1 +#define CONFIG_EFUSE_MAX_BLK_LEN 192 +#define CONFIG_ESP_TLS_USING_MBEDTLS 1 +#define CONFIG_ESP32_REV_MIN_0 1 +#define CONFIG_ESP32_REV_MIN 0 +#define CONFIG_ESP32_DPORT_WORKAROUND 1 +#define CONFIG_ESP32_DEFAULT_CPU_FREQ_160 1 +#define CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ 160 +#define CONFIG_ESP32_TRACEMEM_RESERVE_DRAM 0x0 +#define CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR 1 +#define CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES 4 +#define CONFIG_ESP32_ULP_COPROC_RESERVE_MEM 0 +#define CONFIG_ESP32_DEBUG_OCDAWARE 1 +#define CONFIG_ESP32_BROWNOUT_DET 1 +#define CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_0 1 +#define CONFIG_ESP32_BROWNOUT_DET_LVL 0 +#define CONFIG_ESP32_REDUCE_PHY_TX_POWER 1 +#define CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1 1 +#define CONFIG_ESP32_RTC_CLK_SRC_INT_RC 1 +#define CONFIG_ESP32_RTC_CLK_CAL_CYCLES 1024 +#define CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY 2000 +#define CONFIG_ESP32_XTAL_FREQ_26 1 +#define CONFIG_ESP32_XTAL_FREQ 26 +#define CONFIG_ESP32_DPORT_DIS_INTERRUPT_LVL 5 +#define CONFIG_ADC_CAL_EFUSE_TP_ENABLE 1 +#define CONFIG_ADC_CAL_EFUSE_VREF_ENABLE 1 +#define CONFIG_ADC_CAL_LUT_ENABLE 1 +#define CONFIG_ESP_ERR_TO_NAME_LOOKUP 1 +#define CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE 32 +#define CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE 2304 +#define CONFIG_ESP_MAIN_TASK_STACK_SIZE 6584 +#define CONFIG_ESP_IPC_TASK_STACK_SIZE 1024 +#define CONFIG_ESP_IPC_USES_CALLERS_PRIORITY 1 +#define CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE 2048 +#define CONFIG_ESP_CONSOLE_UART_DEFAULT 1 +#define CONFIG_ESP_CONSOLE_UART_NUM 0 +#define CONFIG_ESP_CONSOLE_UART_TX_GPIO 1 +#define CONFIG_ESP_CONSOLE_UART_RX_GPIO 3 +#define CONFIG_ESP_CONSOLE_UART_BAUDRATE 115200 +#define CONFIG_ESP_INT_WDT 1 +#define CONFIG_ESP_INT_WDT_TIMEOUT_MS 300 +#define CONFIG_ESP_INT_WDT_CHECK_CPU1 1 +#define CONFIG_ESP_TASK_WDT 1 +#define CONFIG_ESP_TASK_WDT_TIMEOUT_S 5 +#define CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0 1 +#define CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_BT 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH 1 +#define CONFIG_ETH_ENABLED 1 +#define CONFIG_ETH_USE_ESP32_EMAC 1 +#define CONFIG_ETH_PHY_INTERFACE_RMII 1 +#define CONFIG_ETH_RMII_CLK_INPUT 1 +#define CONFIG_ETH_RMII_CLK_IN_GPIO 0 +#define CONFIG_ETH_DMA_BUFFER_SIZE 512 +#define CONFIG_ETH_DMA_RX_BUFFER_NUM 10 +#define CONFIG_ETH_DMA_TX_BUFFER_NUM 10 +#define CONFIG_ETH_USE_SPI_ETHERNET 1 +#define CONFIG_ESP_EVENT_POST_FROM_ISR 1 +#define CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR 1 +#define CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS 1 +#define CONFIG_HTTPD_MAX_REQ_HDR_LEN 512 +#define CONFIG_HTTPD_MAX_URI_LEN 512 +#define CONFIG_HTTPD_ERR_RESP_NO_DELAY 1 +#define CONFIG_HTTPD_PURGE_BUF_LEN 32 +#define CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL 120 +#define CONFIG_ESP_NETIF_TCPIP_LWIP 1 +#define CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER 1 +#define CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT 1 +#define CONFIG_ESP_TIMER_TASK_STACK_SIZE 3584 +#define CONFIG_ESP_TIMER_IMPL_TG0_LAC 1 +#define CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM 10 +#define CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM 32 +#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER 1 +#define CONFIG_ESP32_WIFI_TX_BUFFER_TYPE 1 +#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM 32 +#define CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED 1 +#define CONFIG_ESP32_WIFI_TX_BA_WIN 6 +#define CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED 1 +#define CONFIG_ESP32_WIFI_RX_BA_WIN 6 +#define CONFIG_ESP32_WIFI_NVS_ENABLED 1 +#define CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0 1 +#define CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN 752 +#define CONFIG_ESP32_WIFI_MGMT_SBUF_NUM 32 +#define CONFIG_ESP32_WIFI_IRAM_OPT 1 +#define CONFIG_ESP32_WIFI_RX_IRAM_OPT 1 +#define CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE 1 +#define CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE 1 +#define CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER 20 +#define CONFIG_ESP32_PHY_MAX_TX_POWER 20 +#define CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE 1 +#define CONFIG_FATFS_CODEPAGE_437 1 +#define CONFIG_FATFS_CODEPAGE 437 +#define CONFIG_FATFS_LFN_NONE 1 +#define CONFIG_FATFS_FS_LOCK 0 +#define CONFIG_FATFS_TIMEOUT_MS 10000 +#define CONFIG_FATFS_PER_FILE_CACHE 1 +#define CONFIG_FMB_COMM_MODE_RTU_EN 1 +#define CONFIG_FMB_COMM_MODE_ASCII_EN 1 +#define CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND 150 +#define CONFIG_FMB_MASTER_DELAY_MS_CONVERT 200 +#define CONFIG_FMB_QUEUE_LENGTH 20 +#define CONFIG_FMB_SERIAL_TASK_STACK_SIZE 2048 +#define CONFIG_FMB_SERIAL_BUF_SIZE 256 +#define CONFIG_FMB_SERIAL_ASCII_BITS_PER_SYMB 8 +#define CONFIG_FMB_SERIAL_ASCII_TIMEOUT_RESPOND_MS 1000 +#define CONFIG_FMB_SERIAL_TASK_PRIO 10 +#define CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT 20 +#define CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE 20 +#define CONFIG_FMB_CONTROLLER_STACK_SIZE 4096 +#define CONFIG_FMB_EVENT_QUEUE_TIMEOUT 20 +#define CONFIG_FMB_TIMER_PORT_ENABLED 1 +#define CONFIG_FMB_TIMER_GROUP 0 +#define CONFIG_FMB_TIMER_INDEX 0 +#define CONFIG_FREERTOS_NO_AFFINITY 0x7FFFFFFF +#define CONFIG_FREERTOS_CORETIMER_0 1 +#define CONFIG_FREERTOS_HZ 100 +#define CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION 1 +#define CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY 1 +#define CONFIG_FREERTOS_INTERRUPT_BACKTRACE 1 +#define CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS 1 +#define CONFIG_FREERTOS_ASSERT_FAIL_ABORT 1 +#define CONFIG_FREERTOS_IDLE_TASK_STACKSIZE 1536 +#define CONFIG_FREERTOS_ISR_STACKSIZE 1536 +#define CONFIG_FREERTOS_MAX_TASK_NAME_LEN 16 +#define CONFIG_FREERTOS_TIMER_TASK_PRIORITY 1 +#define CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH 2048 +#define CONFIG_FREERTOS_TIMER_QUEUE_LENGTH 10 +#define CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE 0 +#define CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER 1 +#define CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER 1 +#define CONFIG_FREERTOS_DEBUG_OCDAWARE 1 +#define CONFIG_HEAP_POISONING_DISABLED 1 +#define CONFIG_HEAP_TRACING_OFF 1 +#define CONFIG_LOG_DEFAULT_LEVEL_INFO 1 +#define CONFIG_LOG_DEFAULT_LEVEL 3 +#define CONFIG_LOG_COLORS 1 +#define CONFIG_LOG_TIMESTAMP_SOURCE_RTOS 1 +#define CONFIG_LWIP_LOCAL_HOSTNAME "espressif" +#define CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES 1 +#define CONFIG_LWIP_TIMERS_ONDEMAND 1 +#define CONFIG_LWIP_MAX_SOCKETS 10 +#define CONFIG_LWIP_SO_REUSE 1 +#define CONFIG_LWIP_SO_REUSE_RXTOALL 1 +#define CONFIG_LWIP_IP_FRAG 1 +#define CONFIG_LWIP_ESP_GRATUITOUS_ARP 1 +#define CONFIG_LWIP_GARP_TMR_INTERVAL 60 +#define CONFIG_LWIP_TCPIP_RECVMBOX_SIZE 32 +#define CONFIG_LWIP_DHCP_DOES_ARP_CHECK 1 +#define CONFIG_LWIP_DHCPS_LEASE_UNIT 60 +#define CONFIG_LWIP_DHCPS_MAX_STATION_NUM 8 +#define CONFIG_LWIP_NETIF_LOOPBACK 1 +#define CONFIG_LWIP_LOOPBACK_MAX_PBUFS 8 +#define CONFIG_LWIP_MAX_ACTIVE_TCP 16 +#define CONFIG_LWIP_MAX_LISTENING_TCP 16 +#define CONFIG_LWIP_TCP_MAXRTX 12 +#define CONFIG_LWIP_TCP_SYNMAXRTX 6 +#define CONFIG_LWIP_TCP_MSS 1440 +#define CONFIG_LWIP_TCP_TMR_INTERVAL 250 +#define CONFIG_LWIP_TCP_MSL 60000 +#define CONFIG_LWIP_TCP_SND_BUF_DEFAULT 5744 +#define CONFIG_LWIP_TCP_WND_DEFAULT 5744 +#define CONFIG_LWIP_TCP_RECVMBOX_SIZE 6 +#define CONFIG_LWIP_TCP_QUEUE_OOSEQ 1 +#define CONFIG_LWIP_TCP_OVERSIZE_MSS 1 +#define CONFIG_LWIP_MAX_UDP_PCBS 16 +#define CONFIG_LWIP_UDP_RECVMBOX_SIZE 6 +#define CONFIG_LWIP_TCPIP_TASK_STACK_SIZE 3072 +#define CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY 1 +#define CONFIG_LWIP_TCPIP_TASK_AFFINITY 0x7FFFFFFF +#define CONFIG_LWIP_MAX_RAW_PCBS 16 +#define CONFIG_LWIP_DHCP_MAX_NTP_SERVERS 1 +#define CONFIG_LWIP_SNTP_UPDATE_DELAY 3600000 +#define CONFIG_LWIP_ESP_LWIP_ASSERT 1 +#define CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC 1 +#define CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN 1 +#define CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN 16384 +#define CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN 4096 +#define CONFIG_MBEDTLS_CERTIFICATE_BUNDLE 1 +#define CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL 1 +#define CONFIG_MBEDTLS_HARDWARE_AES 1 +#define CONFIG_MBEDTLS_HARDWARE_MPI 1 +#define CONFIG_MBEDTLS_HARDWARE_SHA 1 +#define CONFIG_MBEDTLS_HAVE_TIME 1 +#define CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT 1 +#define CONFIG_MBEDTLS_TLS_SERVER 1 +#define CONFIG_MBEDTLS_TLS_CLIENT 1 +#define CONFIG_MBEDTLS_TLS_ENABLED 1 +#define CONFIG_MBEDTLS_PSK_MODES 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_PSK 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_PSK 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_PSK 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_PSK 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_RSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA 1 +#define CONFIG_MBEDTLS_SSL_RENEGOTIATION 1 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1 1 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_1 1 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_2 1 +#define CONFIG_MBEDTLS_SSL_PROTO_DTLS 1 +#define CONFIG_MBEDTLS_SSL_ALPN 1 +#define CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS 1 +#define CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS 1 +#define CONFIG_MBEDTLS_AES_C 1 +#define CONFIG_MBEDTLS_RC4_DISABLED 1 +#define CONFIG_MBEDTLS_CCM_C 1 +#define CONFIG_MBEDTLS_GCM_C 1 +#define CONFIG_MBEDTLS_PEM_PARSE_C 1 +#define CONFIG_MBEDTLS_PEM_WRITE_C 1 +#define CONFIG_MBEDTLS_X509_CRL_PARSE_C 1 +#define CONFIG_MBEDTLS_X509_CSR_PARSE_C 1 +#define CONFIG_MBEDTLS_ECP_C 1 +#define CONFIG_MBEDTLS_ECDH_C 1 +#define CONFIG_MBEDTLS_ECDSA_C 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_NIST_OPTIM 1 +#define CONFIG_MDNS_MAX_SERVICES 10 +#define CONFIG_MDNS_TASK_PRIORITY 1 +#define CONFIG_MDNS_TASK_AFFINITY_CPU0 1 +#define CONFIG_MDNS_TASK_AFFINITY 0x0 +#define CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS 2000 +#define CONFIG_MDNS_TIMER_PERIOD_MS 100 +#define CONFIG_MQTT_PROTOCOL_311 1 +#define CONFIG_MQTT_TRANSPORT_SSL 1 +#define CONFIG_MQTT_TRANSPORT_WEBSOCKET 1 +#define CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE 1 +#define CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF 1 +#define CONFIG_NEWLIB_STDIN_LINE_ENDING_CR 1 +#define CONFIG_OPENSSL_ASSERT_EXIT 1 +#define CONFIG_PTHREAD_TASK_PRIO_DEFAULT 5 +#define CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT 3072 +#define CONFIG_PTHREAD_STACK_MIN 768 +#define CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY 1 +#define CONFIG_PTHREAD_TASK_CORE_DEFAULT -1 +#define CONFIG_PTHREAD_TASK_NAME_DEFAULT "pthread" +#define CONFIG_SPI_FLASH_ROM_DRIVER_PATCH 1 +#define CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS 1 +#define CONFIG_SPI_FLASH_YIELD_DURING_ERASE 1 +#define CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS 20 +#define CONFIG_SPI_FLASH_ERASE_YIELD_TICKS 1 +#define CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP 1 +#define CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP 1 +#define CONFIG_SPI_FLASH_SUPPORT_GD_CHIP 1 +#define CONFIG_SPIFFS_MAX_PARTITIONS 3 +#define CONFIG_SPIFFS_CACHE 1 +#define CONFIG_SPIFFS_CACHE_WR 1 +#define CONFIG_SPIFFS_PAGE_CHECK 1 +#define CONFIG_SPIFFS_GC_MAX_RUNS 10 +#define CONFIG_SPIFFS_PAGE_SIZE 256 +#define CONFIG_SPIFFS_OBJ_NAME_LEN 32 +#define CONFIG_SPIFFS_USE_MAGIC 1 +#define CONFIG_SPIFFS_USE_MAGIC_LENGTH 1 +#define CONFIG_SPIFFS_META_LENGTH 4 +#define CONFIG_SPIFFS_USE_MTIME 1 +#define CONFIG_USB_DESC_CUSTOM_VID 0x1234 +#define CONFIG_USB_DESC_CUSTOM_PID 0x5678 +#define CONFIG_UNITY_ENABLE_FLOAT 1 +#define CONFIG_UNITY_ENABLE_DOUBLE 1 +#define CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER 1 +#define CONFIG_VFS_SUPPORT_IO 1 +#define CONFIG_VFS_SUPPORT_DIR 1 +#define CONFIG_VFS_SUPPORT_SELECT 1 +#define CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT 1 +#define CONFIG_VFS_SUPPORT_TERMIOS 1 +#define CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS 1 +#define CONFIG_VFS_SEMIHOSTFS_HOST_PATH_MAX_LEN 128 +#define CONFIG_WL_SECTOR_SIZE_4096 1 +#define CONFIG_WL_SECTOR_SIZE 4096 +#define CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES 16 +#define CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT 30 +#define CONFIG_WPA_MBEDTLS_CRYPTO 1 + +/* List of deprecated options */ +#define CONFIG_ADC2_DISABLE_DAC CONFIG_ADC_DISABLE_DAC +#define CONFIG_BROWNOUT_DET CONFIG_ESP32_BROWNOUT_DET +#define CONFIG_BROWNOUT_DET_LVL_SEL_0 CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_0 +#define CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG CONFIG_COMPILER_OPTIMIZATION_DEFAULT +#define CONFIG_CONSOLE_UART_BAUDRATE CONFIG_ESP_CONSOLE_UART_BAUDRATE +#define CONFIG_CONSOLE_UART_DEFAULT CONFIG_ESP_CONSOLE_UART_DEFAULT +#define CONFIG_CONSOLE_UART_RX_GPIO CONFIG_ESP_CONSOLE_UART_RX_GPIO +#define CONFIG_CONSOLE_UART_TX_GPIO CONFIG_ESP_CONSOLE_UART_TX_GPIO +#define CONFIG_ESP32S2_PANIC_PRINT_REBOOT CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT +#define CONFIG_ESP32_APPTRACE_DEST_NONE CONFIG_APPTRACE_DEST_NONE +#define CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY +#define CONFIG_ESP32_PANIC_PRINT_REBOOT CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT +#define CONFIG_ESP32_PTHREAD_STACK_MIN CONFIG_PTHREAD_STACK_MIN +#define CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT CONFIG_PTHREAD_TASK_NAME_DEFAULT +#define CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT CONFIG_PTHREAD_TASK_PRIO_DEFAULT +#define CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT +#define CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC CONFIG_ESP32_RTC_CLK_SRC_INT_RC +#define CONFIG_ESP_GRATUITOUS_ARP CONFIG_LWIP_ESP_GRATUITOUS_ARP +#define CONFIG_FLASHMODE_DIO CONFIG_ESPTOOLPY_FLASHMODE_DIO +#define CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR +#define CONFIG_GARP_TMR_INTERVAL CONFIG_LWIP_GARP_TMR_INTERVAL +#define CONFIG_INT_WDT CONFIG_ESP_INT_WDT +#define CONFIG_INT_WDT_CHECK_CPU1 CONFIG_ESP_INT_WDT_CHECK_CPU1 +#define CONFIG_INT_WDT_TIMEOUT_MS CONFIG_ESP_INT_WDT_TIMEOUT_MS +#define CONFIG_IPC_TASK_STACK_SIZE CONFIG_ESP_IPC_TASK_STACK_SIZE +#define CONFIG_LOG_BOOTLOADER_LEVEL_INFO CONFIG_BOOTLOADER_LOG_LEVEL_INFO +#define CONFIG_MAIN_TASK_STACK_SIZE CONFIG_ESP_MAIN_TASK_STACK_SIZE +#define CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE +#define CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT +#define CONFIG_MB_CONTROLLER_STACK_SIZE CONFIG_FMB_CONTROLLER_STACK_SIZE +#define CONFIG_MB_EVENT_QUEUE_TIMEOUT CONFIG_FMB_EVENT_QUEUE_TIMEOUT +#define CONFIG_MB_MASTER_DELAY_MS_CONVERT CONFIG_FMB_MASTER_DELAY_MS_CONVERT +#define CONFIG_MB_MASTER_TIMEOUT_MS_RESPOND CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND +#define CONFIG_MB_QUEUE_LENGTH CONFIG_FMB_QUEUE_LENGTH +#define CONFIG_MB_SERIAL_BUF_SIZE CONFIG_FMB_SERIAL_BUF_SIZE +#define CONFIG_MB_SERIAL_TASK_PRIO CONFIG_FMB_SERIAL_TASK_PRIO +#define CONFIG_MB_SERIAL_TASK_STACK_SIZE CONFIG_FMB_SERIAL_TASK_STACK_SIZE +#define CONFIG_MB_TIMER_GROUP CONFIG_FMB_TIMER_GROUP +#define CONFIG_MB_TIMER_INDEX CONFIG_FMB_TIMER_INDEX +#define CONFIG_MB_TIMER_PORT_ENABLED CONFIG_FMB_TIMER_PORT_ENABLED +#define CONFIG_MONITOR_BAUD_115200B CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B +#define CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE +#define CONFIG_OPTIMIZATION_LEVEL_DEBUG CONFIG_COMPILER_OPTIMIZATION_DEFAULT +#define CONFIG_POST_EVENTS_FROM_IRAM_ISR CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR +#define CONFIG_POST_EVENTS_FROM_ISR CONFIG_ESP_EVENT_POST_FROM_ISR +#define CONFIG_REDUCE_PHY_TX_POWER CONFIG_ESP32_REDUCE_PHY_TX_POWER +#define CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN CONFIG_VFS_SEMIHOSTFS_HOST_PATH_MAX_LEN +#define CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS +#define CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS +#define CONFIG_STACK_CHECK_NONE CONFIG_COMPILER_STACK_CHECK_MODE_NONE +#define CONFIG_SUPPORT_TERMIOS CONFIG_VFS_SUPPORT_TERMIOS +#define CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT +#define CONFIG_SYSTEM_EVENT_QUEUE_SIZE CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE +#define CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE +#define CONFIG_TASK_WDT CONFIG_ESP_TASK_WDT +#define CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0 CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0 +#define CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1 CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1 +#define CONFIG_TASK_WDT_TIMEOUT_S CONFIG_ESP_TASK_WDT_TIMEOUT_S +#define CONFIG_TCPIP_RECVMBOX_SIZE CONFIG_LWIP_TCPIP_RECVMBOX_SIZE +#define CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY +#define CONFIG_TCPIP_TASK_STACK_SIZE CONFIG_LWIP_TCPIP_TASK_STACK_SIZE +#define CONFIG_TCP_MAXRTX CONFIG_LWIP_TCP_MAXRTX +#define CONFIG_TCP_MSL CONFIG_LWIP_TCP_MSL +#define CONFIG_TCP_MSS CONFIG_LWIP_TCP_MSS +#define CONFIG_TCP_OVERSIZE_MSS CONFIG_LWIP_TCP_OVERSIZE_MSS +#define CONFIG_TCP_QUEUE_OOSEQ CONFIG_LWIP_TCP_QUEUE_OOSEQ +#define CONFIG_TCP_RECVMBOX_SIZE CONFIG_LWIP_TCP_RECVMBOX_SIZE +#define CONFIG_TCP_SND_BUF_DEFAULT CONFIG_LWIP_TCP_SND_BUF_DEFAULT +#define CONFIG_TCP_SYNMAXRTX CONFIG_LWIP_TCP_SYNMAXRTX +#define CONFIG_TCP_WND_DEFAULT CONFIG_LWIP_TCP_WND_DEFAULT +#define CONFIG_TIMER_QUEUE_LENGTH CONFIG_FREERTOS_TIMER_QUEUE_LENGTH +#define CONFIG_TIMER_TASK_PRIORITY CONFIG_FREERTOS_TIMER_TASK_PRIORITY +#define CONFIG_TIMER_TASK_STACK_DEPTH CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH +#define CONFIG_TIMER_TASK_STACK_SIZE CONFIG_ESP_TIMER_TASK_STACK_SIZE +#define CONFIG_TOOLPREFIX CONFIG_SDK_TOOLPREFIX +#define CONFIG_UDP_RECVMBOX_SIZE CONFIG_LWIP_UDP_RECVMBOX_SIZE diff -Nru libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-wrover-kit/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-wrover-kit/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-wrover-kit/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-wrover-kit/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,33 @@ +cmake_minimum_required(VERSION 3.5) + +if (ESP_PLATFORM) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) + project(lws-minimal-esp32 C) + enable_testing() + + target_link_libraries(lws-minimal-esp32.elf websockets) + + option(LWS_WITH_DRIVERS "With generic drivers for gpio, i2c, display etc" ON) + set(LWS_WITH_DRIVERS ON) + option(LWS_WITH_SECURE_STREAMS "With secure streams" ON) + set(LWS_WITH_SECURE_STREAMS ON) + option(LWS_WITH_LWSAC "With lwsac" ON) + set(LWS_WITH_LWSAC ON) + option(LWS_WITH_STRUCT_JSON "With lws_struct JSON" ON) + set(LWS_WITH_STRUCT_JSON ON) + option(LWS_WITH_SYS_NTPCLIENT "With ntpclient" ON) + set(LWS_WITH_SYS_NTPCLIENT ON) + + add_subdirectory(libwebsockets) + + add_test(NAME flashing COMMAND idf.py flash) + set_tests_properties(flashing PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + TIMEOUT 120) + + add_test(NAME boot COMMAND /usr/local/bin/sai-expect) + set_tests_properties(boot PROPERTIES + DEPENDS flashing + TIMEOUT 60) + +endif() diff -Nru libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-wrover-kit/main/cat-565.h libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-wrover-kit/main/cat-565.h --- libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-wrover-kit/main/cat-565.h 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-wrover-kit/main/cat-565.h 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,19200 @@ +0x62, 0xEB, 0x5A, 0xAA, 0x52, 0x8A, 0x52, 0x69, +0x5A, 0xAA, 0x62, 0xEB, 0x73, 0x0C, 0x72, 0xEB, +0x52, 0x08, 0x31, 0x24, 0x4A, 0x08, 0x4A, 0x07, +0x41, 0xE7, 0x39, 0xC6, 0x39, 0xC6, 0x31, 0x85, +0x29, 0x44, 0x21, 0x24, 0x31, 0x85, 0x41, 0xE7, +0x41, 0xE7, 0x39, 0x85, 0x41, 0xA6, 0x39, 0x45, +0x31, 0x24, 0x29, 0x04, 0x20, 0xC3, 0x28, 0xC3, +0x28, 0xC2, 0x28, 0xC2, 0x31, 0x04, 0x49, 0xA6, +0x5A, 0x27, 0x62, 0x48, 0x62, 0x48, 0x52, 0x27, +0x39, 0x86, 0x20, 0xE3, 0x29, 0x24, 0x41, 0xE8, +0x39, 0xA6, 0x4A, 0x48, 0x4A, 0x49, 0x39, 0xC7, +0x31, 0x65, 0x29, 0x24, 0x6B, 0x2C, 0x4A, 0x29, +0x52, 0x69, 0x84, 0x10, 0x63, 0x0B, 0x52, 0x6A, +0x62, 0xEB, 0x4A, 0x08, 0x6B, 0x0C, 0x6B, 0x2C, +0x5A, 0xAB, 0x39, 0xC7, 0x31, 0x86, 0x73, 0xAF, +0xDE, 0xFD, 0xDE, 0xDC, 0xBD, 0xF8, 0x94, 0x92, +0x4A, 0x28, 0x29, 0x44, 0x39, 0xE6, 0x4A, 0x48, +0x6B, 0x2C, 0x52, 0x8A, 0x73, 0x6D, 0x6B, 0x4D, +0x52, 0x69, 0x52, 0x69, 0x84, 0x10, 0xAD, 0x14, +0xBD, 0xB6, 0xC5, 0xF6, 0xC5, 0xB4, 0xA4, 0xAF, +0xA4, 0xAE, 0xA4, 0x8E, 0xA4, 0xAF, 0xB5, 0x10, +0xB5, 0x30, 0xB5, 0x30, 0xBD, 0x51, 0xBD, 0x51, +0xBD, 0x51, 0xBD, 0x52, 0xBD, 0x72, 0xBD, 0x72, +0xB5, 0x31, 0xAC, 0xF0, 0xB5, 0x31, 0xB5, 0x31, +0xB5, 0x31, 0xB5, 0x31, 0xB5, 0x31, 0xB5, 0x31, +0xAD, 0x11, 0xAD, 0x10, 0xB5, 0x10, 0xC5, 0x92, +0xC5, 0x51, 0xAC, 0xD0, 0x9C, 0x8E, 0x9C, 0x6E, +0x94, 0x2E, 0x8B, 0xED, 0x7B, 0xAC, 0x7B, 0x8C, +0x7B, 0x8C, 0x83, 0xAC, 0x8C, 0x0D, 0x94, 0x4D, +0xB5, 0x10, 0x94, 0x0D, 0x83, 0xCC, 0x7B, 0x8B, +0x73, 0x6B, 0x84, 0x0E, 0x94, 0x6F, 0x83, 0xCD, +0x7B, 0xAD, 0x7B, 0xCD, 0x8C, 0x2F, 0x8C, 0x2F, +0xDE, 0xB8, 0xDE, 0xD9, 0xC6, 0x16, 0x9C, 0xB0, +0xAD, 0x53, 0xAD, 0x53, 0xAD, 0x53, 0xAD, 0x52, +0xAD, 0x52, 0xB5, 0x93, 0xCE, 0x35, 0xA4, 0xAF, +0xAC, 0xCF, 0xBD, 0x93, 0x8C, 0x4F, 0x8C, 0x4F, +0x73, 0xAD, 0x7B, 0xAF, 0x4A, 0x29, 0x52, 0x8A, +0x6B, 0x4D, 0x73, 0xAE, 0x7B, 0xCE, 0x9C, 0xB1, +0xA5, 0x33, 0x94, 0xB1, 0x8C, 0x70, 0x94, 0x90, +0x84, 0x2F, 0x8C, 0x4F, 0x84, 0x2F, 0x6B, 0x6D, +0x84, 0x2F, 0x8C, 0x4F, 0x84, 0x0E, 0x8C, 0x70, +0x9C, 0xF2, 0xBD, 0x94, 0xAD, 0x53, 0xAD, 0x12, +0xBD, 0x94, 0xB5, 0x73, 0xAD, 0x53, 0xC5, 0xF6, +0xB5, 0xB4, 0xAD, 0x33, 0xAD, 0x33, 0xA5, 0x32, +0xB5, 0x73, 0x9C, 0xF1, 0xAD, 0x33, 0xBD, 0xD5, +0xAD, 0x53, 0xB5, 0x94, 0xB5, 0x74, 0xB5, 0x94, +0xB5, 0x53, 0xBD, 0xB5, 0xA5, 0x12, 0x7B, 0xAD, +0xAD, 0x32, 0x9C, 0xB0, 0xAD, 0x53, 0xA5, 0x11, +0x9C, 0xB0, 0xAD, 0x32, 0xA4, 0xF1, 0xA5, 0x12, +0x94, 0x4F, 0x83, 0xEE, 0x83, 0xED, 0x8C, 0x2E, +0x94, 0x4F, 0x94, 0x8F, 0x94, 0x6F, 0x94, 0x6F, +0x94, 0x4F, 0xA5, 0x11, 0xAD, 0x31, 0xAD, 0x32, +0xB5, 0x52, 0xA4, 0xF0, 0xAD, 0x31, 0xB5, 0x51, +0xAD, 0x31, 0xAD, 0x31, 0xAD, 0x11, 0xAC, 0xF1, +0xA4, 0xF1, 0x9C, 0xB0, 0xAD, 0x52, 0xBD, 0xB3, +0xAD, 0x32, 0xAC, 0xF1, 0xD5, 0xB3, 0xD5, 0x72, +0xCD, 0x71, 0xBD, 0x10, 0xB5, 0x10, 0xB5, 0x11, +0xB5, 0x10, 0xAC, 0xF0, 0xAC, 0xF0, 0xAC, 0xD0, +0xAC, 0xD0, 0xBD, 0x52, 0xC5, 0xB3, 0xC5, 0x92, +0xCD, 0xF3, 0xCD, 0xF3, 0xC5, 0x92, 0xC5, 0xB3, +0xBD, 0x72, 0xC5, 0xB3, 0xC5, 0xB3, 0xAC, 0xF0, +0xB5, 0x52, 0xB5, 0x53, 0xB5, 0x52, 0xD6, 0x35, +0xCD, 0xD3, 0xBD, 0x72, 0xCD, 0xB3, 0xCD, 0xD4, +0xC5, 0xB3, 0xC5, 0xB3, 0xBD, 0x73, 0xB5, 0x73, +0xA4, 0xF1, 0xA4, 0xF2, 0x94, 0x70, 0xA4, 0xF1, +0xA4, 0xF2, 0x94, 0x90, 0x94, 0x71, 0x8C, 0x70, +0x9C, 0xD2, 0xA5, 0x13, 0xA4, 0xF3, 0x8C, 0x50, +0x8C, 0x50, 0x8C, 0x30, 0x7B, 0xCF, 0x6B, 0x4D, +0x4A, 0x6A, 0x29, 0x66, 0x21, 0x25, 0x21, 0x04, +0x18, 0xE4, 0x18, 0xE4, 0x29, 0x66, 0x4A, 0x6A, +0x6B, 0x6E, 0x8C, 0x51, 0xA4, 0xF4, 0xA5, 0x14, +0xA5, 0x35, 0xA5, 0x14, 0x9C, 0xD3, 0x8C, 0x51, +0x7B, 0xEF, 0x7B, 0xAE, 0x84, 0x10, 0x84, 0x10, +0x6B, 0x2C, 0x7B, 0xAE, 0x84, 0x10, 0x84, 0x32, +0x7C, 0x12, 0x73, 0xD1, 0x7C, 0x12, 0x8C, 0x94, +0x94, 0xD5, 0x8C, 0xB5, 0x94, 0xD5, 0x94, 0xD5, +0x94, 0xD5, 0x94, 0xF5, 0x8C, 0xD5, 0x94, 0xD5, +0x95, 0x16, 0x94, 0xD5, 0x84, 0x73, 0x84, 0x32, +0x84, 0x32, 0x73, 0xD0, 0x7B, 0xD0, 0x84, 0x31, +0x7B, 0xF0, 0x73, 0xAF, 0x73, 0x8F, 0x6B, 0x4E, +0x4A, 0x28, 0x42, 0x07, 0x4A, 0x07, 0x41, 0xE7, +0x4A, 0x08, 0x41, 0xE7, 0x73, 0x4C, 0x7B, 0x4C, +0x31, 0x45, 0x29, 0x03, 0x41, 0xE6, 0x39, 0xA6, +0x39, 0xA6, 0x31, 0x85, 0x39, 0xC6, 0x42, 0x07, +0x39, 0xE7, 0x29, 0x64, 0x31, 0x85, 0x21, 0x03, +0x29, 0x04, 0x31, 0x65, 0x42, 0x07, 0x29, 0x24, +0x31, 0x45, 0x20, 0xC3, 0x28, 0xE3, 0x39, 0x85, +0x5A, 0x28, 0x72, 0xCA, 0x8B, 0x4C, 0x8B, 0x4B, +0xB4, 0x4F, 0xC4, 0xF1, 0xC4, 0xD1, 0xCD, 0x12, +0xB4, 0xB1, 0xA4, 0x71, 0xA4, 0xB2, 0x52, 0x69, +0x18, 0xE3, 0x18, 0xE3, 0x10, 0xA2, 0x18, 0xC3, +0x29, 0x24, 0x41, 0xE7, 0x63, 0x0C, 0x21, 0x24, +0x39, 0xA7, 0x6B, 0x4D, 0x5A, 0xCB, 0x52, 0x69, +0x5A, 0xAA, 0x4A, 0x28, 0x4A, 0x49, 0x42, 0x07, +0x41, 0xE7, 0x39, 0xA6, 0x6B, 0x6D, 0xDE, 0xFD, +0xDE, 0xFD, 0xC6, 0x3A, 0xA4, 0xF4, 0x52, 0x6A, +0x29, 0x45, 0x31, 0x85, 0x52, 0x89, 0x63, 0x2C, +0x6B, 0x2C, 0x31, 0x66, 0x42, 0x28, 0x63, 0x0B, +0x4A, 0x69, 0x39, 0xC7, 0x8C, 0x31, 0xA4, 0xF4, +0xCE, 0x18, 0xD6, 0x38, 0xE6, 0xDA, 0xC5, 0x94, +0x9C, 0x6F, 0x94, 0x4F, 0x9C, 0x6F, 0xA4, 0xD0, +0xBD, 0x92, 0xBD, 0x72, 0xB5, 0x31, 0xB5, 0x31, +0xB5, 0x31, 0xB5, 0x31, 0x94, 0x0D, 0x94, 0x2D, +0xA4, 0xAF, 0xB5, 0x10, 0xAC, 0xF0, 0x83, 0xAB, +0x94, 0x0C, 0x94, 0x2D, 0x94, 0x2D, 0x9C, 0x4E, +0x9C, 0x6E, 0x9C, 0x6E, 0xAC, 0xCF, 0xAC, 0xCF, +0xAC, 0xCF, 0xAC, 0xCF, 0xB5, 0x10, 0xB5, 0x30, +0xB5, 0x10, 0xB5, 0x11, 0xAC, 0xF0, 0xB5, 0x11, +0xA4, 0xD0, 0xA4, 0xD0, 0xB5, 0x11, 0xB4, 0xEF, +0xB5, 0x0F, 0xAC, 0xCF, 0xB4, 0xF0, 0xB5, 0x10, +0xBD, 0x11, 0xB5, 0x31, 0xBD, 0x51, 0xB5, 0x30, +0xB5, 0x10, 0xB5, 0x10, 0xAD, 0x11, 0xA4, 0xD0, +0xA4, 0x8F, 0xA4, 0xAF, 0xA4, 0xCF, 0x9C, 0x8E, +0x9C, 0x6E, 0xA4, 0xAF, 0x9C, 0x8E, 0x94, 0x2D, +0x9C, 0xAF, 0xB5, 0x72, 0x9C, 0x6E, 0xAC, 0xEF, +0xA4, 0xCF, 0xB5, 0x31, 0x9C, 0xAF, 0x8C, 0x2E, +0x6B, 0x0B, 0x41, 0xE7, 0x20, 0xE4, 0x4A, 0x49, +0x73, 0x8E, 0x6B, 0x2C, 0x63, 0x2B, 0x9C, 0xF1, +0xCE, 0x56, 0xB5, 0x73, 0xB5, 0x73, 0xB5, 0xB4, +0xB5, 0xB4, 0xAD, 0x32, 0xA5, 0x12, 0x94, 0x70, +0xBD, 0xB4, 0xB5, 0x73, 0x94, 0x90, 0x84, 0x2F, +0xA4, 0xF2, 0xC5, 0xF5, 0xB5, 0x94, 0xB5, 0x94, +0xDE, 0xB8, 0xD6, 0x98, 0xC6, 0x16, 0xAD, 0x32, +0xCE, 0x37, 0xB5, 0xB4, 0xC6, 0x16, 0xC6, 0x37, +0xAD, 0x53, 0xA5, 0x33, 0xA5, 0x33, 0xB5, 0x94, +0xB5, 0x94, 0xC5, 0xF6, 0xC6, 0x16, 0xC6, 0x37, +0xC6, 0x16, 0xBD, 0xD5, 0xA4, 0xF2, 0x7B, 0xAC, +0xAD, 0x12, 0xAD, 0x33, 0x9C, 0x90, 0x9C, 0x90, +0x94, 0x4F, 0x94, 0x6F, 0xA4, 0xD0, 0xA5, 0x11, +0x94, 0x4F, 0xA4, 0xF1, 0xA4, 0xF1, 0xAD, 0x52, +0xAD, 0x32, 0xA4, 0xF1, 0xA4, 0xD1, 0x9C, 0x90, +0x8C, 0x4E, 0x9C, 0xB0, 0xA4, 0xD0, 0xA4, 0xF0, +0xA4, 0xCF, 0x9C, 0xAF, 0xA4, 0xF0, 0xAD, 0x31, +0xB5, 0x51, 0xAD, 0x31, 0xA5, 0x11, 0xA4, 0xF0, +0xA5, 0x11, 0xAD, 0x11, 0xBD, 0x93, 0xAD, 0x31, +0xAD, 0x32, 0xAD, 0x11, 0xDD, 0xF4, 0xDD, 0xB3, +0xCD, 0x71, 0xC5, 0x30, 0xBD, 0x51, 0xC5, 0x72, +0xB5, 0x31, 0xB5, 0x31, 0xB5, 0x11, 0xAD, 0x10, +0x9C, 0x8F, 0xAC, 0xF0, 0xB5, 0x11, 0xB5, 0x31, +0xBD, 0x72, 0xC5, 0x92, 0xBD, 0x72, 0xC5, 0xB2, +0xC5, 0x92, 0xC5, 0xB3, 0xB5, 0x31, 0xB5, 0x72, +0xB5, 0x52, 0xBD, 0x73, 0xCD, 0xD4, 0xDE, 0x55, +0xCD, 0xD3, 0xBD, 0x71, 0xC5, 0x92, 0xCD, 0xB3, +0xCD, 0xD3, 0xDE, 0x35, 0xDE, 0x55, 0xDE, 0x55, +0xCD, 0xF4, 0xB5, 0x32, 0xA4, 0xD0, 0xAD, 0x12, +0xBD, 0x73, 0xC5, 0xD4, 0xCE, 0x16, 0xC5, 0xD6, +0x94, 0x70, 0x8C, 0x50, 0x94, 0xB2, 0x8C, 0x50, +0xAD, 0x33, 0xA5, 0x33, 0xA5, 0x13, 0x9C, 0xD2, +0x9C, 0xB2, 0x8C, 0x50, 0x6B, 0x4D, 0x4A, 0x6A, +0x39, 0xE7, 0x29, 0x86, 0x29, 0x45, 0x19, 0x04, +0x18, 0xE4, 0x29, 0x45, 0x42, 0x08, 0x4A, 0x49, +0x5A, 0xEC, 0x73, 0xAF, 0x8C, 0x52, 0x94, 0xB3, +0x9C, 0xD4, 0xB5, 0xB7, 0x9C, 0xD3, 0x9D, 0x14, +0x9C, 0xB3, 0x94, 0x72, 0x94, 0x92, 0x9C, 0xD4, +0xA5, 0x36, 0xAD, 0x76, 0xA5, 0x56, 0x9C, 0xF5, +0x8C, 0x93, 0x84, 0x32, 0x7C, 0x12, 0x7B, 0xF1, +0x73, 0xB0, 0x73, 0xD1, 0x7C, 0x12, 0x84, 0x53, +0x8C, 0x94, 0x84, 0x73, 0x7C, 0x12, 0x73, 0xB0, +0x6B, 0x8F, 0x5A, 0xED, 0x52, 0xCC, 0x52, 0xAC, +0x4A, 0x6B, 0x39, 0xE8, 0x31, 0xA7, 0x29, 0x87, +0x31, 0x65, 0x39, 0xA5, 0x39, 0xA5, 0x39, 0x85, +0x31, 0x85, 0x31, 0x65, 0x94, 0x51, 0xD6, 0x38, +0x83, 0xAE, 0x29, 0x44, 0x31, 0x65, 0x31, 0x65, +0x31, 0x85, 0x31, 0x85, 0x31, 0xA6, 0x39, 0xA6, +0x39, 0xA6, 0x21, 0x03, 0x21, 0x24, 0x21, 0x24, +0x73, 0xAE, 0xAD, 0x55, 0xAD, 0x75, 0xA5, 0x14, +0x8C, 0x51, 0x42, 0x07, 0x41, 0xC7, 0x62, 0x8A, +0x8B, 0x4C, 0x93, 0x6C, 0x9B, 0xAD, 0x72, 0x68, +0x82, 0xEA, 0xC4, 0xD0, 0xBC, 0x70, 0x93, 0x6C, +0x9C, 0x0F, 0xA4, 0x51, 0x6A, 0xCA, 0x20, 0xC2, +0x18, 0xC3, 0x18, 0xC3, 0x18, 0xE3, 0x18, 0xE3, +0x18, 0xC3, 0x29, 0x65, 0x42, 0x07, 0x29, 0x24, +0x29, 0x24, 0x4A, 0x69, 0x5A, 0xCA, 0x42, 0x07, +0x42, 0x08, 0x41, 0xE7, 0x39, 0xC6, 0x31, 0xA6, +0x31, 0xA6, 0x39, 0xA6, 0x8C, 0x72, 0xE7, 0x1D, +0xD6, 0x9B, 0xC6, 0x19, 0x7B, 0xD0, 0x31, 0x86, +0x42, 0x07, 0x4A, 0x48, 0x4A, 0x69, 0x4A, 0x28, +0x63, 0x0B, 0x31, 0x65, 0x31, 0xA6, 0x52, 0x8A, +0x42, 0x28, 0x42, 0x08, 0x5A, 0xCB, 0x8C, 0x10, +0xB5, 0x55, 0xBD, 0x96, 0xE6, 0xBA, 0xCD, 0xF7, +0x7B, 0x8D, 0x83, 0xEE, 0x63, 0x0A, 0x8C, 0x4F, +0xAD, 0x11, 0xAD, 0x51, 0x9C, 0x8F, 0xB5, 0x72, +0xBD, 0xB3, 0x94, 0x4F, 0x73, 0x8D, 0x84, 0x0F, +0x8C, 0x6F, 0x94, 0x6F, 0xA4, 0xF0, 0x7B, 0xAB, +0x9C, 0x8F, 0x94, 0x8F, 0x94, 0x6E, 0x94, 0x4E, +0x83, 0xEC, 0x83, 0xCC, 0x83, 0xCB, 0x83, 0xCC, +0x7B, 0x8B, 0x7B, 0x8A, 0x83, 0xCB, 0x83, 0x8B, +0x83, 0xAB, 0x83, 0xCB, 0x9C, 0x6E, 0xA4, 0x8E, +0x94, 0x2D, 0x7B, 0x8B, 0x73, 0x2A, 0x94, 0x2D, +0xAD, 0x10, 0xD6, 0x55, 0xD6, 0x55, 0xD6, 0x14, +0xD6, 0x14, 0xD5, 0xF4, 0xC5, 0x92, 0xB5, 0x30, +0xB5, 0x10, 0xAC, 0xF0, 0xA4, 0xAF, 0xAC, 0xAF, +0xAC, 0xCF, 0xB5, 0x10, 0xB5, 0x10, 0xBD, 0x51, +0xB5, 0x30, 0xB5, 0x10, 0xC5, 0x71, 0xBD, 0x31, +0xBD, 0x30, 0xB5, 0x10, 0xBD, 0x30, 0xBD, 0x50, +0xB5, 0x10, 0xB5, 0x10, 0xB5, 0x10, 0xAC, 0xF0, +0xAC, 0xD0, 0xA4, 0xF0, 0x73, 0x4B, 0x63, 0x2D, +0x84, 0x10, 0x73, 0x8E, 0x7B, 0xAD, 0x9C, 0xB0, +0xA4, 0xAF, 0x9C, 0x6E, 0x9C, 0x6F, 0x94, 0x4E, +0x94, 0x6E, 0x83, 0xCC, 0x83, 0xED, 0x83, 0xED, +0x8C, 0x4E, 0x8C, 0x2E, 0x73, 0x6C, 0x6B, 0x4B, +0x9C, 0xB1, 0xA4, 0xF1, 0x9C, 0xD1, 0x9C, 0xB1, +0xBD, 0xB4, 0xB5, 0x73, 0xA5, 0x12, 0x83, 0xEE, +0xBD, 0xD5, 0xC5, 0xF5, 0xB5, 0x94, 0xA4, 0xF1, +0xA5, 0x12, 0xA4, 0xF2, 0xAD, 0x53, 0xC6, 0x16, +0xC6, 0x16, 0xCE, 0x36, 0xCE, 0x57, 0xC5, 0xF6, +0xC5, 0xF5, 0xCE, 0x57, 0x9C, 0xD1, 0x8C, 0x0E, +0xA5, 0x12, 0xAD, 0x32, 0xAD, 0x12, 0x94, 0x6F, +0x94, 0x6F, 0x9C, 0xB0, 0xA4, 0xF1, 0x9C, 0xB0, +0x83, 0xED, 0xAD, 0x32, 0xAD, 0x52, 0xA5, 0x12, +0x9C, 0xD1, 0x9C, 0xB0, 0x94, 0x8F, 0xA4, 0xF1, +0x94, 0x8F, 0xAD, 0x32, 0xB5, 0x72, 0xA4, 0xF0, +0xAD, 0x31, 0xAD, 0x11, 0xAD, 0x31, 0xB5, 0x51, +0xA4, 0xF0, 0xA5, 0x10, 0x9C, 0xAF, 0x94, 0x6E, +0x8C, 0x2D, 0x8C, 0x0D, 0x94, 0x4E, 0x83, 0xAB, +0xB5, 0x53, 0xB5, 0x52, 0xDD, 0xD3, 0xDD, 0xF3, +0xD5, 0xB3, 0xCD, 0x92, 0xC5, 0x72, 0xC5, 0x93, +0xBD, 0x52, 0xBD, 0x52, 0xB5, 0x31, 0xAD, 0x10, +0xAD, 0x11, 0xAD, 0x11, 0xAC, 0xF0, 0xAC, 0xF0, +0xB5, 0x31, 0xC5, 0x92, 0xB5, 0x31, 0xBD, 0x72, +0xBD, 0x51, 0xC5, 0xB3, 0xC5, 0x93, 0xC5, 0xD4, +0xC5, 0xB3, 0xBD, 0x72, 0xDE, 0x55, 0xD5, 0xF3, +0xD5, 0xF4, 0xC5, 0x92, 0xC5, 0x92, 0xCD, 0x92, +0xC5, 0x92, 0xD6, 0x14, 0xD6, 0x14, 0xDE, 0x34, +0xD6, 0x14, 0xC5, 0x93, 0xB5, 0x10, 0xAC, 0xF1, +0xB5, 0x32, 0xCD, 0xF5, 0xBD, 0xB4, 0xD6, 0x57, +0xD6, 0x78, 0xBD, 0xB5, 0xAD, 0x53, 0x7B, 0xCE, +0x84, 0x2F, 0xA4, 0xF3, 0xAD, 0x54, 0x94, 0x91, +0x83, 0xEF, 0x8C, 0x50, 0x94, 0x91, 0x9C, 0xB2, +0x8C, 0x50, 0x7B, 0xEF, 0x73, 0x6D, 0x5A, 0xEB, +0x31, 0x86, 0x21, 0x05, 0x18, 0xE4, 0x18, 0xE4, +0x21, 0x05, 0x29, 0x46, 0x29, 0x87, 0x3A, 0x08, +0x63, 0x0D, 0x84, 0x31, 0x73, 0x8F, 0x63, 0x4D, +0x6B, 0x6E, 0x73, 0xAF, 0x73, 0x8F, 0x73, 0x8F, +0x73, 0x6E, 0x73, 0x8E, 0x6B, 0x4D, 0x73, 0xAF, +0x9C, 0xD4, 0x9D, 0x15, 0x9D, 0x15, 0x9C, 0xF5, +0x9C, 0xF4, 0x9C, 0xF4, 0x9D, 0x15, 0x9D, 0x15, +0x9C, 0xD5, 0x9D, 0x15, 0xA5, 0x56, 0xAD, 0x97, +0xB5, 0xB8, 0xB5, 0xD9, 0xB5, 0xB8, 0xA5, 0x56, +0x94, 0xD4, 0x84, 0x53, 0x84, 0x32, 0x7B, 0xF1, +0x52, 0xAA, 0x52, 0xCB, 0x52, 0xCA, 0x4A, 0x49, +0x29, 0x24, 0x31, 0x86, 0x7B, 0xCE, 0xCD, 0xF7, +0xA4, 0x71, 0x39, 0x85, 0x21, 0x04, 0x39, 0xC6, +0x29, 0x65, 0x21, 0x24, 0x29, 0x44, 0x39, 0xC6, +0x4A, 0x48, 0x31, 0xA6, 0x31, 0x86, 0x4A, 0x48, +0x7B, 0xAE, 0x9C, 0xB2, 0x94, 0x71, 0x9C, 0xB2, +0x6B, 0x0B, 0x29, 0x03, 0x29, 0x44, 0x62, 0x89, +0x93, 0x6C, 0x83, 0x0A, 0x93, 0x4B, 0x83, 0x0A, +0x41, 0x64, 0x62, 0x89, 0x6A, 0x89, 0x52, 0x48, +0x62, 0xCA, 0x41, 0xE7, 0x5A, 0xCA, 0x4A, 0x28, +0x21, 0x24, 0x29, 0x65, 0x21, 0x24, 0x21, 0x24, +0x21, 0x24, 0x18, 0xC3, 0x18, 0xE3, 0x29, 0x45, +0x21, 0x04, 0x29, 0x44, 0x39, 0xE7, 0x39, 0xC6, +0x39, 0xC6, 0x31, 0xA6, 0x31, 0x85, 0x29, 0x85, +0x31, 0x85, 0x31, 0xC6, 0xB5, 0xD7, 0xE7, 0x5E, +0xD6, 0xBC, 0xB5, 0x77, 0x5A, 0xCB, 0x52, 0x8A, +0x42, 0x28, 0x31, 0x85, 0x42, 0x07, 0x39, 0xE7, +0x5A, 0xEB, 0x39, 0xC7, 0x31, 0x86, 0x39, 0xE7, +0x42, 0x28, 0x63, 0x0C, 0x62, 0xCB, 0x7B, 0xAE, +0xA4, 0xB2, 0xA4, 0xB2, 0xBD, 0x75, 0xDE, 0x79, +0xC5, 0xF7, 0x7B, 0x8D, 0x8C, 0x50, 0xBD, 0xB6, +0x4A, 0x28, 0x84, 0x0E, 0xCE, 0x36, 0xD6, 0x97, +0xD6, 0x56, 0x94, 0x70, 0x73, 0x8D, 0x8C, 0x70, +0x94, 0xB1, 0x94, 0x90, 0xAD, 0x11, 0x7B, 0x6B, +0xA4, 0xD0, 0xA4, 0xF0, 0x94, 0x6F, 0x94, 0x4E, +0x8C, 0x0D, 0x8C, 0x0D, 0x83, 0xCC, 0x8C, 0x2D, +0x94, 0x8F, 0x9C, 0x8F, 0x8C, 0x0C, 0x8C, 0x0D, +0x94, 0x6E, 0x94, 0x2D, 0xAC, 0xF0, 0x94, 0x0D, +0x94, 0x4E, 0xAD, 0x11, 0x9C, 0xD0, 0x94, 0x6F, +0x8C, 0x0D, 0xA5, 0x10, 0xD6, 0x55, 0xD6, 0x35, +0xC5, 0xB2, 0xD6, 0x35, 0xCD, 0xF4, 0x9C, 0x8E, +0x9C, 0x6F, 0x94, 0x2E, 0x94, 0x4E, 0xA4, 0xAF, +0xB5, 0x11, 0xAC, 0xF0, 0xB5, 0x52, 0xB5, 0x31, +0xCE, 0x14, 0xCD, 0xD3, 0xBD, 0x51, 0x94, 0x0C, +0x9C, 0x8E, 0xAD, 0x10, 0xAC, 0xCF, 0xAC, 0xEF, +0xB5, 0x51, 0xAC, 0xCF, 0x94, 0x4D, 0x8C, 0x0C, +0x94, 0x2D, 0xAC, 0xD0, 0xA4, 0xF2, 0x9C, 0xB3, +0x9C, 0xF3, 0x84, 0x0F, 0x8C, 0x0E, 0xA4, 0xD0, +0xA4, 0xAF, 0xA4, 0x8F, 0xA4, 0xAF, 0xAC, 0xF0, +0xAC, 0xF0, 0xAC, 0xF0, 0xBD, 0x73, 0xB5, 0x32, +0xB5, 0x73, 0xB5, 0x73, 0xAD, 0x53, 0xB5, 0x94, +0xBD, 0xD5, 0xB5, 0xB4, 0xBD, 0x94, 0xB5, 0x94, +0xAD, 0x53, 0xAD, 0x53, 0xAD, 0x33, 0xAD, 0x33, +0xA4, 0xD1, 0x94, 0x90, 0x94, 0x4F, 0x9C, 0x90, +0xA4, 0xD1, 0xA4, 0xD1, 0x9C, 0xB1, 0xA4, 0xD1, +0x9C, 0xB0, 0x9C, 0xB1, 0xA4, 0xF1, 0x9C, 0xB0, +0x94, 0x6F, 0x94, 0x70, 0x83, 0xED, 0x73, 0x6C, +0xA4, 0xD1, 0x8C, 0x0E, 0x8C, 0x0E, 0x7B, 0xAC, +0x7B, 0xAC, 0x7B, 0xAC, 0x83, 0xED, 0x84, 0x0E, +0x6B, 0x4B, 0x73, 0x6B, 0x9C, 0xB0, 0x8C, 0x2E, +0x62, 0xEA, 0x84, 0x0E, 0x8C, 0x4E, 0xAD, 0x32, +0xB5, 0x53, 0xB5, 0x93, 0xBD, 0x93, 0xAD, 0x11, +0xBD, 0x93, 0xBD, 0x93, 0xBD, 0xB3, 0xBD, 0xB3, +0xBD, 0x92, 0xB5, 0x51, 0xA4, 0xF0, 0x94, 0x8E, +0x84, 0x0C, 0x7B, 0x8B, 0x7B, 0xAB, 0x83, 0xCC, +0xB5, 0x73, 0xAD, 0x11, 0xDE, 0x56, 0xCD, 0xB3, +0xBD, 0x51, 0xB5, 0x31, 0xB5, 0x31, 0xBD, 0x52, +0xB5, 0x31, 0xB5, 0x52, 0xB5, 0x72, 0xBD, 0x93, +0xB5, 0x72, 0xBD, 0x93, 0xB5, 0x52, 0xBD, 0x72, +0xC5, 0xB3, 0xCD, 0xD3, 0xC5, 0x93, 0xCD, 0xF4, +0xBD, 0x72, 0xB5, 0x51, 0xB5, 0x51, 0xAD, 0x10, +0xA4, 0xAF, 0xB5, 0x11, 0xCD, 0xF4, 0xD6, 0x14, +0xDE, 0x55, 0xD6, 0x14, 0xCD, 0xB2, 0xD5, 0xD3, +0xC5, 0x71, 0xCD, 0xB3, 0xDE, 0x55, 0xD5, 0xF3, +0xD5, 0xF3, 0xD5, 0xF3, 0xBD, 0x51, 0xA4, 0xAF, +0xB5, 0x31, 0xC5, 0xF4, 0xD6, 0x56, 0xDE, 0xB7, +0xC5, 0xF5, 0xA4, 0xF1, 0xDE, 0xB8, 0xCE, 0x37, +0x94, 0x91, 0x7B, 0xCE, 0x83, 0xEF, 0x84, 0x2F, +0x7B, 0xCF, 0x7B, 0xCE, 0x84, 0x0F, 0x9C, 0xB2, +0xA5, 0x33, 0x9C, 0xD2, 0x94, 0x71, 0x84, 0x30, +0x63, 0x2C, 0x39, 0xE8, 0x29, 0x66, 0x21, 0x25, +0x18, 0xE4, 0x10, 0xC4, 0x18, 0xE4, 0x21, 0x25, +0x29, 0x87, 0x42, 0x29, 0x6B, 0x6E, 0x9C, 0xF4, +0xA5, 0x35, 0xA5, 0x15, 0x9C, 0xF5, 0x94, 0x93, +0x84, 0x32, 0x7C, 0x11, 0x73, 0xAF, 0x6B, 0x4E, +0x63, 0x0C, 0x6B, 0x6E, 0x84, 0x31, 0x7B, 0xCF, +0x6B, 0x2C, 0x83, 0xCF, 0x9C, 0xD3, 0x94, 0x93, +0x94, 0x93, 0x9C, 0xD4, 0xA5, 0x15, 0x9C, 0xF5, +0x94, 0xD4, 0x9C, 0xF4, 0xA5, 0x36, 0xAD, 0x77, +0xB5, 0xB8, 0xB5, 0xB8, 0xAD, 0x77, 0x9D, 0x15, +0xAD, 0x96, 0xAD, 0x96, 0xAD, 0x76, 0xA5, 0x55, +0x8C, 0x72, 0x7C, 0x10, 0x73, 0x4D, 0xCD, 0xD6, +0x8B, 0xAE, 0x62, 0xEB, 0x5A, 0xEB, 0x73, 0xAE, +0x73, 0x8D, 0x73, 0x6D, 0x7B, 0xAE, 0x84, 0x2F, +0x8C, 0x30, 0x84, 0x0F, 0x6B, 0x4C, 0x73, 0x8D, +0x39, 0xA6, 0x31, 0x65, 0x62, 0xCA, 0x5A, 0x69, +0x52, 0x69, 0x39, 0xC7, 0x5A, 0xAA, 0x72, 0xEB, +0x8B, 0x4C, 0x82, 0xEA, 0x82, 0xEA, 0x8B, 0x0B, +0x62, 0x68, 0x83, 0xAD, 0x8B, 0xCD, 0x94, 0x0E, +0x8B, 0xED, 0x7B, 0x8D, 0x8C, 0x2F, 0x83, 0xEE, +0x62, 0xEB, 0x4A, 0x69, 0x31, 0xA6, 0x21, 0x03, +0x29, 0x44, 0x29, 0x45, 0x21, 0x24, 0x29, 0x65, +0x21, 0x24, 0x21, 0x03, 0x29, 0x44, 0x29, 0x64, +0x29, 0x44, 0x29, 0x65, 0x29, 0x44, 0x29, 0x24, +0x29, 0x44, 0x63, 0x0C, 0xE7, 0x3D, 0xDE, 0xDC, +0xAD, 0x35, 0x9C, 0xB3, 0xA5, 0x14, 0x7B, 0xEF, +0x39, 0xA6, 0x21, 0x24, 0x4A, 0x48, 0x41, 0xE7, +0x4A, 0x28, 0x31, 0xA6, 0x42, 0x08, 0x5A, 0xEB, +0x5A, 0xEB, 0x6B, 0x2D, 0x83, 0xEF, 0x94, 0x71, +0xAD, 0x13, 0xA4, 0xB2, 0xBD, 0x55, 0xC5, 0x96, +0xDE, 0x9A, 0xC5, 0xD7, 0xAD, 0x55, 0xEF, 0x7D, +0xC6, 0x18, 0x39, 0xC7, 0x52, 0x68, 0x7B, 0xCD, +0x7B, 0xAD, 0x8C, 0x2F, 0x73, 0x8D, 0x9C, 0xD2, +0xA5, 0x53, 0xB5, 0x73, 0xAC, 0xF1, 0x8C, 0x2E, +0xAD, 0x11, 0xA4, 0xF1, 0x94, 0x8F, 0x94, 0x4E, +0x8C, 0x0D, 0x8C, 0x2D, 0x83, 0xED, 0x8C, 0x0D, +0x9C, 0xB0, 0x9C, 0xB0, 0x8C, 0x0D, 0x83, 0xEC, +0x94, 0x6E, 0x9C, 0x8F, 0xB5, 0x31, 0x8C, 0x0C, +0xB5, 0x93, 0xC6, 0x15, 0xB5, 0x93, 0xBD, 0xB4, +0xAD, 0x32, 0x7B, 0xCC, 0xB5, 0x93, 0xCE, 0x35, +0xB5, 0x72, 0xAD, 0x11, 0xA4, 0xD0, 0xBD, 0x94, +0xBD, 0xD4, 0xBD, 0xD4, 0xB5, 0x93, 0xA5, 0x11, +0xC5, 0xD4, 0x8C, 0x0E, 0x7B, 0xAC, 0x8C, 0x4F, +0xAD, 0x32, 0xAC, 0xEF, 0xC5, 0x51, 0x83, 0x6A, +0x8C, 0x6F, 0xB5, 0x93, 0x8C, 0x4E, 0x94, 0x6F, +0x9C, 0xB0, 0x94, 0x4E, 0x9C, 0x90, 0x94, 0x4E, +0xA4, 0xF1, 0xA4, 0xD1, 0xB5, 0x54, 0xA5, 0x35, +0xA5, 0x14, 0x84, 0x10, 0x6B, 0x4B, 0x94, 0x4E, +0xAD, 0x11, 0xAD, 0x11, 0xBD, 0xB3, 0xBD, 0x93, +0xBD, 0x72, 0xA4, 0xAF, 0x9C, 0x6F, 0x73, 0x6C, +0x63, 0x0B, 0x62, 0xEA, 0x6B, 0x2B, 0x83, 0xEE, +0x9C, 0x90, 0xA4, 0xF1, 0x94, 0x6F, 0x83, 0xEE, +0x8C, 0x2E, 0x94, 0x70, 0x94, 0x70, 0x94, 0x4F, +0xAD, 0x12, 0x9C, 0x90, 0x9C, 0xB1, 0xA4, 0xF1, +0xA4, 0xF1, 0xA4, 0xD1, 0xA4, 0xD1, 0xA4, 0xF2, +0xA4, 0xF2, 0xAD, 0x12, 0xAD, 0x32, 0xA4, 0xF1, +0xAD, 0x33, 0xB5, 0x53, 0xBD, 0x94, 0xAD, 0x53, +0xBD, 0x94, 0xB5, 0x74, 0xBD, 0x94, 0xB5, 0x74, +0xB5, 0x94, 0xB5, 0x74, 0xBD, 0x95, 0xBD, 0xB5, +0xB5, 0x94, 0xA5, 0x12, 0xA4, 0xD2, 0xAD, 0x13, +0xB5, 0x74, 0xAD, 0x33, 0xA4, 0xF1, 0xA4, 0xD1, +0xA4, 0xF1, 0xA4, 0xF1, 0x9C, 0x90, 0x94, 0x6F, +0x94, 0x4E, 0x94, 0x4E, 0x94, 0x8F, 0x9C, 0x8F, +0xA4, 0xD0, 0xA4, 0xF0, 0xB5, 0x52, 0xAD, 0x31, +0xA4, 0xD0, 0x9C, 0x8F, 0x73, 0x6A, 0x73, 0x4B, +0xB5, 0x53, 0xAD, 0x12, 0xAD, 0x12, 0xAD, 0x32, +0xAD, 0x32, 0xAC, 0xF1, 0xA4, 0xB0, 0x9C, 0xB0, +0x9C, 0xB0, 0x9C, 0xB0, 0x9C, 0x8F, 0x9C, 0xB0, +0xA4, 0xB0, 0xA4, 0xB0, 0x9C, 0x90, 0x9C, 0x6F, +0x9C, 0xB0, 0x9C, 0x8F, 0x94, 0x4E, 0xA4, 0xB0, +0x9C, 0x8F, 0x9C, 0x6E, 0xA4, 0xD0, 0xB5, 0x52, +0x8C, 0x0D, 0xB5, 0x32, 0x9C, 0x6E, 0xAD, 0x11, +0xB5, 0x11, 0xB5, 0x11, 0xB4, 0xF0, 0xB5, 0x11, +0xAC, 0xCF, 0xA4, 0xAF, 0xB5, 0x11, 0xBD, 0x51, +0xBD, 0x31, 0xC5, 0x71, 0xCD, 0xD3, 0xA4, 0xAF, +0xAC, 0xD0, 0xB5, 0x31, 0xBD, 0x93, 0xD6, 0x56, +0xE6, 0xD8, 0xDE, 0xB8, 0xD6, 0x77, 0xC5, 0xD5, +0xAD, 0x13, 0x8C, 0x50, 0x8C, 0x70, 0xBD, 0xF6, +0xC5, 0xF6, 0xA5, 0x33, 0x7B, 0xCE, 0x9C, 0xD2, +0xB5, 0x74, 0xB5, 0x74, 0xAD, 0x54, 0x9C, 0xD2, +0x8C, 0x50, 0x73, 0xAE, 0x63, 0x0B, 0x4A, 0x8A, +0x42, 0x08, 0x31, 0x86, 0x21, 0x25, 0x21, 0x04, +0x18, 0xE4, 0x21, 0x04, 0x31, 0xA7, 0x52, 0x8A, +0x73, 0xCF, 0x84, 0x11, 0x8C, 0x93, 0x94, 0xB4, +0x9C, 0xF5, 0x9C, 0xF5, 0x9D, 0x15, 0xA5, 0x15, +0x9D, 0x15, 0x94, 0x93, 0x84, 0x10, 0x6B, 0x4D, +0x6B, 0x2C, 0x73, 0x4C, 0x8C, 0x2F, 0xA4, 0xF3, +0x9C, 0x91, 0x8C, 0x0F, 0x83, 0xCF, 0x83, 0xCE, +0x7B, 0xCE, 0x7B, 0xCE, 0x7B, 0xCF, 0x7B, 0xCF, +0x7C, 0x10, 0x84, 0x32, 0x8C, 0x93, 0x9C, 0xF5, +0xA5, 0x55, 0xA5, 0x55, 0xA5, 0x55, 0xA5, 0x35, +0x9D, 0x14, 0x8C, 0x92, 0x52, 0x8A, 0x8B, 0xCE, +0x6B, 0x0B, 0x6B, 0x2C, 0x73, 0x8D, 0x73, 0xAD, +0x73, 0x8D, 0x83, 0xEE, 0x84, 0x0E, 0x8C, 0x4F, +0x94, 0x70, 0x94, 0x90, 0x94, 0x70, 0x83, 0xCD, +0x31, 0x65, 0x39, 0xC6, 0x31, 0x85, 0x6B, 0x2B, +0x73, 0x4B, 0x6B, 0x2B, 0x73, 0x4C, 0x5A, 0x68, +0x7A, 0xEB, 0x7A, 0xCA, 0x82, 0xEB, 0x7A, 0xEA, +0x5A, 0x07, 0x62, 0xA9, 0x83, 0x8C, 0x83, 0xAD, +0x8B, 0xEE, 0x8B, 0xEE, 0x94, 0x4F, 0x8B, 0xED, +0x83, 0xED, 0x8C, 0x0E, 0x8C, 0x2E, 0x7B, 0x8C, +0x4A, 0x07, 0x31, 0x85, 0x29, 0x65, 0x29, 0x44, +0x29, 0x65, 0x21, 0x24, 0x19, 0x03, 0x21, 0x24, +0x21, 0x03, 0x21, 0x03, 0x21, 0x03, 0x19, 0x03, +0x21, 0x45, 0xAD, 0x76, 0xE7, 0x1D, 0xBD, 0xD8, +0x5A, 0xAB, 0x6B, 0x4D, 0xA5, 0x35, 0x8C, 0x51, +0x42, 0x08, 0x42, 0x28, 0x84, 0x30, 0x39, 0xC7, +0x42, 0x07, 0x4A, 0x69, 0x4A, 0x49, 0x4A, 0x69, +0x52, 0x8A, 0x4A, 0x6A, 0x4A, 0x29, 0x5A, 0xCB, +0x7B, 0xAE, 0x83, 0xCF, 0x6B, 0x0C, 0xA4, 0x92, +0xC5, 0x95, 0xA4, 0xB2, 0x84, 0x10, 0xD6, 0xBA, +0xE7, 0x3C, 0x9C, 0xD3, 0x39, 0x66, 0x62, 0xCA, +0xBD, 0xB6, 0x8C, 0x50, 0x6B, 0x6D, 0x94, 0xD2, +0xA5, 0x54, 0xBD, 0xB4, 0xA4, 0xD0, 0x9C, 0x8F, +0xA5, 0x11, 0x9C, 0xB0, 0x9C, 0x8F, 0x9C, 0x8F, +0x8C, 0x2E, 0x8C, 0x2E, 0x8C, 0x0D, 0x83, 0xCC, +0x8C, 0x0D, 0x94, 0x6F, 0x8C, 0x2E, 0x83, 0xEC, +0x94, 0x6E, 0x9C, 0x6E, 0xB5, 0x31, 0x83, 0xAB, +0xAD, 0x52, 0xC5, 0xD5, 0xBD, 0xB4, 0xC6, 0x16, +0xBD, 0xB4, 0x83, 0xCD, 0x7B, 0xAD, 0x84, 0x0E, +0x83, 0xED, 0x84, 0x0E, 0xB5, 0x93, 0xC6, 0x15, +0xC6, 0x16, 0xC5, 0xF5, 0xCE, 0x36, 0xC6, 0x15, +0xBD, 0xD4, 0x73, 0xAC, 0x6B, 0x4B, 0x73, 0x8C, +0x94, 0x6F, 0xA4, 0xAF, 0xC5, 0x71, 0x83, 0x6B, +0x9C, 0xD1, 0xB5, 0x93, 0x94, 0x6F, 0x9C, 0xD0, +0x8C, 0x4E, 0x94, 0x8F, 0xA5, 0x12, 0x9C, 0xB0, +0x9C, 0xD1, 0x9C, 0xD1, 0xB5, 0x95, 0xAD, 0x96, +0xA5, 0x35, 0x94, 0x92, 0x73, 0x8D, 0x94, 0x70, +0xB5, 0x52, 0xAD, 0x11, 0xB5, 0x52, 0xAD, 0x31, +0xAD, 0x52, 0xA4, 0xB0, 0xA4, 0xB0, 0x73, 0x6C, +0x8C, 0x2F, 0x94, 0x70, 0x84, 0x0E, 0x83, 0xEE, +0x8C, 0x4F, 0x94, 0x4F, 0x7B, 0xCD, 0x73, 0x4C, +0x94, 0x70, 0xAD, 0x32, 0x9C, 0xD1, 0x9C, 0x90, +0xA4, 0xD1, 0x9C, 0x90, 0xA4, 0xF2, 0xA4, 0xD1, +0xA4, 0xD1, 0x8C, 0x2F, 0x8C, 0x2F, 0x8C, 0x4F, +0x8C, 0x2E, 0x94, 0x70, 0xA4, 0xF2, 0x9C, 0x90, +0xAD, 0x12, 0x8C, 0x0E, 0x8C, 0x0E, 0xA4, 0xF2, +0xAD, 0x12, 0xAD, 0x33, 0xB5, 0x74, 0xB5, 0x94, +0xAD, 0x33, 0xAD, 0x33, 0xAD, 0x33, 0xA4, 0xF2, +0x9C, 0xB1, 0xAD, 0x12, 0xAD, 0x33, 0xB5, 0x74, +0xA5, 0x12, 0xAD, 0x53, 0x9C, 0xD1, 0x9C, 0x90, +0xA4, 0xF1, 0xAD, 0x12, 0xAD, 0x33, 0xAD, 0x32, +0xAD, 0x32, 0xB5, 0x73, 0xBD, 0xB5, 0xBD, 0x94, +0xBD, 0xB4, 0xAD, 0x12, 0xA4, 0xD0, 0xB5, 0x73, +0xAC, 0xF1, 0xA4, 0xF1, 0xAD, 0x12, 0xAD, 0x32, +0xAD, 0x33, 0xAD, 0x33, 0xBD, 0x94, 0xC5, 0xD5, +0xBD, 0xB5, 0xC5, 0xF5, 0xC5, 0xF5, 0xC5, 0xF6, +0xC5, 0xF5, 0xC5, 0xF5, 0xC5, 0xF5, 0xC5, 0xD5, +0xC5, 0xD5, 0xC5, 0xF5, 0xC5, 0xD5, 0xC5, 0xF6, +0xCD, 0xF5, 0xC5, 0xD5, 0xC5, 0xD5, 0xCD, 0xF6, +0xC5, 0xF5, 0xBD, 0xB4, 0xB5, 0x53, 0xB5, 0x53, +0xBD, 0x74, 0xC5, 0xF5, 0xBD, 0x94, 0xB5, 0x53, +0xBD, 0x73, 0xBD, 0x73, 0xBD, 0x74, 0xBD, 0x73, +0xBD, 0x73, 0xB5, 0x73, 0xAD, 0x12, 0xA4, 0xF1, +0xAD, 0x11, 0xAC, 0xF1, 0xA4, 0xAF, 0xA4, 0x8F, +0x9C, 0x6F, 0x94, 0x4E, 0x94, 0x4E, 0x94, 0x4F, +0x9C, 0x90, 0xAD, 0x12, 0xB5, 0x32, 0xA4, 0xB0, +0xA4, 0xF1, 0xA4, 0xF2, 0x7B, 0xCE, 0x83, 0xEE, +0xA4, 0xF1, 0xBD, 0xD5, 0x83, 0xEE, 0x9C, 0xD2, +0x9C, 0xD1, 0x9C, 0xD2, 0xAD, 0x33, 0xB5, 0x74, +0xAD, 0x13, 0x9C, 0xD2, 0x94, 0x91, 0x8C, 0x50, +0x84, 0x30, 0x7B, 0xEF, 0x6B, 0x6E, 0x5A, 0xCB, +0x39, 0xE8, 0x29, 0x45, 0x21, 0x05, 0x19, 0x04, +0x18, 0xE4, 0x21, 0x45, 0x42, 0x08, 0x5A, 0xCB, +0x6B, 0x4E, 0x7B, 0xD0, 0x7C, 0x10, 0x7C, 0x11, +0x84, 0x31, 0x8C, 0x72, 0x94, 0x92, 0x9C, 0xB3, +0x9C, 0xD2, 0x9C, 0xB2, 0x8C, 0x0F, 0x7B, 0xAD, +0x7B, 0x8C, 0x8B, 0xCE, 0x6B, 0x0B, 0x7B, 0x6C, +0x7B, 0xAD, 0x7B, 0x6C, 0x73, 0x4B, 0x63, 0x2B, +0x6B, 0x2D, 0x7B, 0xF0, 0x7B, 0xF0, 0x84, 0x32, +0xA5, 0x55, 0xA5, 0x55, 0xA5, 0x35, 0xA5, 0x34, +0x9C, 0xF4, 0x8C, 0x51, 0x41, 0xE7, 0x42, 0x07, +0x52, 0x68, 0x63, 0x0B, 0x6B, 0x4B, 0x7B, 0xAD, +0x84, 0x0E, 0x8C, 0x4F, 0x94, 0x4F, 0x8C, 0x0E, +0x8C, 0x2D, 0x9C, 0x8E, 0x9C, 0x8E, 0x94, 0x2D, +0x73, 0x2B, 0x73, 0x4B, 0x5A, 0x88, 0x9C, 0x8F, +0xA4, 0xB0, 0xA4, 0x8F, 0xA4, 0x8F, 0x62, 0xAA, +0x5A, 0x28, 0x6A, 0x69, 0x72, 0x8A, 0x7A, 0xCA, +0x6A, 0x8A, 0x62, 0x89, 0x72, 0xEB, 0x83, 0x8D, +0x83, 0x8D, 0xA4, 0x90, 0xAC, 0xF0, 0xAC, 0xF0, +0xB5, 0x11, 0xB5, 0x31, 0xB5, 0x11, 0xB5, 0x31, +0xA4, 0xD0, 0x4A, 0x27, 0x29, 0x65, 0x29, 0x65, +0x31, 0x65, 0x29, 0x44, 0x29, 0x65, 0x21, 0x24, +0x21, 0x24, 0x19, 0x03, 0x18, 0xE3, 0x29, 0x87, +0x94, 0xB4, 0xE7, 0x3E, 0xCE, 0x5A, 0x9C, 0xD4, +0x39, 0xC8, 0x9C, 0xD3, 0xBD, 0xF7, 0x84, 0x31, +0x84, 0x10, 0x9C, 0xF4, 0xA4, 0xF4, 0x42, 0x29, +0x7B, 0xCF, 0xBD, 0xD7, 0xBD, 0xF8, 0xB5, 0x96, +0x84, 0x10, 0x52, 0x8A, 0x52, 0xAA, 0x5A, 0xEB, +0x39, 0xC7, 0x52, 0x8A, 0x62, 0xCB, 0x5A, 0xAA, +0xA4, 0x91, 0x62, 0xAA, 0x73, 0x6E, 0xBD, 0xF8, +0xD6, 0x9A, 0xC6, 0x39, 0x6B, 0x0C, 0xC5, 0xF6, +0xC5, 0xF6, 0x8C, 0x30, 0x6B, 0x6D, 0x8C, 0x71, +0xB5, 0x94, 0xB5, 0x93, 0xA4, 0xD0, 0x9C, 0xAF, +0xB5, 0x93, 0xB5, 0x52, 0xA4, 0xF0, 0xA4, 0xD0, +0xA4, 0xF0, 0xA4, 0xF0, 0x83, 0xCC, 0x83, 0xEC, +0x8C, 0x4E, 0xA4, 0xF0, 0x8C, 0x2E, 0x8C, 0x0D, +0x84, 0x0C, 0x94, 0x6E, 0xB5, 0x10, 0x7B, 0x8B, +0xB5, 0x93, 0xBD, 0xD4, 0xBD, 0xD5, 0xC6, 0x16, +0xBD, 0xD4, 0x8C, 0x2E, 0x7B, 0xCD, 0x84, 0x0E, +0x83, 0xED, 0x94, 0x6F, 0xAD, 0x53, 0xC6, 0x15, +0xCE, 0x36, 0xC6, 0x15, 0xC6, 0x35, 0xCE, 0x36, +0xBD, 0xD4, 0x8C, 0x4F, 0x73, 0x8C, 0x73, 0xAC, +0x7B, 0x8C, 0xA4, 0xB0, 0xBD, 0x51, 0x7B, 0x4A, +0x9C, 0xD1, 0xB5, 0x73, 0x94, 0xB0, 0xAD, 0x32, +0xA5, 0x11, 0x9C, 0xD1, 0xA5, 0x32, 0x9C, 0xD0, +0x9C, 0xD1, 0x9C, 0xD1, 0xB5, 0xB6, 0xAD, 0x55, +0xA5, 0x15, 0x94, 0x92, 0x6B, 0x6C, 0x9D, 0x12, +0xAD, 0x73, 0xAD, 0x73, 0xB5, 0x73, 0xAD, 0x52, +0xB5, 0x94, 0x8C, 0x2E, 0xA4, 0xF1, 0x83, 0xCD, +0x83, 0xEE, 0x8C, 0x4F, 0x84, 0x0E, 0x83, 0xEE, +0x8C, 0x2F, 0x83, 0xEE, 0x7B, 0xAD, 0x7B, 0xAD, +0xA4, 0xF2, 0xAD, 0x53, 0xA5, 0x12, 0xAD, 0x73, +0xA5, 0x12, 0xA4, 0xF2, 0xA4, 0xF2, 0xA5, 0x12, +0xAD, 0x73, 0xA5, 0x32, 0xA5, 0x12, 0xA5, 0x32, +0x94, 0x70, 0x84, 0x0E, 0xA4, 0xD1, 0xA4, 0xD1, +0x9C, 0xB1, 0x9C, 0xB1, 0xB5, 0x94, 0xBD, 0x94, +0xAD, 0x53, 0xB5, 0x53, 0xB5, 0x73, 0xBD, 0xB4, +0xB5, 0x94, 0xB5, 0x73, 0xAD, 0x53, 0xA4, 0xF1, +0xAD, 0x12, 0xB5, 0x74, 0xAD, 0x12, 0xAD, 0x53, +0x9C, 0x90, 0xAC, 0xF2, 0x83, 0xCD, 0x8C, 0x0E, +0x84, 0x0E, 0x6B, 0x2B, 0x8C, 0x4F, 0x8C, 0x2E, +0x84, 0x0E, 0x9C, 0x90, 0x9C, 0xB0, 0x8C, 0x2E, +0x9C, 0xD1, 0x94, 0x6F, 0x84, 0x0E, 0x84, 0x0D, +0x83, 0xCD, 0x83, 0xCC, 0x94, 0x6E, 0xA4, 0xAF, +0x94, 0x4E, 0x94, 0x6E, 0x94, 0x2E, 0x7B, 0x8B, +0x8C, 0x0D, 0x8C, 0x2D, 0x8C, 0x2D, 0x94, 0x2E, +0x8C, 0x2D, 0x83, 0xCC, 0x8C, 0x2E, 0xB5, 0x52, +0x94, 0x6F, 0x8C, 0x2E, 0x8C, 0x0D, 0x94, 0x4E, +0x9C, 0x8F, 0x9C, 0xB0, 0x9C, 0x90, 0x94, 0x4F, +0xA4, 0xD0, 0xAD, 0x11, 0xAD, 0x12, 0xAC, 0xF1, +0xAC, 0xF2, 0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x12, +0xAC, 0xF2, 0xB5, 0x32, 0xB5, 0x53, 0xB5, 0x53, +0xB5, 0x32, 0xBD, 0x73, 0xC5, 0xD5, 0xCE, 0x16, +0xCE, 0x36, 0xBD, 0x73, 0xAC, 0xF1, 0xAD, 0x11, +0xAC, 0xF1, 0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x12, +0xA4, 0xF1, 0xA4, 0xF1, 0xAD, 0x11, 0xAD, 0x11, +0xB5, 0x32, 0xB5, 0x53, 0xB5, 0x74, 0xB5, 0x53, +0xA4, 0xF2, 0x94, 0x4F, 0x94, 0x90, 0xA5, 0x12, +0xAD, 0x13, 0xA5, 0x13, 0x94, 0x70, 0x8C, 0x0F, +0x94, 0x70, 0xA4, 0xF2, 0xB5, 0x54, 0xB5, 0x74, +0xAD, 0x33, 0xA4, 0xF3, 0x9C, 0xD2, 0x94, 0x92, +0x8C, 0x71, 0x73, 0xAE, 0x5A, 0xEB, 0x42, 0x08, +0x29, 0x66, 0x21, 0x45, 0x21, 0x45, 0x29, 0x45, +0x29, 0x45, 0x31, 0xA7, 0x42, 0x49, 0x5A, 0xEC, +0x63, 0x2D, 0x7C, 0x11, 0x84, 0x31, 0x7C, 0x11, +0x73, 0xAE, 0x73, 0x8E, 0x7B, 0xCF, 0x83, 0xEF, +0x83, 0xEF, 0x8C, 0x10, 0x73, 0x6D, 0x52, 0x89, +0x6B, 0x2B, 0x7B, 0x6C, 0x7B, 0x8C, 0x52, 0x89, +0x52, 0x6A, 0x5A, 0xCB, 0x73, 0x6D, 0x7B, 0xD0, +0xA5, 0x55, 0xA5, 0x55, 0xA5, 0x55, 0x9D, 0x14, +0x9C, 0xF4, 0x84, 0x51, 0x4A, 0x28, 0x7B, 0xCD, +0x8C, 0x2E, 0x9C, 0xB0, 0x94, 0x8F, 0x9C, 0x8F, +0xB5, 0x72, 0xBD, 0xB3, 0xC5, 0xD3, 0xBD, 0xB2, +0xBD, 0x51, 0xC5, 0xB2, 0xC5, 0xB2, 0xBD, 0x71, +0xBD, 0x71, 0xBD, 0x51, 0xBD, 0x71, 0xBD, 0x92, +0xBD, 0x72, 0xBD, 0x72, 0xBD, 0x51, 0x94, 0x2E, +0x6B, 0x0B, 0x5A, 0x28, 0x62, 0x69, 0x72, 0xAA, +0x7A, 0xEB, 0x72, 0xCB, 0x83, 0x6D, 0x8B, 0xCE, +0x83, 0x8C, 0x9C, 0x6F, 0xA4, 0x8F, 0xA4, 0xAF, +0x9C, 0x6E, 0xA4, 0x8F, 0xA4, 0x8F, 0xA4, 0xAF, +0xAC, 0xF0, 0x8C, 0x0E, 0x39, 0xA5, 0x31, 0x85, +0x29, 0x24, 0x29, 0x65, 0x29, 0x64, 0x29, 0x64, +0x29, 0x64, 0x52, 0xAB, 0xA5, 0x15, 0xD6, 0xBC, +0xE7, 0x3E, 0xCE, 0x7A, 0xAD, 0x15, 0x6B, 0x2D, +0x7B, 0xCF, 0xA5, 0x14, 0xB5, 0x96, 0xA5, 0x34, +0xAD, 0x76, 0xA5, 0x35, 0x94, 0x92, 0x5A, 0xEB, +0x7B, 0xEF, 0x6B, 0x6D, 0x63, 0x0C, 0x6B, 0x4D, +0x6B, 0x2C, 0x4A, 0x49, 0x63, 0x2C, 0x83, 0xF0, +0x4A, 0x49, 0x42, 0x08, 0x39, 0xA7, 0x52, 0x69, +0x73, 0x6D, 0x62, 0xEC, 0x84, 0x31, 0xA5, 0x35, +0xBD, 0xF8, 0xD6, 0x7A, 0xA5, 0x34, 0xAD, 0x34, +0xC6, 0x17, 0xC5, 0xF8, 0x84, 0x10, 0xAD, 0x54, +0xBD, 0xD5, 0xB5, 0x73, 0xAC, 0xF0, 0xA4, 0xF0, +0xBD, 0x93, 0xBD, 0xB3, 0xAD, 0x32, 0x9C, 0xAF, +0x94, 0x6E, 0xA4, 0xD0, 0x9C, 0x8F, 0x8C, 0x2D, +0x94, 0x6F, 0xA4, 0xD0, 0x94, 0x6F, 0x9C, 0x8F, +0x94, 0x6E, 0x94, 0x8F, 0xAC, 0xF0, 0x83, 0xAC, +0xA5, 0x32, 0xC6, 0x15, 0xC5, 0xF5, 0xCE, 0x36, +0xC5, 0xF5, 0x7B, 0xCD, 0x83, 0xED, 0x7B, 0xAC, +0x8C, 0x6F, 0xA4, 0xF1, 0xBD, 0xB4, 0xCE, 0x36, +0xC6, 0x35, 0xCE, 0x56, 0xCE, 0x56, 0xC5, 0xF5, +0xAD, 0x53, 0x8C, 0x4F, 0x7B, 0xCD, 0x6B, 0x2B, +0x6B, 0x6C, 0x83, 0xEC, 0xBD, 0x51, 0x73, 0x2A, +0xA4, 0xF2, 0xAD, 0x32, 0x9C, 0xB0, 0xAD, 0x32, +0x94, 0x6F, 0x8C, 0x4E, 0xBD, 0xB4, 0xA4, 0xF1, +0x9C, 0xD1, 0x9C, 0xF2, 0xBD, 0xD6, 0xAD, 0x55, +0xA5, 0x14, 0x9C, 0xD3, 0x7B, 0xCE, 0x9D, 0x12, +0xAD, 0x94, 0xB5, 0x94, 0xB5, 0x94, 0xB5, 0x93, +0xBD, 0xD5, 0x94, 0x6F, 0xAD, 0x32, 0x8C, 0x2E, +0x8C, 0x4F, 0x94, 0x90, 0x94, 0x70, 0x84, 0x0E, +0x9C, 0x90, 0x83, 0xED, 0x83, 0xEE, 0x7B, 0xCE, +0x9C, 0xB1, 0xA5, 0x12, 0x9C, 0xD1, 0xAD, 0x53, +0x9C, 0xD1, 0x94, 0x90, 0x9C, 0xD1, 0xA4, 0xF2, +0xB5, 0x74, 0xA4, 0xF2, 0x9C, 0xF1, 0xAD, 0x53, +0x94, 0x90, 0x8C, 0x2F, 0xA4, 0xF2, 0xA4, 0xF1, +0x9C, 0x90, 0xAD, 0x53, 0xA4, 0xF1, 0x9C, 0xB0, +0xA5, 0x12, 0xAD, 0x32, 0xCE, 0x36, 0xCE, 0x16, +0xC6, 0x16, 0xC6, 0x15, 0xC5, 0xD4, 0xBD, 0xB4, +0xC5, 0xF5, 0xCE, 0x36, 0xC6, 0x15, 0xC5, 0xD5, +0x9C, 0xD1, 0xB5, 0x53, 0xA5, 0x12, 0x84, 0x0E, +0x6B, 0x4B, 0x84, 0x2E, 0xA4, 0xF1, 0x9C, 0xD0, +0x9C, 0xD0, 0x9C, 0xD0, 0x94, 0x6F, 0x83, 0xED, +0x9C, 0xD1, 0xA5, 0x11, 0xAD, 0x52, 0xAD, 0x52, +0x9C, 0x8F, 0x9C, 0xB0, 0xBD, 0xB2, 0xCE, 0x13, +0xCE, 0x13, 0xBD, 0x71, 0xAD, 0x10, 0x7B, 0x8B, +0x94, 0x6E, 0xA4, 0xF0, 0xAD, 0x10, 0xB5, 0x50, +0xBD, 0x91, 0xA4, 0xCF, 0x83, 0xEC, 0xB5, 0x52, +0x94, 0x6E, 0x9C, 0x8F, 0x94, 0x6E, 0xA4, 0xD0, +0xA4, 0xD0, 0xAD, 0x10, 0xAD, 0x10, 0xA4, 0xCF, +0xA4, 0xD0, 0xAC, 0xF0, 0x9C, 0x8F, 0x7B, 0x8B, +0x9C, 0x6F, 0xA4, 0xD0, 0xA4, 0xD0, 0x9C, 0xB0, +0xA4, 0xB0, 0xAD, 0x11, 0x9C, 0x6F, 0xA4, 0xF1, +0xAD, 0x32, 0xAD, 0x32, 0x9C, 0xB0, 0xAC, 0xF2, +0xAD, 0x12, 0x9C, 0x6F, 0x9C, 0xB0, 0xB5, 0x32, +0xB5, 0x73, 0xB5, 0x73, 0xBD, 0x93, 0xBD, 0x94, +0xBD, 0x93, 0xBD, 0x93, 0xC5, 0xD4, 0xBD, 0x93, +0xBD, 0x93, 0xB5, 0x52, 0xB5, 0x32, 0xBD, 0x94, +0xBD, 0x93, 0xB5, 0x73, 0xB5, 0x73, 0xAD, 0x12, +0x8C, 0x2F, 0x8C, 0x2F, 0x9C, 0xD2, 0xA4, 0xF2, +0x9C, 0xB1, 0x8C, 0x2F, 0x83, 0xEE, 0x94, 0x91, +0xAD, 0x33, 0xAD, 0x54, 0xAD, 0x34, 0xA5, 0x13, +0xA5, 0x13, 0x9D, 0x13, 0x9D, 0x13, 0x9C, 0xD2, +0x7C, 0x0F, 0x5A, 0xEB, 0x3A, 0x08, 0x29, 0x87, +0x31, 0xC8, 0x3A, 0x08, 0x39, 0xE8, 0x31, 0xC7, +0x39, 0xE8, 0x52, 0xAB, 0x6B, 0x4E, 0x84, 0x32, +0xA4, 0xF4, 0xA5, 0x15, 0xA5, 0x15, 0x9C, 0xF4, +0x8C, 0x52, 0x73, 0xAF, 0x6B, 0x4E, 0x63, 0x0D, +0x5A, 0xEB, 0x62, 0xEB, 0x62, 0xEB, 0x5A, 0xEB, +0x5A, 0xCB, 0x52, 0x49, 0x4A, 0x28, 0x52, 0x6A, +0xA5, 0x55, 0xA5, 0x55, 0xA5, 0x55, 0xA5, 0x15, +0x9C, 0xF4, 0x84, 0x31, 0x62, 0xEA, 0x9C, 0xB0, +0x94, 0x6E, 0x9C, 0x6E, 0x94, 0x4D, 0xA4, 0xCF, +0xB5, 0x92, 0xBD, 0x92, 0xC5, 0xD2, 0xC5, 0xB2, +0xC5, 0xB2, 0xC5, 0xB1, 0xC5, 0xB1, 0xB5, 0x2F, +0xBD, 0x71, 0xBD, 0x71, 0xCD, 0xF3, 0xC5, 0xB2, +0xC5, 0x92, 0xCD, 0xD3, 0xC5, 0xB2, 0xAC, 0xF0, +0xB5, 0x32, 0x8B, 0xEE, 0x72, 0xEA, 0x7A, 0xEB, +0x72, 0xCA, 0x7B, 0x0B, 0x83, 0x8D, 0x83, 0xAD, +0x94, 0x4F, 0x83, 0xED, 0x7B, 0xAC, 0x8B, 0xED, +0x94, 0x4E, 0x9C, 0x8F, 0x83, 0xCC, 0x83, 0xEC, +0x94, 0x6F, 0x9C, 0xB0, 0x6B, 0x4B, 0x31, 0xA6, +0x29, 0x44, 0x29, 0x65, 0x31, 0x65, 0x31, 0x85, +0x5A, 0xEB, 0xD6, 0xBB, 0xE7, 0x3D, 0xDE, 0xFC, +0xBD, 0xD7, 0x8C, 0x11, 0x73, 0x6E, 0x73, 0x6D, +0x84, 0x30, 0x8C, 0x30, 0xAD, 0x34, 0x94, 0xB2, +0xBD, 0xD7, 0xB5, 0x96, 0xC6, 0x18, 0xA5, 0x34, +0x4A, 0x49, 0x4A, 0x49, 0x42, 0x28, 0x31, 0x66, +0x31, 0x86, 0x39, 0xC7, 0x39, 0xA7, 0x52, 0x6A, +0x52, 0x69, 0x52, 0x8A, 0x52, 0x8A, 0x4A, 0x69, +0x7B, 0x8E, 0x94, 0x92, 0xAD, 0x75, 0xB5, 0xB7, +0xB5, 0x97, 0xDE, 0xDB, 0xC6, 0x18, 0xC6, 0x39, +0xE7, 0x3D, 0xE7, 0x1C, 0xAD, 0x55, 0x8C, 0x2F, +0xA4, 0xD0, 0xAC, 0xF0, 0xA4, 0xCF, 0x9C, 0x6E, +0xA4, 0xD0, 0x9C, 0xAF, 0x9C, 0xAF, 0xA4, 0xD0, +0x9C, 0xAF, 0x94, 0x6E, 0x94, 0x4E, 0xA4, 0xAF, +0xAD, 0x11, 0xB5, 0x72, 0xC5, 0xB3, 0xB5, 0x31, +0x94, 0x4E, 0x94, 0x6E, 0xA4, 0xAF, 0x73, 0x4A, +0x8C, 0x4E, 0xA4, 0xD0, 0xB5, 0x73, 0xB5, 0x93, +0xA4, 0xF1, 0x94, 0x6F, 0x9C, 0xF1, 0x9C, 0xB1, +0x7B, 0xED, 0x9C, 0xB0, 0xC5, 0xF5, 0xD6, 0x77, +0xCE, 0x36, 0xCE, 0x76, 0xCE, 0x55, 0xBD, 0xD4, +0xB5, 0x73, 0x8C, 0x6F, 0x8C, 0x4F, 0x7B, 0xCD, +0x73, 0x8C, 0x73, 0x6A, 0xB5, 0x31, 0x6B, 0x0A, +0x9C, 0xF1, 0xBD, 0xD5, 0x9C, 0xD1, 0x9C, 0xD0, +0x8C, 0x2E, 0x94, 0x8F, 0xB5, 0x73, 0xA5, 0x12, +0x9C, 0xD1, 0xA5, 0x12, 0xBD, 0xF7, 0xAD, 0x76, +0x9C, 0xD3, 0x8C, 0x71, 0x8C, 0x50, 0xA5, 0x32, +0xB5, 0x93, 0xB5, 0x93, 0xB5, 0xB4, 0xB5, 0x94, +0xBD, 0xB4, 0xAD, 0x32, 0xAD, 0x32, 0x8C, 0x2E, +0x94, 0x70, 0x94, 0x70, 0x8C, 0x2F, 0x8C, 0x2F, +0x94, 0x4F, 0x7B, 0xCD, 0x84, 0x0E, 0x84, 0x0E, +0x94, 0xB1, 0xAD, 0x53, 0xA5, 0x12, 0xAD, 0x53, +0xAD, 0x33, 0x9C, 0xD1, 0xA5, 0x33, 0xA4, 0xF2, +0x9C, 0xD1, 0x94, 0x70, 0x94, 0x70, 0x9C, 0xD1, +0x8C, 0x4F, 0x8C, 0x2F, 0xA4, 0xF2, 0xAD, 0x32, +0xA5, 0x32, 0x9C, 0xF1, 0x7B, 0xAD, 0x8C, 0x70, +0xA5, 0x12, 0x94, 0x6F, 0xC6, 0x15, 0xDE, 0xD8, +0xD6, 0x77, 0xCE, 0x56, 0xC5, 0xF5, 0xC5, 0xF5, +0xC5, 0xF5, 0xCE, 0x16, 0xCE, 0x15, 0xC6, 0x15, +0xA4, 0xD1, 0xB5, 0x73, 0xB5, 0x73, 0x94, 0x90, +0x73, 0x8C, 0x7B, 0xAD, 0xAD, 0x32, 0xA5, 0x11, +0xA5, 0x12, 0xA5, 0x11, 0x9C, 0xD0, 0x83, 0xED, +0xA4, 0xF1, 0x9C, 0x8F, 0xB5, 0x93, 0xB5, 0x52, +0xAD, 0x31, 0xB5, 0x72, 0xCE, 0x34, 0xA4, 0xEF, +0x9C, 0x8D, 0xAC, 0xEF, 0xB5, 0x71, 0x83, 0xCB, +0x8C, 0x4E, 0xA4, 0xCF, 0xAC, 0xF0, 0xB5, 0x50, +0xB5, 0x51, 0xAD, 0x10, 0x8C, 0x2E, 0xB5, 0x73, +0x7B, 0xAC, 0x73, 0x4A, 0x6B, 0x29, 0x83, 0xEC, +0x83, 0xCC, 0x9C, 0x8F, 0x9C, 0xAF, 0xA4, 0xF0, +0xB5, 0x72, 0xA4, 0xD0, 0xA4, 0xD0, 0xB5, 0x73, +0xA4, 0xF1, 0x9C, 0xB0, 0xAD, 0x32, 0xA4, 0xD0, +0xA4, 0xF1, 0xBD, 0x94, 0xAD, 0x12, 0xAD, 0x11, +0xBD, 0x93, 0xBD, 0xB3, 0xAD, 0x11, 0xB5, 0x33, +0xAC, 0xF1, 0x9C, 0xD1, 0x9C, 0xD1, 0xB5, 0x53, +0xC5, 0xD4, 0xBD, 0xB3, 0xBD, 0x93, 0xBD, 0x93, +0xBD, 0x94, 0xBD, 0x94, 0xBD, 0x94, 0xBD, 0xB4, +0xC5, 0xD4, 0xBD, 0xB4, 0xC5, 0xF5, 0xC5, 0xD4, +0xC5, 0xD4, 0xCE, 0x15, 0xD6, 0x36, 0xC5, 0xD4, +0xCE, 0x15, 0xCE, 0x36, 0x9C, 0x90, 0x73, 0x8C, +0x9C, 0xB1, 0xAD, 0x33, 0xAD, 0x54, 0x94, 0x91, +0x83, 0xEF, 0x8C, 0x30, 0x8C, 0x50, 0x94, 0x91, +0x9C, 0xD2, 0x94, 0xB2, 0x9C, 0xD2, 0xA5, 0x13, +0x94, 0xB2, 0x8C, 0x71, 0x84, 0x0F, 0x6B, 0x4D, +0x42, 0x49, 0x29, 0x86, 0x21, 0x45, 0x29, 0x46, +0x31, 0xA7, 0x4A, 0x6A, 0x5A, 0xEC, 0x6B, 0x6E, +0x7B, 0xD0, 0x7B, 0xF0, 0x7B, 0xF1, 0x84, 0x11, +0x8C, 0x72, 0x94, 0xB4, 0x9C, 0xF5, 0x9D, 0x15, +0xA5, 0x35, 0xA5, 0x35, 0x9C, 0xF4, 0x94, 0xD4, +0x94, 0xB4, 0x94, 0xD4, 0x8C, 0x72, 0x84, 0x51, +0xA5, 0x55, 0xA5, 0x55, 0xA5, 0x55, 0x9D, 0x34, +0x9C, 0xF4, 0x84, 0x50, 0x63, 0x0A, 0x9C, 0xAF, +0x94, 0x6D, 0x94, 0x4D, 0x9C, 0x8E, 0xA4, 0xF0, +0xAD, 0x51, 0xBD, 0x71, 0xC5, 0xB2, 0xC5, 0xD2, +0xC5, 0xB1, 0xB5, 0x0F, 0xA4, 0xAE, 0xA4, 0xAE, +0xC5, 0xB2, 0x8B, 0xEB, 0xB5, 0x30, 0xB5, 0x10, +0xAD, 0x0F, 0xAD, 0x0F, 0xAD, 0x0F, 0x94, 0x2D, +0xB5, 0x51, 0xA4, 0xAF, 0xA4, 0x6F, 0x83, 0x6C, +0x83, 0xAD, 0x83, 0xCD, 0x8B, 0xEE, 0x62, 0xEA, +0x83, 0xED, 0x83, 0xCD, 0x73, 0x6B, 0x84, 0x0D, +0x5A, 0xC9, 0x63, 0x0A, 0x5A, 0xA8, 0x52, 0x67, +0x6B, 0x4B, 0x84, 0x0E, 0x6B, 0x2B, 0x63, 0x2B, +0x39, 0xC6, 0x29, 0x64, 0x29, 0x64, 0x31, 0xA6, +0xA5, 0x35, 0xE7, 0x1D, 0xB5, 0xB7, 0x94, 0x92, +0x84, 0x10, 0x42, 0x28, 0x4A, 0x28, 0x5A, 0xEB, +0x52, 0x69, 0x7B, 0xAE, 0x8C, 0x50, 0x94, 0x71, +0xB5, 0x96, 0xBD, 0xB6, 0xBD, 0xD7, 0xB5, 0x76, +0x52, 0x69, 0x52, 0x8A, 0x73, 0x6D, 0x42, 0x28, +0x52, 0x89, 0x42, 0x28, 0x31, 0x65, 0x31, 0x86, +0x52, 0x8A, 0x6B, 0x2C, 0x5A, 0xEB, 0x4A, 0x49, +0x73, 0x8E, 0x94, 0x92, 0xA5, 0x35, 0xB5, 0x76, +0x8C, 0x52, 0xD6, 0x9B, 0xAD, 0x56, 0xCE, 0x5A, +0xB5, 0xB7, 0xB5, 0xB7, 0xB5, 0x96, 0x94, 0x90, +0x9C, 0x8F, 0xAC, 0xF0, 0xB5, 0x31, 0x8C, 0x0C, +0x8C, 0x0D, 0x94, 0x2D, 0x94, 0x6E, 0x94, 0x4E, +0xAC, 0xCF, 0xAC, 0xD0, 0xB5, 0x11, 0xC5, 0x92, +0x94, 0x0C, 0x94, 0x2D, 0x94, 0x0C, 0x8B, 0xEC, +0x8C, 0x0C, 0x8B, 0xEC, 0x9C, 0x6E, 0xA4, 0xCF, +0x9C, 0x8F, 0x94, 0x4E, 0x94, 0x2D, 0xA4, 0xAF, +0x9C, 0x6E, 0x94, 0x4E, 0x94, 0x4E, 0x94, 0x6F, +0x8C, 0x0D, 0x94, 0x6E, 0xA4, 0xD0, 0xB5, 0x52, +0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x52, 0xA4, 0xF0, +0xA5, 0x11, 0x94, 0xB0, 0x94, 0x6F, 0x84, 0x2E, +0x7B, 0xCD, 0x73, 0x4A, 0xB5, 0x10, 0x62, 0xC8, +0x9C, 0xF1, 0xBD, 0xD4, 0xAD, 0x32, 0xAD, 0x52, +0xA4, 0xF1, 0xA4, 0xF1, 0xAD, 0x73, 0xB5, 0x73, +0xA5, 0x12, 0xB5, 0x74, 0xC6, 0x58, 0xB5, 0xB7, +0xA5, 0x35, 0x84, 0x30, 0x94, 0xB1, 0xBD, 0xD5, +0xBD, 0xD4, 0xB5, 0x93, 0xB5, 0x94, 0xB5, 0x93, +0xB5, 0x93, 0xB5, 0x73, 0xAD, 0x32, 0x8C, 0x2F, +0x8C, 0x4F, 0x94, 0x70, 0x8C, 0x2E, 0x84, 0x0E, +0x94, 0x6F, 0x83, 0xED, 0x84, 0x0E, 0x94, 0x90, +0xAD, 0x53, 0xB5, 0xD5, 0xB5, 0x74, 0xB5, 0x94, +0xAD, 0x74, 0xAD, 0x74, 0xBD, 0xD6, 0xA5, 0x33, +0x9C, 0xF2, 0x84, 0x0E, 0x8C, 0x2F, 0x8C, 0x4F, +0x8C, 0x4F, 0x8C, 0x2F, 0xB5, 0x53, 0xB5, 0x74, +0xA4, 0xF2, 0x9C, 0xB1, 0x8C, 0x2F, 0x94, 0x90, +0xAD, 0x33, 0x94, 0x6F, 0xCE, 0x57, 0xCE, 0x56, +0xD6, 0x97, 0xCE, 0x36, 0xCE, 0x35, 0xCE, 0x15, +0xCE, 0x36, 0xCE, 0x56, 0xC6, 0x15, 0xC5, 0xF5, +0x9C, 0x90, 0xB5, 0x74, 0xC5, 0xF5, 0x9C, 0xD1, +0x94, 0x90, 0x94, 0x90, 0xAD, 0x52, 0xA4, 0xF1, +0xAD, 0x53, 0xA4, 0xF1, 0x9C, 0xB0, 0x7B, 0x8C, +0x8C, 0x4F, 0x9C, 0xB0, 0xBD, 0xB3, 0xBD, 0xB3, +0xBD, 0xB3, 0xC5, 0xB3, 0xC5, 0xD3, 0x73, 0x8A, +0x9C, 0xAE, 0x9C, 0x6D, 0x94, 0x2D, 0x94, 0x6E, +0xAD, 0x52, 0xC5, 0xF4, 0xB5, 0x71, 0xBD, 0x92, +0xBD, 0x71, 0xAD, 0x30, 0x9C, 0xAF, 0xAD, 0x12, +0x7B, 0x8B, 0x7B, 0x8B, 0x73, 0xAC, 0x94, 0x6F, +0x94, 0x4E, 0x94, 0x6E, 0x9C, 0x8E, 0xAD, 0x10, +0xA4, 0xCF, 0x94, 0x6E, 0xA4, 0xD0, 0xC5, 0xF5, +0xAD, 0x32, 0xA4, 0xF1, 0xB5, 0x93, 0x9C, 0xB0, +0xA4, 0xF1, 0xAD, 0x32, 0xAD, 0x32, 0x94, 0x8F, +0xA4, 0xF0, 0xA5, 0x10, 0xA4, 0xF1, 0xBD, 0x73, +0x9C, 0x90, 0x7B, 0xCE, 0x8C, 0x4F, 0xA5, 0x32, +0xBD, 0xD4, 0xBD, 0x93, 0xB5, 0x72, 0xB5, 0x52, +0xB5, 0x52, 0xB5, 0x73, 0xB5, 0x94, 0xB5, 0x53, +0xBD, 0xB4, 0xC5, 0xF5, 0xBD, 0x93, 0xBD, 0x93, +0xBD, 0xB3, 0xC5, 0xB4, 0xCD, 0xF5, 0xBD, 0x94, +0xBD, 0xB3, 0xD6, 0x56, 0xD6, 0x57, 0x94, 0x4F, +0xA4, 0xF2, 0xAD, 0x33, 0x9C, 0xD2, 0x9C, 0xD1, +0xA4, 0xF2, 0xA5, 0x13, 0x9C, 0xB1, 0xA5, 0x12, +0x8C, 0x70, 0x7B, 0xEE, 0x94, 0x70, 0x94, 0x91, +0x9C, 0xD2, 0x9C, 0xB1, 0x94, 0x91, 0x8C, 0x50, +0x7B, 0xCE, 0x6B, 0x4D, 0x5A, 0xCB, 0x52, 0x8A, +0x39, 0xE8, 0x31, 0x86, 0x29, 0x46, 0x39, 0xE8, +0x52, 0xCB, 0x73, 0x8F, 0x84, 0x31, 0x84, 0x52, +0x6B, 0x6F, 0x63, 0x0D, 0x5A, 0xEC, 0x5A, 0xEC, +0x73, 0x8F, 0x84, 0x31, 0x94, 0xB3, 0x94, 0xD4, +0x94, 0xB3, 0x8C, 0x93, 0x9C, 0xD4, 0x9C, 0xF5, +0xA5, 0x55, 0xA5, 0x55, 0xA5, 0x55, 0x9D, 0x34, +0x9C, 0xF4, 0x84, 0x30, 0x62, 0xE9, 0x94, 0x2D, +0x94, 0x2C, 0x8C, 0x0C, 0x94, 0x4D, 0x94, 0x2C, +0x9C, 0xAE, 0xAD, 0x0F, 0xAC, 0xEF, 0xBD, 0x91, +0xA4, 0xCE, 0xAD, 0x10, 0xB5, 0x50, 0xAD, 0x10, +0xBD, 0x92, 0x73, 0x29, 0x94, 0x4D, 0x9C, 0x8E, +0x9C, 0x6D, 0xA4, 0xCF, 0xAC, 0xCF, 0x8B, 0xEC, +0xA4, 0xEF, 0xAD, 0x10, 0x94, 0x0D, 0x83, 0xCD, +0x7B, 0xAD, 0x9C, 0xB0, 0xA4, 0xF1, 0x6B, 0x6B, +0x94, 0x6F, 0x8C, 0x4F, 0x8C, 0x6F, 0xAD, 0x53, +0x73, 0x6C, 0x73, 0x8D, 0x6B, 0x4C, 0x7B, 0xAD, +0x73, 0x8C, 0x94, 0x4F, 0x8C, 0x0E, 0x9C, 0xB0, +0x7B, 0xCD, 0x39, 0xC6, 0x29, 0x65, 0x39, 0xE7, +0x94, 0xB3, 0xD6, 0xBA, 0xAD, 0x55, 0x4A, 0x29, +0x4A, 0x48, 0x42, 0x28, 0x4A, 0x28, 0x42, 0x28, +0x73, 0x6D, 0x8C, 0x30, 0x94, 0x71, 0x9C, 0xB3, +0xA5, 0x14, 0xAD, 0x34, 0xAD, 0x75, 0xAD, 0x34, +0x6B, 0x6D, 0x5A, 0xCB, 0x63, 0x0B, 0x29, 0x45, +0x39, 0xC7, 0x39, 0xE7, 0x42, 0x28, 0x4A, 0x28, +0x52, 0x89, 0x5A, 0xEB, 0x42, 0x28, 0x4A, 0x69, +0x5A, 0xEB, 0x7C, 0x10, 0x94, 0xD3, 0xAD, 0x96, +0xBD, 0xB7, 0xBD, 0xF8, 0xBD, 0xD8, 0xC6, 0x39, +0xD6, 0xBB, 0xCE, 0x5A, 0xC6, 0x18, 0x9C, 0xD2, +0xAD, 0x52, 0xB5, 0x93, 0xC6, 0x15, 0x9C, 0xD0, +0x8C, 0x2E, 0x8C, 0x2E, 0x94, 0x4E, 0x94, 0x4E, +0x94, 0x4E, 0x8C, 0x2D, 0x94, 0x2D, 0xAC, 0xCF, +0x7B, 0x8B, 0x73, 0x6B, 0x8C, 0x0D, 0x83, 0xEC, +0x73, 0x8B, 0x73, 0x4A, 0x62, 0xC9, 0x83, 0xED, +0x8B, 0xEC, 0x8B, 0xEC, 0x8B, 0xEC, 0xBD, 0x31, +0xA4, 0x6D, 0xAC, 0xCF, 0xA4, 0xAF, 0xA4, 0xAF, +0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0xAF, +0xAC, 0xCF, 0xAC, 0xD0, 0xAC, 0xCF, 0x9C, 0x4D, +0x8C, 0x0D, 0x9C, 0x6E, 0x94, 0x2D, 0x8B, 0xEC, +0x8B, 0xEC, 0xAC, 0xF0, 0xBD, 0x51, 0xAC, 0xAF, +0xA4, 0xCF, 0xA4, 0x8F, 0x9C, 0x4E, 0x9C, 0x6E, +0x94, 0x2D, 0x94, 0x4E, 0x9C, 0x8F, 0xA4, 0xD0, +0x94, 0x4E, 0x94, 0x90, 0xC6, 0x38, 0xB5, 0xD7, +0xB5, 0x76, 0x8C, 0x51, 0x9C, 0xD1, 0xB5, 0xB3, +0xC5, 0xF5, 0xC6, 0x36, 0xC5, 0xF5, 0xBD, 0xB4, +0xA4, 0xF1, 0x83, 0xED, 0xAD, 0x53, 0x94, 0x4F, +0x94, 0x70, 0x9C, 0xD1, 0x94, 0x90, 0x9C, 0xB1, +0xA5, 0x12, 0x94, 0x90, 0x9C, 0xB1, 0xB5, 0x74, +0xB5, 0x74, 0xCE, 0x57, 0xBD, 0xD5, 0xC5, 0xF6, +0xBD, 0xF5, 0xA5, 0x33, 0xBD, 0xD5, 0x9C, 0xD1, +0xA5, 0x12, 0x94, 0x90, 0x9C, 0xB1, 0x8C, 0x2F, +0x9C, 0xD1, 0x94, 0x90, 0xAD, 0x33, 0xA4, 0xF2, +0xBD, 0xD5, 0xB5, 0x94, 0x8C, 0x4F, 0x94, 0x70, +0xA5, 0x12, 0x9C, 0xB0, 0xD6, 0x98, 0xD6, 0x97, +0xD6, 0x97, 0xD6, 0x97, 0xDE, 0xB7, 0xC5, 0xD4, +0xC5, 0xF5, 0xCE, 0x36, 0xD6, 0x76, 0xC5, 0xF5, +0x8C, 0x4F, 0xAD, 0x32, 0xAD, 0x12, 0x9C, 0xD1, +0x94, 0xB0, 0x9C, 0xD1, 0xA5, 0x12, 0xA4, 0xF1, +0x9C, 0x90, 0xA4, 0xD1, 0x94, 0x6F, 0x73, 0x8C, +0x84, 0x0E, 0x9C, 0x8F, 0xBD, 0x92, 0xC5, 0xD3, +0x94, 0x8E, 0xA4, 0xD0, 0xC5, 0xD3, 0xBD, 0xB3, +0xCE, 0x14, 0xC5, 0xD3, 0x94, 0x6E, 0x9C, 0xD0, +0xBD, 0xD4, 0xCE, 0x35, 0xBD, 0xB2, 0xBD, 0xD3, +0xBD, 0xB3, 0xAD, 0x10, 0xA4, 0xF0, 0xA4, 0xF1, +0x7B, 0xAC, 0x94, 0x6F, 0x9C, 0xB0, 0x7B, 0xAC, +0x8C, 0x4E, 0x94, 0x8F, 0xA4, 0xF0, 0xAD, 0x31, +0xA4, 0xF1, 0x94, 0x6E, 0x94, 0x6F, 0xAD, 0x52, +0xB5, 0x94, 0xB5, 0xB4, 0xB5, 0x94, 0x9C, 0xD1, +0xA4, 0xF1, 0xAD, 0x53, 0xAD, 0x33, 0x94, 0x8F, +0xA5, 0x11, 0xA5, 0x11, 0xAD, 0x11, 0xB5, 0x73, +0x9C, 0x90, 0x83, 0xEE, 0x84, 0x2F, 0x9C, 0xD1, +0xB5, 0x72, 0xB5, 0x31, 0xA4, 0xF0, 0xA4, 0xF0, +0xAD, 0x32, 0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x74, +0xBD, 0x94, 0xBD, 0xB4, 0xC5, 0xF5, 0xBD, 0xB3, +0xBD, 0xB4, 0xC5, 0xD4, 0xCE, 0x15, 0xC5, 0xD4, +0xC5, 0xD4, 0xC5, 0xF4, 0xDE, 0x76, 0xB5, 0x32, +0xBD, 0x94, 0xB5, 0x53, 0xAD, 0x53, 0xB5, 0x53, +0xBD, 0xB5, 0xAD, 0x53, 0xA4, 0xF2, 0xC5, 0xD5, +0xD6, 0x57, 0x94, 0x50, 0x7B, 0xAD, 0x8C, 0x2F, +0x8C, 0x50, 0x94, 0x91, 0x9C, 0xD2, 0x9C, 0xD2, +0x8C, 0x50, 0x83, 0xEF, 0x83, 0xEF, 0x84, 0x0F, +0x7B, 0xEF, 0x6B, 0x8D, 0x52, 0x8A, 0x39, 0xC7, +0x29, 0x45, 0x21, 0x04, 0x21, 0x45, 0x39, 0xC8, +0x4A, 0x6A, 0x63, 0x2D, 0x73, 0x8F, 0x73, 0xAF, +0x7B, 0xD0, 0x7B, 0xD0, 0x7B, 0xD0, 0x7C, 0x11, +0x7B, 0xF0, 0x73, 0xAF, 0x7B, 0xF0, 0x73, 0xB0, +0xA5, 0x55, 0xA5, 0x55, 0xA5, 0x55, 0x9D, 0x34, +0x9C, 0xF4, 0x7C, 0x0F, 0x5A, 0xC9, 0x83, 0xAB, +0x83, 0xAB, 0x7B, 0x8B, 0x83, 0xCC, 0x83, 0xCC, +0x8C, 0x0D, 0x9C, 0x8E, 0x9C, 0xAE, 0x94, 0x4D, +0x73, 0x49, 0x94, 0x4D, 0xAD, 0x31, 0xBD, 0x92, +0xC5, 0xD4, 0x8C, 0x0D, 0x94, 0x6E, 0xA4, 0xCF, +0xAC, 0xF0, 0x94, 0x6E, 0x9C, 0x6E, 0x8C, 0x0C, +0x9C, 0x8E, 0xAC, 0xEF, 0x94, 0x2D, 0x7B, 0x8C, +0x7B, 0x8C, 0xA4, 0xD1, 0xA4, 0xF1, 0x7B, 0xCD, +0x9C, 0x91, 0x9C, 0xB1, 0x9C, 0xB0, 0xAD, 0x53, +0x9C, 0xB0, 0xAD, 0x32, 0xAD, 0x33, 0xAD, 0x53, +0xA5, 0x32, 0xA5, 0x12, 0x94, 0x90, 0x9C, 0xD0, +0x8C, 0x4F, 0x73, 0x8C, 0x31, 0xA5, 0x31, 0xA6, +0x41, 0xE7, 0x62, 0xEB, 0x7B, 0xAE, 0x31, 0x86, +0x29, 0x65, 0x39, 0xE7, 0x52, 0x8A, 0x6B, 0x4C, +0x73, 0xAE, 0x7B, 0xCF, 0x8C, 0x51, 0x8C, 0x30, +0x84, 0x10, 0xAD, 0x35, 0xB5, 0x96, 0x94, 0xB2, +0x84, 0x10, 0x8C, 0x71, 0x94, 0xB1, 0x6B, 0x6D, +0x29, 0x24, 0x39, 0xA6, 0x42, 0x28, 0x31, 0x85, +0x31, 0x85, 0x39, 0xE7, 0x31, 0xA6, 0x5A, 0xCA, +0x63, 0x0C, 0x6B, 0x4D, 0x7B, 0xCF, 0xAD, 0x76, +0xA5, 0x35, 0xAD, 0x76, 0xBD, 0xF8, 0xCE, 0x7B, +0xE7, 0x1D, 0xD6, 0xBB, 0xCE, 0x59, 0xB5, 0xB6, +0xB5, 0x74, 0xB5, 0x93, 0xBD, 0xD4, 0xAD, 0x53, +0xA4, 0xF1, 0x9C, 0xD0, 0xA5, 0x11, 0xA5, 0x11, +0xA4, 0xF1, 0xA4, 0xF0, 0xA4, 0xCF, 0xA4, 0xCF, +0x7B, 0x8B, 0x7B, 0xAC, 0x7B, 0x8C, 0x83, 0xED, +0x84, 0x2E, 0x83, 0xED, 0x7B, 0xAD, 0x8C, 0x4F, +0x94, 0x6F, 0x8C, 0x4E, 0x8B, 0xEC, 0xA4, 0x8E, +0x8C, 0x0C, 0x9C, 0x8E, 0x8C, 0x0D, 0x73, 0x6B, +0x73, 0x4A, 0x62, 0xE9, 0x62, 0xA9, 0x62, 0xE9, +0x6B, 0x09, 0x73, 0x4A, 0x94, 0x2D, 0x8B, 0xCB, +0x7B, 0x8A, 0x8B, 0xCB, 0x94, 0x2D, 0x94, 0x0D, +0x83, 0xAB, 0x83, 0x8A, 0x8B, 0xEC, 0xA4, 0x6E, +0xAC, 0xCF, 0xAC, 0x8E, 0xBD, 0x31, 0xB5, 0x10, +0xBD, 0x30, 0xBD, 0x31, 0xB5, 0x30, 0xB5, 0x10, +0xAC, 0xF0, 0xA4, 0xF1, 0xCE, 0x79, 0xBD, 0xD8, +0xBD, 0xB7, 0x9C, 0xD1, 0xA4, 0xF0, 0xAD, 0x10, +0xAC, 0xD0, 0xA4, 0xAF, 0xA4, 0xAF, 0x9C, 0x6E, +0x94, 0x6E, 0xA4, 0xD1, 0xBD, 0x94, 0xAD, 0x53, +0xA4, 0xF2, 0x94, 0x90, 0x94, 0x70, 0x8C, 0x4F, +0x8C, 0x4F, 0x8C, 0x4F, 0x8C, 0x4F, 0x94, 0x70, +0x8C, 0x2F, 0x8C, 0x2F, 0x84, 0x0E, 0x8C, 0x4F, +0x94, 0x70, 0x7B, 0xAD, 0x83, 0xEE, 0x94, 0x6F, +0xA5, 0x32, 0xAD, 0x33, 0xA5, 0x12, 0xAD, 0x53, +0xA5, 0x33, 0x83, 0xEE, 0xA5, 0x12, 0x9C, 0xD1, +0xB5, 0xB4, 0xB5, 0x94, 0x9C, 0xB1, 0x94, 0x90, +0xAD, 0x32, 0xAD, 0x32, 0xCE, 0x36, 0xCE, 0x77, +0xD6, 0x77, 0xD6, 0x56, 0xB5, 0x53, 0x94, 0x90, +0x94, 0x6F, 0x8C, 0x0E, 0xBD, 0xB4, 0xB5, 0x94, +0x83, 0xEE, 0xB5, 0x53, 0x9C, 0xD1, 0xC6, 0x36, +0x9C, 0xB1, 0xAD, 0x32, 0xAD, 0x52, 0xA4, 0xF1, +0xA4, 0xD1, 0xA4, 0xF1, 0x9C, 0xB0, 0x7B, 0xED, +0x7B, 0xCD, 0x94, 0x8F, 0xAD, 0x51, 0xBD, 0xD3, +0xB5, 0x72, 0x73, 0x6B, 0x9C, 0x8F, 0xC6, 0x14, +0xCE, 0x35, 0xD6, 0x96, 0x9C, 0xAF, 0xAD, 0x31, +0xCE, 0x15, 0xCE, 0x35, 0xBD, 0xD3, 0xCE, 0x35, +0xCE, 0x35, 0xB5, 0x72, 0xA4, 0xCF, 0xA4, 0xF1, +0x62, 0xE9, 0x5A, 0xE9, 0x6B, 0x2A, 0x83, 0xED, +0x94, 0x8F, 0xB5, 0x73, 0xC5, 0xD5, 0xAD, 0x53, +0xAD, 0x32, 0x9C, 0xB0, 0x9C, 0xB0, 0xA5, 0x12, +0xB5, 0x94, 0xBD, 0xF5, 0xA5, 0x32, 0x9C, 0xD1, +0xB5, 0x74, 0xC6, 0x16, 0xBD, 0xD5, 0xAD, 0x53, +0xB5, 0x73, 0xB5, 0x73, 0xAD, 0x11, 0xB5, 0x73, +0x8C, 0x4F, 0x7B, 0xCE, 0x8C, 0x50, 0x9C, 0xD1, +0xAD, 0x11, 0xAD, 0x11, 0xA4, 0xAF, 0x9C, 0x8F, +0xA5, 0x11, 0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x73, +0xB5, 0x73, 0xAD, 0x32, 0xB5, 0x93, 0xB5, 0x73, +0xB5, 0x73, 0xB5, 0x73, 0xBD, 0xB3, 0xC5, 0xB3, +0xCD, 0xF4, 0xC5, 0xF4, 0xC5, 0xD4, 0xB5, 0x32, +0xB5, 0x53, 0x9C, 0xB1, 0x9C, 0xD1, 0x9C, 0xD0, +0xAD, 0x32, 0xC5, 0xD5, 0xBD, 0xD5, 0xBD, 0xD5, +0xC5, 0xF5, 0x8C, 0x4F, 0x94, 0x70, 0xB5, 0x54, +0xA4, 0xD2, 0x8C, 0x2F, 0x94, 0x91, 0x9C, 0xB1, +0x94, 0x91, 0x94, 0x71, 0x94, 0x70, 0x8C, 0x70, +0x8C, 0x50, 0x8C, 0x50, 0x84, 0x0F, 0x73, 0x8E, +0x5B, 0x0C, 0x4A, 0x69, 0x39, 0xE7, 0x31, 0x86, +0x21, 0x25, 0x21, 0x25, 0x21, 0x45, 0x31, 0xA7, +0x42, 0x29, 0x5A, 0xCC, 0x63, 0x2D, 0x6B, 0x8F, +0x7B, 0xF1, 0x8C, 0x93, 0x8C, 0x72, 0x84, 0x52, +0xA5, 0x55, 0xA5, 0x55, 0xA5, 0x55, 0x9D, 0x34, +0x9C, 0xF4, 0x7B, 0xCF, 0x52, 0x68, 0x6A, 0xE9, +0x5A, 0x88, 0x62, 0xC9, 0x62, 0xE9, 0x52, 0x68, +0x62, 0xE9, 0x73, 0x6B, 0x73, 0x6B, 0x83, 0xEC, +0x6B, 0x2A, 0x83, 0xED, 0x9C, 0xAF, 0x8C, 0x2D, +0xC5, 0xF4, 0x9C, 0xAF, 0xA4, 0xF0, 0xB5, 0x51, +0xA4, 0xF0, 0x94, 0x6E, 0x9C, 0xAF, 0x9C, 0xAF, +0xA4, 0xAF, 0xA4, 0xCF, 0x83, 0xAB, 0x5A, 0xA9, +0x5A, 0xCA, 0x94, 0x90, 0x94, 0x6F, 0x63, 0x0A, +0x8C, 0x2F, 0x7B, 0xCD, 0x94, 0x90, 0x94, 0x90, +0x7B, 0xAC, 0x9C, 0xD0, 0x8C, 0x4F, 0xA4, 0xF1, +0x9C, 0xB0, 0x9C, 0xD0, 0x9C, 0xD1, 0x8C, 0x4E, +0x8C, 0x2E, 0x94, 0x6F, 0x5A, 0xEA, 0x31, 0x85, +0x39, 0xE7, 0x42, 0x28, 0x42, 0x07, 0x31, 0x86, +0x31, 0xA6, 0x42, 0x28, 0x52, 0xAA, 0x52, 0xAA, +0x5A, 0xCA, 0x63, 0x0C, 0x73, 0x8D, 0x7B, 0xAE, +0x73, 0x6D, 0x94, 0xB2, 0xB5, 0x96, 0x84, 0x30, +0x52, 0x8A, 0x52, 0x69, 0x9C, 0xD2, 0xAD, 0x74, +0x8C, 0x70, 0x29, 0x65, 0x21, 0x04, 0x29, 0x65, +0x31, 0x85, 0x31, 0x85, 0x4A, 0x48, 0x5A, 0xAA, +0x5A, 0xEB, 0x5A, 0xEB, 0x63, 0x4D, 0x8C, 0x51, +0xAD, 0x76, 0xBD, 0xD8, 0xBD, 0xD8, 0xCE, 0x5A, +0xC6, 0x39, 0x94, 0x92, 0x8C, 0x51, 0xDE, 0xBB, +0x94, 0x91, 0xB5, 0x94, 0xC6, 0x16, 0xB5, 0x94, +0xA5, 0x12, 0x94, 0x8F, 0x94, 0x8F, 0x9C, 0xD0, +0x8C, 0x2E, 0x9C, 0xAF, 0x9C, 0x6E, 0xA4, 0x8E, +0x8C, 0x0D, 0x7B, 0xED, 0x7B, 0xCD, 0x7B, 0xED, +0x94, 0xB1, 0x8C, 0x4F, 0x7B, 0xCE, 0x8C, 0x70, +0x9C, 0xD1, 0x94, 0x70, 0x8B, 0xED, 0xA4, 0x8F, +0x7B, 0xAC, 0x84, 0x0D, 0x8C, 0x2E, 0x84, 0x0E, +0x84, 0x0E, 0x8C, 0x4F, 0x7B, 0xAD, 0x4A, 0x27, +0x6B, 0x4B, 0x83, 0xCD, 0x94, 0x6F, 0x8C, 0x0D, +0x8B, 0xEC, 0x8C, 0x2D, 0x94, 0x4E, 0xA4, 0xF0, +0xB5, 0x73, 0x8C, 0x6F, 0x9C, 0xB0, 0xC5, 0xF4, +0xD6, 0x55, 0xB5, 0x30, 0xAC, 0xCF, 0x9C, 0x4D, +0x9C, 0x4D, 0xB5, 0x10, 0xB5, 0x51, 0xA4, 0xD0, +0x9C, 0x8F, 0xA4, 0xF2, 0xDE, 0xFB, 0xBD, 0xF8, +0xAD, 0x34, 0x9C, 0x90, 0x94, 0x2E, 0x94, 0x0D, +0x94, 0x2D, 0xA4, 0xCF, 0x94, 0x4D, 0x94, 0x2D, +0x94, 0x2D, 0x8C, 0x0D, 0x94, 0x4E, 0x9C, 0xD1, +0xB5, 0x53, 0xAD, 0x33, 0xAD, 0x12, 0xBD, 0xB5, +0xAD, 0x33, 0xB5, 0x53, 0xAD, 0x33, 0xAD, 0x53, +0xBD, 0x94, 0xB5, 0x54, 0xB5, 0x53, 0xB5, 0x53, +0xAD, 0x53, 0xB5, 0x74, 0xB5, 0x74, 0xB5, 0x74, +0xAD, 0x32, 0xA4, 0xF1, 0xA5, 0x12, 0xA5, 0x12, +0xA5, 0x12, 0x9C, 0xB1, 0xB5, 0x74, 0xBD, 0xB5, +0xAD, 0x53, 0x94, 0x90, 0x9C, 0x90, 0x94, 0x70, +0x94, 0x6F, 0x8C, 0x0E, 0x84, 0x0F, 0x84, 0x0E, +0x84, 0x0E, 0x94, 0x2F, 0x9C, 0xB0, 0xA5, 0x12, +0xA4, 0xF1, 0x8C, 0x0F, 0x7B, 0xAD, 0x73, 0x8C, +0x8C, 0x2F, 0xAD, 0x12, 0x7B, 0xAC, 0xB5, 0x94, +0xA4, 0xD1, 0x94, 0x8F, 0x94, 0x6F, 0x83, 0xCD, +0x83, 0xED, 0xA4, 0xF1, 0xA5, 0x12, 0x94, 0x4F, +0x7B, 0xAD, 0x9C, 0xB0, 0xB5, 0x92, 0xC5, 0xF3, +0xCE, 0x14, 0xBD, 0xB3, 0xBD, 0xB3, 0xB5, 0x92, +0xD6, 0x55, 0xDE, 0xB7, 0x94, 0x4E, 0xCE, 0x35, +0xCE, 0x35, 0xD6, 0x55, 0xCE, 0x35, 0xD6, 0x96, +0xD6, 0x75, 0xBD, 0xB2, 0xA4, 0xF0, 0xA4, 0xF1, +0x6B, 0x4B, 0x5A, 0xCA, 0x5A, 0xC9, 0x7B, 0x8C, +0x94, 0x6F, 0xA5, 0x31, 0xA5, 0x11, 0x9C, 0x90, +0x7B, 0xCC, 0x9C, 0xB0, 0xA4, 0xF1, 0xB5, 0x73, +0xB5, 0x73, 0xB5, 0xB4, 0xAD, 0x53, 0xB5, 0xB4, +0xB5, 0xB4, 0xAD, 0x93, 0x9C, 0xB1, 0x7B, 0xAD, +0x94, 0x6F, 0xAD, 0x11, 0xA4, 0xF1, 0xB5, 0x73, +0x7B, 0xAD, 0x7B, 0xCE, 0x84, 0x2F, 0x9C, 0xD1, +0xA4, 0xF1, 0x9C, 0xAF, 0xA4, 0xD0, 0x9C, 0x8F, +0x9C, 0xB0, 0xA5, 0x12, 0xA5, 0x12, 0xAD, 0x33, +0xBD, 0xB5, 0xB5, 0x73, 0xAD, 0x32, 0xAD, 0x12, +0xAD, 0x32, 0xB5, 0x73, 0xB5, 0x73, 0x9C, 0xB0, +0xB5, 0x52, 0xB5, 0x51, 0xB5, 0x72, 0xAD, 0x12, +0xB5, 0x53, 0x9C, 0xB0, 0x9C, 0xB1, 0xA4, 0xF1, +0x9C, 0xB0, 0x9C, 0xD0, 0x94, 0x6F, 0xA4, 0xF1, +0xCE, 0x15, 0xC6, 0x15, 0xBD, 0xB4, 0xAD, 0x33, +0xAD, 0x12, 0xA4, 0xD2, 0x84, 0x0F, 0x7B, 0x8D, +0x73, 0x8C, 0x84, 0x0F, 0x8C, 0x50, 0x9C, 0xB1, +0x9C, 0xB1, 0x94, 0x91, 0x94, 0x91, 0x8C, 0x50, +0x84, 0x2F, 0x83, 0xEF, 0x73, 0x8E, 0x6B, 0x4C, +0x5A, 0xEB, 0x42, 0x29, 0x31, 0xA6, 0x29, 0x45, +0x21, 0x25, 0x21, 0x24, 0x21, 0x25, 0x29, 0x66, +0x39, 0xC8, 0x63, 0x2D, 0x84, 0x11, 0x84, 0x31, +0xA5, 0x55, 0xA5, 0x55, 0xA5, 0x55, 0x9D, 0x14, +0x9C, 0xF3, 0x84, 0x0F, 0x62, 0xC9, 0x6B, 0x09, +0x73, 0x4A, 0x73, 0x6B, 0x7B, 0x8B, 0x7B, 0x8B, +0x73, 0x4A, 0x73, 0x2A, 0x73, 0x4B, 0x7B, 0xAB, +0x83, 0xCC, 0x6B, 0x2A, 0x73, 0x4A, 0x5A, 0xA8, +0x8C, 0x4E, 0x7B, 0x8B, 0x9C, 0x8F, 0x83, 0xED, +0x73, 0x6A, 0x8C, 0x0D, 0x9C, 0x8E, 0x94, 0x6E, +0xAD, 0x10, 0xAC, 0xCF, 0x8B, 0xEC, 0x8C, 0x4F, +0x8C, 0x2F, 0x94, 0x6F, 0xAD, 0x12, 0x8C, 0x4F, +0x84, 0x0E, 0x84, 0x0E, 0x8C, 0x6F, 0x94, 0x4F, +0x94, 0x4F, 0x94, 0x6F, 0x9C, 0xD1, 0x9C, 0xD0, +0x7B, 0xAC, 0x63, 0x2A, 0x73, 0x6B, 0x73, 0x4B, +0x7B, 0xCD, 0x73, 0x8C, 0x8C, 0x4F, 0x4A, 0x48, +0x31, 0x85, 0x39, 0xC6, 0x31, 0x85, 0x39, 0xC6, +0x39, 0xC6, 0x42, 0x07, 0x4A, 0x28, 0x39, 0xC6, +0x5A, 0xCA, 0x6B, 0x2C, 0x73, 0x6D, 0x7B, 0xEF, +0x5A, 0xEB, 0x84, 0x30, 0x84, 0x30, 0x94, 0x92, +0x8C, 0x30, 0x42, 0x29, 0x7B, 0xEF, 0xAD, 0x73, +0xBD, 0xB4, 0x9C, 0xD1, 0x63, 0x0B, 0x4A, 0x28, +0x21, 0x04, 0x31, 0x86, 0x39, 0xE7, 0x4A, 0x48, +0x5A, 0xEB, 0x63, 0x2C, 0x6B, 0x6D, 0x73, 0x8E, +0x8C, 0x72, 0x9C, 0xF4, 0xB5, 0x76, 0x9C, 0xF4, +0xA5, 0x15, 0xC5, 0xF8, 0xCE, 0x5A, 0xDE, 0xDC, +0xCE, 0x59, 0xAD, 0x54, 0xBD, 0xD5, 0xB5, 0xB4, +0xAD, 0x53, 0x94, 0x6F, 0x7B, 0xAC, 0xA5, 0x11, +0xA4, 0xD1, 0x8C, 0x2E, 0x9C, 0x8F, 0x94, 0x2D, +0x94, 0x6F, 0x73, 0xAC, 0x6B, 0x6C, 0x7C, 0x0E, +0xA5, 0x33, 0x94, 0x90, 0x8C, 0x70, 0x9C, 0xD2, +0x9C, 0xF2, 0x9C, 0xD1, 0x94, 0x2E, 0x9C, 0x8F, +0x8C, 0x0E, 0x94, 0x90, 0x94, 0x6F, 0x8C, 0x4F, +0x8C, 0x4F, 0xA5, 0x12, 0x7B, 0xAD, 0x6B, 0x2C, +0x73, 0x8C, 0x94, 0x90, 0xA5, 0x11, 0x94, 0x8F, +0x8C, 0x4E, 0x94, 0x6F, 0x94, 0x6F, 0xAD, 0x52, +0xCE, 0x76, 0xBD, 0xD4, 0xC6, 0x15, 0xDE, 0xB6, +0xD6, 0x55, 0xBD, 0x92, 0xA4, 0xAF, 0x9C, 0x6D, +0xAC, 0xF0, 0xB5, 0x71, 0xC6, 0x14, 0xCE, 0x35, +0xBD, 0xD5, 0xCE, 0x58, 0xC6, 0x18, 0x5A, 0xAC, +0x94, 0xB2, 0xD6, 0x98, 0xC5, 0xF4, 0xC5, 0xF4, +0xBD, 0xB3, 0xCE, 0x36, 0xB5, 0x73, 0xAD, 0x52, +0xAD, 0x11, 0xA5, 0x11, 0xBD, 0xD4, 0xCE, 0x36, +0xD6, 0x76, 0xCE, 0x56, 0x94, 0x70, 0xB5, 0x74, +0x9C, 0xB1, 0xCE, 0x16, 0xB5, 0x53, 0x94, 0x70, +0x8C, 0x0E, 0x94, 0x6F, 0x9C, 0x90, 0xA4, 0xF1, +0xAD, 0x12, 0x94, 0x4F, 0x9C, 0xB1, 0x94, 0x90, +0x94, 0x4F, 0x9C, 0xB0, 0x9C, 0xB0, 0x83, 0xED, +0x8C, 0x2E, 0x9C, 0xB0, 0xB5, 0x74, 0x94, 0x6F, +0x94, 0x6F, 0xA4, 0xF1, 0xA5, 0x12, 0xBD, 0x94, +0xA4, 0xF1, 0xA5, 0x12, 0xA5, 0x12, 0xAD, 0x53, +0xB5, 0x53, 0xAD, 0x32, 0xA4, 0xF1, 0x9C, 0x90, +0xA4, 0xF2, 0xA4, 0xF2, 0xAD, 0x33, 0xB5, 0x95, +0xAD, 0x33, 0xAD, 0x33, 0xAD, 0x53, 0xBD, 0xD4, +0xB5, 0x94, 0xBD, 0x94, 0xBD, 0xB5, 0xB5, 0x74, +0xBD, 0x94, 0xB5, 0x53, 0xAD, 0x12, 0xAD, 0x33, +0xBD, 0xB5, 0xBD, 0xB4, 0xAD, 0x51, 0x9C, 0xAF, +0x9C, 0xAF, 0x9C, 0xB0, 0x94, 0x4E, 0x94, 0x4E, +0x9C, 0x90, 0x94, 0x8F, 0x83, 0xCC, 0x94, 0x6F, +0xA4, 0xF1, 0xA4, 0xD0, 0xA4, 0xF0, 0xAD, 0x51, +0xAD, 0x10, 0xA4, 0xAF, 0xA4, 0xAF, 0xAD, 0x11, +0xA4, 0xD1, 0x94, 0x6F, 0x8C, 0x2E, 0x8C, 0x2E, +0x9C, 0xB0, 0x9C, 0xAF, 0x9C, 0xB0, 0x9C, 0xB0, +0x9C, 0xB0, 0xA4, 0xD1, 0xB5, 0x73, 0xB5, 0xB4, +0xAD, 0x32, 0xB5, 0x94, 0xAD, 0x53, 0xB5, 0xB4, +0xBD, 0xD5, 0xC5, 0xF5, 0xB5, 0x94, 0xAD, 0x53, +0xB5, 0x74, 0x9C, 0xD0, 0x94, 0x6F, 0xA4, 0xD1, +0x8C, 0x4F, 0x94, 0x90, 0x73, 0xAE, 0x94, 0x70, +0x9C, 0xB0, 0x94, 0x2E, 0x94, 0x4E, 0x8C, 0x2E, +0x9C, 0xB0, 0x9C, 0xD1, 0x9C, 0xD1, 0x9C, 0xD1, +0xA4, 0xF2, 0xB5, 0x94, 0xAD, 0x12, 0x94, 0x70, +0x94, 0x6F, 0xA4, 0xF1, 0xA5, 0x12, 0x9C, 0xB0, +0xA4, 0xF1, 0xAD, 0x31, 0xB5, 0x72, 0xAD, 0x12, +0xB5, 0x53, 0x9C, 0x90, 0x9C, 0xB1, 0x9C, 0xB0, +0x9C, 0xB1, 0x9C, 0xB0, 0x94, 0x6F, 0x94, 0x6F, +0x94, 0x6F, 0x9C, 0x8F, 0xA4, 0xF1, 0xA4, 0xF1, +0xB5, 0x73, 0xA4, 0xF2, 0x9C, 0xD1, 0xAD, 0x53, +0xAD, 0x33, 0xB5, 0x94, 0x83, 0xCE, 0x73, 0x6C, +0x83, 0xCE, 0x8C, 0x2F, 0x9C, 0xB2, 0xA4, 0xD2, +0x9C, 0xB1, 0x9C, 0xB1, 0x94, 0x70, 0x8C, 0x4F, +0x84, 0x0F, 0x73, 0xAD, 0x63, 0x0B, 0x4A, 0x8A, +0x42, 0x08, 0x31, 0xA7, 0x29, 0x86, 0x29, 0x86, +0x31, 0xA7, 0x52, 0x8B, 0x6B, 0x4E, 0x84, 0x11, +0xA5, 0x55, 0xA5, 0x55, 0xA5, 0x55, 0x9D, 0x14, +0x9C, 0xF4, 0x7B, 0xCF, 0x62, 0xC9, 0x73, 0x4A, +0x7B, 0x6A, 0x83, 0xAB, 0x8B, 0xEC, 0x94, 0x4D, +0x9C, 0x4D, 0x9C, 0x6E, 0xA4, 0x8F, 0x9C, 0x6E, +0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0xCF, 0xA4, 0x8F, +0x9C, 0x8F, 0x94, 0x4E, 0x94, 0x2D, 0x9C, 0x6E, +0x94, 0x4E, 0x94, 0x2D, 0x94, 0x2D, 0x8B, 0xEC, +0x9C, 0x4D, 0xB4, 0xEF, 0x94, 0x0C, 0x73, 0x6B, +0x7B, 0x8C, 0x73, 0x6B, 0x83, 0xED, 0x8C, 0x4E, +0x8C, 0x0E, 0x94, 0x4F, 0x9C, 0xB0, 0x8C, 0x4F, +0x94, 0x6F, 0x73, 0x6B, 0x9C, 0x90, 0xAD, 0x52, +0x9C, 0xD1, 0x83, 0xEE, 0x7B, 0xAC, 0x8C, 0x2F, +0x94, 0x70, 0x9C, 0xD1, 0x94, 0x70, 0x63, 0x2B, +0x4A, 0x48, 0x39, 0xE7, 0x39, 0xC6, 0x41, 0xE7, +0x42, 0x07, 0x42, 0x28, 0x4A, 0x48, 0x4A, 0x48, +0x5A, 0xCA, 0x63, 0x2C, 0x7B, 0xCE, 0x8C, 0x71, +0x94, 0xB2, 0x7B, 0xEF, 0x84, 0x31, 0xA4, 0xF4, +0x94, 0x71, 0x4A, 0x69, 0x84, 0x30, 0xBD, 0xB4, +0xB5, 0x73, 0xB5, 0x94, 0x9C, 0xB0, 0x94, 0xB0, +0x63, 0x0A, 0x42, 0x27, 0x31, 0x85, 0x41, 0xE7, +0x52, 0xAA, 0x63, 0x2C, 0x6B, 0x4D, 0x5A, 0xEB, +0x6B, 0x6D, 0x7B, 0xAF, 0x94, 0xB3, 0xA5, 0x14, +0xBD, 0xD8, 0xCE, 0x59, 0x94, 0x93, 0xA5, 0x15, +0xCE, 0x7A, 0xC6, 0x18, 0xBD, 0xF6, 0xB5, 0x94, +0xAD, 0x53, 0x8C, 0x4E, 0x73, 0x8B, 0x94, 0x8F, +0xA5, 0x11, 0xA5, 0x11, 0x9C, 0x8F, 0x9C, 0x8E, +0x94, 0x6F, 0x73, 0x8C, 0x73, 0x8C, 0x84, 0x2F, +0x8C, 0x4F, 0x4A, 0x48, 0x8C, 0x70, 0xA5, 0x33, +0xA5, 0x32, 0xA5, 0x12, 0x94, 0x6F, 0x9C, 0x8F, +0x94, 0x6F, 0xA5, 0x12, 0x94, 0x90, 0x9C, 0xD1, +0xA5, 0x32, 0xB5, 0x94, 0x7B, 0xAD, 0x7B, 0xEE, +0x84, 0x2F, 0x94, 0xB1, 0xAD, 0x32, 0xA4, 0xF1, +0x8C, 0x4E, 0x94, 0x8F, 0xA4, 0xF1, 0xB5, 0x93, +0xD6, 0x77, 0xCE, 0x56, 0xD6, 0x76, 0xDE, 0x96, +0xD6, 0x55, 0xBD, 0x72, 0xA4, 0xCF, 0xA4, 0xAE, +0xAD, 0x31, 0xBD, 0xD3, 0xC5, 0xF4, 0xCE, 0x55, +0xCE, 0x36, 0xCE, 0x78, 0x9C, 0xD3, 0x52, 0xAB, +0x94, 0xB2, 0xD6, 0xB8, 0xC6, 0x15, 0xCE, 0x35, +0xBD, 0xF4, 0xD6, 0x77, 0xC6, 0x15, 0xC5, 0xF5, +0xC5, 0xF5, 0xC6, 0x15, 0xB5, 0x93, 0xCE, 0x36, +0xD6, 0x76, 0xE6, 0xD8, 0x94, 0x90, 0xBD, 0x94, +0xA4, 0xD1, 0xCE, 0x57, 0xBD, 0xD5, 0x9C, 0xD1, +0x8C, 0x4F, 0xAD, 0x12, 0xA5, 0x11, 0xA4, 0xF1, +0xB5, 0x53, 0xAD, 0x12, 0xB5, 0x53, 0xB5, 0x73, +0xA5, 0x12, 0xAD, 0x52, 0xA5, 0x11, 0xAD, 0x32, +0xA4, 0xF1, 0x94, 0x6F, 0xBD, 0x94, 0xBD, 0xB4, +0xBD, 0x94, 0xAD, 0x52, 0x8C, 0x2E, 0xB5, 0x73, +0xA4, 0xF1, 0xAD, 0x12, 0xA5, 0x12, 0xB5, 0x73, +0xC5, 0xD4, 0xBD, 0x93, 0xB5, 0x32, 0x94, 0x6F, +0x8C, 0x2E, 0x94, 0x4F, 0xAD, 0x12, 0xBD, 0xB4, +0xBD, 0x94, 0xBD, 0xB4, 0x9C, 0x90, 0xB5, 0x53, +0xA4, 0xF1, 0xAD, 0x12, 0xA5, 0x11, 0x9C, 0xB0, +0xA4, 0xD1, 0xAC, 0xF1, 0xAD, 0x12, 0xB5, 0x53, +0xA4, 0xF1, 0xB5, 0x53, 0xAD, 0x52, 0xAD, 0x32, +0xAD, 0x12, 0xAD, 0x12, 0xB5, 0x52, 0xB5, 0x53, +0xBD, 0x94, 0xCD, 0xF6, 0xA4, 0xD1, 0x94, 0x6F, +0xB5, 0x52, 0xB5, 0x52, 0xAD, 0x32, 0xAD, 0x11, +0xAD, 0x11, 0xAD, 0x11, 0xBD, 0xB4, 0xC5, 0xF5, +0xCD, 0xF5, 0xBD, 0xB4, 0xBD, 0x94, 0xBD, 0x94, +0xC5, 0xB4, 0xBD, 0xB4, 0xC5, 0xD5, 0xC5, 0xD5, +0xCE, 0x16, 0xCE, 0x15, 0xC5, 0xF5, 0xCE, 0x15, +0xC5, 0xD5, 0xBD, 0x94, 0xB5, 0x32, 0xB5, 0x52, +0xB5, 0x53, 0xB5, 0x53, 0xB5, 0x53, 0xAD, 0x32, +0xAD, 0x32, 0xA4, 0xF2, 0xB5, 0x32, 0xC5, 0xB4, +0xB5, 0x53, 0xB5, 0x73, 0xA4, 0xF2, 0x9C, 0xD1, +0xB5, 0x53, 0xB5, 0x53, 0xB5, 0x52, 0xAD, 0x32, +0xAC, 0xF2, 0xA4, 0xF1, 0x9C, 0xD1, 0x8C, 0x2F, +0x94, 0x50, 0xA4, 0xF2, 0xA4, 0xD1, 0x9C, 0x90, +0x94, 0x90, 0x94, 0x6F, 0x94, 0x90, 0x94, 0x6F, +0x9C, 0xB0, 0x8C, 0x2E, 0xBD, 0x93, 0xC5, 0xD4, +0xA4, 0xF1, 0xAD, 0x32, 0xB5, 0x73, 0x9C, 0xB0, +0xA4, 0xF1, 0xA5, 0x12, 0xA4, 0xF2, 0xA4, 0xF1, +0xA4, 0xF2, 0x9C, 0xB0, 0x94, 0x6F, 0x83, 0xCD, +0x8C, 0x2E, 0xAD, 0x32, 0xB5, 0x73, 0xB5, 0x94, +0xB5, 0x74, 0xBD, 0xB5, 0xBD, 0xD5, 0xAD, 0x74, +0xA5, 0x13, 0x83, 0xEE, 0x6B, 0x2C, 0x83, 0xEE, +0x9C, 0xB1, 0xAD, 0x13, 0xAD, 0x33, 0xA4, 0xF2, +0x94, 0x91, 0x8C, 0x2F, 0x7B, 0xEE, 0x6B, 0x6D, +0x63, 0x0C, 0x52, 0x8A, 0x3A, 0x08, 0x31, 0xA7, +0x29, 0x66, 0x29, 0x86, 0x31, 0xA6, 0x39, 0xE8, +0xA5, 0x55, 0xA5, 0x35, 0xA5, 0x35, 0x9D, 0x14, +0x94, 0xD3, 0x83, 0xEF, 0x6B, 0x2B, 0x6B, 0x2A, +0x62, 0xE9, 0x62, 0xE9, 0x73, 0x4A, 0x7B, 0x6B, +0x83, 0xCB, 0x83, 0xCB, 0x8B, 0xEC, 0x8B, 0xCC, +0x9C, 0x6E, 0x9C, 0x8E, 0x9C, 0x6E, 0x94, 0x0D, +0xAC, 0xD0, 0xBD, 0x51, 0xB5, 0x30, 0xA4, 0xAF, +0xAC, 0xD0, 0xAC, 0xF0, 0xAC, 0xCF, 0xAC, 0xCF, +0xAC, 0xCF, 0xAC, 0xEF, 0xAC, 0xEF, 0xA4, 0xAF, +0x9C, 0x6E, 0x9C, 0x6E, 0x9C, 0x8F, 0x9C, 0x6E, +0x9C, 0x6E, 0x94, 0x4E, 0x8C, 0x0D, 0x83, 0xCC, +0x83, 0xCC, 0x83, 0xCC, 0x7B, 0x8C, 0x7B, 0x8B, +0x83, 0xCC, 0x7B, 0x8B, 0x6B, 0x2A, 0x62, 0xE9, +0x62, 0xE9, 0x63, 0x0A, 0x62, 0xE9, 0x6B, 0x2A, +0x52, 0x68, 0x39, 0xC6, 0x39, 0xC6, 0x39, 0xC6, +0x39, 0xC6, 0x31, 0xA6, 0x42, 0x07, 0x4A, 0x48, +0x5A, 0xCA, 0x63, 0x2C, 0x83, 0xEF, 0x8C, 0x50, +0x9C, 0xB2, 0x94, 0x71, 0xB5, 0x96, 0xBD, 0xD7, +0x8C, 0x51, 0x31, 0x86, 0x7B, 0xEE, 0xB5, 0x73, +0xB5, 0x73, 0xBD, 0xB4, 0xB5, 0x93, 0xA5, 0x11, +0x7B, 0xAC, 0x9C, 0x90, 0x4A, 0x27, 0x42, 0x07, +0x42, 0x27, 0x52, 0x89, 0x5A, 0xEB, 0x63, 0x0B, +0x5A, 0xEB, 0x63, 0x0C, 0x94, 0x72, 0xA5, 0x35, +0xAD, 0x55, 0x8C, 0x51, 0x83, 0xF0, 0x8C, 0x31, +0xC6, 0x18, 0xE7, 0x1C, 0x94, 0xB2, 0xB5, 0x94, +0xBD, 0xF5, 0xA5, 0x12, 0xA5, 0x11, 0x9C, 0xD0, +0x8C, 0x6E, 0x9C, 0xD0, 0x83, 0xCB, 0x9C, 0x8E, +0x8C, 0x4E, 0x8C, 0x2E, 0x84, 0x2E, 0x8C, 0x6F, +0x84, 0x0E, 0x4A, 0x48, 0x8C, 0x70, 0xB5, 0x94, +0xB5, 0x94, 0xB5, 0x94, 0x9C, 0x8F, 0xA4, 0xAF, +0x94, 0x6F, 0x9C, 0xF2, 0xA5, 0x12, 0xAD, 0x73, +0xAD, 0x73, 0xB5, 0x73, 0x8C, 0x2F, 0x8C, 0x70, +0x8C, 0x90, 0x9C, 0xF1, 0xB5, 0x93, 0xBD, 0x93, +0x9C, 0x8F, 0x8C, 0x4E, 0xAD, 0x32, 0xBD, 0xF4, +0xD6, 0x77, 0xC6, 0x15, 0xD6, 0x96, 0xDE, 0xB6, +0xD6, 0x76, 0xBD, 0x92, 0xAC, 0xEF, 0x9C, 0x8E, +0xA4, 0xAF, 0xAD, 0x31, 0xB5, 0x72, 0xC6, 0x15, +0xC6, 0x15, 0xCE, 0x78, 0x9C, 0xF3, 0x8C, 0x72, +0xA5, 0x54, 0xD6, 0x98, 0xD6, 0x76, 0xD6, 0x76, +0xC6, 0x15, 0xCE, 0x36, 0xCE, 0x35, 0xCE, 0x35, +0xD6, 0x97, 0xD6, 0x56, 0xAD, 0x52, 0xCE, 0x36, +0xDE, 0x97, 0xDE, 0xD8, 0x94, 0x6F, 0xB5, 0x74, +0xA4, 0xF2, 0xCE, 0x36, 0xBD, 0xB4, 0x9C, 0xB0, +0x94, 0x70, 0xA4, 0xF1, 0xAD, 0x32, 0xA4, 0xF1, +0xB5, 0x73, 0xB5, 0x73, 0xBD, 0xD5, 0xC5, 0xF5, +0xA4, 0xF1, 0xAD, 0x12, 0x83, 0xED, 0x9C, 0xB0, +0xB5, 0x94, 0x9C, 0xB0, 0xBD, 0xB4, 0xB5, 0xB4, +0xB5, 0x94, 0xAD, 0x32, 0x8C, 0x2E, 0xA5, 0x12, +0x9C, 0xB0, 0x94, 0x8F, 0x9C, 0xB0, 0xA5, 0x11, +0x9C, 0xAF, 0xAD, 0x10, 0xB5, 0x31, 0xA4, 0xF1, +0x94, 0x6F, 0x9C, 0x90, 0xBD, 0xB5, 0xC5, 0xD5, +0xBD, 0xB4, 0xB5, 0x73, 0x94, 0x6F, 0xA4, 0xF1, +0xA4, 0xD0, 0x9C, 0xAF, 0x94, 0x4E, 0x8C, 0x2D, +0xA4, 0xD0, 0xAD, 0x32, 0xBD, 0x93, 0xBD, 0xB4, +0xAD, 0x11, 0xA4, 0xF1, 0x9C, 0x8F, 0x9C, 0x8F, +0x9C, 0x8F, 0x9C, 0xB0, 0xAD, 0x32, 0xA4, 0xF1, +0x94, 0x4F, 0xB5, 0x53, 0x9C, 0x90, 0xC5, 0xD4, +0xBD, 0x93, 0xBD, 0x94, 0xC5, 0xF5, 0xC5, 0xB4, +0xBD, 0xB4, 0xBD, 0xB4, 0xBD, 0xB4, 0xA4, 0xF1, +0xAD, 0x32, 0xBD, 0x94, 0xAC, 0xF1, 0x9C, 0xB0, +0x9C, 0x8F, 0x94, 0x4F, 0xA4, 0xD1, 0x9C, 0x6F, +0x8C, 0x0E, 0x8C, 0x0D, 0x94, 0x4F, 0x9C, 0x90, +0xA4, 0xD1, 0xAC, 0xF1, 0xAC, 0xF1, 0xA4, 0xD1, +0xB5, 0x73, 0xB5, 0x32, 0xA4, 0xF1, 0xAD, 0x12, +0xAC, 0xF1, 0xAC, 0xF1, 0xB5, 0x53, 0xB5, 0x53, +0xBD, 0x73, 0xB5, 0x32, 0xAD, 0x12, 0xBD, 0x94, +0xCE, 0x36, 0xCD, 0xF6, 0xCD, 0xF5, 0xCE, 0x16, +0xCE, 0x36, 0xCE, 0x16, 0xCE, 0x16, 0xCE, 0x36, +0xCE, 0x36, 0xCE, 0x16, 0xD6, 0x36, 0xCD, 0xF5, +0xC5, 0xD5, 0xC5, 0xB4, 0xBD, 0x94, 0xB5, 0x53, +0xB5, 0x53, 0xAD, 0x12, 0xAD, 0x32, 0xAC, 0xF1, +0x94, 0x4F, 0x83, 0xED, 0x8C, 0x0E, 0x83, 0xED, +0x83, 0xCD, 0x7B, 0x8C, 0x7B, 0xAD, 0x7B, 0xAD, +0x7B, 0xAD, 0x83, 0xCD, 0x8C, 0x2F, 0x94, 0x4F, +0x94, 0x4F, 0x94, 0x90, 0xAD, 0x12, 0xBD, 0xB4, +0xBD, 0xD5, 0xC5, 0xD5, 0xCE, 0x36, 0xC6, 0x16, +0xCE, 0x37, 0xCE, 0x17, 0x9C, 0xB1, 0x8C, 0x2F, +0x7B, 0xAD, 0x73, 0x8C, 0x83, 0xEE, 0x9C, 0xD1, +0xAD, 0x33, 0xA5, 0x13, 0x9C, 0xB1, 0x8C, 0x50, +0x84, 0x0F, 0x7B, 0xEF, 0x73, 0xAE, 0x6B, 0x8D, +0x63, 0x0C, 0x4A, 0x69, 0x31, 0xC7, 0x31, 0x86, +0x94, 0xD3, 0x9D, 0x14, 0x9C, 0xF4, 0x94, 0xB3, +0x94, 0xB3, 0x83, 0xEF, 0x73, 0x8C, 0x7B, 0x8C, +0x7B, 0xAC, 0x6B, 0x2A, 0x7B, 0x8B, 0x8C, 0x0D, +0x94, 0x2E, 0x94, 0x2D, 0x94, 0x2E, 0x8C, 0x0D, +0x94, 0x2D, 0x9C, 0x6E, 0x9C, 0x8F, 0x73, 0x2A, +0x6A, 0xE8, 0x94, 0x2D, 0xA4, 0x8E, 0x9C, 0x6E, +0x83, 0xAB, 0x83, 0x8B, 0x7B, 0x6B, 0x7B, 0x6B, +0x73, 0x29, 0x73, 0x29, 0x8C, 0x0D, 0x7B, 0x6A, +0x8B, 0xEC, 0x8B, 0xEC, 0x8B, 0xED, 0x8B, 0xCC, +0x8B, 0xEC, 0x8B, 0xED, 0x94, 0x0D, 0x83, 0xCC, +0x83, 0xAC, 0x8B, 0xED, 0x8C, 0x0D, 0x9C, 0x4E, +0x9C, 0x4E, 0xAC, 0xD0, 0x94, 0x0D, 0x8C, 0x2E, +0x94, 0x0E, 0x94, 0x2E, 0x94, 0x4E, 0x94, 0x2E, +0x8C, 0x0E, 0x52, 0x68, 0x31, 0xA6, 0x39, 0xC6, +0x31, 0x85, 0x31, 0x85, 0x42, 0x07, 0x4A, 0x28, +0x52, 0x89, 0x52, 0xAA, 0x63, 0x0B, 0x73, 0x8D, +0x8C, 0x30, 0x94, 0x71, 0xB5, 0x96, 0xBD, 0xD7, +0xB5, 0x76, 0x39, 0xC7, 0x39, 0xE7, 0x8C, 0x2E, +0x8C, 0x0D, 0x83, 0xCC, 0x83, 0xCC, 0x83, 0xAC, +0x83, 0xCD, 0xAD, 0x10, 0x9C, 0x6E, 0x6B, 0x0A, +0x42, 0x07, 0x4A, 0x69, 0x52, 0x89, 0x63, 0x0C, +0x52, 0xAA, 0x5A, 0xEC, 0x63, 0x2D, 0x84, 0x10, +0xA5, 0x14, 0x73, 0x8E, 0x63, 0x0D, 0x8C, 0x51, +0x94, 0xB3, 0xAD, 0x55, 0x7B, 0xEF, 0xB5, 0x74, +0xB5, 0x74, 0x9C, 0xB0, 0x9C, 0xB0, 0xA4, 0xD0, +0x8C, 0x4E, 0x9C, 0x8F, 0x8B, 0xEC, 0x94, 0x0D, +0x62, 0xC8, 0x6B, 0x4A, 0x73, 0x6B, 0x83, 0xED, +0x83, 0xED, 0x4A, 0x68, 0x7C, 0x0E, 0xAD, 0x73, +0xBD, 0xB4, 0xB5, 0x73, 0x9C, 0x8E, 0xA4, 0xAF, +0x8C, 0x2D, 0xA5, 0x12, 0xA4, 0xF1, 0xAD, 0x32, +0xAD, 0x53, 0xAD, 0x32, 0x9C, 0xD1, 0x94, 0x90, +0x8C, 0x4F, 0xA5, 0x12, 0xBD, 0xD4, 0xBD, 0xD4, +0x94, 0x8F, 0x7B, 0xAC, 0xB5, 0x93, 0xCE, 0x35, +0xCE, 0x56, 0xAD, 0x51, 0xCE, 0x14, 0xD6, 0x96, +0xDE, 0xB6, 0xBD, 0x92, 0xB5, 0x10, 0x94, 0x2C, +0x9C, 0x8E, 0xB5, 0x51, 0xAD, 0x51, 0xC5, 0xF4, +0xBD, 0xD4, 0xCE, 0x78, 0xAD, 0x55, 0xA4, 0xF4, +0xC6, 0x17, 0xCE, 0x36, 0xCE, 0x35, 0xB5, 0x93, +0xCE, 0x55, 0xCE, 0x56, 0xBD, 0xD4, 0xCE, 0x36, +0xD6, 0x97, 0xCE, 0x55, 0xCE, 0x56, 0xD6, 0x77, +0xDE, 0xB7, 0xDE, 0xD8, 0x8C, 0x4F, 0xB5, 0x74, +0xA4, 0xF2, 0xCE, 0x37, 0xBD, 0x94, 0x9C, 0x90, +0x94, 0x90, 0xA4, 0xF1, 0xA5, 0x11, 0xAD, 0x32, +0xBD, 0xD5, 0xB5, 0x73, 0xB5, 0x73, 0xCE, 0x36, +0xB5, 0x73, 0xB5, 0x74, 0xAD, 0x12, 0x94, 0x90, +0xCE, 0x36, 0xC6, 0x16, 0xC5, 0xF5, 0xC6, 0x16, +0xC5, 0xF5, 0xB5, 0x94, 0x8C, 0x2E, 0xA4, 0xF2, +0x94, 0x6F, 0x8C, 0x2E, 0x94, 0x8F, 0x9C, 0xAF, +0xA4, 0xAF, 0xC5, 0xB3, 0xC5, 0xB3, 0xA4, 0xF1, +0x83, 0xED, 0xA4, 0xD1, 0xB5, 0x73, 0xB5, 0x73, +0xB5, 0x73, 0xAD, 0x32, 0x94, 0x6F, 0xB5, 0x32, +0xB5, 0x72, 0xA4, 0xD0, 0xA4, 0xF1, 0xA4, 0xD0, +0xB5, 0x52, 0xB5, 0x52, 0xB5, 0x52, 0xAD, 0x11, +0x94, 0x4E, 0x94, 0x6E, 0x8C, 0x2E, 0x94, 0x4E, +0x94, 0x4E, 0x8C, 0x2D, 0x9C, 0x8F, 0xAD, 0x12, +0x94, 0x4F, 0xBD, 0xB4, 0xBD, 0x93, 0xCE, 0x15, +0xC5, 0xF5, 0xC5, 0xB4, 0xCE, 0x15, 0xC5, 0xF4, +0xC5, 0xF5, 0xC5, 0xD4, 0xBD, 0xB3, 0xC5, 0xF5, +0xBD, 0xB4, 0xAD, 0x32, 0x8C, 0x2E, 0x8C, 0x2E, +0xA4, 0xF1, 0x9C, 0xB0, 0x9C, 0xB0, 0xA4, 0xF1, +0xA4, 0xD1, 0x94, 0x90, 0x9C, 0x90, 0x94, 0x90, +0x8C, 0x2F, 0xAD, 0x12, 0xBD, 0xB4, 0xCE, 0x36, +0xCE, 0x36, 0xCE, 0x16, 0xD6, 0x57, 0xD6, 0x57, +0xA4, 0xF1, 0x83, 0xED, 0x83, 0xED, 0xAC, 0xF2, +0xB5, 0x32, 0x94, 0x4F, 0x94, 0x4F, 0x9C, 0x90, +0x9C, 0x6F, 0x9C, 0xB0, 0x94, 0x6F, 0x8C, 0x4E, +0x94, 0x6F, 0xA4, 0xF1, 0x9C, 0x90, 0x9C, 0x6F, +0xA4, 0xD0, 0xAC, 0xF1, 0xB5, 0x53, 0xAD, 0x11, +0xB5, 0x32, 0xB5, 0x32, 0xAD, 0x11, 0xAC, 0xF1, +0xB5, 0x32, 0xB5, 0x53, 0xAD, 0x32, 0xB5, 0x53, +0xB5, 0x33, 0xB5, 0x53, 0xBD, 0x73, 0xBD, 0x94, +0xB5, 0x53, 0xB5, 0x73, 0xB5, 0x53, 0x94, 0x70, +0xA4, 0xD1, 0xA4, 0xF1, 0xA4, 0xF1, 0xB5, 0x53, +0xAD, 0x32, 0xAD, 0x32, 0xB5, 0x53, 0xB5, 0x52, +0xB5, 0x52, 0xBD, 0x93, 0xBD, 0x93, 0xBD, 0xB4, +0xBD, 0x94, 0xBD, 0xB4, 0x9C, 0x90, 0xA5, 0x12, +0xAD, 0x33, 0x9C, 0xD2, 0x94, 0x70, 0x7B, 0xAD, +0x7B, 0x8D, 0x7B, 0xCE, 0x8C, 0x50, 0x9C, 0xB1, +0x9C, 0xD2, 0x9C, 0xB1, 0x94, 0x70, 0x8C, 0x50, +0x8C, 0x50, 0x84, 0x30, 0x7B, 0xCE, 0x5A, 0xEB, +0xAD, 0x75, 0xA5, 0x55, 0xA5, 0x55, 0xA5, 0x35, +0x9C, 0xF4, 0x84, 0x10, 0x6B, 0x2B, 0x7B, 0x8C, +0x83, 0xED, 0x84, 0x0D, 0x84, 0x0D, 0x8C, 0x0D, +0x8C, 0x0D, 0x8C, 0x2E, 0xA4, 0xB0, 0x94, 0x6F, +0x94, 0x4E, 0x7B, 0x8B, 0x8B, 0xED, 0x83, 0xCC, +0x94, 0x6E, 0xA4, 0xCF, 0xAC, 0xAF, 0xB5, 0x11, +0xA4, 0x8F, 0x9C, 0x4E, 0x9C, 0x4F, 0xA4, 0x90, +0x8B, 0xED, 0x8C, 0x2E, 0xA4, 0xB0, 0x8C, 0x0D, +0xA4, 0xB0, 0xA4, 0xD0, 0xB5, 0x52, 0x9C, 0x8F, +0x94, 0x4F, 0x9C, 0x8F, 0xA4, 0xF0, 0x94, 0x6E, +0x83, 0xCC, 0x9C, 0x6F, 0xB5, 0x32, 0xB5, 0x72, +0x83, 0xCC, 0x9C, 0x4E, 0x7B, 0x4A, 0x8B, 0xCD, +0x83, 0xCD, 0x83, 0xAC, 0x83, 0xAC, 0x7B, 0x8B, +0x8B, 0xEE, 0x73, 0x8D, 0x4A, 0x28, 0x39, 0xE7, +0x31, 0xA6, 0x31, 0x85, 0x39, 0xC6, 0x41, 0xE7, +0x4A, 0x28, 0x4A, 0x28, 0x5A, 0xCB, 0x73, 0x8D, +0x8C, 0x30, 0x94, 0x92, 0xA4, 0xF3, 0xC6, 0x18, +0xBD, 0xD7, 0x83, 0xF0, 0x20, 0xE4, 0x8C, 0x4F, +0xA4, 0xB0, 0x94, 0x2D, 0x9C, 0x8F, 0x9C, 0x6F, +0x9C, 0x6F, 0xA4, 0xAF, 0xA4, 0xAF, 0x9C, 0x6F, +0x62, 0xEA, 0x52, 0x89, 0x5B, 0x0B, 0x73, 0xAE, +0x52, 0x8A, 0x5A, 0xAA, 0x4A, 0x49, 0x63, 0x0C, +0x8C, 0x51, 0x94, 0x92, 0xA4, 0xF4, 0xB5, 0x97, +0xB5, 0x96, 0xCE, 0x59, 0xB5, 0xB6, 0xCE, 0x38, +0xBD, 0x95, 0x9C, 0x70, 0x9C, 0x4E, 0x9C, 0x4D, +0x94, 0x4D, 0x9C, 0x6E, 0xA4, 0x8E, 0xBD, 0x51, +0xBD, 0x71, 0xB5, 0x30, 0xAC, 0xEF, 0xAC, 0xCF, +0xAC, 0xCF, 0xA4, 0xAF, 0xAC, 0xD0, 0xA4, 0xAF, +0xA4, 0xCF, 0xAC, 0xCF, 0xB5, 0x30, 0xA4, 0x8E, +0x83, 0xCC, 0x8B, 0xEC, 0x83, 0xAB, 0x83, 0xEC, +0x94, 0x4D, 0x83, 0xEC, 0x83, 0xED, 0x7B, 0xAC, +0x83, 0xED, 0x9C, 0xAF, 0xAD, 0x52, 0xAD, 0x31, +0x8C, 0x4E, 0x5A, 0xC8, 0xAD, 0x32, 0xCE, 0x56, +0xBD, 0xB3, 0x94, 0x6E, 0xBD, 0xB3, 0xD6, 0x55, +0xDE, 0x76, 0xA4, 0xAF, 0xB5, 0x30, 0x94, 0x0C, +0xA4, 0xEF, 0xBD, 0xD3, 0xB5, 0x72, 0xC5, 0xD4, +0xB5, 0x72, 0xC6, 0x17, 0xB5, 0x96, 0xA5, 0x35, +0xD6, 0x78, 0xD6, 0x76, 0xCE, 0x35, 0xBD, 0xD4, +0xCE, 0x15, 0xD6, 0x76, 0xBD, 0xD4, 0xD6, 0x76, +0xDE, 0xB7, 0xD6, 0x76, 0xD6, 0x97, 0xDE, 0x97, +0xDE, 0xB8, 0xDE, 0xD8, 0x94, 0x70, 0xB5, 0x53, +0xB5, 0x73, 0xCE, 0x36, 0xAD, 0x53, 0x9C, 0xB0, +0x9C, 0xD0, 0xC5, 0xF5, 0xBD, 0xB4, 0xB5, 0xB4, +0xC5, 0xF5, 0xBD, 0xD5, 0xCE, 0x36, 0xC5, 0xF5, +0xBD, 0xB4, 0xC5, 0xF5, 0xBD, 0xD5, 0xAD, 0x33, +0xD6, 0x77, 0xCE, 0x57, 0xC5, 0xF5, 0xC6, 0x16, +0xBD, 0xD5, 0xBD, 0xB4, 0x8C, 0x4E, 0x9C, 0xD0, +0x8C, 0x2E, 0x7B, 0xAC, 0x8C, 0x2E, 0x7B, 0xCC, +0x8C, 0x0D, 0x9C, 0xAF, 0xA4, 0xD0, 0xA4, 0xF1, +0x7B, 0xAC, 0xA5, 0x12, 0xBD, 0xB4, 0xAD, 0x32, +0xB5, 0x73, 0xA4, 0xF1, 0x8C, 0x2E, 0xAD, 0x32, +0xAD, 0x11, 0xA4, 0xCF, 0x9C, 0x8F, 0x9C, 0x6E, +0xB5, 0x73, 0x9C, 0xB0, 0xAD, 0x11, 0xA4, 0xF0, +0x9C, 0xAF, 0xA4, 0xF1, 0x9C, 0xAF, 0x9C, 0x8F, +0x8C, 0x2E, 0x94, 0x6E, 0xAD, 0x11, 0xB5, 0x73, +0x94, 0x6F, 0xBD, 0x94, 0xA4, 0xF1, 0xAD, 0x31, +0xBD, 0xB3, 0xC5, 0xF4, 0xCE, 0x35, 0xC5, 0xD4, +0xC5, 0xF4, 0xC5, 0xF4, 0xC5, 0xD4, 0xBD, 0xD4, +0xBD, 0x93, 0xB5, 0x52, 0x9C, 0xB0, 0xAD, 0x32, +0xB5, 0x73, 0xAD, 0x32, 0xA4, 0xF1, 0xAD, 0x32, +0xAD, 0x32, 0xA4, 0xF1, 0xA4, 0xF1, 0x9C, 0xD1, +0x84, 0x0E, 0xAD, 0x32, 0xA5, 0x12, 0xA4, 0xF1, +0xA4, 0xD1, 0x9C, 0x90, 0xA4, 0xD1, 0xA4, 0xF1, +0x9C, 0x90, 0x9C, 0xB0, 0x9C, 0xD1, 0x9C, 0x90, +0xAD, 0x32, 0xA4, 0xF1, 0xAD, 0x11, 0xA4, 0xD1, +0xAD, 0x12, 0xB5, 0x73, 0xBD, 0x94, 0xB5, 0x93, +0xB5, 0x73, 0xBD, 0xD5, 0xC5, 0xF5, 0xB5, 0x73, +0xA5, 0x11, 0x94, 0x6F, 0xA4, 0xD0, 0x9C, 0x6F, +0x9C, 0x6F, 0x9C, 0x6F, 0xA4, 0xB0, 0xA4, 0xD0, +0xAD, 0x11, 0xAD, 0x11, 0xA4, 0xF1, 0xAD, 0x11, +0xAC, 0xF1, 0xA4, 0xF1, 0x9C, 0x8F, 0x94, 0x4F, +0x9C, 0x6F, 0xAC, 0xF1, 0xAD, 0x11, 0x94, 0x6F, +0xAC, 0xF1, 0x9C, 0x8F, 0x9C, 0x6F, 0xAD, 0x31, +0xAD, 0x31, 0xAD, 0x11, 0x9C, 0x8F, 0x9C, 0x6F, +0x94, 0x4E, 0x9C, 0x6F, 0x8C, 0x2D, 0x8C, 0x0D, +0x94, 0x4E, 0x9C, 0xB0, 0xAD, 0x32, 0xBD, 0x94, +0xAD, 0x12, 0xA5, 0x12, 0xAD, 0x32, 0xA5, 0x12, +0x9C, 0xB1, 0x8C, 0x0F, 0x6B, 0x2B, 0x8C, 0x30, +0x8C, 0x50, 0x94, 0x91, 0x94, 0x91, 0x8C, 0x70, +0x8C, 0x70, 0x8C, 0x50, 0x8C, 0x30, 0x7B, 0xCE, +0xAD, 0x76, 0xAD, 0x75, 0xAD, 0x55, 0xA5, 0x55, +0xA5, 0x35, 0x8C, 0x51, 0x5A, 0xC9, 0x73, 0x8B, +0x83, 0xCC, 0x84, 0x0D, 0x84, 0x0D, 0x8C, 0x4E, +0x8C, 0x2D, 0x8C, 0x0D, 0x94, 0x8F, 0x94, 0x6F, +0x9C, 0x90, 0x8C, 0x2E, 0x94, 0x4E, 0x52, 0x88, +0xA4, 0xD0, 0x9C, 0x8E, 0xA4, 0xAF, 0xAC, 0xD0, +0x9C, 0x8F, 0x9C, 0x8F, 0x94, 0x4E, 0xA4, 0xB0, +0x9C, 0x8F, 0xAD, 0x11, 0xA4, 0xF1, 0xA4, 0xF0, +0xA4, 0xF1, 0xAD, 0x31, 0xB5, 0x52, 0x9C, 0xAF, +0x94, 0x6F, 0xA4, 0xD0, 0xAD, 0x31, 0xB5, 0x52, +0x9C, 0xB0, 0xAD, 0x32, 0xB5, 0x52, 0xAD, 0x32, +0x94, 0x4E, 0x94, 0x4E, 0x73, 0x4A, 0x8C, 0x0D, +0x94, 0x2E, 0x8B, 0xCD, 0x7B, 0x8C, 0x73, 0x4B, +0x7B, 0xAD, 0x73, 0x8D, 0x62, 0xEB, 0x4A, 0x69, +0x41, 0xE7, 0x31, 0x85, 0x31, 0x65, 0x41, 0xE7, +0x41, 0xE7, 0x4A, 0x49, 0x52, 0x8A, 0x6B, 0x4C, +0x7B, 0xAE, 0x83, 0xEF, 0x94, 0x71, 0xB5, 0x76, +0xB5, 0x76, 0xD6, 0x7A, 0x4A, 0x6A, 0x73, 0x6C, +0x94, 0x2E, 0x7B, 0x8B, 0x73, 0x6B, 0x62, 0xC9, +0x62, 0xC9, 0x73, 0x4A, 0x73, 0x4A, 0x73, 0x4B, +0x73, 0x6B, 0x52, 0x89, 0x4A, 0x69, 0x5A, 0xEB, +0x52, 0xAA, 0x5A, 0xCB, 0x5A, 0xAA, 0x5A, 0xEB, +0x73, 0x8E, 0x84, 0x10, 0x9C, 0xD4, 0xC6, 0x39, +0xE6, 0xFC, 0xE7, 0x1C, 0xC5, 0xD7, 0xB5, 0x55, +0xD6, 0x59, 0xBD, 0x75, 0x8B, 0xED, 0x8B, 0xCB, +0x9C, 0x4D, 0x94, 0x2D, 0x9C, 0x4D, 0x93, 0xEB, +0xA4, 0x6D, 0xAC, 0xCF, 0xB4, 0xEF, 0xAC, 0xEF, +0xAC, 0xCF, 0xA4, 0x6E, 0xC5, 0x91, 0xBD, 0x30, +0xAC, 0xAE, 0xAC, 0xCF, 0xB5, 0x10, 0xB4, 0xEF, +0xA4, 0xAE, 0xB4, 0xEF, 0xBD, 0x51, 0xB4, 0xEF, +0xAC, 0xCF, 0xAC, 0xEF, 0xB5, 0x10, 0xB5, 0x10, +0xB5, 0x10, 0xB5, 0x10, 0xAC, 0xF0, 0xAC, 0xCF, +0xA4, 0x8E, 0x94, 0x2D, 0x94, 0x2D, 0x9C, 0x6D, +0x94, 0x2C, 0x83, 0xEB, 0x94, 0x4D, 0x9C, 0x8E, +0x9C, 0x8E, 0x7B, 0x6A, 0xBD, 0x51, 0xA4, 0xAE, +0x94, 0x4C, 0x9C, 0x6E, 0xC5, 0xD3, 0xBD, 0xB3, +0xB5, 0x53, 0xCE, 0x38, 0xB5, 0xB7, 0xAD, 0x35, +0xDE, 0x98, 0xCE, 0x35, 0xD6, 0x76, 0xC6, 0x15, +0xCE, 0x15, 0xDE, 0x97, 0xD6, 0x97, 0xD6, 0x56, +0xCE, 0x15, 0xD6, 0x97, 0xDE, 0xB7, 0xD6, 0x97, +0xDE, 0xB7, 0xDE, 0xB8, 0x94, 0x90, 0xAD, 0x53, +0xB5, 0x53, 0xD6, 0x77, 0xC5, 0xF5, 0xAD, 0x52, +0x94, 0x90, 0xB5, 0x93, 0xB5, 0x73, 0xB5, 0x93, +0xC6, 0x15, 0xB5, 0xB4, 0xBD, 0xD4, 0xBD, 0xD4, +0xB5, 0x93, 0xBD, 0xD4, 0xBD, 0xD4, 0xAD, 0x73, +0xD6, 0x77, 0xD6, 0x77, 0xAD, 0x73, 0xBD, 0xB4, +0xAD, 0x53, 0xB5, 0xB4, 0x84, 0x0D, 0x9C, 0xD1, +0x94, 0x8F, 0x8C, 0x0E, 0x8C, 0x2E, 0x83, 0xED, +0x9C, 0x8F, 0x9C, 0xCF, 0xAD, 0x31, 0xAD, 0x52, +0x94, 0x6F, 0xA5, 0x12, 0xBD, 0xB4, 0xB5, 0x53, +0xBD, 0x94, 0x94, 0x90, 0x7B, 0xCD, 0xA5, 0x11, +0x94, 0x6E, 0x9C, 0xAF, 0x94, 0x6E, 0x94, 0x4E, +0xAD, 0x31, 0x94, 0x6E, 0xA4, 0xF0, 0xAD, 0x11, +0x9C, 0x8F, 0xA4, 0xF0, 0xA4, 0xF0, 0xB5, 0x72, +0xA4, 0xF0, 0xB5, 0x52, 0xA4, 0xD0, 0xBD, 0x94, +0x94, 0x6F, 0xBD, 0x73, 0x9C, 0x8F, 0xAD, 0x32, +0xBD, 0xB3, 0xCE, 0x35, 0xC5, 0xD4, 0xBD, 0x93, +0xC5, 0xD4, 0xC5, 0xF4, 0xCE, 0x15, 0xCE, 0x35, +0xC5, 0xF4, 0xB5, 0x93, 0xBD, 0x94, 0xC5, 0xF5, +0xB5, 0x73, 0xB5, 0x53, 0xA4, 0xD1, 0xB5, 0x53, +0xAD, 0x33, 0xA4, 0xD1, 0xAD, 0x12, 0x9C, 0xB0, +0x8C, 0x2F, 0xB5, 0x53, 0xAD, 0x32, 0xAD, 0x52, +0xAD, 0x32, 0xAD, 0x32, 0xAD, 0x32, 0xAD, 0x52, +0xB5, 0x73, 0xAD, 0x32, 0xAD, 0x53, 0xB5, 0x94, +0xBD, 0xB4, 0xBD, 0xB4, 0xB5, 0x94, 0xA5, 0x12, +0xAD, 0x12, 0xB5, 0x73, 0xBD, 0xD5, 0xB5, 0x93, +0xB5, 0x93, 0xC5, 0xF5, 0xBD, 0xD4, 0xC5, 0xF5, +0xB5, 0x73, 0x9C, 0x90, 0x9C, 0xB0, 0xA5, 0x11, +0xA5, 0x11, 0xAD, 0x32, 0xB5, 0x52, 0xB5, 0x52, +0xB5, 0x52, 0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x11, +0xAD, 0x11, 0xA4, 0xF1, 0xA4, 0xD1, 0x94, 0x6F, +0x94, 0x6F, 0x94, 0x2E, 0xB5, 0x32, 0x9C, 0x6E, +0xB5, 0x71, 0xBD, 0x72, 0xBD, 0x71, 0xB5, 0x71, +0xBD, 0x92, 0xBD, 0x72, 0xBD, 0xB3, 0xB5, 0x52, +0xB5, 0x72, 0xB5, 0x52, 0xAD, 0x31, 0xAD, 0x32, +0xB5, 0x52, 0xBD, 0x93, 0xC5, 0xD4, 0xD6, 0x34, +0xCE, 0x14, 0xC5, 0xD3, 0xBD, 0x93, 0x8C, 0x0E, +0x9C, 0xD1, 0xAD, 0x33, 0x8C, 0x2F, 0xCE, 0x36, +0xC5, 0xD5, 0xB5, 0x53, 0x9C, 0xB1, 0x84, 0x2F, +0x84, 0x2F, 0x8C, 0x70, 0x8C, 0x50, 0x84, 0x2F, +0x8C, 0x92, 0x8C, 0x92, 0x8C, 0x92, 0x8C, 0x72, +0x94, 0x92, 0x7B, 0xCF, 0x42, 0x27, 0x63, 0x0A, +0x73, 0x4B, 0x73, 0x8C, 0x8C, 0x0D, 0x94, 0x4E, +0x8C, 0x0D, 0x8C, 0x4E, 0x94, 0x8F, 0x9C, 0xB0, +0x9C, 0xB0, 0x94, 0x6F, 0x9C, 0xB0, 0x9C, 0xB0, +0x9C, 0xD0, 0xA4, 0x8E, 0xAC, 0xF0, 0xAC, 0xF0, +0xA4, 0x8F, 0xA4, 0x8F, 0x94, 0x6F, 0xA4, 0xF1, +0xA4, 0xF1, 0xAD, 0x11, 0xB5, 0x73, 0xAD, 0x32, +0xBD, 0xB4, 0xBD, 0xB4, 0xBD, 0x73, 0xA4, 0xF1, +0x94, 0x4E, 0xA4, 0xD0, 0xAD, 0x11, 0x94, 0x6E, +0x94, 0x6F, 0xAD, 0x32, 0xB5, 0x52, 0xB5, 0x52, +0x94, 0x2E, 0xA4, 0x8F, 0x7B, 0x8B, 0x9C, 0x4F, +0xA4, 0x6F, 0x8B, 0xCC, 0x83, 0xAC, 0x83, 0xAC, +0x83, 0xCD, 0x84, 0x2F, 0x84, 0x0F, 0x6B, 0x4C, +0x39, 0xC6, 0x39, 0xC7, 0x39, 0xC6, 0x39, 0xC7, +0x41, 0xE7, 0x42, 0x08, 0x4A, 0x49, 0x5A, 0xAA, +0x5A, 0xCB, 0x7B, 0xAE, 0x9C, 0xD3, 0xA4, 0xF4, +0xB5, 0x96, 0xD6, 0x9A, 0xBD, 0xB7, 0x94, 0x91, +0x9C, 0xB1, 0x8C, 0x2E, 0x9C, 0x90, 0x8C, 0x0D, +0x7B, 0xAC, 0x83, 0xED, 0x7B, 0xAC, 0x8C, 0x0D, +0x9C, 0xB0, 0x8C, 0x0E, 0x52, 0x89, 0x42, 0x27, +0x42, 0x28, 0x52, 0x8A, 0x52, 0x89, 0x5A, 0xAA, +0x52, 0x8A, 0x5A, 0xEB, 0x6B, 0x4E, 0xB5, 0x76, +0xD6, 0x7A, 0xDE, 0xBB, 0xCE, 0x19, 0xCE, 0x18, +0xD6, 0x59, 0xBD, 0x96, 0xA4, 0xD2, 0x94, 0x4F, +0xA4, 0xAF, 0x9C, 0x6E, 0x9C, 0x6E, 0xA4, 0x8E, +0x9C, 0x6D, 0xB5, 0x52, 0xD6, 0x55, 0xD6, 0x34, +0xCE, 0x14, 0xBD, 0x72, 0xAC, 0xEF, 0xAC, 0xCF, +0x94, 0x4D, 0x8C, 0x0C, 0x9C, 0xAE, 0x8B, 0xCC, +0x94, 0x2D, 0x9C, 0x4D, 0x94, 0x0C, 0x94, 0x4D, +0xAD, 0x11, 0xB5, 0x51, 0x94, 0x0C, 0x8B, 0xEC, +0x8B, 0xCC, 0x8B, 0xEC, 0x9C, 0x4D, 0xA4, 0x8E, +0xB4, 0xF0, 0xB4, 0xF0, 0xB5, 0x10, 0xBD, 0x10, +0xB4, 0xF0, 0xB5, 0x10, 0xBD, 0x51, 0xB5, 0x10, +0xAC, 0xF0, 0xB5, 0x30, 0xBD, 0x51, 0xBD, 0x51, +0xC5, 0x72, 0xBD, 0x51, 0xAD, 0x10, 0xA4, 0xCF, +0x9C, 0xB1, 0xC6, 0x38, 0xB5, 0x97, 0x9C, 0xD3, +0x94, 0x6F, 0x94, 0x4D, 0x9C, 0x8E, 0x94, 0x6E, +0x94, 0x4D, 0x94, 0x6E, 0x9C, 0x8F, 0x94, 0x6E, +0x94, 0x4E, 0x9C, 0xB0, 0xAD, 0x11, 0xAD, 0x11, +0xAD, 0x32, 0x94, 0x90, 0x9C, 0xB1, 0xAD, 0x33, +0x9C, 0xB0, 0xB5, 0x73, 0xB5, 0x73, 0x9C, 0xB0, +0x83, 0xED, 0x94, 0x6F, 0x8C, 0x4E, 0x8C, 0x2E, +0x94, 0x8F, 0x94, 0x6F, 0x8C, 0x2E, 0xAD, 0x32, +0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x73, 0xA5, 0x11, +0xB5, 0xB4, 0xBD, 0xB4, 0xB5, 0x73, 0xBD, 0x94, +0xB5, 0x73, 0xB5, 0x73, 0x7B, 0xAC, 0x9C, 0xB0, +0xA4, 0xF1, 0xB5, 0x53, 0xA5, 0x11, 0x9C, 0xB0, +0xC5, 0xF5, 0xCE, 0x15, 0xCE, 0x35, 0xB5, 0x52, +0x8C, 0x4E, 0xAD, 0x32, 0xC5, 0xD5, 0xB5, 0x53, +0xB5, 0x93, 0x94, 0x4F, 0xAD, 0x32, 0xBD, 0x93, +0xA5, 0x11, 0xA4, 0xF0, 0x9C, 0xD0, 0x94, 0x8F, +0xAD, 0x32, 0xAD, 0x11, 0x9C, 0x8F, 0x9C, 0xAF, +0x8C, 0x2D, 0x9C, 0xAF, 0x9C, 0xB0, 0xB5, 0x52, +0xA4, 0xD0, 0xB5, 0x73, 0xB5, 0x52, 0xBD, 0xB4, +0x94, 0x6F, 0xB5, 0x53, 0xA4, 0xF1, 0xB5, 0x53, +0xB5, 0x73, 0xBD, 0x93, 0xB5, 0x72, 0xA4, 0xD0, +0xB5, 0x52, 0xBD, 0x93, 0xBD, 0xB3, 0xB5, 0x52, +0xAD, 0x31, 0xBD, 0xB3, 0xAD, 0x32, 0x9C, 0xB0, +0x9C, 0x90, 0xB5, 0x53, 0xB5, 0x73, 0xAD, 0x53, +0xB5, 0x53, 0xB5, 0x53, 0xAD, 0x12, 0x9C, 0x90, +0x9C, 0x90, 0xAD, 0x33, 0xA4, 0xF1, 0xBD, 0x94, +0xA4, 0xF1, 0xAD, 0x32, 0xAD, 0x12, 0xAD, 0x32, +0xAD, 0x12, 0xB5, 0x53, 0xB5, 0x73, 0xBD, 0x94, +0xC5, 0xF5, 0xBD, 0xD5, 0xBD, 0xB5, 0xBD, 0x94, +0xB5, 0x93, 0xB5, 0x93, 0xAD, 0x52, 0xAD, 0x52, +0xB5, 0x73, 0xBD, 0xB4, 0xC6, 0x15, 0xC6, 0x15, +0xAD, 0x32, 0x9C, 0xB0, 0xB5, 0x52, 0xBD, 0x93, +0xB5, 0x32, 0xC5, 0xB4, 0xBD, 0x93, 0xBD, 0x93, +0xC5, 0xB4, 0xAD, 0x32, 0xB5, 0x52, 0xBD, 0x73, +0xA4, 0xF1, 0xA4, 0xF0, 0xA4, 0xD0, 0x9C, 0xB0, +0x94, 0x6F, 0x9C, 0x90, 0xBD, 0x73, 0x8C, 0x2D, +0xAD, 0x10, 0xAC, 0xEF, 0xAD, 0x30, 0xAD, 0x10, +0xAC, 0xEF, 0x8C, 0x0C, 0x9C, 0xAF, 0xA4, 0xCF, +0xA4, 0xD0, 0xA4, 0xF1, 0xAC, 0xF1, 0xA4, 0xD0, +0xA4, 0xF0, 0xB5, 0x52, 0xB5, 0x72, 0xCD, 0xF3, +0xD6, 0x34, 0xD6, 0x13, 0xC5, 0xD3, 0xB5, 0x52, +0xCE, 0x36, 0xCE, 0x16, 0x9C, 0xB0, 0xDE, 0xD7, +0xDE, 0xB7, 0xDE, 0xB7, 0xDE, 0x97, 0xCE, 0x57, +0xB5, 0x94, 0x94, 0x70, 0x8C, 0x50, 0x94, 0x91, +0x8C, 0x92, 0x94, 0xD3, 0xA5, 0x55, 0x9D, 0x35, +0x9D, 0x14, 0x5A, 0xCB, 0x42, 0x07, 0x5A, 0xC9, +0x6B, 0x2A, 0x62, 0xE9, 0x73, 0x8B, 0x8C, 0x0D, +0x83, 0xEC, 0x8C, 0x2E, 0x94, 0x6F, 0x9C, 0xB0, +0xAD, 0x11, 0xA4, 0xF1, 0xAD, 0x32, 0xB5, 0x52, +0xA4, 0xD0, 0x9C, 0x4D, 0xAC, 0xCF, 0xA4, 0x8F, +0xA4, 0x8F, 0xA4, 0x8F, 0x9C, 0xB0, 0xB5, 0x72, +0xBD, 0x93, 0xB5, 0x73, 0xB5, 0x93, 0x73, 0x4B, +0xBD, 0x94, 0xBD, 0x94, 0xC5, 0xD4, 0xAD, 0x11, +0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x32, 0xA4, 0xD0, +0xA4, 0xD1, 0xB5, 0x73, 0xAD, 0x11, 0xB5, 0x52, +0x8B, 0xED, 0xAC, 0xD0, 0x83, 0x8C, 0xA4, 0x90, +0xA4, 0x6F, 0x83, 0x8B, 0x83, 0xAC, 0x83, 0x8C, +0x8C, 0x2F, 0x8C, 0x70, 0x94, 0x70, 0xA5, 0x12, +0x5A, 0xCA, 0x41, 0xE7, 0x41, 0xE7, 0x39, 0xC6, +0x39, 0xC6, 0x39, 0xC6, 0x39, 0xE7, 0x4A, 0x48, +0x5A, 0xCA, 0x6B, 0x4D, 0x8C, 0x51, 0x9C, 0xD3, +0xA5, 0x14, 0xC5, 0xF8, 0xC6, 0x18, 0xD6, 0xBA, +0x9C, 0xB1, 0xA4, 0xD1, 0xBD, 0x93, 0xA4, 0xF1, +0x94, 0x6F, 0xA4, 0xF1, 0x94, 0x4F, 0x9C, 0xB0, +0xB5, 0x73, 0xBD, 0x94, 0xA4, 0xB0, 0x63, 0x0A, +0x31, 0xA5, 0x4A, 0x48, 0x62, 0xEB, 0x52, 0x69, +0x52, 0x69, 0x5A, 0xEC, 0x94, 0x72, 0xAD, 0x35, +0xC5, 0xF8, 0xCE, 0x59, 0xD6, 0x7A, 0xBD, 0x96, +0xB5, 0x55, 0xCE, 0x38, 0xA4, 0xD3, 0x94, 0x30, +0xBD, 0x73, 0xAC, 0xD0, 0xAC, 0xD0, 0xAC, 0xCF, +0x9C, 0x6D, 0x94, 0x4E, 0xCE, 0x34, 0xDE, 0x95, +0xE6, 0xB6, 0xD6, 0x34, 0xAC, 0xEF, 0xB4, 0xEF, +0xAC, 0xF0, 0x83, 0xCC, 0x84, 0x0D, 0x8C, 0x0D, +0x94, 0x4E, 0x8C, 0x0D, 0x8C, 0x2D, 0xAD, 0x52, +0xC5, 0xF5, 0xB5, 0x73, 0x94, 0x6F, 0x73, 0x8B, +0x83, 0xED, 0x8C, 0x0E, 0x8C, 0x4E, 0x94, 0x6E, +0xAD, 0x31, 0xB5, 0x72, 0xB5, 0x31, 0x8C, 0x0C, +0x8B, 0xEC, 0x94, 0x2C, 0xAC, 0xCF, 0x8B, 0xCB, +0x83, 0xAB, 0x83, 0xCC, 0x94, 0x2D, 0x94, 0x0C, +0x7B, 0x8B, 0x8B, 0xEC, 0x94, 0x0C, 0x94, 0x2D, +0xA4, 0xF2, 0xC6, 0x38, 0xAD, 0x76, 0x9C, 0xF3, +0x94, 0x4F, 0x9C, 0x6E, 0x9C, 0x8F, 0x9C, 0x8F, +0x9C, 0x6E, 0x9C, 0x6E, 0x9C, 0x8E, 0x9C, 0x6E, +0x9C, 0xAF, 0xA4, 0xAF, 0xAC, 0xF1, 0xA4, 0xD1, +0x7B, 0xAD, 0x8C, 0x2E, 0x8C, 0x2F, 0xA5, 0x12, +0xAD, 0x12, 0xA4, 0xD1, 0xA4, 0xF1, 0xA5, 0x12, +0xAD, 0x32, 0xB5, 0x73, 0xB5, 0x73, 0xAD, 0x12, +0xAD, 0x33, 0xAD, 0x12, 0x9C, 0xB1, 0x9C, 0xD1, +0xA4, 0xD1, 0x9C, 0xB0, 0x94, 0x6F, 0x94, 0x6F, +0x94, 0x4F, 0x94, 0x6F, 0x94, 0x4F, 0x94, 0x4F, +0x84, 0x0D, 0x83, 0xED, 0x7B, 0xCD, 0x94, 0x70, +0x9C, 0xB0, 0xBD, 0xB4, 0xAD, 0x52, 0x8C, 0x4E, +0x9C, 0xB0, 0x94, 0x4E, 0x8C, 0x2E, 0x9C, 0x8F, +0x7B, 0xCC, 0x9C, 0xB0, 0xB5, 0x53, 0xA4, 0xF1, +0xAD, 0x52, 0x9C, 0xB0, 0x8C, 0x2E, 0xAD, 0x52, +0xC5, 0xF5, 0xC6, 0x15, 0xD6, 0x77, 0xBD, 0xB3, +0xCE, 0x35, 0xBD, 0x93, 0xA4, 0xD0, 0xB5, 0x52, +0xA4, 0xF0, 0xB5, 0x72, 0xA4, 0xF0, 0x8C, 0x4E, +0x8C, 0x2D, 0xAD, 0x11, 0xB5, 0x52, 0x9C, 0xB0, +0x83, 0xCD, 0xB5, 0x53, 0x8C, 0x2E, 0xAD, 0x11, +0xBD, 0x93, 0xBD, 0xB3, 0xCE, 0x15, 0xB5, 0x72, +0xB5, 0x52, 0xC5, 0xD4, 0xB5, 0x72, 0xA4, 0xF1, +0x9C, 0xB0, 0xBD, 0x73, 0xAD, 0x52, 0xAD, 0x11, +0x94, 0x4F, 0x9C, 0xB0, 0xA4, 0xF1, 0xB5, 0x52, +0xB5, 0x53, 0xAD, 0x32, 0xA4, 0xF1, 0x9C, 0xB0, +0x94, 0x4F, 0xA5, 0x11, 0x9C, 0xD0, 0xC5, 0xF5, +0xB5, 0x73, 0xB5, 0x53, 0xBD, 0x94, 0xBD, 0xB4, +0xAD, 0x12, 0xB5, 0x93, 0xCE, 0x16, 0xCE, 0x16, +0xC5, 0xF5, 0xC5, 0xD5, 0xB5, 0x94, 0xC5, 0xD5, +0xC6, 0x15, 0xC5, 0xF5, 0xBD, 0x94, 0xBD, 0xD5, +0xBD, 0xB4, 0xBD, 0xB4, 0xCE, 0x36, 0xC5, 0xF5, +0xAD, 0x32, 0xA4, 0xD0, 0xB5, 0x52, 0xC5, 0xD4, +0xBD, 0x72, 0xBD, 0x93, 0xB5, 0x52, 0xC5, 0xB3, +0xBD, 0x93, 0xA4, 0xD0, 0xB5, 0x73, 0xC5, 0xD4, +0x9C, 0xB0, 0x9C, 0x8F, 0xA4, 0xF1, 0x94, 0x6F, +0x83, 0xED, 0xA4, 0xB0, 0xB5, 0x32, 0x83, 0xEC, +0xAD, 0x11, 0xA4, 0xF0, 0xBD, 0x92, 0xB5, 0x72, +0xAD, 0x31, 0x94, 0x6F, 0x83, 0xCC, 0x94, 0x8F, +0xAD, 0x11, 0xA4, 0xD0, 0x9C, 0x8F, 0x8C, 0x2E, +0x83, 0xED, 0x94, 0x6F, 0x9C, 0x8F, 0xA4, 0xF0, +0xB5, 0x51, 0xB5, 0x30, 0xA4, 0xEF, 0xA4, 0xF0, +0xCE, 0x14, 0xBD, 0x73, 0xAC, 0xF1, 0xE6, 0xD7, +0xCE, 0x34, 0xCD, 0xF4, 0xCE, 0x14, 0xD6, 0x76, +0xD6, 0x97, 0xD6, 0x98, 0x9C, 0xD2, 0x84, 0x0F, +0x9D, 0x14, 0x9D, 0x14, 0x9C, 0xF4, 0x94, 0xD3, +0x9D, 0x14, 0x4A, 0x8A, 0x31, 0x85, 0x4A, 0x07, +0x5A, 0xA9, 0x5A, 0xA8, 0x63, 0x0A, 0x73, 0x4A, +0x73, 0x6B, 0x7B, 0x8C, 0x8C, 0x0D, 0x83, 0xEC, +0xA4, 0xF1, 0xAD, 0x12, 0xB5, 0x52, 0xA4, 0xD0, +0x9C, 0xAF, 0x9C, 0x4D, 0xA4, 0xAF, 0x9C, 0x6E, +0xA4, 0xD0, 0xA4, 0xD0, 0xB5, 0x52, 0xAD, 0x32, +0xAD, 0x31, 0xAD, 0x11, 0xA4, 0xD0, 0x94, 0x6F, +0xA4, 0xF1, 0xB5, 0x52, 0xC5, 0xD4, 0xA4, 0xF1, +0xAD, 0x52, 0xBD, 0x94, 0xBD, 0x94, 0xB5, 0x93, +0xAD, 0x11, 0xC5, 0xF5, 0xAD, 0x11, 0xB5, 0x73, +0x83, 0xAC, 0xAC, 0xF1, 0x83, 0x8B, 0xA4, 0x8F, +0xA4, 0x4F, 0x93, 0xED, 0x8C, 0x0E, 0x8C, 0x0E, +0x94, 0x90, 0x8C, 0x4F, 0x9C, 0xD1, 0xAD, 0x53, +0x7B, 0xAD, 0x5A, 0xCA, 0x31, 0x85, 0x29, 0x44, +0x31, 0x85, 0x31, 0xA6, 0x39, 0xC6, 0x4A, 0x69, +0x52, 0x89, 0x63, 0x2C, 0x7B, 0xCE, 0x94, 0x92, +0xA5, 0x35, 0xB5, 0xB7, 0xC6, 0x39, 0xE7, 0x1C, +0x9C, 0xD2, 0xB5, 0x73, 0xBD, 0xD4, 0xA4, 0xF1, +0xA4, 0xD0, 0xAD, 0x32, 0x94, 0x6F, 0xA4, 0xF1, +0xB5, 0x73, 0xA4, 0xD0, 0xBD, 0x72, 0xB5, 0x93, +0x73, 0x8C, 0x41, 0xE7, 0x4A, 0x28, 0x4A, 0x48, +0x52, 0xAA, 0x62, 0xEC, 0x4A, 0x69, 0x73, 0xAE, +0x8C, 0x51, 0x94, 0x72, 0xCE, 0x39, 0xBD, 0xB6, +0xA4, 0xD3, 0xBD, 0x76, 0x8C, 0x10, 0x62, 0xEB, +0xAD, 0x13, 0xBD, 0x74, 0xAC, 0xD0, 0xAC, 0xF0, +0x9C, 0x6E, 0x9C, 0x6E, 0xDE, 0x96, 0xDE, 0xB6, +0xE6, 0xB6, 0xD6, 0x34, 0xB5, 0x30, 0x9C, 0x6E, +0xB5, 0x31, 0x62, 0xE9, 0x63, 0x0A, 0x7B, 0xCD, +0x94, 0x6F, 0x8C, 0x2E, 0x8C, 0x4F, 0xC6, 0x36, +0xD6, 0x97, 0xCE, 0x36, 0x94, 0xB0, 0x7B, 0xAD, +0x84, 0x0E, 0x8C, 0x6F, 0x94, 0x6F, 0x94, 0xB0, +0xB5, 0x73, 0xC5, 0xF4, 0xB5, 0x72, 0x9C, 0xB0, +0x9C, 0x8F, 0x9C, 0x8E, 0xA4, 0xCF, 0x8B, 0xCC, +0x94, 0x4E, 0x9C, 0x8F, 0x94, 0x6F, 0x94, 0x6E, +0x83, 0xED, 0x8C, 0x2E, 0x94, 0x6F, 0x73, 0x8C, +0xB5, 0x95, 0xC6, 0x18, 0xAD, 0x76, 0x9C, 0xD3, +0xA5, 0x12, 0x7B, 0xAC, 0x7B, 0xAC, 0x8C, 0x0E, +0x84, 0x0D, 0x94, 0x6F, 0x94, 0x6F, 0x94, 0x8F, +0x8C, 0x0D, 0x83, 0xEC, 0xAD, 0x32, 0x94, 0x70, +0x62, 0xEA, 0x73, 0x8D, 0x73, 0xAD, 0x84, 0x0E, +0x8C, 0x0E, 0x84, 0x0E, 0x7B, 0xAD, 0x7B, 0xAC, +0x8C, 0x4F, 0x8C, 0x0E, 0x94, 0x4F, 0x8C, 0x0E, +0x8C, 0x0E, 0x9C, 0x90, 0x9C, 0x90, 0x8C, 0x4F, +0x8C, 0x4F, 0x8C, 0x2F, 0x83, 0xEE, 0x9C, 0x90, +0x8C, 0x0E, 0x8C, 0x4F, 0x9C, 0xD1, 0x8C, 0x2E, +0xAD, 0x12, 0xAD, 0x32, 0xAD, 0x32, 0xB5, 0x53, +0xAD, 0x32, 0x9C, 0xB1, 0xA4, 0xF1, 0xA4, 0xD1, +0xAC, 0xF2, 0xA4, 0xD1, 0xA4, 0xF2, 0x9C, 0xB1, +0xA4, 0xF1, 0xA5, 0x12, 0xB5, 0x53, 0xB5, 0x73, +0xB5, 0x53, 0xA4, 0xF2, 0xAD, 0x33, 0xAD, 0x52, +0x9C, 0xB0, 0x94, 0x4F, 0xA4, 0xD1, 0x9C, 0xB0, +0x9C, 0x8F, 0x9C, 0x8F, 0xA4, 0xD1, 0xA4, 0xF1, +0xA4, 0xD0, 0x9C, 0xB0, 0x9C, 0xB0, 0xAD, 0x32, +0x9C, 0x90, 0x94, 0x6F, 0x94, 0x6F, 0x73, 0x6B, +0x7B, 0xAD, 0xBD, 0xB4, 0x8C, 0x2E, 0xA4, 0xD1, +0xB5, 0x53, 0xAD, 0x52, 0xB5, 0x73, 0xAD, 0x32, +0x9C, 0x8F, 0xB5, 0x73, 0x9C, 0xB0, 0x9C, 0x90, +0xA4, 0xF1, 0xAD, 0x12, 0x9C, 0x8F, 0x83, 0xED, +0x8C, 0x0E, 0xAD, 0x52, 0xAD, 0x32, 0xA4, 0xF1, +0xAD, 0x12, 0xB5, 0x73, 0xB5, 0x73, 0x94, 0x6F, +0x83, 0xED, 0x9C, 0xD1, 0xA4, 0xD0, 0xBD, 0x93, +0xA4, 0xF1, 0xB5, 0x32, 0xC5, 0xB4, 0xCD, 0xF5, +0xC5, 0xF5, 0xBD, 0xB4, 0xC5, 0xD4, 0xCE, 0x36, +0xD6, 0x77, 0xCE, 0x36, 0xB5, 0x94, 0xC5, 0xF5, +0xCE, 0x36, 0xCE, 0x35, 0xC5, 0xF5, 0xB5, 0x52, +0xBD, 0x93, 0xBD, 0xD4, 0xCE, 0x35, 0xBD, 0xD4, +0x9C, 0xD0, 0xA4, 0xF1, 0xB5, 0x72, 0xBD, 0xB3, +0xC5, 0xD4, 0xC5, 0xF4, 0xBD, 0x93, 0xC5, 0xD4, +0xC5, 0xB4, 0xAD, 0x11, 0xBD, 0x73, 0xBD, 0x93, +0x8C, 0x4E, 0x9C, 0x90, 0xAC, 0xF1, 0x9C, 0x90, +0x73, 0x6C, 0x9C, 0xB0, 0xAD, 0x11, 0x94, 0x4E, +0xB5, 0x73, 0xA4, 0xF1, 0xAD, 0x32, 0xB5, 0x73, +0xAD, 0x52, 0xBD, 0x94, 0xAD, 0x32, 0xAD, 0x12, +0xAD, 0x12, 0xAD, 0x32, 0x9C, 0x90, 0x8C, 0x2E, +0x52, 0x89, 0x7B, 0xAD, 0x9C, 0xB0, 0x9C, 0xB0, +0x94, 0x6F, 0x94, 0x4E, 0x9C, 0xAF, 0xAD, 0x11, +0xC5, 0xB3, 0xB5, 0x52, 0xB5, 0x32, 0xE6, 0xD7, +0xD6, 0x34, 0xD6, 0x55, 0xDE, 0x96, 0xD6, 0x75, +0xD6, 0x56, 0xD6, 0x97, 0xDE, 0x97, 0xC5, 0xF5, +0x9D, 0x14, 0x9D, 0x14, 0x9D, 0x14, 0x94, 0xF4, +0x94, 0xB3, 0x5A, 0xCB, 0x52, 0x68, 0x5A, 0xA9, +0x5A, 0xC9, 0x62, 0xC9, 0x62, 0xEA, 0x6A, 0xEA, +0x73, 0x2A, 0x73, 0x2A, 0x7B, 0x4A, 0x7B, 0x8B, +0x83, 0xCC, 0x8C, 0x0D, 0x94, 0x2D, 0x94, 0x2E, +0x7B, 0x8B, 0x9C, 0x4E, 0x93, 0xEC, 0x7B, 0x6A, +0x83, 0xCC, 0x7B, 0x8B, 0xA4, 0xD1, 0x9C, 0xB0, +0xA4, 0xD0, 0xB5, 0x73, 0xAD, 0x32, 0xAD, 0x32, +0xA4, 0xF1, 0xB5, 0x52, 0xBD, 0xD4, 0xB5, 0x73, +0xC5, 0xD5, 0xBD, 0x94, 0xB5, 0x94, 0xC5, 0xF5, +0x9C, 0x90, 0xC5, 0xD5, 0x94, 0x6F, 0x6B, 0x0A, +0x73, 0x4A, 0xA4, 0xB0, 0x9C, 0x4E, 0xB5, 0x11, +0xAC, 0xD0, 0xA4, 0x8F, 0xA4, 0xB0, 0xA4, 0xB1, +0xA4, 0xD1, 0x94, 0x70, 0xA5, 0x12, 0xB5, 0x73, +0x94, 0x70, 0x7B, 0xAD, 0x41, 0xE6, 0x29, 0x64, +0x29, 0x44, 0x39, 0xC6, 0x39, 0xE7, 0x39, 0xE7, +0x42, 0x07, 0x52, 0xAA, 0x63, 0x2C, 0x83, 0xEF, +0x9C, 0xF3, 0xA5, 0x14, 0xBD, 0xD8, 0xCE, 0x59, +0x9C, 0xB2, 0xB5, 0x94, 0xBD, 0xB4, 0xB5, 0x73, +0x9C, 0xB0, 0xA4, 0xD1, 0x9C, 0x90, 0xAD, 0x32, +0xBD, 0x73, 0xA4, 0xD0, 0xB5, 0x32, 0xBD, 0x93, +0xB5, 0x52, 0x62, 0xEA, 0x39, 0xC6, 0x42, 0x07, +0x4A, 0x69, 0x5A, 0xAA, 0x52, 0x8A, 0x6B, 0x2C, +0x84, 0x10, 0x52, 0x6A, 0x4A, 0x69, 0x9C, 0xB2, +0xBD, 0xB6, 0xBD, 0x96, 0xB5, 0x34, 0xD6, 0x59, +0x73, 0x6D, 0x9C, 0x70, 0xBD, 0x53, 0xAC, 0xCF, +0x9C, 0x6D, 0xA4, 0xAF, 0xE6, 0xD7, 0xE6, 0xB6, +0xE6, 0xB6, 0xCE, 0x14, 0xB5, 0x30, 0x9C, 0x4D, +0xA4, 0xD0, 0x73, 0x6B, 0x73, 0xAC, 0x83, 0xEE, +0x8C, 0x4F, 0x83, 0xCD, 0x83, 0xED, 0xBD, 0xD4, +0xDE, 0xD8, 0xCE, 0x76, 0x9C, 0xD1, 0x8C, 0x2F, +0x84, 0x0E, 0x9C, 0xB1, 0x8C, 0x2F, 0x94, 0x90, +0xBD, 0xD5, 0xC5, 0xF5, 0xCE, 0x15, 0xAD, 0x32, +0x83, 0xED, 0x9C, 0x8F, 0xAC, 0xF0, 0x83, 0x8B, +0x94, 0x4E, 0x94, 0x6F, 0x94, 0x4F, 0x94, 0x4F, +0x94, 0x90, 0x94, 0x70, 0xAD, 0x53, 0x9C, 0xD2, +0xCE, 0x59, 0xB5, 0xB7, 0xAD, 0x55, 0x9C, 0xF3, +0xC5, 0xF6, 0xB5, 0xB4, 0xAD, 0x53, 0xAD, 0x53, +0x94, 0x6F, 0x9C, 0xD1, 0xA5, 0x12, 0xCE, 0x57, +0xC5, 0xF5, 0x8C, 0x2E, 0xAD, 0x12, 0x94, 0x4F, +0x8C, 0x70, 0x94, 0xB1, 0x9C, 0xD1, 0xAD, 0x33, +0xA5, 0x12, 0x94, 0x90, 0x94, 0x6F, 0x94, 0x90, +0x94, 0x90, 0x7B, 0xCD, 0x83, 0xEE, 0x8C, 0x2F, +0x83, 0xEE, 0xA4, 0xD1, 0xB5, 0x52, 0xAD, 0x32, +0xB5, 0x73, 0xAD, 0x53, 0xAD, 0x12, 0xAD, 0x32, +0x9C, 0xD1, 0x94, 0x90, 0x94, 0x4F, 0x62, 0xEA, +0x73, 0x8C, 0x7B, 0xED, 0x84, 0x0E, 0x8C, 0x2F, +0x94, 0x90, 0x94, 0x70, 0x8C, 0x0E, 0x83, 0xED, +0x83, 0xED, 0x9C, 0xB0, 0x94, 0x70, 0x83, 0xEE, +0x8C, 0x4F, 0x94, 0x70, 0x7B, 0xCD, 0x7B, 0xAD, +0x7B, 0xAD, 0x83, 0xCE, 0x8C, 0x0F, 0x94, 0x4F, +0x9C, 0xB0, 0xA4, 0xB1, 0xB5, 0x74, 0xCE, 0x16, +0xB5, 0x53, 0xBD, 0x73, 0xB5, 0x73, 0xB5, 0x53, +0xB5, 0x53, 0xBD, 0x73, 0xB5, 0x73, 0xBD, 0x93, +0xBD, 0xB4, 0xC5, 0xD4, 0xBD, 0xB4, 0xB5, 0x73, +0xB5, 0x74, 0xC5, 0xD5, 0xCE, 0x37, 0xCE, 0x37, +0xCE, 0x16, 0xCE, 0x16, 0xCE, 0x16, 0xCD, 0xF6, +0xCD, 0xF5, 0xC5, 0xD5, 0xBD, 0xB5, 0xBD, 0x94, +0xAD, 0x32, 0xAD, 0x12, 0xAD, 0x12, 0xAC, 0xF2, +0xA4, 0xB1, 0xA4, 0xB0, 0xA4, 0xB0, 0x9C, 0xB0, +0x9C, 0xB0, 0xA4, 0xD1, 0x9C, 0x90, 0x8C, 0x2E, +0xAD, 0x12, 0xB5, 0x73, 0x9C, 0x90, 0xA4, 0xD0, +0x94, 0x2E, 0x8C, 0x0E, 0x9C, 0x6F, 0x94, 0x6F, +0x94, 0x4E, 0x83, 0xCD, 0x94, 0x4F, 0x9C, 0xB0, +0xB5, 0x73, 0xB5, 0x53, 0xAD, 0x33, 0xBD, 0xB4, +0xCD, 0xF5, 0xCE, 0x36, 0xBD, 0xB4, 0xAD, 0x52, +0xB5, 0x52, 0xC6, 0x16, 0xCE, 0x56, 0xB5, 0x73, +0x94, 0x8F, 0xAD, 0x32, 0xBD, 0xB3, 0xB5, 0x52, +0xBD, 0x93, 0xBD, 0x93, 0xAD, 0x31, 0xB5, 0x72, +0xBD, 0x93, 0xB5, 0x51, 0xC5, 0xD4, 0xBD, 0x73, +0xAD, 0x32, 0xBD, 0x93, 0xB5, 0x73, 0x83, 0xED, +0x6B, 0x2B, 0x9C, 0xB0, 0xB5, 0x52, 0x8C, 0x4F, +0xB5, 0x94, 0xAD, 0x32, 0xB5, 0x73, 0xBD, 0xD5, +0xAD, 0x32, 0x8C, 0x4F, 0xBD, 0xD5, 0xB5, 0x94, +0xA4, 0xF2, 0xAD, 0x73, 0xA5, 0x12, 0x9C, 0xF2, +0x73, 0xAD, 0x6B, 0x2B, 0x9C, 0xD1, 0xA4, 0xF1, +0x94, 0x90, 0x8C, 0x2F, 0x9C, 0xB0, 0x9C, 0xAF, +0xAD, 0x10, 0xA4, 0xF0, 0xAD, 0x11, 0xDE, 0x96, +0xD6, 0x34, 0xD6, 0x34, 0xDE, 0x95, 0xDE, 0xB6, +0xDE, 0xB6, 0xDE, 0xB7, 0xD6, 0x76, 0xD6, 0x76, +0xA5, 0x35, 0xA5, 0x34, 0x9D, 0x14, 0x9C, 0xF4, +0x94, 0xB3, 0x5A, 0xCA, 0x5A, 0xA9, 0x62, 0xE9, +0x6B, 0x0A, 0x73, 0x2A, 0x7B, 0x6B, 0x7B, 0x6B, +0x83, 0xAC, 0x83, 0xAB, 0x83, 0x8B, 0x83, 0x8B, +0x83, 0xAB, 0x8B, 0xCC, 0x8B, 0xEC, 0x94, 0x2D, +0x9C, 0x6E, 0xAC, 0xCF, 0xB4, 0xF0, 0xAC, 0xD0, +0x9C, 0x4E, 0x8B, 0xEC, 0x94, 0x2E, 0x94, 0x4E, +0x94, 0x4E, 0x94, 0x2E, 0x94, 0x2D, 0x94, 0x2D, +0x94, 0x4E, 0x94, 0x4E, 0x94, 0x4E, 0x94, 0x4E, +0xA4, 0xB0, 0xAD, 0x11, 0xA4, 0xD0, 0xA4, 0xD0, +0x94, 0x4E, 0x9C, 0xAF, 0x83, 0xCC, 0x62, 0xC8, +0x94, 0x4E, 0x9C, 0x6E, 0x94, 0x0D, 0xB5, 0x11, +0xB5, 0x11, 0xAC, 0xB0, 0xAC, 0xF1, 0xAD, 0x12, +0xA4, 0xF1, 0x8C, 0x4F, 0xA4, 0xF2, 0xBD, 0xB4, +0x73, 0x8C, 0x5A, 0xCA, 0x4A, 0x28, 0x39, 0xC6, +0x3A, 0x07, 0x42, 0x07, 0x39, 0xE7, 0x39, 0xA6, +0x39, 0xE7, 0x4A, 0x49, 0x5A, 0xCA, 0x6B, 0x6D, +0x84, 0x0F, 0x9C, 0xF3, 0xB5, 0xB6, 0x73, 0x8E, +0x9C, 0xB3, 0xD6, 0x79, 0xB5, 0x53, 0xBD, 0x93, +0xB5, 0x52, 0xBD, 0x94, 0xB5, 0x73, 0xBD, 0x73, +0xC5, 0xB4, 0xB5, 0x32, 0xB5, 0x32, 0xB5, 0x31, +0xB5, 0x32, 0x9C, 0x8F, 0x6B, 0x2A, 0x31, 0x85, +0x42, 0x07, 0x5A, 0xEB, 0x4A, 0x49, 0x73, 0x8D, +0x7B, 0x8E, 0x31, 0x86, 0x4A, 0x29, 0x62, 0xEB, +0x83, 0xF0, 0xB5, 0x55, 0xCD, 0xF7, 0xCE, 0x17, +0xCD, 0xF7, 0x6B, 0x0B, 0xAC, 0xD2, 0xBD, 0x73, +0x7B, 0x8A, 0xAC, 0xF0, 0xE6, 0xD7, 0xDE, 0xB6, +0xE6, 0xD6, 0xD6, 0x14, 0xB5, 0x30, 0x8B, 0xAB, +0x9C, 0x8F, 0x73, 0x6B, 0x5A, 0xCA, 0x6B, 0x4B, +0x8C, 0x2E, 0x73, 0x8C, 0x83, 0xED, 0xB5, 0x73, +0xD6, 0x76, 0xCE, 0x56, 0xA5, 0x12, 0x94, 0xB1, +0x8C, 0x4F, 0xA5, 0x12, 0x9C, 0xB0, 0xA5, 0x12, +0xC5, 0xF5, 0xC6, 0x15, 0xCE, 0x35, 0xB5, 0x52, +0x83, 0xEC, 0x94, 0x6E, 0xAD, 0x11, 0x83, 0x8B, +0x83, 0xED, 0x8C, 0x4E, 0x94, 0x4F, 0x8C, 0x4E, +0x8C, 0x4E, 0x8C, 0x2E, 0x94, 0x6F, 0xA4, 0xF2, +0xCE, 0x38, 0xB5, 0x96, 0xAD, 0x55, 0x94, 0x71, +0xB5, 0x74, 0xAD, 0x53, 0xB5, 0x94, 0xA5, 0x12, +0x8C, 0x4F, 0x9C, 0xD1, 0x9C, 0xD0, 0xA4, 0xF1, +0xB5, 0x94, 0x9C, 0xD1, 0xAD, 0x33, 0x8C, 0x4F, +0x94, 0x90, 0x94, 0x90, 0xA5, 0x12, 0xAD, 0x32, +0x9C, 0xD1, 0x9C, 0xD1, 0x9C, 0xB0, 0x94, 0x90, +0x8C, 0x4F, 0x63, 0x2B, 0x5B, 0x0B, 0x6B, 0x6C, +0x73, 0x6C, 0x94, 0x90, 0xAD, 0x52, 0xBD, 0xB4, +0xA5, 0x11, 0xAD, 0x32, 0xB5, 0x93, 0xB5, 0x93, +0xB5, 0x73, 0x9C, 0xD1, 0x94, 0x90, 0x73, 0x6C, +0x73, 0x8D, 0x7B, 0xAD, 0x6B, 0x4C, 0x73, 0x6C, +0x6B, 0x4C, 0x6B, 0x4C, 0x6B, 0x2B, 0x6B, 0x2B, +0x73, 0x6C, 0x83, 0xCD, 0x94, 0x6F, 0x83, 0xCD, +0x83, 0xCD, 0x8C, 0x2F, 0x7B, 0xAD, 0x6B, 0x4C, +0x63, 0x0B, 0x6B, 0x2B, 0x6B, 0x2B, 0x6B, 0x4B, +0x83, 0xCD, 0x83, 0xCD, 0x83, 0xED, 0xAD, 0x12, +0x94, 0x6F, 0xA4, 0xF1, 0xA4, 0xF1, 0xA4, 0xD0, +0x9C, 0xAF, 0xA4, 0xD0, 0x94, 0x6F, 0x7B, 0xCD, +0x7B, 0x8C, 0x7B, 0xAD, 0x7B, 0xAD, 0x7B, 0x8C, +0x83, 0xED, 0x83, 0xCD, 0x8B, 0xEE, 0x9C, 0xB0, +0xAD, 0x12, 0x9C, 0x70, 0x8C, 0x2F, 0x94, 0x4F, +0x9C, 0x70, 0x9C, 0x90, 0xB5, 0x74, 0xC5, 0xD5, +0xA4, 0xF1, 0xAD, 0x12, 0xA4, 0xF1, 0xAD, 0x32, +0xB5, 0x53, 0xB5, 0x53, 0xB5, 0x53, 0xB5, 0x32, +0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x53, 0xBD, 0x73, +0xC5, 0xB4, 0xBD, 0x94, 0xBD, 0x73, 0xBD, 0x73, +0xB5, 0x52, 0xB5, 0x32, 0xB5, 0x53, 0xB5, 0x32, +0xB5, 0x73, 0xBD, 0x94, 0xC5, 0xB4, 0xC5, 0xB4, +0xBD, 0x73, 0xB5, 0x53, 0xAD, 0x12, 0xAD, 0x12, +0xAD, 0x12, 0xA4, 0xF1, 0x9C, 0xB0, 0x94, 0x6F, +0x9C, 0x90, 0xAD, 0x12, 0xAD, 0x11, 0x94, 0x6F, +0x9C, 0xB0, 0xA4, 0xF1, 0x9C, 0xB0, 0x8C, 0x2E, +0x8C, 0x0E, 0x83, 0xCD, 0x8B, 0xED, 0x94, 0x4E, +0x9C, 0x6F, 0xAD, 0x11, 0xAD, 0x11, 0xAC, 0xF1, +0xBD, 0x73, 0xBD, 0x73, 0xB5, 0x52, 0x73, 0x6B, +0x6B, 0x2A, 0x9C, 0xB0, 0xA4, 0xF1, 0xA4, 0xD1, +0xBD, 0xD4, 0xBD, 0xB4, 0xBD, 0xD4, 0xBD, 0xD5, +0xBD, 0xB4, 0xBD, 0xD5, 0xC5, 0xF5, 0xC6, 0x16, +0xBD, 0xD5, 0xAD, 0x74, 0xAD, 0x53, 0xAD, 0x73, +0x94, 0xB1, 0x84, 0x0F, 0xAD, 0x32, 0xB5, 0x94, +0xA5, 0x32, 0xA4, 0xF2, 0xA4, 0xF1, 0xA4, 0xF1, +0xA4, 0xF0, 0x9C, 0xAF, 0xA4, 0xB0, 0xD6, 0x55, +0xDE, 0x95, 0xD6, 0x54, 0xD6, 0x75, 0xDE, 0x75, +0xDE, 0x75, 0xD6, 0x96, 0xE6, 0xB7, 0xDE, 0x96, +0xA5, 0x35, 0xA5, 0x34, 0x9D, 0x14, 0x9C, 0xF4, +0x94, 0xD3, 0x52, 0xAA, 0x52, 0x68, 0x63, 0x0A, +0x6B, 0x2A, 0x6B, 0x09, 0x73, 0x2A, 0x73, 0x2A, +0x83, 0xCC, 0x8C, 0x0D, 0x94, 0x2D, 0x9C, 0x6F, +0x7B, 0xAB, 0x73, 0x6A, 0x7B, 0xAB, 0x8B, 0xEC, +0x94, 0x2D, 0x94, 0x0C, 0x93, 0xEC, 0x8B, 0xAB, +0x6A, 0xA8, 0x9C, 0x4D, 0xA4, 0xAF, 0xA4, 0x6E, +0x9C, 0x6E, 0x94, 0x2D, 0x9C, 0x8E, 0xA4, 0xCF, +0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0xAF, +0xA4, 0x8F, 0x9C, 0x4E, 0xA4, 0x8E, 0x9C, 0x4D, +0x9C, 0x4D, 0x9C, 0x6E, 0x94, 0x4D, 0xA4, 0xCF, +0xAC, 0xF0, 0xA4, 0xAF, 0x83, 0xAB, 0x8B, 0xEC, +0x83, 0x8B, 0x62, 0xC9, 0x62, 0xC9, 0x62, 0xC9, +0x62, 0xE9, 0x62, 0xC9, 0x5A, 0x88, 0x5A, 0xA9, +0x62, 0xC9, 0x4A, 0x27, 0x4A, 0x28, 0x52, 0x89, +0x4A, 0x48, 0x4A, 0x28, 0x39, 0xA6, 0x31, 0xA6, +0x39, 0xE6, 0x4A, 0x48, 0x52, 0xAA, 0x73, 0xAE, +0x8C, 0x51, 0x9C, 0xD3, 0x9C, 0xD3, 0x6B, 0x6E, +0x8C, 0x72, 0xDE, 0xBA, 0xC6, 0x16, 0xA4, 0xD0, +0xB5, 0x32, 0xB5, 0x52, 0xB5, 0x52, 0xB5, 0x32, +0xB5, 0x52, 0xAC, 0xF1, 0x9C, 0xAF, 0xA4, 0xD0, +0x9C, 0x6F, 0x94, 0x2E, 0xB5, 0x31, 0x62, 0xEA, +0x39, 0xA6, 0x39, 0xA6, 0x52, 0x8A, 0x73, 0x8E, +0x52, 0x8A, 0x62, 0xEB, 0x63, 0x0C, 0x6B, 0x4D, +0x8C, 0x31, 0x5A, 0x8A, 0x9C, 0x92, 0x94, 0x31, +0xE6, 0x99, 0xDE, 0x79, 0x8B, 0xCF, 0xBD, 0x74, +0xAC, 0xF1, 0x9C, 0xB0, 0xDE, 0x97, 0xCE, 0x14, +0xE6, 0xF7, 0xCE, 0x14, 0xB4, 0xF0, 0x7B, 0x6A, +0x94, 0x6F, 0x7B, 0xAC, 0x5A, 0xCA, 0x6B, 0x4C, +0x8C, 0x4F, 0x8C, 0x2F, 0x9C, 0xB0, 0xBD, 0xB4, +0xDE, 0xB7, 0xD6, 0x77, 0xB5, 0x94, 0xA5, 0x33, +0xA5, 0x12, 0xA5, 0x12, 0xAD, 0x32, 0xAD, 0x53, +0xCE, 0x36, 0xD6, 0x56, 0xCE, 0x36, 0xAD, 0x11, +0x94, 0x6F, 0x9C, 0xD0, 0xB5, 0x31, 0x83, 0x8B, +0x94, 0x4E, 0x9C, 0x90, 0x94, 0x4F, 0xA5, 0x12, +0xA5, 0x11, 0xA4, 0xD1, 0xAD, 0x53, 0xB5, 0x54, +0xC5, 0xF7, 0xAD, 0x55, 0xA5, 0x14, 0x9C, 0xB2, +0xAD, 0x33, 0xAD, 0x12, 0xB5, 0x73, 0xAD, 0x33, +0x94, 0x70, 0x9C, 0xB1, 0x94, 0x8F, 0x94, 0x90, +0xB5, 0x94, 0xBD, 0xB4, 0xAD, 0x33, 0x8C, 0x2F, +0x94, 0x70, 0x8C, 0x6F, 0xA5, 0x12, 0xA5, 0x12, +0xA4, 0xF2, 0xA5, 0x32, 0xA4, 0xF1, 0x9C, 0xB1, +0x84, 0x0E, 0x6B, 0x6C, 0x63, 0x4C, 0x6B, 0x8D, +0x6B, 0x6C, 0x84, 0x2F, 0xAD, 0x53, 0xBD, 0xB4, +0xAD, 0x52, 0xBD, 0xB4, 0xB5, 0x93, 0xAD, 0x53, +0xAD, 0x53, 0xA4, 0xD1, 0x94, 0x90, 0x83, 0xEE, +0x73, 0x6D, 0x7B, 0x8D, 0x7B, 0x8D, 0x7B, 0xCD, +0x8C, 0x2F, 0x94, 0x90, 0x8C, 0x2F, 0x83, 0xEE, +0x8C, 0x2F, 0x8C, 0x4F, 0x9C, 0xB1, 0x84, 0x0E, +0x94, 0x4F, 0x94, 0x4F, 0x84, 0x0E, 0x7B, 0x8D, +0x73, 0x8D, 0x73, 0x6C, 0x5A, 0xCA, 0x6B, 0x0B, +0x73, 0x6C, 0x73, 0x6C, 0x8C, 0x4F, 0xAD, 0x12, +0x9C, 0xB0, 0xA4, 0xF0, 0x9C, 0xB0, 0x9C, 0xD0, +0x94, 0x6E, 0x94, 0x4E, 0x8C, 0x2E, 0x84, 0x0E, +0x6B, 0x4B, 0x6B, 0x4B, 0x6B, 0x2B, 0x6B, 0x2B, +0x6B, 0x6B, 0x6B, 0x4B, 0x73, 0xAD, 0x8C, 0x2F, +0x94, 0x4F, 0x84, 0x0E, 0x94, 0x91, 0x84, 0x2F, +0x83, 0xCD, 0x6B, 0x0B, 0x73, 0x6D, 0xB5, 0x53, +0xD6, 0x77, 0xBD, 0xB4, 0xAD, 0x32, 0xB5, 0x53, +0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x94, 0xBD, 0x94, +0xBD, 0xB4, 0xBD, 0x94, 0xB5, 0x53, 0xA5, 0x12, +0xAD, 0x33, 0xAD, 0x12, 0xA4, 0xB0, 0xA4, 0xD0, +0xA4, 0xF1, 0x94, 0x4F, 0x8C, 0x0E, 0x94, 0x2E, +0x8C, 0x0E, 0x8C, 0x0E, 0x8C, 0x0E, 0xAD, 0x12, +0x9C, 0x90, 0x8C, 0x0E, 0x8C, 0x0D, 0x8C, 0x0E, +0xA4, 0xB0, 0x9C, 0x90, 0x9C, 0x8F, 0xA4, 0xB0, +0xA4, 0xD0, 0xA4, 0xD1, 0xAD, 0x31, 0xAD, 0x11, +0xAD, 0x12, 0xAD, 0x11, 0xAD, 0x11, 0xB5, 0x32, +0xB5, 0x53, 0xB5, 0x32, 0xAD, 0x11, 0xB5, 0x52, +0xB5, 0x32, 0xB5, 0x73, 0xB5, 0x52, 0xA4, 0xF1, +0x9C, 0x6F, 0x94, 0x4E, 0x83, 0xED, 0x7B, 0xAC, +0x7B, 0xAD, 0xA4, 0xD1, 0xAD, 0x11, 0xAD, 0x12, +0xB5, 0x53, 0xAD, 0x32, 0xAD, 0x12, 0xAD, 0x32, +0xAD, 0x12, 0x9C, 0xD1, 0x9C, 0xD1, 0xAD, 0x32, +0xAD, 0x52, 0xAD, 0x32, 0xA5, 0x12, 0xA5, 0x12, +0xA4, 0xF1, 0x9C, 0xB1, 0xA4, 0xF2, 0xA5, 0x12, +0x94, 0x6F, 0x94, 0x6F, 0x9C, 0xB0, 0x9C, 0xB0, +0x94, 0x6F, 0x94, 0x4F, 0x83, 0xAC, 0xC5, 0xB3, +0xE6, 0xB6, 0xDE, 0x95, 0xE6, 0xB6, 0xE6, 0xD6, +0xE6, 0xB6, 0xE6, 0xB6, 0xE6, 0xD7, 0xDE, 0x96, +0xA5, 0x35, 0xA5, 0x35, 0xA5, 0x34, 0x9C, 0xF4, +0x94, 0xB3, 0x5A, 0xCB, 0x5A, 0xA9, 0x73, 0x8B, +0x83, 0xCC, 0x83, 0xAC, 0x8C, 0x0D, 0x8C, 0x0D, +0x94, 0x4E, 0xA4, 0xF1, 0xA4, 0xD0, 0xAC, 0xF1, +0x9C, 0x6F, 0x94, 0x6F, 0x9C, 0x6F, 0xA4, 0xB0, +0xB5, 0x31, 0xAC, 0xF0, 0xAC, 0xD0, 0x7B, 0x4A, +0x52, 0x26, 0xA4, 0xAF, 0xAC, 0xF0, 0xAD, 0x11, +0xBD, 0xB3, 0xC5, 0xD4, 0x94, 0x6F, 0xA5, 0x11, +0xA4, 0xF1, 0xAD, 0x32, 0xAD, 0x31, 0xAD, 0x31, +0xB5, 0x72, 0xA4, 0xF0, 0xA4, 0xD0, 0xA4, 0xD0, +0xA5, 0x11, 0xAD, 0x11, 0x8C, 0x2E, 0x73, 0x6A, +0x7B, 0xAB, 0x73, 0x4A, 0x6B, 0x09, 0x9C, 0x6F, +0xA4, 0xB0, 0x7B, 0xAB, 0x94, 0x4E, 0x94, 0x2D, +0x83, 0xAC, 0x83, 0xCC, 0x8B, 0xED, 0x8B, 0xEC, +0x83, 0xCB, 0x83, 0xAC, 0x41, 0xE6, 0x52, 0x89, +0x42, 0x07, 0x39, 0xE7, 0x39, 0xE6, 0x29, 0x65, +0x31, 0xA6, 0x42, 0x08, 0x4A, 0x48, 0x63, 0x2C, +0x63, 0x2C, 0x73, 0xAE, 0x6B, 0x2C, 0x8C, 0x72, +0xBD, 0xB7, 0xB5, 0x96, 0xDE, 0xBA, 0xA4, 0xF3, +0x83, 0xAD, 0x8C, 0x0D, 0x8B, 0xCC, 0x8B, 0xCC, +0x8B, 0xCC, 0x93, 0xED, 0x8B, 0xEC, 0x8B, 0xEC, +0x7B, 0x8B, 0x73, 0x29, 0x7B, 0x4A, 0x4A, 0x07, +0x42, 0x07, 0x42, 0x28, 0x52, 0x69, 0x31, 0x65, +0x42, 0x08, 0x4A, 0x69, 0x4A, 0x69, 0x62, 0xEB, +0x94, 0x72, 0x41, 0xE8, 0x6B, 0x2D, 0xAD, 0x14, +0xB5, 0x34, 0xCE, 0x17, 0xC5, 0x75, 0x8B, 0xAE, +0xD6, 0x58, 0xA4, 0xD1, 0xA4, 0xB0, 0x9C, 0x8F, +0xBD, 0xB3, 0xAC, 0xF0, 0xAC, 0xAE, 0x73, 0x4A, +0x62, 0xEA, 0x63, 0x0A, 0x6B, 0x4B, 0x73, 0x6C, +0x83, 0xEE, 0x84, 0x0E, 0x9C, 0xB0, 0xBD, 0xD4, +0xDE, 0xD8, 0xD6, 0x97, 0xBD, 0xD4, 0xA5, 0x12, +0xBD, 0xD5, 0xAD, 0x53, 0xA5, 0x12, 0xAD, 0x53, +0xCE, 0x56, 0xCE, 0x15, 0xD6, 0x56, 0x9C, 0xB0, +0x94, 0x4F, 0x9C, 0x6E, 0xB5, 0x31, 0x7B, 0x8B, +0x9C, 0x90, 0xAD, 0x52, 0xBD, 0xB4, 0xC5, 0xF5, +0xBD, 0xD4, 0xBD, 0xB4, 0xB5, 0x93, 0xBD, 0xB5, +0xC6, 0x18, 0xAD, 0x35, 0x9C, 0xF4, 0xBD, 0xB5, +0xB5, 0x74, 0xB5, 0x73, 0xBD, 0x94, 0xC5, 0xD5, +0xA5, 0x12, 0xA4, 0xF2, 0xA5, 0x32, 0xAD, 0x33, +0xBD, 0xD5, 0xBD, 0xD5, 0xAD, 0x32, 0x8C, 0x2E, +0x8C, 0x4F, 0x8C, 0x6F, 0x9C, 0xD1, 0xA5, 0x12, +0xAD, 0x33, 0xA5, 0x32, 0x9C, 0xD1, 0x9C, 0xB0, +0x84, 0x2E, 0x7B, 0xEE, 0x7B, 0xCE, 0x7B, 0xEF, +0x84, 0x2F, 0xA5, 0x33, 0xBD, 0xD4, 0xBD, 0xD4, +0xAD, 0x53, 0xC5, 0xF5, 0xBD, 0xB4, 0xA5, 0x32, +0xAD, 0x32, 0x9C, 0xB1, 0x9C, 0x90, 0x7B, 0x8C, +0x6B, 0x4C, 0x6B, 0x6C, 0x7B, 0xAD, 0x7B, 0xCD, +0x8C, 0x4F, 0x9C, 0xD1, 0x9C, 0x90, 0x94, 0x90, +0x94, 0x90, 0x94, 0x90, 0x9C, 0xB1, 0x94, 0x70, +0x9C, 0xB1, 0x8C, 0x2F, 0x94, 0x70, 0x8C, 0x0F, +0x83, 0xEE, 0x7B, 0xAD, 0x62, 0xEA, 0x63, 0x2B, +0x73, 0x6C, 0x63, 0x0B, 0x94, 0x90, 0xAD, 0x32, +0xB5, 0x93, 0x9C, 0x8F, 0x9C, 0xB0, 0x94, 0x8F, +0x9C, 0xB0, 0xAD, 0x12, 0x9C, 0xB0, 0x8C, 0x6F, +0x73, 0xAD, 0x7B, 0xCD, 0x73, 0x8C, 0x6B, 0x4C, +0x6B, 0x4C, 0x7B, 0xEE, 0x94, 0xB1, 0xAD, 0x53, +0xA5, 0x12, 0xA5, 0x33, 0xAD, 0xB5, 0x94, 0xB2, +0x7B, 0xAE, 0x7B, 0xCE, 0x83, 0xEE, 0xB5, 0x73, +0xCE, 0x36, 0xB5, 0x94, 0xA4, 0xD1, 0x8C, 0x0E, +0x8C, 0x2E, 0x94, 0x6F, 0x94, 0x4F, 0x9C, 0xB1, +0xA5, 0x12, 0xA4, 0xD1, 0x9C, 0xB1, 0x94, 0x4F, +0x8C, 0x4F, 0x94, 0x4F, 0x94, 0x6F, 0x94, 0x6F, +0x9C, 0x90, 0x9C, 0x90, 0xA4, 0xD0, 0xA4, 0xF0, +0xA4, 0xF1, 0xA4, 0xF1, 0x94, 0x4F, 0xB5, 0x12, +0x7B, 0x8C, 0x73, 0x4B, 0x8C, 0x2E, 0x83, 0xCD, +0x94, 0x4E, 0x94, 0x6F, 0x8C, 0x2E, 0x94, 0x4E, +0x8C, 0x2E, 0x7B, 0xAC, 0x8C, 0x0D, 0x7B, 0xAC, +0x94, 0x6F, 0x94, 0x4E, 0x73, 0x6B, 0x73, 0x6B, +0x73, 0x4B, 0x73, 0x4B, 0x7B, 0x8C, 0x83, 0xED, +0x8B, 0xED, 0x8B, 0xED, 0x9C, 0x8F, 0xB5, 0x72, +0x8C, 0x0D, 0x9C, 0x6F, 0x94, 0x4F, 0x94, 0x90, +0x8C, 0x4F, 0x94, 0x4F, 0x9C, 0x90, 0xA4, 0xD1, +0xAD, 0x12, 0xAD, 0x33, 0xAD, 0x32, 0xB5, 0x32, +0xBD, 0x94, 0xAD, 0x32, 0xAD, 0x32, 0xAD, 0x32, +0xB5, 0x73, 0xB5, 0x53, 0xB5, 0x73, 0xC5, 0xB4, +0xC5, 0xB4, 0xC5, 0xD5, 0xC5, 0xB4, 0xBD, 0xB4, +0xBD, 0x74, 0xBD, 0x94, 0xBD, 0x73, 0xBD, 0x94, +0xC5, 0xD5, 0xCD, 0xF5, 0xA4, 0xD1, 0xAC, 0xF0, +0xB5, 0x31, 0xB5, 0x31, 0xAC, 0xF0, 0xA4, 0xAF, +0xA4, 0xB0, 0xAD, 0x11, 0xAD, 0x31, 0xC5, 0xB3, +0xA5, 0x55, 0xA5, 0x35, 0xA5, 0x34, 0x9C, 0xF4, +0x94, 0xB2, 0x6B, 0x4C, 0x6B, 0x4B, 0x7B, 0xAC, +0x8C, 0x0D, 0x8B, 0xED, 0x8C, 0x0D, 0x8C, 0x2D, +0x8C, 0x2E, 0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x31, +0xA4, 0xD0, 0xA4, 0xB0, 0xA4, 0xD0, 0xAC, 0xF1, +0xBD, 0x93, 0xAC, 0xF0, 0xA4, 0x6E, 0x73, 0x09, +0x73, 0x4A, 0x94, 0x0C, 0xB5, 0x31, 0xBD, 0x72, +0xBD, 0xD4, 0xCE, 0x36, 0xA5, 0x32, 0xAD, 0x53, +0xAD, 0x53, 0xB5, 0x94, 0xBD, 0xB4, 0xC5, 0xF5, +0xA5, 0x12, 0xB5, 0x73, 0xBD, 0xD4, 0xBD, 0xB4, +0xB5, 0x73, 0xB5, 0xB4, 0xAD, 0x52, 0x9C, 0xF1, +0xAD, 0x53, 0x94, 0x90, 0x73, 0x8C, 0x84, 0x0E, +0x83, 0xEE, 0x7B, 0xAC, 0x9C, 0x8E, 0xAD, 0x10, +0xCE, 0x14, 0xCE, 0x14, 0xDE, 0x96, 0xCE, 0x14, +0xC5, 0xD2, 0xCD, 0xF3, 0xB5, 0x51, 0x94, 0x4E, +0x39, 0xC5, 0x41, 0xE7, 0x42, 0x27, 0x29, 0x64, +0x29, 0x65, 0x42, 0x07, 0x4A, 0x69, 0x52, 0xAA, +0x5A, 0xCB, 0x5A, 0xEB, 0x62, 0xEB, 0xA4, 0xF4, +0xC5, 0xF8, 0x7B, 0xF0, 0xAD, 0x76, 0xDE, 0xBB, +0xA4, 0xF3, 0x94, 0x50, 0x83, 0xAC, 0x9C, 0x6E, +0x94, 0x2D, 0x94, 0x2E, 0x94, 0x0D, 0x7B, 0x6A, +0x83, 0xCC, 0x7B, 0x4A, 0x73, 0x2A, 0x29, 0x44, +0x52, 0xA9, 0x5A, 0xCA, 0x42, 0x07, 0x31, 0x65, +0x39, 0xC7, 0x4A, 0x49, 0x52, 0x6A, 0x62, 0xEC, +0x84, 0x10, 0x6B, 0x0D, 0x41, 0xC7, 0xAD, 0x34, +0xB5, 0x34, 0xC5, 0xB6, 0xE6, 0x99, 0xAC, 0xD2, +0x6B, 0x0B, 0xBD, 0xB6, 0x9C, 0x91, 0x7B, 0x8C, +0x8B, 0xEC, 0x9C, 0x4D, 0xA4, 0xAE, 0xAC, 0xAF, +0xA4, 0x8F, 0x94, 0x4E, 0x8B, 0xEC, 0x7B, 0xAC, +0x83, 0xCC, 0x8C, 0x0D, 0x8B, 0xEC, 0x8C, 0x2D, +0xA4, 0xD0, 0xAC, 0xF0, 0x9C, 0x8F, 0x83, 0xEC, +0x94, 0x6F, 0x8C, 0x2E, 0x83, 0xED, 0x8C, 0x4E, +0xB5, 0x52, 0xB5, 0x93, 0xB5, 0x93, 0x7B, 0xAC, +0x6B, 0x4B, 0x7B, 0xAB, 0xA4, 0xAF, 0x73, 0x2A, +0x9C, 0xB0, 0xBD, 0xD4, 0xC5, 0xF5, 0xC6, 0x15, +0xC6, 0x15, 0xC5, 0xF5, 0xAD, 0x73, 0xB5, 0x74, +0xC6, 0x38, 0xAD, 0x76, 0xA5, 0x34, 0xCE, 0x57, +0xC6, 0x16, 0xB5, 0x73, 0xBD, 0xF5, 0xCE, 0x56, +0xC5, 0xF5, 0xBD, 0xF5, 0xBD, 0xD5, 0xC5, 0xF6, +0xC6, 0x36, 0xBD, 0xD5, 0xA5, 0x12, 0x7B, 0xCD, +0x8C, 0x2E, 0x94, 0x90, 0xBD, 0xD5, 0xC5, 0xF6, +0xBD, 0xD5, 0xB5, 0x73, 0xAD, 0x53, 0x94, 0x90, +0x8C, 0x2E, 0x8C, 0x4F, 0x84, 0x4F, 0x8C, 0x90, +0x8C, 0x70, 0xA5, 0x12, 0xBD, 0xF5, 0xBD, 0xD5, +0xB5, 0x94, 0xC5, 0xF5, 0xBD, 0xD4, 0xB5, 0x73, +0xA4, 0xD1, 0xA4, 0xF2, 0x9C, 0xB0, 0x83, 0xEE, +0x73, 0x4C, 0x73, 0x6C, 0x7B, 0x8D, 0x7B, 0xAD, +0x7B, 0xAD, 0x83, 0xCD, 0x7B, 0xAD, 0x7B, 0xCD, +0x83, 0xEE, 0x8C, 0x0E, 0x83, 0xEE, 0x83, 0xCD, +0x7B, 0xAD, 0x7B, 0xCD, 0x7B, 0xAD, 0x7B, 0xAD, +0x73, 0x8D, 0x6B, 0x4C, 0x5A, 0xEA, 0x6B, 0x4C, +0x73, 0x8D, 0x6B, 0x6C, 0xA4, 0xF2, 0xB5, 0x73, +0xCE, 0x16, 0x8C, 0x0D, 0x94, 0x6F, 0x94, 0x8F, +0x9C, 0xD1, 0xA5, 0x32, 0x9C, 0xB0, 0xA4, 0xF1, +0x9C, 0xF2, 0x94, 0x90, 0x7C, 0x0E, 0x73, 0x8D, +0x84, 0x0F, 0x8C, 0x70, 0xA5, 0x33, 0xB5, 0x94, +0xBD, 0xF6, 0xB5, 0xD5, 0xBD, 0xF6, 0xA5, 0x54, +0x94, 0x91, 0xA5, 0x12, 0x8C, 0x4F, 0xB5, 0x94, +0xBD, 0x94, 0xBD, 0xB4, 0xA4, 0xD1, 0x94, 0x4F, +0x9C, 0x90, 0x9C, 0x90, 0x9C, 0xB1, 0x9C, 0xD1, +0x9C, 0xB1, 0x9C, 0x90, 0x9C, 0xD1, 0xA5, 0x12, +0x9C, 0xB1, 0x9C, 0xD1, 0xA4, 0xD1, 0x9C, 0xD1, +0xA4, 0xF1, 0xAD, 0x52, 0xC5, 0xD4, 0xB5, 0x52, +0xAD, 0x11, 0xBD, 0xB3, 0x9C, 0xB0, 0xAD, 0x32, +0x9C, 0xB0, 0x83, 0xEE, 0x8C, 0x2E, 0xA4, 0xD0, +0xAD, 0x11, 0x9C, 0xB0, 0xB5, 0x53, 0xB5, 0x93, +0xB5, 0x73, 0x9C, 0xD1, 0x94, 0x8F, 0x9C, 0x90, +0xA4, 0xD1, 0x9C, 0xD0, 0x9C, 0xB0, 0xA4, 0xF1, +0x9C, 0xD0, 0x9C, 0xD1, 0x9C, 0xB0, 0x94, 0x6E, +0x83, 0xED, 0x9C, 0x8F, 0x83, 0xCC, 0xB5, 0x73, +0x9C, 0xB0, 0xBD, 0x93, 0xAD, 0x52, 0xB5, 0x93, +0xAD, 0x32, 0xB5, 0x73, 0xBD, 0xB4, 0xB5, 0x93, +0xB5, 0x93, 0xB5, 0x73, 0xAD, 0x53, 0xA4, 0xF1, +0x9C, 0xD1, 0x9C, 0x90, 0x94, 0x6F, 0x94, 0x90, +0xAD, 0x12, 0xAD, 0x33, 0x9C, 0x90, 0xA4, 0xD1, +0xA4, 0xD1, 0x94, 0x2E, 0xA4, 0xD1, 0xBD, 0x94, +0x8C, 0x2E, 0x8C, 0x0E, 0x7B, 0x8C, 0x83, 0xED, +0x94, 0x2E, 0x9C, 0x6F, 0x8C, 0x0E, 0x94, 0x4E, +0xA4, 0xB0, 0xAD, 0x11, 0xB5, 0x52, 0xAC, 0xF1, +0xB5, 0x52, 0xAD, 0x11, 0xB5, 0x32, 0xAD, 0x11, +0xA5, 0x55, 0xA5, 0x55, 0xA5, 0x35, 0x9C, 0xF4, +0x8C, 0x92, 0x63, 0x0B, 0x6B, 0x4B, 0x7B, 0xAC, +0x8C, 0x0D, 0x8C, 0x2E, 0x8C, 0x2E, 0x94, 0x4E, +0x94, 0x4E, 0xAD, 0x11, 0xB5, 0x52, 0xB5, 0x72, +0xA4, 0xD0, 0xA4, 0xD0, 0xAD, 0x11, 0xB5, 0x31, +0xBD, 0x72, 0x94, 0x2D, 0x8B, 0xCC, 0x8B, 0xCC, +0x9C, 0x2E, 0x8B, 0xCC, 0xB5, 0x10, 0xBD, 0x73, +0xCE, 0x56, 0xC6, 0x15, 0xAD, 0x73, 0xB5, 0x73, +0xB5, 0x94, 0xBD, 0xB5, 0xBD, 0xF5, 0xBD, 0xF5, +0x84, 0x0E, 0xC6, 0x16, 0xCE, 0x36, 0xC6, 0x16, +0xC6, 0x16, 0xBD, 0xD5, 0xAD, 0x32, 0xAD, 0x53, +0xB5, 0xD5, 0xAD, 0x33, 0x94, 0x90, 0x94, 0x70, +0x8C, 0x0E, 0x94, 0x6E, 0xB5, 0x51, 0xCE, 0x13, +0xCE, 0x55, 0xCE, 0x34, 0xDE, 0xB6, 0xDE, 0x74, +0xD6, 0x12, 0xD6, 0x33, 0xC5, 0xB1, 0xD6, 0x54, +0xAD, 0x31, 0x52, 0x88, 0x42, 0x27, 0x39, 0xE7, +0x29, 0x65, 0x29, 0x65, 0x4A, 0x69, 0x4A, 0x48, +0x52, 0x8A, 0x62, 0xEC, 0x7B, 0xCF, 0xA5, 0x35, +0xA4, 0xF4, 0xAD, 0x55, 0xB5, 0xB7, 0xC6, 0x39, +0xDE, 0xDB, 0x9C, 0xD2, 0x94, 0x4F, 0xA4, 0xAF, +0x9C, 0x8F, 0xA4, 0xD0, 0xAC, 0xF0, 0xA4, 0x6F, +0x9C, 0x4E, 0xA4, 0xAF, 0x83, 0xAC, 0x31, 0x65, +0x52, 0xAA, 0x4A, 0x48, 0x39, 0xA6, 0x42, 0x07, +0x42, 0x28, 0x4A, 0x49, 0x52, 0x6A, 0xA5, 0x34, +0xA5, 0x14, 0x94, 0x31, 0x5A, 0x6A, 0x62, 0xAA, +0xB5, 0x54, 0xBD, 0x95, 0xC5, 0x95, 0xDE, 0x78, +0xA4, 0xB2, 0x73, 0x4C, 0xB5, 0x33, 0xAC, 0xF1, +0xAC, 0xF1, 0x8C, 0x0C, 0x94, 0x0C, 0x8B, 0xEC, +0x9C, 0x4E, 0xA4, 0x8E, 0xAC, 0xCF, 0xB4, 0xF0, +0xAC, 0xD0, 0xAC, 0xCF, 0xAC, 0xCF, 0xB5, 0x10, +0xB5, 0x30, 0xB5, 0x10, 0xB5, 0x10, 0xB5, 0x30, +0xAC, 0xF0, 0xAC, 0xEF, 0xAC, 0xCF, 0xAC, 0xD0, +0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0xAE, 0x94, 0x2D, +0x94, 0x2D, 0x9C, 0x6E, 0xB5, 0x10, 0xAC, 0xCF, +0x9C, 0x8E, 0x94, 0x4E, 0x94, 0x0D, 0x8C, 0x0D, +0x94, 0x4E, 0x94, 0x2D, 0x8C, 0x0D, 0x94, 0x6F, +0xCE, 0x59, 0xAD, 0x96, 0x9C, 0xD3, 0x83, 0xCD, +0x9C, 0x8F, 0x8C, 0x2E, 0x84, 0x0D, 0xAD, 0x11, +0xAD, 0x11, 0xB5, 0x72, 0xBD, 0xB4, 0xBD, 0xD5, +0xA5, 0x11, 0x7B, 0xAC, 0x9C, 0xF1, 0x7B, 0xCD, +0x83, 0xED, 0x8C, 0x2F, 0xA5, 0x12, 0xAD, 0x53, +0xAD, 0x32, 0x94, 0x6F, 0x7B, 0xCD, 0x94, 0x6F, +0x9C, 0xB0, 0x94, 0x70, 0x94, 0x90, 0x94, 0x90, +0x94, 0x90, 0x7B, 0xAD, 0xA5, 0x12, 0xBD, 0xD5, +0xAD, 0x52, 0xC5, 0xF5, 0xB5, 0x93, 0xBD, 0xD5, +0xAD, 0x53, 0xAD, 0x53, 0x9C, 0xD1, 0x7B, 0xAD, +0x6B, 0x0B, 0x63, 0x0B, 0x6B, 0x4C, 0x73, 0x6C, +0x73, 0x8C, 0x7B, 0xAC, 0x83, 0xCD, 0x6B, 0x2B, +0x84, 0x0E, 0x83, 0xEE, 0x84, 0x0E, 0x73, 0x8C, +0x7B, 0x8C, 0x7B, 0xAC, 0x7B, 0x8C, 0x73, 0x6C, +0x63, 0x2B, 0x5A, 0xCA, 0x52, 0xAA, 0x63, 0x2B, +0x6B, 0x4C, 0x6B, 0x4C, 0xAD, 0x33, 0xAD, 0x53, +0xCE, 0x56, 0x8C, 0x2E, 0x94, 0x6F, 0x9C, 0xB0, +0xA4, 0xF1, 0xA5, 0x11, 0xA4, 0xF1, 0xA4, 0xF1, +0x94, 0x90, 0x9C, 0xD1, 0x94, 0xB0, 0x7B, 0xEE, +0x8C, 0x70, 0x9C, 0xD1, 0xA5, 0x53, 0xB5, 0x94, +0xBE, 0x16, 0xB5, 0xB5, 0xBD, 0xD5, 0x9D, 0x13, +0x9C, 0xD2, 0xAD, 0x74, 0x94, 0x70, 0xBD, 0x94, +0xBD, 0xB4, 0xB5, 0x53, 0x9C, 0x90, 0x9C, 0x90, +0xA4, 0xD1, 0x9C, 0xB0, 0xA4, 0xF1, 0xAD, 0x53, +0xAD, 0x12, 0xAD, 0x12, 0xAD, 0x73, 0xBD, 0xB5, +0xAD, 0x53, 0x9C, 0xB0, 0xA4, 0xD1, 0xAD, 0x53, +0xB5, 0x74, 0xBD, 0x94, 0xBD, 0x73, 0xAD, 0x11, +0xB5, 0x72, 0xCE, 0x15, 0x9C, 0xB0, 0xAD, 0x32, +0xB5, 0x72, 0x8C, 0x2E, 0x8C, 0x0D, 0xA4, 0xB0, +0x8C, 0x2E, 0x84, 0x0D, 0x9C, 0x90, 0xBD, 0xD4, +0xBD, 0xD4, 0xAD, 0x53, 0xA5, 0x11, 0xAD, 0x32, +0xAD, 0x52, 0xAD, 0x32, 0xAD, 0x32, 0xBD, 0xD4, +0xB5, 0x94, 0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x73, +0xAD, 0x11, 0xAD, 0x31, 0x94, 0x6F, 0xBD, 0x93, +0xAD, 0x32, 0xB5, 0x73, 0xB5, 0x93, 0xB5, 0x93, +0xBD, 0x94, 0xCE, 0x36, 0xC6, 0x15, 0xC6, 0x36, +0xC6, 0x36, 0xC6, 0x36, 0xCE, 0x36, 0xC6, 0x36, +0xBD, 0xD5, 0xB5, 0xB4, 0xBD, 0xD5, 0xBD, 0xD5, +0xD6, 0x98, 0xD6, 0x77, 0xC6, 0x16, 0xCE, 0x57, +0xD6, 0x77, 0xAD, 0x52, 0x83, 0xED, 0xB5, 0x53, +0x83, 0xCD, 0x8C, 0x4E, 0x8C, 0x0E, 0x94, 0x70, +0xA4, 0xD0, 0xAD, 0x11, 0xC5, 0xB3, 0xCD, 0xF4, +0xCD, 0xF4, 0xD6, 0x35, 0xC5, 0xD4, 0x9C, 0x8F, +0xBD, 0x72, 0xD6, 0x54, 0xDE, 0x55, 0xDE, 0x75, +0xA5, 0x55, 0xA5, 0x35, 0xA5, 0x35, 0x9C, 0xF4, +0x8C, 0x92, 0x62, 0xEB, 0x5A, 0xA9, 0x7B, 0xAC, +0x83, 0xEC, 0x94, 0x4E, 0x8C, 0x2D, 0x94, 0x4E, +0x94, 0x6F, 0xAD, 0x32, 0xAC, 0xF1, 0xAD, 0x11, +0xAC, 0xF1, 0xA4, 0xD0, 0xB5, 0x32, 0xB5, 0x52, +0xC5, 0xB3, 0x94, 0x2E, 0x8B, 0xCC, 0x9C, 0x4E, +0x9C, 0x2E, 0x83, 0x8B, 0xB5, 0x11, 0xB5, 0x52, +0xC5, 0xF5, 0xBD, 0xB5, 0xAD, 0x74, 0xAD, 0x73, +0xAD, 0x53, 0xB5, 0xB4, 0xC5, 0xF5, 0xC6, 0x36, +0xBD, 0xD5, 0xCE, 0x77, 0xC6, 0x16, 0xC6, 0x16, +0xB5, 0x94, 0xB5, 0x94, 0xAD, 0x53, 0xAD, 0x53, +0xAD, 0x73, 0xA4, 0xF1, 0x9C, 0xB1, 0x9C, 0xB1, +0x94, 0x6F, 0xA4, 0xAF, 0xBD, 0x71, 0xC5, 0xD2, +0xBD, 0xB2, 0xC5, 0xF3, 0xCE, 0x34, 0xCD, 0xF2, +0xD6, 0x33, 0xCE, 0x13, 0xCD, 0xF2, 0xCD, 0xF3, +0xDE, 0x96, 0xB5, 0x72, 0x4A, 0x07, 0x4A, 0x48, +0x31, 0xA6, 0x31, 0xC6, 0x4A, 0x69, 0x4A, 0x69, +0x4A, 0x49, 0x63, 0x2C, 0x7B, 0xAE, 0x94, 0x92, +0x8C, 0x51, 0xBD, 0xD7, 0x9C, 0xB3, 0xA5, 0x35, +0xD6, 0xBB, 0xB5, 0x75, 0x83, 0xEE, 0x5A, 0xA9, +0x83, 0xCE, 0xAD, 0x32, 0xAC, 0xF1, 0x8B, 0xED, +0x9C, 0x6E, 0xCD, 0xD4, 0xBD, 0x73, 0x83, 0xEE, +0x31, 0x86, 0x29, 0x44, 0x52, 0xA9, 0x6B, 0x2C, +0x42, 0x08, 0x8C, 0x71, 0x7B, 0xCF, 0x9C, 0xD3, +0xB5, 0x96, 0xAD, 0x14, 0x7B, 0x8E, 0x4A, 0x08, +0x7B, 0x8D, 0xBD, 0x75, 0xB5, 0x13, 0xC5, 0x95, +0xCD, 0xF7, 0x94, 0x50, 0x6B, 0x0B, 0x7B, 0x6D, +0x8B, 0xEE, 0x83, 0xCD, 0x7B, 0xAD, 0x7B, 0x8C, +0x6B, 0x2A, 0x83, 0xAB, 0xAC, 0xF0, 0x7B, 0x6B, +0x73, 0x2A, 0x7B, 0x8B, 0x7B, 0x6B, 0x7B, 0x6B, +0x6A, 0xE9, 0x6B, 0x09, 0x7B, 0x8B, 0x83, 0xAB, +0x83, 0xAC, 0x83, 0xAB, 0x94, 0x0D, 0x94, 0x0D, +0x93, 0xEC, 0x9C, 0x2D, 0xAC, 0xEF, 0xA4, 0xAF, +0xA4, 0x8E, 0xA4, 0x8E, 0xB4, 0xEF, 0xAC, 0xCF, +0xB5, 0x30, 0xB5, 0x30, 0xBD, 0x71, 0xAC, 0xCF, +0xA4, 0x6E, 0xA4, 0x6E, 0xA4, 0x8E, 0xAC, 0xF2, +0xCE, 0x59, 0xB5, 0xB7, 0xAD, 0x75, 0xA4, 0xD1, +0xAC, 0xCF, 0xAC, 0xCF, 0xAC, 0xCF, 0xA4, 0xAE, +0x9C, 0x8E, 0x9C, 0x6E, 0x9C, 0x6E, 0x9C, 0x6F, +0x9C, 0x6E, 0x9C, 0x4E, 0xAD, 0x32, 0xB5, 0x32, +0xAD, 0x32, 0xA4, 0xF2, 0xA4, 0xF1, 0xA4, 0xD1, +0xA4, 0xF1, 0x9C, 0xD1, 0x9C, 0xB1, 0x9C, 0xD1, +0x9C, 0xB1, 0x94, 0x70, 0x94, 0x6F, 0x8C, 0x0E, +0x8C, 0x2E, 0x84, 0x0E, 0x8C, 0x2E, 0x8C, 0x2F, +0x83, 0xEE, 0x94, 0x6F, 0x9C, 0xB0, 0x94, 0x90, +0x83, 0xED, 0x73, 0x6C, 0x9C, 0xD1, 0x7B, 0xCD, +0x7B, 0x8D, 0x5A, 0xCA, 0x5A, 0xAA, 0x83, 0xEE, +0x94, 0x70, 0x8C, 0x2F, 0x83, 0xEE, 0x84, 0x0E, +0x8C, 0x4F, 0x94, 0xB0, 0x94, 0x90, 0x8C, 0x2F, +0x7B, 0xCD, 0x7B, 0xAD, 0x73, 0x6C, 0x6B, 0x4C, +0x6B, 0x4C, 0x6B, 0x4C, 0x63, 0x2C, 0x63, 0x2C, +0x63, 0x0B, 0x73, 0x6C, 0xAD, 0x53, 0xB5, 0x73, +0xD6, 0x77, 0x94, 0x8F, 0x94, 0x6F, 0x9C, 0x90, +0x9C, 0xD0, 0xA5, 0x11, 0xB5, 0x73, 0xAD, 0x52, +0x9C, 0xD1, 0xA5, 0x32, 0xAD, 0x53, 0x94, 0xB0, +0x9C, 0xF1, 0xA5, 0x32, 0xAD, 0x53, 0xC6, 0x36, +0xC6, 0x16, 0xBD, 0xD5, 0xC6, 0x16, 0xA5, 0x33, +0x9D, 0x13, 0xAD, 0x53, 0xA4, 0xD1, 0xB5, 0x94, +0xB5, 0x53, 0xA4, 0xD1, 0x9C, 0x90, 0xAD, 0x32, +0xBD, 0x93, 0xAD, 0x12, 0xB5, 0x53, 0xC5, 0xD5, +0xB5, 0x53, 0xA5, 0x12, 0xB5, 0x94, 0xC5, 0xD5, +0xA4, 0xF1, 0xA4, 0xF1, 0xA4, 0xD1, 0xAD, 0x32, +0xB5, 0x94, 0xC5, 0xF5, 0xBD, 0xB4, 0xB5, 0x72, +0xAD, 0x11, 0xD6, 0x36, 0xA4, 0xB0, 0xAD, 0x11, +0xAD, 0x32, 0x83, 0xED, 0x83, 0xCC, 0xA4, 0xB0, +0x9C, 0x8F, 0x8C, 0x0D, 0x84, 0x0D, 0xAD, 0x11, +0xC5, 0xF5, 0x94, 0x8F, 0xAD, 0x32, 0xA5, 0x11, +0xB5, 0x73, 0xB5, 0x94, 0xBD, 0xB4, 0xC5, 0xD5, +0xB5, 0x73, 0xB5, 0x94, 0xBD, 0xB4, 0xB5, 0x93, +0x9C, 0xB0, 0xA4, 0xF0, 0x94, 0x4E, 0xBD, 0x93, +0xB5, 0x73, 0xB5, 0x93, 0xBD, 0xB4, 0xBD, 0xB4, +0xBD, 0xB4, 0xD6, 0x77, 0xCE, 0x56, 0xCE, 0x56, +0xD6, 0x76, 0xC6, 0x15, 0xBD, 0xD5, 0xBD, 0xD5, +0xBD, 0xF5, 0xBD, 0xD5, 0xBD, 0xF5, 0xCE, 0x56, +0xCE, 0x36, 0xBD, 0xB4, 0xAD, 0x52, 0xAD, 0x32, +0xAD, 0x73, 0xAD, 0x32, 0x94, 0x6F, 0xB5, 0x53, +0xA4, 0xB1, 0xB5, 0x53, 0xAD, 0x53, 0xAD, 0x32, +0xAD, 0x32, 0xC5, 0xB4, 0xB5, 0x72, 0xC5, 0xD3, +0xC5, 0xD3, 0xC5, 0xD3, 0xC5, 0x93, 0xA4, 0xB0, +0xD6, 0x14, 0xE6, 0x95, 0xDE, 0x53, 0xDE, 0x53, +0xA5, 0x55, 0xA5, 0x35, 0xA5, 0x35, 0x9C, 0xF4, +0x8C, 0x92, 0x52, 0x89, 0x4A, 0x27, 0x7B, 0x8C, +0x8C, 0x0D, 0x8C, 0x0D, 0x8C, 0x0D, 0x94, 0x4E, +0x9C, 0x6F, 0xA4, 0xB0, 0x94, 0x2E, 0x83, 0xEC, +0xAD, 0x11, 0xAD, 0x31, 0xB5, 0x52, 0xBD, 0x73, +0xCD, 0xD4, 0x9C, 0x6E, 0x83, 0xAC, 0x73, 0x2A, +0x52, 0x27, 0x52, 0x47, 0xAC, 0xF0, 0xA4, 0xD0, +0xB5, 0x94, 0xBD, 0xD5, 0xB5, 0x94, 0xAD, 0x73, +0xAD, 0x53, 0xBD, 0xD5, 0xBD, 0xF5, 0xBD, 0xF5, +0xB5, 0x73, 0xC6, 0x36, 0xB5, 0xB4, 0xBD, 0xF5, +0xB5, 0x94, 0xBD, 0xD5, 0xAD, 0x53, 0xAD, 0x53, +0xAD, 0x53, 0xA5, 0x12, 0x94, 0xB1, 0x9C, 0xF2, +0x94, 0x90, 0xA4, 0xF0, 0xBD, 0x71, 0xB5, 0x71, +0x8C, 0x0C, 0x94, 0x6E, 0x8C, 0x2D, 0xBD, 0x91, +0xCE, 0x13, 0xCE, 0x13, 0xD6, 0x33, 0xCD, 0xD2, +0xCE, 0x13, 0xDE, 0x76, 0x94, 0x4E, 0x41, 0xE6, +0x39, 0xC6, 0x3A, 0x07, 0x42, 0x28, 0x4A, 0x48, +0x4A, 0x69, 0x52, 0x8A, 0x63, 0x0C, 0x63, 0x0C, +0x9C, 0xB3, 0xBD, 0xD7, 0xAD, 0x56, 0xA5, 0x15, +0xBD, 0xD7, 0xBD, 0xB6, 0x94, 0x92, 0x4A, 0x69, +0x6B, 0x2C, 0xCE, 0x16, 0xA4, 0xB0, 0x8B, 0xED, +0x9C, 0x6E, 0xB5, 0x32, 0xAC, 0xF0, 0xAD, 0x12, +0xA4, 0xF2, 0xA5, 0x12, 0xB5, 0x74, 0x6B, 0x4C, +0x42, 0x07, 0x94, 0xB2, 0x94, 0xB2, 0xA4, 0xF4, +0xB5, 0x96, 0xBD, 0xD7, 0xA4, 0xF3, 0x9C, 0x92, +0x41, 0xE8, 0x83, 0xCE, 0xB5, 0x33, 0xB5, 0x13, +0xA4, 0xB1, 0xC5, 0xB6, 0x8B, 0xCF, 0x7B, 0x4C, +0x94, 0x4F, 0x94, 0x70, 0x94, 0xB1, 0x9C, 0xB1, +0x84, 0x0E, 0x9C, 0x6F, 0xB5, 0x31, 0x83, 0xAC, +0x62, 0xE9, 0x84, 0x0E, 0x7B, 0xED, 0x7B, 0xCD, +0x63, 0x2B, 0x6B, 0x4B, 0x84, 0x4F, 0x9C, 0xD1, +0x94, 0xB1, 0x94, 0x90, 0x84, 0x2E, 0x6B, 0x2B, +0x5A, 0x89, 0x52, 0x68, 0x62, 0xEA, 0x5A, 0xA9, +0x63, 0x2A, 0x7B, 0xCC, 0x8C, 0x0E, 0x8C, 0x0D, +0x94, 0x4D, 0x9C, 0x6D, 0xBD, 0x51, 0x9C, 0x2D, +0x62, 0xA8, 0x62, 0xE9, 0x6B, 0x0A, 0x94, 0x91, +0xC6, 0x38, 0xBD, 0xF8, 0xCE, 0x59, 0x8B, 0xEE, +0x73, 0x4A, 0x83, 0x8C, 0x8B, 0xEC, 0x94, 0x0D, +0x94, 0x0D, 0x7B, 0x6B, 0x8B, 0xCC, 0x83, 0x8B, +0x7B, 0x6A, 0x83, 0xAC, 0x93, 0xED, 0x94, 0x0D, +0x8B, 0xEE, 0x94, 0x0E, 0xB5, 0x53, 0xAD, 0x12, +0xA4, 0xD1, 0x94, 0x70, 0xA4, 0xD1, 0x9C, 0xB1, +0x94, 0x4F, 0xA4, 0xF2, 0xAD, 0x12, 0x9C, 0xB1, +0xA5, 0x12, 0xAD, 0x32, 0xAD, 0x33, 0xB5, 0x53, +0xB5, 0x74, 0xAD, 0x33, 0xAD, 0x53, 0xB5, 0x53, +0xAD, 0x33, 0xAD, 0x33, 0xB5, 0x94, 0xAD, 0x12, +0x9C, 0xD1, 0x9C, 0xB1, 0xA4, 0xD2, 0x94, 0x90, +0x94, 0x6F, 0x94, 0x4F, 0x94, 0x90, 0x9C, 0x90, +0x84, 0x0E, 0x94, 0x6F, 0x94, 0x6F, 0x9C, 0x90, +0x94, 0x90, 0x94, 0x70, 0x7B, 0xCE, 0x7B, 0xAD, +0x73, 0x8C, 0x73, 0x6C, 0x6B, 0x4C, 0x6B, 0x2C, +0x63, 0x0B, 0x73, 0x6C, 0xAD, 0x53, 0x9C, 0xD1, +0xAD, 0x12, 0x8C, 0x4E, 0x83, 0xCD, 0x7B, 0xAC, +0x83, 0xED, 0x84, 0x0D, 0x84, 0x0E, 0xAD, 0x53, +0xBD, 0xD4, 0xB5, 0xB4, 0xB5, 0x94, 0xAD, 0x73, +0x94, 0x90, 0xA5, 0x12, 0xA5, 0x32, 0xBD, 0xD5, +0xA5, 0x33, 0x8C, 0x4F, 0xB5, 0x94, 0xAD, 0x53, +0xAD, 0x74, 0xA5, 0x33, 0xAD, 0x12, 0xB5, 0x73, +0xD6, 0x57, 0xAD, 0x53, 0xA4, 0xF1, 0xC5, 0xD4, +0xC5, 0xD4, 0xC5, 0xF5, 0xC6, 0x15, 0xB5, 0x52, +0x9C, 0xB0, 0xA4, 0xF1, 0xBD, 0xB5, 0xBD, 0xD5, +0xB5, 0x94, 0xBD, 0xB5, 0xBD, 0xB5, 0xB5, 0x94, +0xB5, 0x73, 0xC5, 0xF4, 0xCE, 0x35, 0xD6, 0x35, +0xBD, 0x72, 0xC5, 0xB4, 0xA4, 0xD0, 0x94, 0x6F, +0xB5, 0x52, 0x94, 0x6F, 0x8C, 0x2E, 0xA4, 0xF1, +0x9C, 0xAF, 0x9C, 0xAF, 0x83, 0xCD, 0x9C, 0xD0, +0xC5, 0xF5, 0x9C, 0xD0, 0xAD, 0x52, 0xA4, 0xF1, +0xBD, 0xB4, 0xB5, 0xB4, 0xB5, 0x93, 0xC5, 0xD5, +0xBD, 0x94, 0xB5, 0x73, 0xAD, 0x52, 0xAD, 0x53, +0x94, 0x4E, 0x9C, 0xB0, 0x8C, 0x2D, 0xAD, 0x32, +0xBD, 0xB4, 0xB5, 0x73, 0xB5, 0x73, 0xBD, 0xD4, +0xBD, 0xB4, 0xD6, 0x97, 0xD6, 0x76, 0xCE, 0x56, +0xCE, 0x56, 0xC6, 0x15, 0xC6, 0x15, 0xC6, 0x15, +0xAD, 0x53, 0x8C, 0x4F, 0xB5, 0x73, 0xD6, 0x77, +0xC5, 0xF5, 0xBD, 0xB4, 0xAD, 0x53, 0xA5, 0x12, +0x9C, 0xF1, 0x9C, 0xB0, 0x8C, 0x0D, 0xB5, 0x53, +0xA4, 0xF1, 0xBD, 0xB4, 0xC5, 0xD5, 0xB5, 0x94, +0xB5, 0x73, 0xC5, 0xD4, 0xAD, 0x10, 0xCD, 0xF4, +0xCE, 0x14, 0xC5, 0xD4, 0xBD, 0x72, 0xA4, 0x8F, +0xDE, 0x55, 0xDE, 0x33, 0xD5, 0xF2, 0xCD, 0x91, +0xA5, 0x35, 0xB5, 0xB7, 0xA5, 0x34, 0x9C, 0xF4, +0x8C, 0x92, 0x63, 0x0B, 0x62, 0xC9, 0x62, 0xC9, +0x6B, 0x09, 0x6B, 0x09, 0x73, 0x4A, 0x73, 0x4A, +0x73, 0x4A, 0x6B, 0x2A, 0x7B, 0x8B, 0x73, 0x29, +0x8C, 0x0D, 0x9C, 0x6F, 0x9C, 0x6E, 0xAD, 0x11, +0xBD, 0x73, 0x8B, 0xCC, 0xB4, 0xF1, 0x93, 0xED, +0x5A, 0x68, 0x62, 0x88, 0xAC, 0xF1, 0xB5, 0x52, +0xB5, 0x73, 0xB5, 0x93, 0xB5, 0xB4, 0xBD, 0xF5, +0xB5, 0xD5, 0xBD, 0xF5, 0xC6, 0x16, 0xBD, 0xF5, +0xBD, 0xD5, 0xC6, 0x57, 0xC6, 0x36, 0xBD, 0xF5, +0xB5, 0x94, 0xB5, 0xB5, 0xB5, 0xB4, 0xAD, 0x74, +0xB5, 0x94, 0xAD, 0x94, 0xA5, 0x13, 0xA5, 0x12, +0x9C, 0xD1, 0xAD, 0x10, 0xB5, 0x30, 0xCE, 0x14, +0xC5, 0xD4, 0x73, 0x8B, 0x7B, 0x8B, 0x84, 0x0C, +0xCE, 0x34, 0xCD, 0xF2, 0xCD, 0xF2, 0xBD, 0x91, +0xC5, 0xB2, 0xD6, 0x54, 0xD6, 0x35, 0x73, 0x4B, +0x39, 0xC6, 0x42, 0x07, 0x42, 0x07, 0x42, 0x28, +0x4A, 0x69, 0x52, 0xAA, 0x5A, 0xEB, 0x6B, 0x6D, +0x9C, 0xD3, 0xAD, 0x55, 0xB5, 0x96, 0x94, 0xB3, +0xBD, 0xD7, 0xA5, 0x14, 0xAD, 0x35, 0x73, 0x8E, +0x73, 0x8E, 0xC5, 0xF6, 0xBD, 0x74, 0xAC, 0xD0, +0xA4, 0xB0, 0xAC, 0xD0, 0xAC, 0xF1, 0xB5, 0x53, +0xCE, 0x15, 0xD6, 0x56, 0x94, 0x70, 0x31, 0x45, +0x29, 0x65, 0x42, 0x08, 0x4A, 0x49, 0x7B, 0xAF, +0x84, 0x10, 0xA4, 0xF3, 0x94, 0x92, 0xAD, 0x34, +0x94, 0x51, 0x4A, 0x28, 0x8B, 0xEE, 0xAC, 0xF2, +0xB5, 0x12, 0xBD, 0x54, 0xB5, 0x33, 0x94, 0x0F, +0x7B, 0x4C, 0x8C, 0x2F, 0xAD, 0x33, 0x94, 0x91, +0x94, 0x70, 0xA4, 0xD1, 0xB5, 0x31, 0x83, 0xAB, +0x62, 0xEA, 0x73, 0xAD, 0x73, 0xAD, 0x73, 0xAD, +0x6B, 0x6D, 0x73, 0x8D, 0x8C, 0x4F, 0xA5, 0x33, +0xB5, 0x95, 0xBD, 0xF6, 0xA5, 0x53, 0x7B, 0xCE, +0x6B, 0x6C, 0x52, 0xAA, 0x5A, 0xCA, 0x6B, 0x4C, +0x8C, 0x70, 0xB5, 0xB4, 0xB5, 0x74, 0xAD, 0x53, +0x94, 0x8F, 0x9C, 0x6D, 0xBD, 0x51, 0xAC, 0xCF, +0x83, 0xAC, 0x83, 0xCD, 0x83, 0xCD, 0xA5, 0x34, +0xBD, 0xF7, 0xB5, 0xB7, 0x84, 0x10, 0x83, 0xEF, +0x73, 0x4B, 0x8C, 0x0E, 0x8C, 0x0E, 0x8C, 0x0D, +0xA4, 0xD0, 0x94, 0x4E, 0x8B, 0xCC, 0x7B, 0x4B, +0x6B, 0x0A, 0x6A, 0xCA, 0x73, 0x0A, 0x7B, 0x0A, +0x73, 0x0A, 0x7B, 0x4B, 0xB5, 0x53, 0x8C, 0x2E, +0xA5, 0x12, 0xA4, 0xD1, 0x94, 0x70, 0x9C, 0xB1, +0xA5, 0x12, 0xAD, 0x53, 0xA5, 0x12, 0x7B, 0xCD, +0x83, 0xEE, 0xA5, 0x12, 0xA4, 0xF1, 0xA4, 0xD1, +0x94, 0x70, 0x73, 0x6C, 0x7B, 0xAD, 0xA4, 0xD1, +0xB5, 0x74, 0xAD, 0x13, 0xAD, 0x12, 0xAD, 0x33, +0xAD, 0x12, 0x8C, 0x4F, 0x9C, 0xD1, 0xAD, 0x33, +0xA4, 0xF2, 0xA4, 0xD1, 0xA4, 0xF1, 0x9C, 0xB1, +0x9C, 0xB1, 0xA4, 0xF1, 0x9C, 0xD1, 0x94, 0x90, +0xAD, 0x13, 0x9C, 0xB1, 0x9C, 0xD1, 0xA5, 0x12, +0xAD, 0x33, 0xAD, 0x33, 0xAD, 0x12, 0xAD, 0x33, +0xAD, 0x33, 0xAD, 0x12, 0xB5, 0x73, 0xB5, 0x73, +0xB5, 0x53, 0xA4, 0xF1, 0xAD, 0x32, 0xAD, 0x12, +0xAD, 0x12, 0xAD, 0x12, 0xA4, 0xD1, 0x9C, 0xD1, +0x94, 0x90, 0x94, 0x90, 0x8C, 0x4F, 0x8C, 0x4F, +0x83, 0xEE, 0x94, 0x4F, 0x83, 0xEE, 0x8C, 0x4F, +0x8C, 0x6F, 0x8C, 0x2E, 0x9C, 0xB0, 0x84, 0x0E, +0xA4, 0xF2, 0x8C, 0x2F, 0xA5, 0x12, 0xA4, 0xF1, +0xB5, 0x94, 0xB5, 0x73, 0xAD, 0x32, 0xB5, 0x32, +0xB5, 0x32, 0xB5, 0x52, 0xB5, 0x52, 0x8C, 0x2E, +0x94, 0x4F, 0x9C, 0xB0, 0x94, 0x6F, 0x9C, 0xD0, +0xB5, 0x73, 0xA5, 0x12, 0xB5, 0x53, 0xBD, 0xD5, +0xBD, 0xB4, 0xA4, 0xF1, 0xBD, 0x73, 0xCE, 0x15, +0xD6, 0x35, 0xC5, 0xD4, 0x94, 0x4E, 0xA4, 0xD0, +0xAD, 0x52, 0x7B, 0x8C, 0xB5, 0x52, 0x6B, 0x4B, +0x73, 0x6B, 0xA4, 0xF1, 0xA5, 0x11, 0xA5, 0x11, +0x9C, 0xB0, 0xAD, 0x52, 0xBD, 0xB4, 0xBD, 0xB4, +0xBD, 0xF5, 0x8C, 0x4F, 0xAD, 0x32, 0xC5, 0xF5, +0xC5, 0xF5, 0x94, 0x70, 0x6B, 0x4B, 0xBD, 0xD5, +0xBD, 0xB4, 0xAD, 0x32, 0x94, 0x6F, 0xAD, 0x11, +0xC5, 0xD5, 0xBD, 0xD4, 0xB5, 0x93, 0xBD, 0xD4, +0xC5, 0xF5, 0xCE, 0x15, 0xCE, 0x15, 0xBD, 0xD4, +0xC6, 0x15, 0xC6, 0x15, 0xD6, 0x56, 0xC6, 0x15, +0xB5, 0x94, 0x9C, 0xB1, 0x94, 0x70, 0xCE, 0x36, +0xCE, 0x57, 0xC6, 0x15, 0xBD, 0xD5, 0xBD, 0xF5, +0xB5, 0x94, 0xB5, 0x94, 0x94, 0x6F, 0xB5, 0x73, +0xAD, 0x12, 0xB5, 0x94, 0xB5, 0x94, 0xBD, 0x94, +0xBD, 0x93, 0xC5, 0xB3, 0xB5, 0x72, 0xC5, 0xD3, +0xCE, 0x14, 0xCE, 0x14, 0xC5, 0xB3, 0x9C, 0x8F, +0xDE, 0x55, 0xD6, 0x12, 0xBD, 0x50, 0xBD, 0x50, +0xA5, 0x35, 0xBD, 0xF8, 0xA5, 0x35, 0x9C, 0xF4, +0x8C, 0x72, 0x73, 0x6C, 0x7B, 0x8B, 0x83, 0xAC, +0x83, 0xCC, 0x8B, 0xCC, 0x8B, 0xEC, 0x94, 0x0C, +0x94, 0x4D, 0x94, 0x4D, 0x94, 0x2D, 0x94, 0x2D, +0xA4, 0x8E, 0xA4, 0x8F, 0xA4, 0x6E, 0x9C, 0x4D, +0x94, 0x2D, 0x8B, 0xEC, 0x94, 0x0C, 0x94, 0x0C, +0x94, 0x2D, 0xA4, 0x8F, 0xB5, 0x10, 0xAC, 0xEF, +0xAD, 0x10, 0xAD, 0x31, 0x9C, 0xAF, 0xA4, 0xF1, +0xAD, 0x52, 0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x93, +0xAD, 0x52, 0xB5, 0x73, 0xC5, 0xF5, 0xBD, 0xB4, +0xAD, 0x32, 0xBD, 0xB4, 0xC6, 0x16, 0xC5, 0xF5, +0xCE, 0x57, 0xCE, 0x77, 0xC6, 0x16, 0xC5, 0xF5, +0xB5, 0x93, 0xA4, 0xCF, 0xAC, 0xEF, 0xCE, 0x13, +0xCE, 0x34, 0xAC, 0xF1, 0x5A, 0xA8, 0x73, 0x6A, +0xCE, 0x14, 0xD6, 0x13, 0xCD, 0xF3, 0xCD, 0xF2, +0xD6, 0x13, 0xD6, 0x14, 0xD6, 0x34, 0xC5, 0x93, +0x4A, 0x07, 0x31, 0xA6, 0x42, 0x07, 0x42, 0x27, +0x42, 0x28, 0x52, 0x89, 0x5A, 0xCB, 0x63, 0x2C, +0x83, 0xF0, 0xA5, 0x14, 0xAD, 0x55, 0x9C, 0xB3, +0xAD, 0x76, 0xAD, 0x55, 0xA5, 0x35, 0x94, 0x92, +0x42, 0x08, 0x73, 0x6D, 0xC5, 0xD6, 0x94, 0x2F, +0x94, 0x2E, 0xA4, 0x8F, 0x94, 0x2E, 0xA4, 0xF0, +0xBD, 0xB4, 0xB5, 0x52, 0x8C, 0x0E, 0x29, 0x24, +0x29, 0x45, 0x29, 0x65, 0x41, 0xE7, 0x4A, 0x49, +0x7B, 0xCF, 0xAD, 0x34, 0xB5, 0x96, 0xBD, 0xB6, +0x83, 0xEF, 0x73, 0x4D, 0x39, 0x86, 0x62, 0xCB, +0xA4, 0x91, 0xAC, 0xD2, 0x9C, 0x50, 0x7B, 0x6C, +0x7B, 0x6D, 0x94, 0x50, 0xC5, 0xD6, 0xCD, 0xF7, +0x9C, 0xB2, 0xAC, 0xF1, 0xB5, 0x31, 0x7B, 0x6B, +0x84, 0x0F, 0x84, 0x50, 0x84, 0x2F, 0x7B, 0xEF, +0x73, 0xAE, 0x7B, 0xCE, 0x94, 0x90, 0xAD, 0x33, +0xC6, 0x16, 0xB5, 0xB4, 0x9C, 0xF2, 0x94, 0x91, +0x73, 0xAE, 0x6B, 0x6D, 0x6B, 0x6C, 0x84, 0x0F, +0xA5, 0x13, 0xC6, 0x16, 0xC5, 0xF6, 0xBD, 0xD5, +0xA5, 0x32, 0x9C, 0x6E, 0xBD, 0x51, 0xA4, 0x6E, +0x94, 0x2E, 0x83, 0xED, 0x7B, 0xAD, 0xB5, 0xB6, +0xB5, 0xB7, 0x94, 0x92, 0x63, 0x2C, 0x94, 0x71, +0x7B, 0x8C, 0x7B, 0x8C, 0x7B, 0xCC, 0x7B, 0xAC, +0x83, 0xED, 0x9C, 0x6F, 0x8B, 0xED, 0x7B, 0x8B, +0x7B, 0x8C, 0x7B, 0x6B, 0x73, 0x0A, 0x83, 0x4B, +0x83, 0x4B, 0x8B, 0xAD, 0xBD, 0x94, 0xA5, 0x12, +0xC6, 0x16, 0xB5, 0xB5, 0xAD, 0x74, 0xA5, 0x33, +0xAD, 0x74, 0xB5, 0xB5, 0xB5, 0x94, 0xAD, 0x74, +0xAD, 0x73, 0xB5, 0xB4, 0xB5, 0x94, 0xB5, 0x94, +0xB5, 0x74, 0x84, 0x0E, 0x73, 0x8C, 0x83, 0xED, +0xC6, 0x16, 0xCE, 0x36, 0xC5, 0xD5, 0xC5, 0xF5, +0xBD, 0xD5, 0x8C, 0x2F, 0x8C, 0x2F, 0x94, 0xB0, +0x94, 0x90, 0x7B, 0xED, 0x9C, 0xD1, 0x94, 0x90, +0x94, 0x4F, 0x9C, 0xD1, 0xA4, 0xF2, 0xA5, 0x12, +0xB5, 0x94, 0xAD, 0x53, 0x8C, 0x4F, 0x94, 0x90, +0xA4, 0xD1, 0xB5, 0x74, 0xB5, 0x53, 0xB5, 0x53, +0xA4, 0xD1, 0x9C, 0x90, 0x8C, 0x4F, 0x84, 0x0E, +0x94, 0x4F, 0x9C, 0x90, 0x7B, 0xCD, 0x8C, 0x2F, +0xAD, 0x32, 0xB5, 0x32, 0xBD, 0x94, 0xBD, 0xB4, +0x9C, 0xB0, 0x9C, 0x70, 0x9C, 0xB0, 0x9C, 0xB0, +0xA4, 0xD1, 0xA4, 0xF1, 0xB5, 0x32, 0xAD, 0x12, +0xA4, 0xD1, 0xAD, 0x12, 0xA4, 0xD0, 0x9C, 0xB0, +0x9C, 0xB0, 0x9C, 0x90, 0xAD, 0x32, 0xB5, 0x73, +0xB5, 0x32, 0xAD, 0x12, 0xAD, 0x12, 0xB5, 0x53, +0xC5, 0xD5, 0xC5, 0xB4, 0xBD, 0x94, 0x94, 0x6F, +0xA5, 0x12, 0xAD, 0x32, 0xAD, 0x12, 0xA4, 0xF1, +0x9C, 0x90, 0xA4, 0xB1, 0xA4, 0xD1, 0xA4, 0xF1, +0xAC, 0xF2, 0xA4, 0xD1, 0xAC, 0xF1, 0xA4, 0xD0, +0xA4, 0xB0, 0xAC, 0xD0, 0xAD, 0x12, 0xB5, 0x73, +0xAD, 0x12, 0x94, 0x8F, 0xA4, 0xF1, 0x73, 0x4C, +0x73, 0x6C, 0x8C, 0x4E, 0xA5, 0x11, 0xAD, 0x31, +0xAD, 0x11, 0xB5, 0x53, 0xB5, 0x93, 0xBD, 0xB4, +0xC5, 0xF5, 0xA5, 0x11, 0xAD, 0x32, 0xC6, 0x15, +0xC5, 0xF5, 0xAD, 0x32, 0xA5, 0x12, 0xC5, 0xD5, +0xC6, 0x15, 0xAD, 0x52, 0xA4, 0xD0, 0xB5, 0x73, +0xC5, 0xF5, 0xD6, 0x97, 0xCE, 0x36, 0xCE, 0x35, +0xCE, 0x56, 0xCE, 0x56, 0xD6, 0x76, 0xCE, 0x35, +0xCE, 0x36, 0xC5, 0xF4, 0xCE, 0x15, 0xC5, 0xF5, +0xC5, 0xF5, 0xC5, 0xF5, 0x9C, 0xB1, 0xA4, 0xF1, +0xDE, 0xD8, 0xD6, 0x77, 0xCE, 0x36, 0xCE, 0x56, +0xCE, 0x36, 0xBD, 0xD4, 0x9C, 0x8F, 0xB5, 0x73, +0x9C, 0x90, 0xB5, 0x53, 0xB5, 0x94, 0xC5, 0xD4, +0xC5, 0xD4, 0xC5, 0xD3, 0xBD, 0x72, 0xC5, 0xB3, +0xCE, 0x14, 0xD6, 0x35, 0xCE, 0x14, 0x9C, 0x8F, +0xDE, 0x35, 0xD5, 0xF2, 0xBD, 0x50, 0xBD, 0x30, +0xA5, 0x35, 0xB5, 0xB7, 0x9D, 0x14, 0x94, 0xF3, +0x8C, 0x71, 0x62, 0xEA, 0x73, 0x4B, 0x6B, 0x2A, +0x6B, 0x2A, 0x83, 0xCC, 0x94, 0x2D, 0x83, 0xCB, +0x8C, 0x0D, 0x9C, 0xAF, 0xA4, 0xF0, 0x9C, 0x6E, +0x9C, 0x6E, 0x9C, 0x6E, 0xA4, 0xAF, 0xB5, 0x30, +0xB5, 0x10, 0xAC, 0xEF, 0xAC, 0xF0, 0xA4, 0x8E, +0xB5, 0x10, 0xB5, 0x10, 0x9C, 0x2D, 0xAC, 0xCF, +0xB5, 0x10, 0xB5, 0x31, 0xA4, 0xCF, 0xA4, 0xAF, +0xA4, 0x8F, 0xA4, 0xAF, 0xA4, 0x8E, 0x9C, 0x8E, +0x9C, 0x8E, 0x9C, 0x6E, 0xA4, 0x8E, 0xA4, 0xAF, +0xAC, 0xCF, 0xA4, 0xCF, 0xA4, 0xCF, 0xA4, 0xCF, +0x9C, 0x8E, 0x9C, 0x8E, 0x9C, 0x8E, 0xA4, 0xAF, +0xA4, 0xCF, 0xAC, 0xCF, 0xAD, 0x0F, 0xAC, 0xEF, +0xB5, 0x51, 0xAC, 0xEF, 0x83, 0xCB, 0x8B, 0xEC, +0xBD, 0x71, 0xBD, 0x71, 0xC5, 0x91, 0xC5, 0xB1, +0xC5, 0x91, 0xB5, 0x0F, 0xAD, 0x0F, 0xCD, 0xF3, +0x83, 0xCC, 0x39, 0xC6, 0x42, 0x27, 0x42, 0x07, +0x42, 0x28, 0x39, 0xC6, 0x4A, 0x28, 0x52, 0x8A, +0x63, 0x0C, 0x84, 0x31, 0x94, 0x92, 0x9C, 0xF4, +0xA5, 0x14, 0xB5, 0x96, 0xA5, 0x15, 0x94, 0x92, +0x63, 0x0C, 0x29, 0x45, 0x8C, 0x30, 0xC5, 0xD5, +0xB5, 0x11, 0xBD, 0x52, 0xB5, 0x32, 0xAD, 0x11, +0xBD, 0x73, 0xBD, 0x72, 0xBD, 0x73, 0x83, 0xCD, +0x52, 0x68, 0x29, 0x44, 0x29, 0x65, 0x41, 0xE7, +0x4A, 0x28, 0x62, 0xEB, 0x73, 0x4C, 0x52, 0x69, +0x39, 0xC7, 0x29, 0x45, 0x18, 0xC3, 0x4A, 0x07, +0x62, 0xCB, 0x7B, 0x4C, 0xA4, 0x71, 0x8B, 0xCF, +0xB5, 0x55, 0xC5, 0xD6, 0xAD, 0x13, 0xDE, 0x9A, +0xBD, 0x75, 0xA4, 0xB1, 0xB5, 0x10, 0x94, 0x2E, +0x84, 0x0F, 0x94, 0x91, 0x8C, 0x71, 0x84, 0x30, +0x7B, 0xEF, 0x84, 0x0F, 0x94, 0x90, 0x9C, 0xF2, +0xA5, 0x33, 0x9C, 0xD1, 0x8C, 0x6F, 0x73, 0xCD, +0x73, 0xAD, 0x73, 0xCE, 0x7B, 0xCE, 0x84, 0x0F, +0x9C, 0xF2, 0xC6, 0x16, 0xB5, 0xD5, 0xA5, 0x32, +0xAD, 0x53, 0x94, 0x4D, 0xB5, 0x10, 0x8B, 0xCB, +0xA4, 0xD0, 0xA4, 0xF0, 0x8C, 0x0E, 0xBD, 0xF7, +0xB5, 0x76, 0x9C, 0xD3, 0x73, 0xAE, 0x83, 0xEE, +0x8C, 0x2E, 0x83, 0xCD, 0x73, 0x6B, 0x84, 0x0D, +0x8C, 0x0D, 0xA4, 0xD0, 0x7B, 0x6B, 0x8B, 0xED, +0x8C, 0x0D, 0x94, 0x0E, 0x83, 0x6B, 0x8B, 0x6C, +0x8B, 0x8C, 0x94, 0x0E, 0xBD, 0x94, 0xAD, 0x53, +0xC6, 0x36, 0xBD, 0xB5, 0xAD, 0x74, 0xAD, 0x53, +0xB5, 0x74, 0xBD, 0xD5, 0xB5, 0x74, 0x8C, 0x4F, +0x9C, 0xF1, 0xA5, 0x12, 0xB5, 0x94, 0xBD, 0xF5, +0xBD, 0xB5, 0x94, 0x90, 0x8C, 0x4F, 0x62, 0xE9, +0xB5, 0x73, 0xCE, 0x77, 0xCE, 0x77, 0xCE, 0x36, +0xC6, 0x16, 0x8C, 0x2F, 0x94, 0x70, 0x9C, 0xD1, +0xA5, 0x32, 0x94, 0x90, 0xA5, 0x12, 0xA4, 0xF1, +0xA5, 0x12, 0xAD, 0x73, 0xAD, 0x74, 0xAD, 0x53, +0xB5, 0x74, 0xAD, 0x53, 0x8C, 0x2F, 0x9C, 0xB1, +0xA4, 0xD1, 0xA4, 0xF1, 0xAD, 0x32, 0x94, 0x6F, +0x94, 0x4F, 0xA4, 0xF1, 0x94, 0x6F, 0x84, 0x0E, +0x8C, 0x4F, 0x83, 0xED, 0x7B, 0xAC, 0x8C, 0x2E, +0xBD, 0x93, 0xC5, 0xF5, 0xDE, 0xD8, 0xDE, 0xB7, +0xB5, 0x53, 0x8C, 0x0E, 0x8C, 0x0D, 0x83, 0xED, +0x7B, 0xAC, 0x83, 0xAC, 0x83, 0xCC, 0x94, 0x4F, +0xAC, 0xF2, 0xCE, 0x16, 0xD6, 0x98, 0xBD, 0xB4, +0x8C, 0x0E, 0x8C, 0x0E, 0xA4, 0xB0, 0xBD, 0x52, +0xBD, 0x73, 0xBD, 0x73, 0xAC, 0xD0, 0x9C, 0x6F, +0xA4, 0xD0, 0x9C, 0x8F, 0x94, 0x4F, 0x9C, 0x6F, +0xA4, 0xB0, 0x9C, 0x6F, 0x9C, 0xB0, 0xA4, 0xB1, +0x94, 0x4F, 0x8C, 0x0E, 0x94, 0x4F, 0x94, 0x2F, +0x94, 0x4F, 0x9C, 0x90, 0xA4, 0xD1, 0xAC, 0xF1, +0xAC, 0xF1, 0xB5, 0x32, 0xBD, 0x73, 0xBD, 0x93, +0xC5, 0xB4, 0xC5, 0xD4, 0xC5, 0xF5, 0xC5, 0xF5, +0xCE, 0x16, 0xBD, 0x73, 0xAD, 0x12, 0xB5, 0x32, +0xBD, 0x73, 0xB5, 0x52, 0xB5, 0x52, 0xA4, 0xD1, +0xA4, 0xD0, 0xA4, 0xB0, 0x9C, 0xB0, 0x9C, 0xB0, +0x9C, 0x8F, 0x9C, 0x8F, 0xA4, 0xF1, 0xAC, 0xF1, +0xAD, 0x11, 0x9C, 0xB0, 0xB5, 0x53, 0xAD, 0x11, +0xA4, 0xF1, 0xB5, 0x52, 0xAD, 0x32, 0xAD, 0x11, +0xAD, 0x11, 0xAD, 0x32, 0xB5, 0x52, 0xB5, 0x73, +0xAD, 0x32, 0x9C, 0x8F, 0x94, 0x6F, 0xAD, 0x32, +0xBD, 0xD5, 0xC5, 0xD5, 0xB5, 0x73, 0x9C, 0xB0, +0xCE, 0x56, 0xCE, 0x56, 0xCE, 0x56, 0xD6, 0x56, +0xC5, 0xF5, 0xBD, 0x93, 0x9C, 0x90, 0xB5, 0x73, +0xC5, 0xD5, 0xCE, 0x15, 0xC5, 0xF5, 0xCE, 0x15, +0xCE, 0x35, 0xCE, 0x14, 0xC5, 0xF4, 0xD6, 0x55, +0xD6, 0x55, 0xD6, 0x55, 0xC5, 0xB3, 0x94, 0x4E, +0xDE, 0x35, 0xBD, 0x50, 0xA4, 0xAE, 0x94, 0x2D, +0xA5, 0x35, 0xB5, 0xB7, 0x9D, 0x14, 0x9C, 0xF3, +0x8C, 0x92, 0x7B, 0xEE, 0x84, 0x2F, 0x84, 0x0E, +0x7B, 0xED, 0x9C, 0xD0, 0xAD, 0x52, 0xA5, 0x11, +0x9C, 0xF0, 0xA5, 0x31, 0xB5, 0x93, 0xA4, 0xF1, +0xAD, 0x11, 0xAD, 0x31, 0xBD, 0xB3, 0xAC, 0xCF, +0xAC, 0xCF, 0xA4, 0xCF, 0x8C, 0x2D, 0x9C, 0x8F, +0xBD, 0x93, 0xAD, 0x31, 0x63, 0x0A, 0xAD, 0x32, +0x94, 0x6E, 0xAD, 0x32, 0xCE, 0x36, 0xB5, 0x73, +0xBD, 0x93, 0xC5, 0xF4, 0xA4, 0xF0, 0xAD, 0x31, +0x94, 0x6E, 0x94, 0x6F, 0x9C, 0x8F, 0x94, 0x6F, +0xA4, 0xAF, 0xB5, 0x51, 0xAC, 0xF0, 0xB5, 0x10, +0x94, 0x0C, 0x83, 0xCB, 0x94, 0x2D, 0x94, 0x2D, +0x94, 0x0C, 0x9C, 0x6E, 0xA4, 0xCE, 0xAC, 0xEF, +0xAC, 0xCF, 0xA4, 0xCF, 0xB5, 0x10, 0xAC, 0xEF, +0xAC, 0xEF, 0xB4, 0xEF, 0xAC, 0xCE, 0xAC, 0xCE, +0xAC, 0xCF, 0xAC, 0xEF, 0xAC, 0xCF, 0xAC, 0xCF, +0xAC, 0xF0, 0x7B, 0x8B, 0x39, 0xA5, 0x39, 0xC6, +0x41, 0xE6, 0x42, 0x07, 0x4A, 0x48, 0x4A, 0x48, +0x63, 0x2C, 0x73, 0x8E, 0x94, 0x92, 0xA5, 0x14, +0x9C, 0xD3, 0xB5, 0x76, 0xAD, 0x55, 0x94, 0xB3, +0x73, 0x6E, 0x29, 0x25, 0x39, 0xE7, 0xA4, 0xF2, +0xBD, 0x73, 0xAC, 0xF0, 0xAC, 0xD0, 0xAC, 0xF1, +0xAD, 0x11, 0xAC, 0xF1, 0xB5, 0x32, 0xBD, 0x93, +0xB5, 0x32, 0x73, 0x4B, 0x29, 0x44, 0x39, 0xA6, +0x4A, 0x48, 0x29, 0x45, 0x31, 0x85, 0x31, 0x65, +0x39, 0xA6, 0x4A, 0x49, 0x39, 0xC7, 0x31, 0x45, +0x52, 0x28, 0x6A, 0xAA, 0x94, 0x0F, 0x9C, 0x51, +0xA4, 0xD3, 0x94, 0x51, 0xB5, 0x34, 0xA4, 0xD3, +0xCE, 0x18, 0xBD, 0x74, 0xB5, 0x31, 0xB5, 0x32, +0x84, 0x0F, 0xB5, 0x95, 0xAD, 0x94, 0xAD, 0x74, +0x94, 0x91, 0xA5, 0x13, 0xAD, 0x74, 0xB5, 0x94, +0xAD, 0x54, 0x73, 0xAD, 0x6B, 0x4C, 0x5A, 0xEA, +0x73, 0xAD, 0x7B, 0xEF, 0x8C, 0x50, 0x8C, 0x70, +0xB5, 0xB5, 0xC6, 0x37, 0xC6, 0x16, 0x83, 0xEE, +0x83, 0xEE, 0x9C, 0x6E, 0xB5, 0x10, 0x7B, 0x8A, +0xA4, 0xD0, 0xAC, 0xF1, 0xA5, 0x12, 0xC6, 0x18, +0xB5, 0x76, 0x9C, 0xF4, 0x73, 0x8D, 0x83, 0xAD, +0x9C, 0x90, 0x83, 0xED, 0x73, 0x4B, 0x8C, 0x2E, +0xA4, 0xB0, 0xAD, 0x11, 0xA4, 0xB0, 0xA4, 0xB0, +0x9C, 0x6F, 0xA4, 0x8F, 0x83, 0x6B, 0x93, 0xAC, +0x93, 0xAC, 0x94, 0x0E, 0xBD, 0x94, 0xB5, 0x94, +0xC6, 0x36, 0xB5, 0xB4, 0xB5, 0x74, 0xAD, 0x53, +0xB5, 0x94, 0xAD, 0x73, 0xAD, 0x32, 0x9C, 0xB1, +0xA5, 0x32, 0xB5, 0x94, 0xB5, 0x94, 0xBD, 0xD5, +0xBD, 0xD5, 0xBD, 0xD5, 0xBD, 0xF5, 0x9C, 0xD1, +0x94, 0x6F, 0xB5, 0x94, 0xCE, 0x36, 0xC6, 0x16, +0xC5, 0xF5, 0x84, 0x2E, 0x9C, 0xD1, 0xA5, 0x12, +0xA4, 0xF2, 0x9C, 0xB1, 0xA5, 0x12, 0xA5, 0x32, +0xA5, 0x33, 0xBD, 0xF5, 0xAD, 0x74, 0xA5, 0x33, +0xB5, 0x94, 0xAD, 0x73, 0x83, 0xEE, 0x9C, 0xD1, +0xA4, 0xF1, 0x9C, 0xD1, 0xA4, 0xF2, 0x84, 0x0E, +0x84, 0x0E, 0xA5, 0x12, 0x9C, 0xB0, 0x94, 0x4F, +0x94, 0x90, 0x8C, 0x2E, 0x94, 0x4F, 0x9C, 0x90, +0xBD, 0x93, 0xCE, 0x36, 0xDE, 0xB7, 0xD6, 0x76, +0xCE, 0x15, 0xA4, 0xD1, 0x94, 0x6F, 0x94, 0x4E, +0x7B, 0xAC, 0x7B, 0x8C, 0x7B, 0xAD, 0x94, 0x6F, +0xAD, 0x12, 0xB5, 0x53, 0xC5, 0xD5, 0xAD, 0x32, +0x83, 0xEE, 0x94, 0x4F, 0xB5, 0x12, 0xBD, 0x52, +0xC5, 0x93, 0xBD, 0x73, 0x9C, 0x2E, 0xA4, 0x6F, +0xA4, 0xB0, 0x94, 0x4F, 0x9C, 0x90, 0xAD, 0x32, +0xAD, 0x32, 0xAD, 0x12, 0x9C, 0xB0, 0x9C, 0x90, +0x94, 0x6F, 0xA4, 0xF1, 0x9C, 0xD1, 0x94, 0x6F, +0x8C, 0x2F, 0x94, 0x6F, 0x8C, 0x2E, 0xA4, 0xD1, +0x8C, 0x2E, 0x94, 0x70, 0x9C, 0xB0, 0x8C, 0x2E, +0x7B, 0xAC, 0x83, 0xCD, 0x83, 0xCD, 0x83, 0xCD, +0xB5, 0x53, 0x8C, 0x2E, 0x8C, 0x2E, 0x94, 0x6F, +0x9C, 0x70, 0x9C, 0x90, 0x9C, 0x90, 0x94, 0x2E, +0x94, 0x4F, 0x9C, 0x8F, 0x94, 0x6F, 0x9C, 0x6F, +0x9C, 0xB0, 0xA4, 0xD1, 0xAD, 0x32, 0xAD, 0x11, +0xAC, 0xF1, 0xAC, 0xF1, 0xB5, 0x32, 0xB5, 0x32, +0xB5, 0x53, 0xBD, 0x73, 0xB5, 0x53, 0xB5, 0x32, +0xBD, 0x73, 0xB5, 0x32, 0xAC, 0xF2, 0xAC, 0xD1, +0xA4, 0xD1, 0xAC, 0xF1, 0xAC, 0xF1, 0xA4, 0xF1, +0xAC, 0xF1, 0xAC, 0xF1, 0xAC, 0xF2, 0xAD, 0x12, +0xAC, 0xF1, 0xA4, 0xF1, 0xA4, 0xB0, 0x9C, 0xB0, +0x9C, 0x90, 0x9C, 0xB0, 0xAD, 0x12, 0xB5, 0x53, +0xA4, 0xD1, 0xA4, 0xF1, 0xA4, 0xF1, 0xA4, 0xF1, +0xAC, 0xF0, 0xA4, 0xD0, 0xA4, 0xD0, 0xAC, 0xF0, +0xA4, 0xD0, 0xA4, 0xD0, 0x94, 0x2D, 0xA4, 0xB0, +0xCD, 0xB3, 0xC5, 0x91, 0xBD, 0x72, 0x9C, 0x6E, +0xA5, 0x35, 0xAD, 0x96, 0x9D, 0x14, 0x9C, 0xF4, +0x8C, 0x92, 0x84, 0x0F, 0x8C, 0x90, 0x8C, 0x70, +0x8C, 0x4F, 0xA5, 0x11, 0xB5, 0x73, 0xAD, 0x52, +0xA5, 0x11, 0xAD, 0x52, 0xBD, 0xB4, 0xB5, 0x73, +0xAD, 0x52, 0xA4, 0xF1, 0xC5, 0xF4, 0xA4, 0xAF, +0xAC, 0xEF, 0xBD, 0xD3, 0xA5, 0x11, 0xA5, 0x12, +0xB5, 0x93, 0xAD, 0x52, 0xAD, 0x53, 0xAD, 0x53, +0x9C, 0xD1, 0xBD, 0xD5, 0xBD, 0xB4, 0xC6, 0x15, +0xB5, 0x93, 0xB5, 0x94, 0xB5, 0x73, 0xB5, 0x93, +0xB5, 0x93, 0xAD, 0x73, 0xBD, 0xD5, 0xBD, 0xB4, +0xA4, 0xF1, 0xB5, 0x93, 0xAD, 0x11, 0xB5, 0x10, +0x9C, 0x4E, 0x9C, 0xB0, 0xAD, 0x32, 0xAD, 0x32, +0xA4, 0xF1, 0xAD, 0x52, 0xB5, 0x72, 0xBD, 0xB4, +0xBD, 0x93, 0xB5, 0x52, 0xB5, 0x72, 0xB5, 0x52, +0x94, 0x6F, 0xB5, 0x52, 0xB5, 0x32, 0xA4, 0xF0, +0xBD, 0x73, 0xAC, 0xF0, 0x9C, 0x8F, 0x9C, 0x8F, +0xA4, 0xCF, 0x94, 0x2E, 0x52, 0x88, 0x31, 0xA5, +0x39, 0xE6, 0x41, 0xE6, 0x42, 0x07, 0x39, 0xC7, +0x4A, 0x69, 0x6B, 0x4D, 0x84, 0x10, 0x9C, 0xD3, +0x9C, 0xF3, 0xAD, 0x76, 0xB5, 0x97, 0xB5, 0x96, +0xA5, 0x35, 0x7B, 0xAF, 0x7B, 0xEE, 0xA4, 0xF1, +0xAC, 0xF1, 0xB4, 0xF0, 0xB4, 0xF0, 0xB4, 0xF0, +0xA4, 0xAF, 0xA4, 0xAF, 0xB5, 0x11, 0xAC, 0xF0, +0xAC, 0xCF, 0xAC, 0xD0, 0x8B, 0xED, 0x7B, 0xAC, +0x52, 0x48, 0x31, 0x85, 0x39, 0xC6, 0x39, 0xE7, +0x39, 0xC6, 0x6B, 0x0C, 0x6B, 0x2C, 0x5A, 0xAA, +0x41, 0xA6, 0x62, 0x8A, 0x83, 0x4C, 0x6A, 0xAA, +0x9C, 0x92, 0x8B, 0xF0, 0xC5, 0xD7, 0xA4, 0xD3, +0xAD, 0x34, 0xC5, 0xD6, 0xD5, 0xF5, 0xCD, 0x93, +0xAC, 0xD0, 0x94, 0x6F, 0x9C, 0xB0, 0x9C, 0xD1, +0x94, 0x70, 0x9C, 0xD1, 0xB5, 0x94, 0xBD, 0xD5, +0xB5, 0xB4, 0x94, 0xB0, 0x84, 0x0E, 0x73, 0xAE, +0x7B, 0xCE, 0x7C, 0x0F, 0x9C, 0xF2, 0xAD, 0x95, +0xDE, 0xDA, 0xCE, 0x79, 0xC6, 0x17, 0xB5, 0x95, +0xBD, 0x95, 0xB5, 0x32, 0xB5, 0x10, 0xA4, 0xAF, +0xBD, 0x93, 0xBD, 0x93, 0xBD, 0xB4, 0xC6, 0x18, +0xAD, 0x56, 0xA4, 0xF3, 0xA4, 0xF2, 0x9C, 0x90, +0x94, 0x2E, 0x7B, 0xAC, 0x7B, 0xAC, 0x94, 0x4F, +0xAD, 0x11, 0xB5, 0x72, 0xBD, 0x72, 0xAC, 0xD0, +0xAC, 0xD0, 0xA4, 0x8F, 0x7B, 0x0A, 0x83, 0x6B, +0x8B, 0x6B, 0x9C, 0x4F, 0xB5, 0x73, 0xBD, 0xF5, +0xC6, 0x36, 0xBD, 0xD5, 0xBD, 0xB5, 0xB5, 0x94, +0xBD, 0xD5, 0xB5, 0x94, 0xA4, 0xF2, 0xA5, 0x12, +0xA5, 0x32, 0xA5, 0x32, 0xAD, 0x53, 0xBD, 0xB5, +0xBD, 0xF5, 0xB5, 0xB4, 0xB5, 0xB4, 0xBD, 0xF5, +0xBD, 0xD5, 0xC6, 0x16, 0xC6, 0x36, 0xC6, 0x16, +0xBD, 0xD5, 0x84, 0x2E, 0xA5, 0x12, 0xAD, 0x33, +0xA4, 0xF2, 0x9C, 0xD1, 0x9C, 0xF1, 0x94, 0x90, +0x9C, 0xB1, 0xAD, 0x73, 0xAD, 0x53, 0xB5, 0xB5, +0xBD, 0xF6, 0xB5, 0xB5, 0x8C, 0x6F, 0xA5, 0x12, +0x9C, 0xD1, 0xAD, 0x12, 0xBD, 0xB5, 0xB5, 0x74, +0xA5, 0x12, 0xA4, 0xF1, 0x9C, 0xD1, 0x9C, 0xD1, +0x9C, 0xB0, 0x9C, 0x90, 0x9C, 0xB1, 0x9C, 0xB1, +0xBD, 0x73, 0xCE, 0x35, 0xC5, 0xF4, 0xCE, 0x15, +0xC5, 0xF4, 0xA4, 0xF0, 0xA4, 0xD0, 0xAD, 0x11, +0x8B, 0xED, 0xA4, 0xD1, 0x94, 0x6F, 0x9C, 0xB0, +0x9C, 0xB1, 0x94, 0x70, 0xB5, 0x74, 0x94, 0x90, +0x8C, 0x2F, 0xA4, 0xD1, 0xAC, 0xF2, 0xBD, 0x53, +0xCD, 0xB4, 0xC5, 0x73, 0x83, 0x8C, 0xA4, 0x6F, +0xA4, 0xF1, 0x9C, 0xB0, 0x94, 0x6F, 0xB5, 0x53, +0xB5, 0x73, 0xAD, 0x53, 0xA4, 0xF2, 0xA4, 0xD1, +0x9C, 0xB1, 0xB5, 0x73, 0xAD, 0x53, 0xA5, 0x12, +0xA4, 0xF1, 0x94, 0x90, 0x9C, 0x90, 0xA4, 0xF2, +0xA4, 0xF2, 0xAD, 0x53, 0xAD, 0x53, 0xA5, 0x12, +0x9C, 0xB1, 0x7B, 0xCD, 0x94, 0x70, 0x8C, 0x4F, +0xAD, 0x33, 0x83, 0xED, 0x9C, 0x90, 0xA4, 0xF1, +0x8C, 0x2E, 0x8B, 0xED, 0x9C, 0x6F, 0x94, 0x2E, +0x94, 0x4E, 0x83, 0xCD, 0x83, 0xED, 0x8B, 0xEE, +0xA4, 0xD1, 0x94, 0x4F, 0x94, 0x8F, 0x9C, 0x90, +0x94, 0x2E, 0x8B, 0xED, 0x8C, 0x0E, 0x9C, 0x90, +0xA4, 0xD1, 0x9C, 0xB0, 0xAD, 0x11, 0x9C, 0xB0, +0xA4, 0xD1, 0x9C, 0xB0, 0x8B, 0xED, 0x7B, 0x8C, +0x8C, 0x0E, 0xB5, 0x53, 0xB5, 0x53, 0x9C, 0x90, +0xA4, 0xD1, 0xA4, 0xB0, 0xAC, 0xF1, 0xA4, 0xF1, +0x9C, 0x90, 0xA4, 0xD1, 0xB5, 0x32, 0xB5, 0x32, +0xBD, 0x53, 0xB5, 0x32, 0xB5, 0x53, 0xB5, 0x53, +0xBD, 0x94, 0xBD, 0x94, 0xBD, 0x73, 0xC5, 0xB5, +0xC5, 0xB4, 0xCD, 0xD5, 0xBD, 0x94, 0xBD, 0x73, +0xBD, 0x93, 0xC5, 0x94, 0xC5, 0x94, 0xC5, 0xB4, +0xC5, 0x93, 0xBD, 0x72, 0xB5, 0x52, 0xB5, 0x32, +0xA5, 0x35, 0xB5, 0xB7, 0x9D, 0x14, 0x9C, 0xF3, +0x8C, 0x92, 0x84, 0x0F, 0x8C, 0x91, 0x94, 0xB1, +0x8C, 0x4F, 0xA5, 0x12, 0xB5, 0x93, 0xAD, 0x31, +0xAD, 0x31, 0x9C, 0xF0, 0xBD, 0xD4, 0xB5, 0x94, +0xBD, 0xD4, 0xAD, 0x32, 0xC6, 0x14, 0xA4, 0xAF, +0xA4, 0xAE, 0xBD, 0xB3, 0xAD, 0x52, 0xA5, 0x32, +0xB5, 0x73, 0xAD, 0x32, 0xA5, 0x32, 0xA5, 0x32, +0xA5, 0x12, 0xBD, 0xD4, 0xC5, 0xF5, 0xBD, 0xF4, +0xB5, 0x73, 0xB5, 0xB4, 0xB5, 0x93, 0xBD, 0xB4, +0xC5, 0xD5, 0xB5, 0xB4, 0xB5, 0x93, 0xB5, 0x73, +0xB5, 0x52, 0xBD, 0x93, 0xB5, 0x72, 0xAD, 0x10, +0x83, 0xAB, 0xAD, 0x53, 0xAD, 0x53, 0xB5, 0xB4, +0x94, 0xB1, 0xB5, 0xB4, 0xB5, 0xB4, 0xC6, 0x16, +0xBD, 0xD5, 0xC6, 0x16, 0xC6, 0x36, 0xBD, 0xF6, +0xA5, 0x12, 0xAD, 0x53, 0xAD, 0x53, 0xAD, 0x74, +0xBD, 0xF5, 0xBD, 0xF5, 0xBD, 0xF5, 0xC6, 0x16, +0xC6, 0x16, 0xA5, 0x32, 0x8C, 0x2E, 0x4A, 0x27, +0x39, 0xC6, 0x41, 0xE7, 0x42, 0x07, 0x4A, 0x28, +0x42, 0x28, 0x63, 0x2C, 0x7B, 0xCF, 0x7B, 0xCF, +0xA5, 0x35, 0x94, 0x92, 0x9C, 0xD3, 0xAD, 0x55, +0xAD, 0x75, 0xB5, 0xB6, 0xC5, 0xF7, 0xBD, 0xD5, +0xC5, 0xD4, 0xC5, 0xD4, 0xBD, 0x92, 0xB5, 0x51, +0xB5, 0x52, 0xCD, 0xF4, 0xB5, 0x10, 0x9C, 0x6E, +0x83, 0x8A, 0x83, 0xAB, 0x8B, 0xCC, 0x83, 0xED, +0x52, 0x68, 0x29, 0x44, 0x31, 0x85, 0x39, 0xA6, +0x41, 0xE7, 0x63, 0x0C, 0x5A, 0xAA, 0x5A, 0x8A, +0x83, 0xEF, 0x52, 0x6A, 0x62, 0x69, 0x93, 0xEF, +0xA4, 0x92, 0x9C, 0x71, 0xC5, 0xD7, 0xD6, 0x38, +0xBD, 0x75, 0xBD, 0x55, 0xB5, 0x33, 0xBD, 0x52, +0xBD, 0x31, 0xB5, 0x10, 0xA4, 0xAF, 0x9C, 0x6E, +0xA4, 0x8F, 0xAC, 0xD0, 0xA4, 0xAF, 0xA4, 0xAF, +0xA4, 0xD0, 0x9C, 0x8F, 0x9C, 0x8F, 0x94, 0x4F, +0x94, 0x6F, 0x9C, 0x8F, 0xA4, 0xAF, 0xA4, 0xF1, +0x7B, 0xAD, 0x6B, 0x2B, 0x5A, 0x89, 0x52, 0x69, +0x8C, 0x30, 0xA4, 0xF2, 0xC5, 0xD5, 0xB5, 0x52, +0xBD, 0x93, 0xAD, 0x11, 0xC5, 0xB5, 0xC6, 0x38, +0xA5, 0x55, 0x94, 0x71, 0xBD, 0x73, 0xAD, 0x11, +0xA4, 0xB0, 0xA4, 0xB0, 0x8C, 0x2E, 0x94, 0x2E, +0x94, 0x4E, 0x8C, 0x0D, 0x9C, 0x6E, 0xAC, 0xF0, +0xB5, 0x11, 0x8B, 0xEC, 0x73, 0x0A, 0x72, 0xE9, +0x73, 0x0A, 0x9C, 0x6F, 0xAD, 0x12, 0xB5, 0x73, +0xBD, 0xD5, 0xBD, 0xD5, 0xBD, 0xD5, 0xB5, 0x74, +0xB5, 0x94, 0xAD, 0x33, 0xA4, 0xF2, 0xAD, 0x73, +0x94, 0x6F, 0xA4, 0xF1, 0xAD, 0x53, 0xC5, 0xF6, +0xBD, 0xD5, 0xBD, 0xD5, 0xB5, 0x94, 0xC5, 0xF5, +0xCE, 0x36, 0xCE, 0x36, 0xC6, 0x16, 0xC6, 0x16, +0xBD, 0xB4, 0x7B, 0xCD, 0x94, 0x90, 0xB5, 0x94, +0xB5, 0xB4, 0xAD, 0x53, 0xB5, 0xB4, 0x84, 0x0E, +0x94, 0x70, 0xA5, 0x12, 0xA5, 0x12, 0xB5, 0xB5, +0xBD, 0xD5, 0xBD, 0xD5, 0x9C, 0xB1, 0xAD, 0x33, +0x9C, 0xD1, 0xAD, 0x32, 0xDE, 0xB8, 0xC6, 0x16, +0xC5, 0xF5, 0xBD, 0xB4, 0xB5, 0x73, 0xBD, 0x94, +0xBD, 0xD5, 0xBD, 0xD4, 0xC5, 0xF5, 0xA4, 0xF2, +0xBD, 0x94, 0xC5, 0xD4, 0xC6, 0x15, 0xC5, 0xF4, +0xC5, 0xD4, 0xAD, 0x11, 0xAC, 0xF0, 0xAD, 0x11, +0x9C, 0x8F, 0x9C, 0x90, 0x9C, 0x90, 0xA5, 0x12, +0xAD, 0x33, 0xAD, 0x54, 0xBD, 0xD5, 0xA4, 0xF2, +0x94, 0x70, 0xAC, 0xF1, 0xB5, 0x12, 0xC5, 0x94, +0xCD, 0xB3, 0xCD, 0x93, 0x8B, 0x8C, 0xA4, 0x90, +0x9C, 0x90, 0xA4, 0xF1, 0x9C, 0xB0, 0xA4, 0xF1, +0xBD, 0xD4, 0xBD, 0xB4, 0xB5, 0x73, 0xA4, 0xF2, +0xA5, 0x12, 0xAD, 0x32, 0xBD, 0xB4, 0xAD, 0x53, +0xBD, 0xD5, 0xAD, 0x53, 0xAD, 0x74, 0xB5, 0x74, +0xB5, 0x74, 0xBD, 0xD5, 0xBD, 0xD4, 0xBD, 0xF5, +0xBD, 0xB5, 0xAD, 0x32, 0x8C, 0x2E, 0x8C, 0x2E, +0xA4, 0xF1, 0x8C, 0x0E, 0xAD, 0x12, 0xA4, 0xD1, +0x8C, 0x0E, 0x7B, 0xCC, 0x9C, 0x8F, 0xAD, 0x11, +0x8C, 0x2E, 0x94, 0x6F, 0x9C, 0xB0, 0x9C, 0x90, +0xBD, 0xB4, 0x9C, 0xB0, 0x8C, 0x2E, 0xA4, 0xD1, +0x8C, 0x2E, 0x8B, 0xED, 0x9C, 0x8F, 0xAD, 0x32, +0x94, 0x4E, 0xB5, 0x52, 0x9C, 0x8F, 0x9C, 0x8F, +0xAD, 0x12, 0x94, 0x8F, 0x83, 0xED, 0x6B, 0x0A, +0xAD, 0x12, 0xB5, 0x53, 0xBD, 0x93, 0xA4, 0xD0, +0xA4, 0xF1, 0xB5, 0x73, 0xAD, 0x32, 0x9C, 0xB0, +0x8C, 0x2F, 0x94, 0x90, 0xAD, 0x33, 0xA5, 0x32, +0xBD, 0xB4, 0x8C, 0x2F, 0x9C, 0xB0, 0xAD, 0x52, +0x9C, 0xD0, 0x9C, 0x90, 0x94, 0x6F, 0x8C, 0x0E, +0x8C, 0x2E, 0xB5, 0x52, 0xA4, 0xD1, 0xAD, 0x11, +0xAC, 0xF1, 0xA4, 0xD0, 0x9C, 0x6F, 0x9C, 0x90, +0x8C, 0x0E, 0xA4, 0xB0, 0xA4, 0xF1, 0xAD, 0x11, +0xA5, 0x35, 0xB5, 0xB7, 0x9D, 0x14, 0x9C, 0xF4, +0x8C, 0x71, 0x84, 0x50, 0x8C, 0x90, 0x94, 0xD1, +0x84, 0x2F, 0xA5, 0x11, 0xB5, 0x93, 0xB5, 0x73, +0xA5, 0x11, 0xAD, 0x72, 0xB5, 0xB4, 0xB5, 0x94, +0xBD, 0xB4, 0xAD, 0x52, 0xC5, 0xF4, 0xA4, 0x8E, +0x9C, 0x6E, 0xB5, 0x72, 0xB5, 0xB4, 0xAD, 0x73, +0xAD, 0x52, 0xAD, 0x53, 0xA5, 0x32, 0xB5, 0x74, +0xA5, 0x12, 0xBD, 0xF5, 0xC5, 0xF5, 0xC6, 0x15, +0xB5, 0xB4, 0xBD, 0xB4, 0xC6, 0x15, 0xBD, 0xD5, +0xB5, 0x94, 0xB5, 0x73, 0xB5, 0x73, 0xA5, 0x11, +0xB5, 0x72, 0xBD, 0xD4, 0xB5, 0x72, 0xAC, 0xEF, +0x8C, 0x0D, 0xB5, 0xB4, 0xB5, 0x94, 0xBD, 0xF6, +0xAD, 0x94, 0xC6, 0x16, 0xBD, 0xF6, 0xBD, 0xF6, +0xBD, 0xD5, 0xBE, 0x16, 0xC6, 0x37, 0xC6, 0x16, +0xC6, 0x16, 0xBD, 0xF6, 0xBD, 0xD5, 0xB5, 0xB5, +0xBD, 0xF6, 0xBD, 0xD5, 0xCE, 0x77, 0xCE, 0x57, +0xC6, 0x16, 0xB5, 0xB4, 0x9C, 0xB0, 0x94, 0x4F, +0x39, 0xA5, 0x31, 0x85, 0x39, 0xE7, 0x39, 0xA6, +0x31, 0x85, 0x41, 0xE7, 0x4A, 0x28, 0x73, 0x6D, +0x8C, 0x51, 0x8C, 0x51, 0xB5, 0x75, 0x9C, 0xB3, +0x8C, 0x51, 0x94, 0xB2, 0xC6, 0x38, 0xD6, 0x98, +0xC6, 0x15, 0xD6, 0x76, 0xCE, 0x55, 0xB5, 0x72, +0xAD, 0x31, 0xBD, 0x92, 0x9C, 0x8E, 0xAC, 0xF0, +0x83, 0xAB, 0x8C, 0x2D, 0x94, 0x4E, 0x9C, 0xD0, +0x9C, 0xD0, 0x7B, 0xCD, 0x39, 0xA5, 0x39, 0xA6, +0x4A, 0x48, 0x42, 0x07, 0x41, 0xE7, 0x83, 0xCF, +0x8C, 0x51, 0xC5, 0xF7, 0x52, 0x29, 0x6A, 0xCB, +0x72, 0xEB, 0x94, 0x31, 0xA4, 0xB3, 0xCD, 0xF7, +0xD6, 0x58, 0xAC, 0xD3, 0x6B, 0x0B, 0x83, 0x8D, +0xAC, 0xD1, 0x73, 0x2A, 0x83, 0x8A, 0x83, 0xAB, +0x7B, 0x6A, 0x94, 0x0D, 0x94, 0x2D, 0x94, 0x2D, +0x9C, 0x4E, 0x94, 0x2D, 0x94, 0x2E, 0x9C, 0x6E, +0xA4, 0xAF, 0xAC, 0xCF, 0xB5, 0x31, 0xB5, 0x10, +0xBD, 0x52, 0xBD, 0x52, 0xAC, 0xF0, 0x9C, 0x4F, +0x6B, 0x2B, 0x42, 0x07, 0x73, 0x6D, 0x94, 0x71, +0xB5, 0x74, 0xAC, 0xF2, 0xC5, 0xD6, 0xCE, 0x59, +0xAD, 0x76, 0x94, 0x71, 0xAC, 0xF1, 0xB5, 0x31, +0xB5, 0x31, 0xB5, 0x31, 0xB5, 0x31, 0xB5, 0x31, +0xB5, 0x52, 0xB5, 0x11, 0xAC, 0xD0, 0xAC, 0xF0, +0xAC, 0xD0, 0xAC, 0xF1, 0xA4, 0xB1, 0xA4, 0xB1, +0x9C, 0xB1, 0xAD, 0x12, 0xB5, 0x74, 0xA4, 0xF2, +0xA4, 0xD1, 0x94, 0x70, 0x8C, 0x4F, 0x94, 0x6F, +0x9C, 0xB0, 0x9C, 0xB1, 0x94, 0x70, 0x8C, 0x2E, +0x8C, 0x2E, 0x83, 0xED, 0x83, 0xED, 0x94, 0x90, +0x9C, 0xF1, 0xB5, 0x94, 0xAD, 0x52, 0xBD, 0xB4, +0xBD, 0xD5, 0xBD, 0xB4, 0xB5, 0x94, 0xBD, 0xB4, +0xAD, 0x52, 0x7B, 0xAC, 0x94, 0x90, 0xA4, 0xF1, +0xB5, 0x94, 0xAD, 0x33, 0xAD, 0x53, 0x8C, 0x2F, +0x84, 0x0E, 0x9C, 0xD0, 0xA5, 0x11, 0xB5, 0x94, +0xBD, 0xD5, 0xB5, 0xB4, 0x94, 0x6F, 0xB5, 0x73, +0xAD, 0x12, 0xAD, 0x32, 0xC5, 0xD5, 0xC5, 0xF5, +0xD6, 0x76, 0xD6, 0x76, 0xD6, 0x76, 0xD6, 0x56, +0xBD, 0xD4, 0xBD, 0xD5, 0xD6, 0x77, 0xAD, 0x11, +0xB5, 0x73, 0xCE, 0x15, 0xC5, 0xF5, 0xCE, 0x15, +0xC5, 0xF4, 0xB5, 0x32, 0xA4, 0xD0, 0xA4, 0xF0, +0x9C, 0x8F, 0xBD, 0x73, 0xA4, 0xF1, 0x9C, 0xF1, +0xAD, 0x53, 0xAD, 0x53, 0xAD, 0x53, 0xA5, 0x12, +0xA4, 0xF1, 0xB5, 0x32, 0xBD, 0x53, 0xCD, 0xD4, +0xD5, 0xF4, 0xCD, 0xB3, 0x8B, 0x8C, 0xA4, 0x90, +0x94, 0x4F, 0x9C, 0xB0, 0xA4, 0xD1, 0xA4, 0xD1, +0xC6, 0x15, 0xC5, 0xF5, 0xB5, 0xB4, 0x9C, 0xB0, +0xA5, 0x32, 0xAD, 0x33, 0xB5, 0x94, 0xAD, 0x53, +0xBD, 0xB4, 0xB5, 0x73, 0xA5, 0x12, 0xAD, 0x53, +0xB5, 0x74, 0xAD, 0x53, 0xB5, 0x74, 0xBD, 0xD5, +0xBD, 0xD5, 0xBD, 0xB4, 0xA4, 0xF1, 0x94, 0x4F, +0xA4, 0xF1, 0x9C, 0x90, 0xA4, 0xF1, 0x9C, 0xB0, +0x8C, 0x2E, 0x84, 0x0D, 0x94, 0x4F, 0x94, 0x8F, +0x8C, 0x2E, 0x8C, 0x2E, 0xAD, 0x32, 0x9C, 0x90, +0xB5, 0x53, 0x9C, 0x8F, 0x94, 0x6F, 0xA5, 0x11, +0x94, 0x6F, 0x94, 0x2E, 0xAD, 0x12, 0xBD, 0x72, +0xBD, 0x93, 0xC5, 0x93, 0x94, 0x4E, 0x9C, 0xB0, +0xB5, 0x53, 0x9C, 0x90, 0x8C, 0x4F, 0x73, 0x4B, +0xA4, 0xD1, 0xAD, 0x11, 0xA4, 0xF1, 0x9C, 0x90, +0xA4, 0xD1, 0xB5, 0x53, 0xAD, 0x32, 0xA5, 0x32, +0xAD, 0x53, 0xAD, 0x53, 0xBD, 0xD5, 0xB5, 0x94, +0xC6, 0x16, 0x9C, 0xB0, 0xAD, 0x53, 0xC5, 0xF5, +0xB5, 0x93, 0xA4, 0xD1, 0xA4, 0xD1, 0xAC, 0xF2, +0x8C, 0x4F, 0xB5, 0x53, 0xB5, 0x52, 0xD6, 0x55, +0xBD, 0x93, 0xBD, 0x72, 0xBD, 0xD4, 0xC5, 0xF4, +0xB5, 0x52, 0x94, 0x6F, 0xB5, 0x73, 0xB5, 0x73, +0xA5, 0x35, 0xB5, 0xB7, 0x9D, 0x14, 0x9C, 0xF3, +0x8C, 0x91, 0x84, 0x70, 0x8C, 0x91, 0x94, 0xB1, +0x94, 0xB0, 0xA5, 0x52, 0xAD, 0x72, 0xAD, 0x52, +0xA5, 0x11, 0xBD, 0xB4, 0xBD, 0xD4, 0xBD, 0xB4, +0xBD, 0xB4, 0xAD, 0x52, 0xCE, 0x15, 0x9C, 0x6E, +0x94, 0x4D, 0xAD, 0x31, 0xAD, 0x53, 0xB5, 0x94, +0xBD, 0xB4, 0x9C, 0xF1, 0xB5, 0xB5, 0xAD, 0x74, +0xA5, 0x12, 0xBD, 0xD4, 0xB5, 0x73, 0xBD, 0xF5, +0xBD, 0xF5, 0xBD, 0xD5, 0xC5, 0xF5, 0xB5, 0xB4, +0xB5, 0x73, 0xB5, 0x73, 0xA5, 0x11, 0x94, 0xAF, +0xA5, 0x31, 0xB5, 0x93, 0xAD, 0x11, 0xAC, 0xF0, +0x8C, 0x2D, 0xB5, 0xB4, 0xBD, 0xF6, 0xBD, 0xF6, +0xB5, 0xD5, 0xC6, 0x36, 0xC6, 0x16, 0xB5, 0xD5, +0xB5, 0xB4, 0xBD, 0xF6, 0xBD, 0xF6, 0xC6, 0x16, +0xC6, 0x37, 0xCE, 0x57, 0x9C, 0xD1, 0xAD, 0x94, +0xCE, 0x98, 0xCE, 0x57, 0xD6, 0x78, 0xCE, 0x57, +0xCE, 0x37, 0xB5, 0x94, 0xAD, 0x32, 0xB5, 0x52, +0x73, 0x6C, 0x31, 0xA6, 0x39, 0xC6, 0x42, 0x07, +0x42, 0x07, 0x42, 0x07, 0x52, 0x8A, 0x63, 0x2C, +0x7B, 0xCF, 0x9C, 0xD3, 0xBD, 0xF7, 0xA5, 0x14, +0x6B, 0x4D, 0x73, 0xAF, 0xBD, 0xD7, 0xDE, 0xBA, +0xB5, 0x54, 0x63, 0x0B, 0xA4, 0xF1, 0xBD, 0xD4, +0xAD, 0x31, 0xB5, 0x72, 0x94, 0x4D, 0xB5, 0x51, +0x94, 0x4E, 0xAD, 0x32, 0xAD, 0x53, 0xB5, 0x94, +0xB5, 0x73, 0xAD, 0x52, 0x7B, 0xAD, 0x29, 0x24, +0x29, 0x45, 0x39, 0xC6, 0x42, 0x07, 0x5A, 0xAA, +0x8C, 0x51, 0xC5, 0xF7, 0x94, 0x51, 0x83, 0xAF, +0x6A, 0xCB, 0x9C, 0x51, 0xAC, 0xD3, 0x8B, 0xEF, +0x7B, 0x8E, 0x83, 0x8E, 0x8B, 0xEF, 0x83, 0xAD, +0xAD, 0x13, 0xCE, 0x37, 0x94, 0x4F, 0x83, 0x8C, +0x83, 0xAC, 0x73, 0x4A, 0x6B, 0x0A, 0x7B, 0x6B, +0x7B, 0x4A, 0x6A, 0xE9, 0x62, 0xC9, 0x52, 0x27, +0x4A, 0x27, 0x5A, 0x67, 0x6A, 0xE9, 0x8B, 0xCC, +0xC5, 0x92, 0xA4, 0x6D, 0x94, 0x2D, 0xA4, 0x8E, +0xAC, 0xF0, 0x9C, 0x8F, 0x84, 0x0E, 0x5A, 0xCA, +0x4A, 0x48, 0x5A, 0xEB, 0x9C, 0xB2, 0xCE, 0x59, +0x9C, 0xD3, 0x7B, 0xAD, 0x8B, 0xEC, 0xB5, 0x11, +0x7B, 0x6B, 0x83, 0x8B, 0x83, 0xAB, 0x83, 0xAC, +0x83, 0x8B, 0x83, 0xAC, 0x8B, 0xCC, 0x94, 0x0D, +0xA4, 0xB0, 0xAD, 0x12, 0xAD, 0x12, 0xB5, 0x32, +0xB5, 0x74, 0xBD, 0x94, 0xB5, 0x53, 0xB5, 0x73, +0xB5, 0x74, 0xBD, 0x94, 0xC5, 0xB5, 0xBD, 0x94, +0xBD, 0x94, 0xBD, 0x94, 0xBD, 0xB5, 0xBD, 0x94, +0xB5, 0x74, 0xBD, 0xB4, 0xB5, 0x74, 0xB5, 0x74, +0xB5, 0x74, 0xA5, 0x12, 0x9C, 0x90, 0x9C, 0xB0, +0x9C, 0x90, 0x9C, 0x90, 0x8C, 0x2F, 0x8C, 0x0E, +0x8C, 0x0E, 0x8C, 0x4F, 0x9C, 0xB1, 0x8C, 0x4F, +0x8C, 0x2E, 0x84, 0x0E, 0x7B, 0xCD, 0x83, 0xED, +0x84, 0x0E, 0x94, 0x6F, 0x94, 0x4F, 0x9C, 0xB0, +0xA5, 0x12, 0x9C, 0x90, 0x7B, 0x8C, 0xA5, 0x12, +0x9C, 0xD0, 0x9C, 0xB0, 0xAD, 0x32, 0xA5, 0x11, +0xB5, 0x52, 0xB5, 0x52, 0xB5, 0x73, 0xBD, 0x93, +0xC5, 0xD4, 0xCE, 0x35, 0xBD, 0x93, 0x94, 0x6F, +0xB5, 0x73, 0xCE, 0x15, 0xBD, 0xB4, 0xC5, 0xB4, +0xBD, 0xB4, 0xAD, 0x11, 0x94, 0x6F, 0x9C, 0x8F, +0x8C, 0x2E, 0xAD, 0x11, 0xA4, 0xF1, 0xA5, 0x12, +0xB5, 0x94, 0xAD, 0x74, 0xBD, 0xD5, 0xB5, 0x94, +0xBD, 0x94, 0xC5, 0x93, 0xBD, 0x52, 0xBD, 0x52, +0xDE, 0x15, 0xCD, 0x93, 0x83, 0x6B, 0xAC, 0xD1, +0x8C, 0x0E, 0xA4, 0xD0, 0xBD, 0x94, 0xBD, 0xB4, +0xCE, 0x36, 0xCE, 0x15, 0xBD, 0xD4, 0xAD, 0x32, +0x9C, 0xD1, 0xA4, 0xF1, 0xB5, 0x74, 0xB5, 0x94, +0xBD, 0xB5, 0xAD, 0x53, 0xA5, 0x12, 0xAD, 0x33, +0xBD, 0xB4, 0xB5, 0xB4, 0xB5, 0x94, 0xBD, 0xF5, +0xB5, 0x73, 0xA4, 0xF1, 0xA5, 0x11, 0x94, 0x4F, +0xB5, 0x53, 0xA4, 0xD1, 0xB5, 0x53, 0xAD, 0x32, +0x9C, 0x90, 0x9C, 0xB0, 0xA4, 0xF1, 0xAD, 0x12, +0xAD, 0x12, 0x9C, 0xB0, 0xC5, 0xD5, 0xB5, 0x73, +0xC6, 0x15, 0xB5, 0x93, 0xA4, 0xF1, 0x9C, 0xB0, +0xA4, 0xF1, 0xAD, 0x11, 0x9C, 0x6F, 0xBD, 0x72, +0xC5, 0xB3, 0xC5, 0xB3, 0x9C, 0x8F, 0xAD, 0x12, +0xAD, 0x11, 0x9C, 0xB0, 0x94, 0x4F, 0x73, 0x8C, +0x94, 0x6F, 0xC5, 0xD4, 0xBD, 0x73, 0xAD, 0x12, +0xAD, 0x33, 0xA4, 0xD1, 0x94, 0x6F, 0xAD, 0x32, +0xA5, 0x32, 0xAD, 0x94, 0xCE, 0x57, 0xBD, 0xD5, +0xBD, 0xB4, 0xAD, 0x33, 0xC6, 0x16, 0xC6, 0x35, +0xC6, 0x15, 0xAD, 0x32, 0x9C, 0x90, 0xB5, 0x73, +0xA5, 0x12, 0xBD, 0x93, 0xC5, 0xB3, 0xD6, 0x55, +0xCE, 0x14, 0xA4, 0xAF, 0xC5, 0xD4, 0xCE, 0x55, +0xC5, 0xF4, 0xAD, 0x31, 0xBD, 0xD4, 0xC6, 0x35, +0xA5, 0x35, 0xB5, 0x97, 0xA5, 0x34, 0x9C, 0xF4, +0x8C, 0x92, 0x8C, 0x90, 0x94, 0xB1, 0x9C, 0xF2, +0x9D, 0x12, 0xB5, 0x94, 0xB5, 0x93, 0xB5, 0x93, +0xB5, 0xB4, 0xC6, 0x36, 0xBD, 0xB4, 0xC6, 0x15, +0xC6, 0x15, 0xBD, 0xD4, 0xCE, 0x36, 0x9C, 0x4D, +0xB5, 0x31, 0xC5, 0xF4, 0xBD, 0xD4, 0xB5, 0xB4, +0xBD, 0xF5, 0xAD, 0x73, 0xC6, 0x37, 0xB5, 0xB5, +0x9D, 0x12, 0xC6, 0x36, 0xBD, 0xD5, 0xC6, 0x15, +0xC6, 0x16, 0xC6, 0x16, 0xC6, 0x36, 0xC6, 0x16, +0xC5, 0xF5, 0xC5, 0xF5, 0xAD, 0x32, 0xB5, 0x93, +0xBD, 0xF5, 0xCE, 0x35, 0x9C, 0x8F, 0xAC, 0xF0, +0x8C, 0x2D, 0xAD, 0x74, 0xB5, 0xB5, 0xBD, 0xF6, +0xC6, 0x16, 0xCE, 0x57, 0xBD, 0xF6, 0xBD, 0xF6, +0xB5, 0xD5, 0xB5, 0x94, 0xB5, 0xB5, 0xBD, 0xD5, +0xC6, 0x36, 0xBD, 0xF6, 0x9C, 0xF2, 0xBE, 0x16, +0xAD, 0x74, 0xCE, 0x57, 0xCE, 0x57, 0xCE, 0x57, +0xC6, 0x16, 0xBD, 0xB5, 0xAD, 0x32, 0xB5, 0x52, +0xAD, 0x32, 0x63, 0x2B, 0x42, 0x07, 0x42, 0x07, +0x4A, 0x48, 0x52, 0xAA, 0x63, 0x2C, 0x63, 0x0C, +0x6B, 0x2C, 0x84, 0x30, 0x9C, 0xD3, 0xA5, 0x14, +0x94, 0xB3, 0xAD, 0x56, 0xAD, 0x76, 0xCE, 0x59, +0xBD, 0xB7, 0x21, 0x05, 0x63, 0x2C, 0xC6, 0x36, +0xC5, 0xF4, 0xD6, 0x56, 0xA4, 0xAF, 0xB5, 0x51, +0xA4, 0xD0, 0xBD, 0xF5, 0xBD, 0xD5, 0xC5, 0xF5, +0xB5, 0x94, 0xAD, 0x52, 0xAD, 0x32, 0x73, 0x8C, +0x18, 0xC3, 0x39, 0xC6, 0x31, 0xA6, 0x6B, 0x4D, +0x9C, 0xD3, 0x7B, 0xAE, 0x94, 0x92, 0xD6, 0x59, +0xB5, 0x34, 0x72, 0xEC, 0x94, 0x30, 0x49, 0xE7, +0x52, 0x28, 0x83, 0x8D, 0xA4, 0xD2, 0xCD, 0xF6, +0x83, 0xCE, 0xAD, 0x13, 0xCE, 0x16, 0x9C, 0x90, +0x8C, 0x0E, 0x94, 0x2E, 0x8C, 0x2E, 0x8C, 0x2E, +0x94, 0x2E, 0x8C, 0x0E, 0x8C, 0x0E, 0x83, 0xEE, +0x83, 0xCD, 0x83, 0xAD, 0x6B, 0x0A, 0x6B, 0x0A, +0xBD, 0x72, 0x8B, 0xEB, 0x7B, 0xAB, 0x94, 0x4E, +0x9C, 0x4E, 0x8B, 0xEC, 0x94, 0x8F, 0x94, 0x6F, +0x6B, 0x4B, 0x39, 0xE7, 0x73, 0x8E, 0xA5, 0x35, +0x94, 0x92, 0x8C, 0x2E, 0x83, 0x8B, 0xB5, 0x31, +0x9C, 0x4E, 0x94, 0x4E, 0x94, 0x4E, 0x8B, 0xED, +0x7B, 0x8B, 0x8C, 0x0D, 0x94, 0x4E, 0x94, 0x4E, +0xA4, 0xD1, 0xB5, 0x53, 0x9C, 0x8F, 0xA4, 0xD0, +0xAD, 0x11, 0xBD, 0x93, 0xA4, 0xD1, 0xBD, 0xB4, +0xBD, 0xB4, 0x94, 0x70, 0x94, 0x4F, 0x9C, 0x90, +0xAD, 0x12, 0x9C, 0x90, 0x7B, 0x8D, 0x73, 0x6C, +0x83, 0xCD, 0x83, 0xEE, 0x9C, 0x90, 0xAD, 0x12, +0x94, 0x4F, 0xA4, 0xF1, 0x9C, 0xB0, 0x94, 0x6F, +0x9C, 0xD1, 0xAD, 0x12, 0xB5, 0x73, 0xBD, 0x94, +0xBD, 0x94, 0xB5, 0x53, 0xB5, 0x53, 0xB5, 0x53, +0xAD, 0x12, 0xB5, 0x53, 0xA4, 0xF1, 0xA4, 0xF1, +0xAD, 0x32, 0xA4, 0xF1, 0xAD, 0x32, 0xB5, 0x53, +0xAD, 0x12, 0xAD, 0x12, 0xB5, 0x53, 0xBD, 0x94, +0xA4, 0xD1, 0xA4, 0xF1, 0xB5, 0x53, 0xAD, 0x12, +0xAD, 0x12, 0xB5, 0x53, 0xAD, 0x32, 0xB5, 0x33, +0xAD, 0x32, 0xB5, 0x52, 0xAD, 0x32, 0xBD, 0xB4, +0xB5, 0x52, 0xAD, 0x12, 0xB5, 0x53, 0xBD, 0x73, +0xB5, 0x32, 0xAD, 0x12, 0xAD, 0x32, 0xA4, 0xD1, +0x9C, 0x8F, 0xA4, 0xD0, 0x9C, 0x8F, 0xA4, 0xD1, +0x8C, 0x2F, 0x94, 0x91, 0x94, 0x70, 0x9C, 0xD1, +0x9C, 0x90, 0xAC, 0xD1, 0xAC, 0xF1, 0xAC, 0xD0, +0xAC, 0xF0, 0x9C, 0x2E, 0x7B, 0x2A, 0xAC, 0xF1, +0x83, 0xAC, 0x9C, 0xB0, 0xAD, 0x32, 0xC6, 0x15, +0xBD, 0xD4, 0xC5, 0xF4, 0xBD, 0xD4, 0xBD, 0xD5, +0xBD, 0xD4, 0xB5, 0x94, 0xB5, 0x94, 0xB5, 0x94, +0xB5, 0xB4, 0xBD, 0xB5, 0xBD, 0xD5, 0xC5, 0xF5, +0xC6, 0x15, 0xC6, 0x15, 0xC6, 0x15, 0xC5, 0xF5, +0xAD, 0x32, 0xB5, 0x53, 0x9C, 0xD0, 0x8C, 0x2E, +0xAD, 0x52, 0x8C, 0x0E, 0xCE, 0x36, 0x9C, 0xB0, +0x94, 0x6F, 0x83, 0xED, 0xA4, 0xF1, 0xA4, 0xF1, +0x94, 0x6F, 0x9C, 0x90, 0xBD, 0xB4, 0xBD, 0xB4, +0xC5, 0xF4, 0xA5, 0x11, 0x8C, 0x2E, 0xA4, 0xF1, +0xAC, 0xF1, 0xB5, 0x52, 0xAC, 0xF0, 0xB5, 0x11, +0xBD, 0x72, 0xAC, 0xF0, 0xA4, 0xD0, 0xB5, 0x73, +0xB5, 0x53, 0x9C, 0xB0, 0x9C, 0xB1, 0x8C, 0x0E, +0x9C, 0xB0, 0xCE, 0x36, 0xC5, 0xF5, 0xB5, 0x73, +0xB5, 0x53, 0xB5, 0x73, 0xBD, 0xD5, 0xB5, 0x94, +0xA4, 0xF2, 0xA5, 0x33, 0xC6, 0x16, 0xC6, 0x16, +0xCE, 0x36, 0xA5, 0x32, 0xBD, 0xD5, 0xC6, 0x15, +0xCE, 0x15, 0xC5, 0xD5, 0xA4, 0xD1, 0xB5, 0xB4, +0xAD, 0x33, 0xB5, 0x73, 0xCD, 0xF4, 0xCE, 0x14, +0xBD, 0xB2, 0x9C, 0xAF, 0xCE, 0x14, 0xCE, 0x35, +0xB5, 0x52, 0xBD, 0xB3, 0xBD, 0xD4, 0xCE, 0x56, +0xA5, 0x35, 0xB5, 0xB7, 0x9D, 0x14, 0x9C, 0xF4, +0x7B, 0xEF, 0x5A, 0xC9, 0x63, 0x09, 0x6B, 0x2A, +0x6B, 0x4A, 0x73, 0x8B, 0x73, 0x8B, 0x83, 0xCC, +0x83, 0xEC, 0x83, 0xED, 0x7B, 0x6B, 0x83, 0xED, +0x83, 0xED, 0x7B, 0x8C, 0x7B, 0x8C, 0x83, 0xAB, +0x7B, 0x8A, 0x7B, 0x8B, 0x8C, 0x0D, 0x7B, 0xAC, +0x7B, 0xAC, 0x94, 0x6F, 0xA4, 0xF1, 0x94, 0xB0, +0x94, 0xB0, 0xB5, 0x73, 0xAD, 0x73, 0xB5, 0xB4, +0xBD, 0xD4, 0xC5, 0xF5, 0xCE, 0x36, 0xD6, 0x77, +0xCE, 0x57, 0xCE, 0x57, 0xAD, 0x32, 0x9C, 0xB0, +0xBD, 0xB4, 0xC5, 0xD4, 0x83, 0xAC, 0xAC, 0xD0, +0x94, 0x8F, 0xBD, 0xF5, 0xC6, 0x16, 0xC6, 0x37, +0xC6, 0x16, 0xCE, 0x57, 0xCE, 0x57, 0xC6, 0x16, +0xC6, 0x16, 0xBD, 0xD5, 0xB5, 0xB4, 0xBD, 0xF6, +0xCE, 0x57, 0xCE, 0x98, 0xA5, 0x12, 0xCE, 0x57, +0xBD, 0xF6, 0xC6, 0x37, 0xD6, 0x78, 0xD6, 0x98, +0xCE, 0x77, 0xC5, 0xF5, 0xAD, 0x11, 0xBD, 0x92, +0x9C, 0xAF, 0x94, 0x70, 0x52, 0x89, 0x4A, 0x69, +0x52, 0x89, 0x84, 0x10, 0x7B, 0xAE, 0x52, 0x8A, +0x5A, 0xEB, 0x73, 0x8E, 0x94, 0x92, 0xB5, 0xB6, +0x9C, 0xD3, 0xB5, 0xB7, 0xB5, 0xB7, 0xB5, 0xB7, +0xC6, 0x18, 0x84, 0x10, 0x6B, 0x4D, 0xC6, 0x37, +0x9C, 0xD1, 0xC5, 0xF5, 0xA4, 0xF0, 0xB5, 0x31, +0xAD, 0x52, 0xC6, 0x16, 0xBD, 0xB5, 0xC5, 0xF5, +0xB5, 0x73, 0x8C, 0x4E, 0x8C, 0x2E, 0x94, 0x90, +0x31, 0x65, 0x21, 0x04, 0x31, 0x86, 0x42, 0x08, +0x4A, 0x28, 0x31, 0x86, 0x39, 0xA7, 0x84, 0x10, +0xDE, 0x9A, 0x8C, 0x10, 0x4A, 0x08, 0x41, 0xE7, +0x94, 0x2F, 0xAC, 0xF2, 0x94, 0x0F, 0xC5, 0xD6, +0xBD, 0x94, 0xBD, 0x74, 0x9C, 0x91, 0xCE, 0x16, +0xBD, 0x94, 0x9C, 0x90, 0xA4, 0xB0, 0xA4, 0xF1, +0xAD, 0x32, 0x9C, 0x90, 0x8B, 0xED, 0x8C, 0x0E, +0x94, 0x2E, 0x8C, 0x2F, 0x83, 0xCD, 0x8C, 0x0E, +0xBD, 0x31, 0xAC, 0xF0, 0xAD, 0x11, 0xBD, 0xB3, +0xB5, 0x72, 0xAD, 0x52, 0xAD, 0x52, 0xB5, 0x73, +0xAD, 0x32, 0x6B, 0x4C, 0x63, 0x0C, 0x8C, 0x51, +0x94, 0x71, 0x9C, 0x90, 0x83, 0xAB, 0xBD, 0x51, +0xAC, 0xCF, 0x8C, 0x0D, 0x7B, 0xAB, 0x7B, 0xAB, +0x6B, 0x09, 0x83, 0xEC, 0x7B, 0x8B, 0x8C, 0x0E, +0xA4, 0xF1, 0xA4, 0xF1, 0x7B, 0x8C, 0x9C, 0x90, +0xA4, 0xD0, 0x9C, 0xAF, 0xAD, 0x32, 0xC5, 0xF5, +0xCE, 0x36, 0xA5, 0x12, 0x83, 0xCD, 0x9C, 0xB0, +0x9C, 0xB0, 0x8C, 0x4F, 0x7B, 0xAD, 0x83, 0xEE, +0x83, 0xCD, 0x83, 0xEE, 0xB5, 0x73, 0xCE, 0x36, +0xAD, 0x32, 0xB5, 0x73, 0xBD, 0x94, 0xB5, 0x53, +0x94, 0x4F, 0x94, 0x6F, 0x94, 0x6F, 0xA4, 0xD1, +0xA4, 0xF1, 0xA4, 0xD0, 0xAD, 0x32, 0xB5, 0x53, +0xAD, 0x32, 0xB5, 0x32, 0xAD, 0x32, 0xB5, 0x52, +0xAD, 0x32, 0xB5, 0x94, 0xBD, 0xB4, 0xBD, 0xB4, +0xB5, 0x74, 0xB5, 0x93, 0xB5, 0x53, 0xB5, 0x73, +0x9C, 0xB0, 0x94, 0x6F, 0x9C, 0xB1, 0xAD, 0x32, +0xAD, 0x12, 0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x32, +0xB5, 0x53, 0xB5, 0x53, 0xB5, 0x53, 0xBD, 0x94, +0xC5, 0xB4, 0xBD, 0xB4, 0xBD, 0x94, 0xC5, 0xB4, +0xC5, 0xD5, 0xC5, 0xD5, 0xC5, 0xD5, 0xC5, 0xF5, +0xC5, 0xD5, 0xCE, 0x15, 0xC5, 0xD4, 0xBD, 0x94, +0xBD, 0x94, 0xBD, 0x94, 0xBD, 0x74, 0xBD, 0x74, +0xBD, 0x74, 0xC5, 0x94, 0xBD, 0x73, 0xBD, 0x72, +0xBD, 0x73, 0xB5, 0x32, 0xB5, 0x12, 0xBD, 0x94, +0x9C, 0x6F, 0x8C, 0x0E, 0x94, 0x6F, 0xA4, 0xD0, +0x94, 0x2E, 0x9C, 0x90, 0xA4, 0xD0, 0xA4, 0xD0, +0xAD, 0x12, 0xAD, 0x32, 0xAD, 0x53, 0xA5, 0x12, +0xAD, 0x32, 0xB5, 0x73, 0xB5, 0x73, 0xBD, 0x94, +0xB5, 0x73, 0xB5, 0x73, 0xC5, 0xD5, 0xBD, 0xB4, +0xBD, 0x93, 0xB5, 0x73, 0x94, 0x6F, 0x84, 0x0E, +0xA4, 0xF1, 0xA4, 0xD1, 0xAD, 0x32, 0x94, 0x4F, +0x9C, 0xB1, 0x9C, 0x90, 0x83, 0xED, 0x9C, 0xB1, +0x8C, 0x2E, 0x8C, 0x2E, 0xB5, 0x53, 0xAC, 0xF1, +0xBD, 0x93, 0x83, 0xED, 0x5A, 0xA9, 0x94, 0x4F, +0x94, 0x4E, 0x9C, 0x6F, 0xA4, 0x8F, 0xA4, 0xAF, +0x9C, 0x6E, 0x9C, 0x4E, 0xA4, 0xD0, 0xB5, 0x32, +0xB5, 0x53, 0x9C, 0x90, 0xB5, 0x53, 0x9C, 0xB0, +0x94, 0x6F, 0xCE, 0x36, 0xD6, 0x56, 0xBD, 0xB4, +0xB5, 0x53, 0xAD, 0x33, 0xBD, 0xB4, 0xB5, 0x94, +0xAD, 0x33, 0xAD, 0x73, 0xCE, 0x57, 0xD6, 0x77, +0xCE, 0x56, 0xAD, 0x53, 0xBD, 0xB4, 0xC5, 0xF5, +0xC5, 0xD4, 0xC5, 0xD4, 0xAD, 0x12, 0xBD, 0xD5, +0xAD, 0x32, 0xB5, 0x73, 0xC5, 0xB3, 0xD6, 0x14, +0xBD, 0x72, 0x9C, 0xAF, 0xCE, 0x55, 0xD6, 0x75, +0xAD, 0x31, 0xA4, 0xF0, 0xBD, 0xB3, 0xC5, 0xF4, +0xA5, 0x35, 0xB5, 0xB7, 0x9D, 0x14, 0x94, 0xF3, +0x7C, 0x10, 0x62, 0xCA, 0x62, 0xE9, 0x6B, 0x0A, +0x73, 0x6B, 0x83, 0xAC, 0x8B, 0xEC, 0x8B, 0xCC, +0x94, 0x2E, 0x9C, 0x6E, 0xA4, 0x8F, 0x9C, 0x6E, +0xA4, 0x8F, 0xA4, 0xAF, 0xAC, 0xF0, 0xB5, 0x10, +0xAD, 0x10, 0xAC, 0xD0, 0xA4, 0xAF, 0xAC, 0xF0, +0xAC, 0xF0, 0xAC, 0xD0, 0xA4, 0x8F, 0x9C, 0x6D, +0x9C, 0x6E, 0x9C, 0x8E, 0x9C, 0x4E, 0x94, 0x0D, +0x94, 0x0C, 0x93, 0xEC, 0x8C, 0x0C, 0x94, 0x0D, +0x8B, 0xEC, 0x83, 0xCC, 0x83, 0xAB, 0x83, 0xAB, +0x7B, 0x8B, 0x7B, 0x6A, 0x94, 0x2D, 0xAC, 0xCF, +0x94, 0x4D, 0xAD, 0x32, 0xAD, 0x53, 0xAD, 0x32, +0xA4, 0xF1, 0xB5, 0x73, 0xB5, 0x93, 0xAD, 0x53, +0xA5, 0x11, 0xA4, 0xF1, 0x94, 0x4F, 0x94, 0x6F, +0xAD, 0x53, 0xCE, 0x77, 0xBD, 0xB4, 0xD6, 0x98, +0xD6, 0xB8, 0xD6, 0x98, 0xD6, 0x77, 0xCE, 0x77, +0xC6, 0x36, 0xCE, 0x16, 0x9C, 0x8F, 0xB5, 0x31, +0xBD, 0x93, 0xC5, 0xD5, 0x94, 0x70, 0x4A, 0x69, +0x39, 0xE7, 0x52, 0x89, 0x52, 0x69, 0x42, 0x07, +0x5A, 0xAA, 0x6B, 0x4C, 0x84, 0x10, 0x8C, 0x30, +0x9C, 0xF4, 0xAD, 0x56, 0xB5, 0x96, 0xA5, 0x35, +0xC6, 0x18, 0xD6, 0x7A, 0x9C, 0xD3, 0xC6, 0x17, +0x94, 0x70, 0x73, 0x8D, 0xA4, 0xD0, 0xB5, 0x52, +0xB5, 0x93, 0xBD, 0xD5, 0xBD, 0xD5, 0xC5, 0xF5, +0xBD, 0xB4, 0xA5, 0x12, 0xB5, 0x73, 0xB5, 0x73, +0x94, 0x90, 0x39, 0x85, 0x42, 0x07, 0x39, 0xC6, +0x4A, 0x28, 0x4A, 0x49, 0x42, 0x08, 0x4A, 0x29, +0xA4, 0xF4, 0xAD, 0x55, 0x83, 0xAE, 0x7B, 0x8D, +0xBD, 0x53, 0xCD, 0xB5, 0xD6, 0x37, 0xDE, 0x78, +0xDE, 0x58, 0xC5, 0x74, 0xB5, 0x33, 0x8C, 0x0F, +0xBD, 0x94, 0xAC, 0xF1, 0x9C, 0x8F, 0xA4, 0xD0, +0xB5, 0x52, 0xA4, 0xD1, 0x8C, 0x0E, 0x8B, 0xCE, +0x94, 0x4F, 0x8C, 0x0E, 0x83, 0xCD, 0xA4, 0xAF, +0xB5, 0x30, 0xB5, 0x11, 0xBD, 0xB3, 0xBD, 0xB3, +0xBD, 0xB3, 0xC5, 0xD4, 0xBD, 0xB4, 0xBD, 0x93, +0xBD, 0xB4, 0xA4, 0xF2, 0x8C, 0x72, 0x8C, 0x51, +0x94, 0x71, 0x94, 0x2E, 0x73, 0x29, 0xBD, 0x51, +0x94, 0x0D, 0x83, 0xCC, 0x83, 0xCC, 0x8C, 0x0E, +0x7B, 0xAC, 0x8C, 0x4E, 0x84, 0x0D, 0x94, 0x6F, +0xA5, 0x11, 0x9C, 0xB0, 0x7B, 0xCD, 0x9C, 0x90, +0xAD, 0x11, 0x8C, 0x2E, 0xA4, 0xD1, 0xBD, 0xD5, +0xC5, 0xF5, 0x9C, 0xB1, 0x63, 0x0A, 0x9C, 0xD1, +0x8C, 0x2E, 0x6B, 0x4B, 0x83, 0xED, 0x83, 0xED, +0x83, 0xCD, 0x83, 0xED, 0x9C, 0x90, 0x9C, 0xB0, +0xA4, 0xF1, 0xAD, 0x11, 0xB5, 0x52, 0xB5, 0x52, +0x94, 0x70, 0x9C, 0x90, 0x8C, 0x0E, 0x83, 0xED, +0x9C, 0x8F, 0x94, 0x6E, 0xA4, 0xD0, 0xAD, 0x11, +0xA4, 0xD0, 0xAD, 0x11, 0xAD, 0x31, 0xAD, 0x11, +0x9C, 0xAF, 0xA4, 0xF1, 0xBD, 0x93, 0xBD, 0x93, +0xB5, 0x73, 0xAD, 0x32, 0xAD, 0x31, 0xB5, 0x52, +0xB5, 0x52, 0xA5, 0x11, 0xAD, 0x32, 0x9C, 0x6F, +0x94, 0x6F, 0xB5, 0x53, 0xD6, 0x56, 0xCE, 0x15, +0xC5, 0xD4, 0xAD, 0x32, 0x94, 0x4F, 0x73, 0x6B, +0x73, 0x4B, 0x6B, 0x2B, 0x7B, 0x8C, 0x84, 0x0D, +0x9C, 0x90, 0x94, 0x6F, 0x84, 0x0D, 0x83, 0xCD, +0x8C, 0x0E, 0x8C, 0x0D, 0x8C, 0x0E, 0x94, 0x2E, +0x94, 0x4F, 0x8C, 0x0E, 0x94, 0x2F, 0x8C, 0x0E, +0xA4, 0xB0, 0xBD, 0x73, 0xAC, 0xF1, 0xAD, 0x11, +0xBD, 0x53, 0xBD, 0x73, 0xC5, 0xD4, 0xC5, 0xD4, +0xCD, 0xD5, 0xCD, 0xF5, 0xCD, 0xF5, 0xCD, 0xF6, +0xCE, 0x16, 0xCD, 0xF5, 0xC5, 0xD5, 0xCD, 0xF5, +0xC5, 0xD5, 0xC5, 0xB4, 0xC5, 0xD5, 0xB5, 0x53, +0xAC, 0xF1, 0xBD, 0x73, 0xB5, 0x53, 0xAD, 0x12, +0xB5, 0x53, 0xB5, 0x73, 0xBD, 0x73, 0xC5, 0xB4, +0xAC, 0xF1, 0xA4, 0xD1, 0x9C, 0x90, 0xAD, 0x12, +0xB5, 0x33, 0xAC, 0xF2, 0xAD, 0x12, 0xA4, 0xD1, +0x9C, 0xB0, 0xAD, 0x12, 0x9C, 0x90, 0xA4, 0xD1, +0x9C, 0x90, 0x94, 0x4F, 0xAD, 0x32, 0xB5, 0x52, +0xBD, 0x93, 0x73, 0x6C, 0x6B, 0x2B, 0x9C, 0xB0, +0xAD, 0x32, 0x94, 0x4E, 0x83, 0xAC, 0x94, 0x0E, +0x8C, 0x0D, 0x83, 0xAC, 0x9C, 0x6F, 0x94, 0x4E, +0xAD, 0x12, 0x9C, 0xD0, 0xAD, 0x32, 0x73, 0x8C, +0x6B, 0x0A, 0xA5, 0x11, 0xCE, 0x15, 0xCE, 0x15, +0xB5, 0x94, 0xB5, 0x94, 0xBD, 0xB4, 0xBD, 0xD5, +0xB5, 0xB5, 0xB5, 0xB5, 0xCE, 0x57, 0xCE, 0x56, +0xCE, 0x36, 0xC5, 0xD4, 0xAD, 0x32, 0xBD, 0xD4, +0xBD, 0xD4, 0xBD, 0xB4, 0xAD, 0x32, 0xC5, 0xD5, +0xA5, 0x12, 0xB5, 0x53, 0xBD, 0x52, 0xCE, 0x14, +0xD6, 0x35, 0x9C, 0x8F, 0xC6, 0x14, 0xC5, 0xF4, +0xA4, 0xD0, 0x94, 0x8F, 0xC5, 0xF5, 0xC6, 0x15, +0xA5, 0x35, 0xB5, 0xB7, 0x9D, 0x14, 0x94, 0xD3, +0x73, 0xAE, 0x63, 0x0B, 0x63, 0x2B, 0x63, 0x0A, +0x52, 0x68, 0x5A, 0x88, 0x5A, 0xA8, 0x52, 0x68, +0x5A, 0xC9, 0x63, 0x0A, 0x5A, 0xA9, 0x52, 0x47, +0x73, 0x4B, 0x8B, 0xED, 0x94, 0x6E, 0x8B, 0xED, +0x83, 0xAB, 0x83, 0xAB, 0x8B, 0xCC, 0x94, 0x0D, +0x9C, 0x2D, 0x9C, 0x4D, 0xAC, 0xEF, 0xAC, 0xCF, +0xA4, 0x8E, 0x9C, 0x4D, 0x8B, 0xCB, 0x8B, 0xAB, +0x94, 0x0D, 0xA4, 0x6E, 0x9C, 0x6D, 0xA4, 0x8E, +0xAC, 0xAF, 0xAC, 0xCF, 0xBD, 0x10, 0xBD, 0x30, +0xBD, 0x30, 0xBD, 0x51, 0xC5, 0x51, 0xBD, 0x50, +0xB5, 0x30, 0xB5, 0x10, 0xB4, 0xF0, 0xAC, 0xCF, +0xA4, 0x8E, 0x9C, 0x6E, 0x9C, 0x6E, 0xA4, 0xAE, +0xA4, 0xAE, 0x9C, 0x6E, 0xA4, 0x8E, 0xA4, 0xAF, +0x9C, 0x6E, 0x9C, 0x6E, 0x9C, 0x6E, 0x9C, 0x8F, +0x9C, 0x6E, 0xA4, 0xAF, 0xA4, 0xD0, 0xA4, 0xAF, +0x9C, 0x8F, 0x94, 0x4D, 0x9C, 0x4D, 0xBD, 0x31, +0xA4, 0xAF, 0x9C, 0x8F, 0x7B, 0x8C, 0x52, 0x68, +0x29, 0x45, 0x29, 0x45, 0x39, 0xA6, 0x42, 0x08, +0x52, 0x69, 0x5A, 0xCB, 0x4A, 0x49, 0x5A, 0xCB, +0x8C, 0x71, 0xAD, 0x35, 0xA5, 0x35, 0x9C, 0xF4, +0xBD, 0xB7, 0xD6, 0x9A, 0xB5, 0xB6, 0xBD, 0xF7, +0xAD, 0x54, 0x5A, 0x8A, 0x94, 0x6F, 0xB5, 0x73, +0xC6, 0x16, 0xC6, 0x16, 0xC6, 0x16, 0xC5, 0xF5, +0xBD, 0xD4, 0xCE, 0x76, 0xD6, 0x97, 0xD6, 0x76, +0xC5, 0xD4, 0xA4, 0xD1, 0x39, 0xC6, 0x21, 0x03, +0x39, 0xA6, 0x52, 0xAA, 0x31, 0x86, 0x21, 0x24, +0x4A, 0x49, 0x4A, 0x49, 0x73, 0x6D, 0x9C, 0x50, +0x83, 0xAD, 0xAC, 0xD2, 0xBD, 0x54, 0xD6, 0x17, +0xDE, 0x58, 0xD6, 0x37, 0xBD, 0x74, 0x7B, 0x8D, +0x94, 0x50, 0xC5, 0xB5, 0xC5, 0xD5, 0xA4, 0xB0, +0xA4, 0xD0, 0xAD, 0x11, 0x9C, 0x6F, 0x9C, 0x6F, +0x9C, 0x6F, 0x9C, 0x6F, 0x8B, 0xED, 0xA4, 0x8F, +0xBD, 0x51, 0xB5, 0x51, 0xC5, 0xD3, 0xC5, 0xF4, +0xCE, 0x14, 0xCE, 0x55, 0xC6, 0x15, 0xBD, 0xF4, +0xBD, 0xD4, 0xB5, 0x95, 0xA5, 0x35, 0x9C, 0xD3, +0x8C, 0x50, 0x6B, 0x2B, 0x73, 0x0A, 0xBD, 0x51, +0x8B, 0xCC, 0x7B, 0x8B, 0x7B, 0xAC, 0x8C, 0x0D, +0x8C, 0x0D, 0x94, 0x4F, 0x94, 0x6F, 0x9C, 0x8F, +0xA5, 0x12, 0x9C, 0xB0, 0x83, 0xEE, 0x94, 0x8F, +0xAD, 0x32, 0x8C, 0x2E, 0xA4, 0xF1, 0xB5, 0x94, +0xBD, 0xD4, 0xA4, 0xF2, 0x63, 0x0A, 0xAD, 0x53, +0x94, 0x90, 0x83, 0xEE, 0x94, 0x70, 0x94, 0x70, +0x83, 0xED, 0x84, 0x0E, 0x94, 0x6F, 0xA4, 0xD0, +0xAD, 0x11, 0xAD, 0x32, 0xB5, 0x72, 0xB5, 0x52, +0x94, 0x70, 0x9C, 0x90, 0x7B, 0xAC, 0x73, 0x6C, +0x9C, 0x8F, 0x94, 0x2D, 0xA4, 0xB0, 0xB5, 0x52, +0x9C, 0x6E, 0x94, 0x6E, 0x9C, 0x6E, 0x9C, 0x6E, +0x8C, 0x2E, 0xA4, 0xD0, 0xA4, 0xD0, 0xB5, 0x52, +0xAD, 0x11, 0x9C, 0x6F, 0xA4, 0xD0, 0x94, 0x2D, +0x8C, 0x0D, 0x8C, 0x2D, 0x83, 0xEC, 0x8C, 0x0D, +0x94, 0x4F, 0xAD, 0x32, 0xAD, 0x32, 0x83, 0xED, +0xA4, 0xD1, 0xBD, 0x94, 0xAD, 0x32, 0x8C, 0x4F, +0x63, 0x2B, 0x6B, 0x4C, 0x8C, 0x2E, 0x9C, 0xD1, +0xAD, 0x32, 0x9C, 0xB0, 0xAD, 0x53, 0xA5, 0x12, +0x9C, 0xB0, 0x7B, 0xCD, 0x7B, 0xAC, 0x94, 0x4F, +0x9C, 0xB0, 0x94, 0x4F, 0x6B, 0x0A, 0x7B, 0x8C, +0x94, 0x2E, 0xBD, 0x73, 0xB5, 0x32, 0xBD, 0x73, +0x8C, 0x0E, 0x7B, 0x6B, 0x83, 0xCD, 0xA4, 0xD1, +0x8C, 0x0E, 0x8B, 0xED, 0x8C, 0x2E, 0x94, 0x4E, +0x94, 0x4E, 0x94, 0x2E, 0x94, 0x4F, 0x9C, 0x90, +0x9C, 0x90, 0x9C, 0xB0, 0xA4, 0xD1, 0xA4, 0xB0, +0x9C, 0x6F, 0xA4, 0xD0, 0xA4, 0xD1, 0x9C, 0x90, +0xA4, 0xB0, 0xBD, 0x53, 0xB5, 0x32, 0xB5, 0x52, +0xBD, 0x93, 0xBD, 0x93, 0xB5, 0x32, 0xB5, 0x32, +0xBD, 0x94, 0xC5, 0xB4, 0xC5, 0xB4, 0xC5, 0xD4, +0xC5, 0xB4, 0xCD, 0xF5, 0xC5, 0xF5, 0xC5, 0xD5, +0xCE, 0x15, 0xC5, 0xD4, 0xB5, 0x53, 0xB5, 0x53, +0xBD, 0xB4, 0xB5, 0x53, 0xBD, 0xB4, 0xB5, 0x73, +0xA4, 0xF1, 0xA4, 0xB0, 0x9C, 0xB0, 0x94, 0x6F, +0x94, 0x4F, 0x8C, 0x0E, 0x8C, 0x2E, 0x94, 0x2E, +0xA4, 0xD1, 0x9C, 0x90, 0x9C, 0x90, 0x94, 0x70, +0x9C, 0x90, 0x9C, 0xB0, 0xA4, 0xF0, 0xAD, 0x32, +0xB5, 0x53, 0xBD, 0xB4, 0xC5, 0xF5, 0xBD, 0xD5, +0xB5, 0x94, 0xBD, 0xD5, 0xBD, 0xD5, 0xCE, 0x77, +0xD6, 0x76, 0xC5, 0xF5, 0xC5, 0xF5, 0xCE, 0x35, +0xCE, 0x35, 0xC5, 0xD5, 0xC5, 0xD5, 0xC6, 0x15, +0x9C, 0x90, 0xB5, 0x73, 0xC5, 0xB3, 0xDE, 0x55, +0xDE, 0x76, 0x9C, 0x8F, 0xC5, 0xD4, 0xB5, 0x92, +0x9C, 0xAF, 0x9C, 0x8F, 0xCE, 0x35, 0xCE, 0x35, +0xA5, 0x55, 0xAD, 0x96, 0x9D, 0x14, 0x94, 0xD3, +0x7B, 0xEF, 0x84, 0x0F, 0x94, 0x90, 0x8C, 0x4F, +0x52, 0x88, 0x6B, 0x4B, 0x73, 0x8C, 0x6B, 0x2B, +0x73, 0x8C, 0x6B, 0x4B, 0x52, 0x88, 0x6B, 0x4B, +0x73, 0x6C, 0x8C, 0x4F, 0x9C, 0xD0, 0x73, 0x8C, +0x6B, 0x0A, 0x62, 0xC9, 0x73, 0x8C, 0xAD, 0x32, +0xB5, 0x32, 0xA4, 0x8F, 0xAC, 0xAF, 0xA4, 0x6E, +0xB4, 0xF0, 0xC5, 0x72, 0xBD, 0x92, 0xB5, 0x51, +0xAC, 0xF0, 0x94, 0x4E, 0x83, 0xCC, 0x8B, 0xCC, +0x8B, 0xEC, 0x8B, 0xCB, 0x8B, 0xCB, 0x8B, 0xEB, +0x8B, 0xCB, 0x83, 0xAA, 0x83, 0x6A, 0x7B, 0x6A, +0x83, 0x8A, 0x9C, 0x4E, 0xB5, 0x10, 0xAC, 0xEF, +0xB5, 0x10, 0xB4, 0xF0, 0xAC, 0xCF, 0xB5, 0x10, +0xAC, 0xCF, 0xA4, 0x8E, 0xAC, 0xCF, 0xAC, 0xAF, +0xA4, 0x8E, 0xA4, 0x8E, 0xA4, 0x8E, 0xA4, 0xAF, +0xB4, 0xEF, 0xB4, 0xF0, 0xB4, 0xEF, 0xAC, 0xCF, +0xAC, 0xCF, 0xB4, 0xEF, 0xBD, 0x30, 0xBD, 0x51, +0xB5, 0x10, 0xB4, 0xEF, 0xAC, 0xEF, 0x94, 0x2E, +0x52, 0x68, 0x31, 0xA6, 0x39, 0xE7, 0x42, 0x07, +0x4A, 0x48, 0x4A, 0x69, 0x42, 0x08, 0x63, 0x0C, +0x7B, 0xCF, 0xAD, 0x35, 0xAD, 0x55, 0xAD, 0x56, +0xAD, 0x76, 0xBD, 0xD7, 0xBD, 0xD7, 0xC6, 0x38, +0xD6, 0x79, 0xA4, 0xD3, 0x6B, 0x2B, 0x7B, 0x8D, +0xA4, 0xF1, 0xAD, 0x31, 0xAC, 0xF1, 0xA4, 0xF0, +0x9C, 0xAF, 0xA4, 0xCF, 0xA4, 0xF0, 0x9C, 0x6E, +0x7B, 0x8B, 0xA4, 0xB0, 0x7B, 0x8C, 0x31, 0x64, +0x18, 0xE3, 0x31, 0xA5, 0x39, 0xA6, 0x31, 0xA6, +0x39, 0xC7, 0x6B, 0x4D, 0xAD, 0x55, 0xAD, 0x14, +0x9C, 0x71, 0x9C, 0x70, 0xBD, 0x74, 0xAC, 0xF2, +0xBD, 0x53, 0xD6, 0x17, 0x9C, 0x50, 0x7B, 0x8D, +0xA4, 0xD3, 0xBD, 0x75, 0xAD, 0x13, 0xAC, 0xF2, +0xAC, 0xF1, 0xAD, 0x12, 0xA4, 0xD1, 0xC5, 0xF5, +0xC5, 0xB4, 0xC5, 0xB4, 0x8C, 0x0D, 0x9C, 0x6E, +0xBD, 0x51, 0xBD, 0xB2, 0xC6, 0x14, 0xC5, 0xD3, +0xC5, 0xD3, 0xC6, 0x34, 0xC6, 0x15, 0xC6, 0x15, +0xC6, 0x15, 0xB5, 0xB6, 0xAD, 0x56, 0x9C, 0xD3, +0x83, 0xEF, 0x6B, 0x2B, 0x7B, 0x6B, 0xB5, 0x31, +0x83, 0xCB, 0x7B, 0xAC, 0x7B, 0xAC, 0x83, 0xCC, +0x7B, 0xAC, 0x83, 0xED, 0x94, 0x6F, 0x8C, 0x2E, +0xAD, 0x32, 0xA4, 0xD1, 0x83, 0xCD, 0x9C, 0xB0, +0x9C, 0xB0, 0x83, 0xEC, 0xA4, 0xF1, 0xBD, 0xB4, +0xBD, 0xD5, 0xB5, 0x53, 0x7B, 0x8C, 0xAD, 0x53, +0x9C, 0xB0, 0x9C, 0x90, 0xAD, 0x32, 0x9C, 0xB1, +0xA5, 0x12, 0x9C, 0x90, 0x94, 0x90, 0xB5, 0x53, +0xC5, 0xF5, 0xC5, 0xD4, 0xCE, 0x15, 0xB5, 0x73, +0x94, 0x6F, 0x8C, 0x0E, 0x73, 0x6C, 0x7B, 0x8C, +0x94, 0x4F, 0x8B, 0xED, 0xA4, 0xD0, 0xAD, 0x31, +0x94, 0x2D, 0x8C, 0x0C, 0x8B, 0xEC, 0x94, 0x4E, +0x83, 0xED, 0x9C, 0x8F, 0x94, 0x4E, 0xAD, 0x11, +0xA4, 0xD0, 0x8C, 0x2D, 0x8C, 0x2E, 0x83, 0xCC, +0x94, 0x4E, 0x8C, 0x2D, 0x9C, 0x8F, 0xA4, 0xF1, +0x94, 0x4F, 0xAD, 0x32, 0xAD, 0x11, 0x7B, 0xAD, +0x83, 0xEE, 0xB5, 0x94, 0xB5, 0x73, 0xA5, 0x12, +0x8C, 0x2F, 0x7B, 0xAD, 0x9C, 0xD0, 0xBD, 0xD4, +0xA5, 0x11, 0x9C, 0xD0, 0xAD, 0x52, 0xB5, 0x74, +0xB5, 0x73, 0x8C, 0x2E, 0x83, 0xEE, 0x7B, 0xCD, +0x83, 0xED, 0x83, 0xEE, 0x63, 0x0A, 0x7B, 0xAD, +0x94, 0x6F, 0xB5, 0x53, 0x9C, 0x90, 0xAD, 0x32, +0xA4, 0xD1, 0x83, 0xEE, 0x83, 0xEE, 0x94, 0x6F, +0x94, 0x6F, 0x9C, 0x90, 0x9C, 0xB0, 0x9C, 0xB0, +0xA4, 0xF1, 0x9C, 0xD1, 0x9C, 0xB0, 0x94, 0x4F, +0x9C, 0xB0, 0xA4, 0xD1, 0x9C, 0x90, 0x94, 0x6F, +0x8C, 0x2E, 0x8C, 0x0E, 0x83, 0xEE, 0x7B, 0x8C, +0x94, 0x4F, 0xB5, 0x52, 0xC5, 0xB4, 0xBD, 0x92, +0xBD, 0x72, 0xB5, 0x52, 0xB5, 0x31, 0xB5, 0x52, +0xC5, 0xB4, 0xAC, 0xF1, 0x9C, 0x6E, 0x8B, 0xED, +0x94, 0x2E, 0x9C, 0x8F, 0x94, 0x2E, 0x9C, 0x8F, +0xAD, 0x11, 0xAC, 0xF1, 0xA4, 0xF0, 0xAD, 0x11, +0x94, 0x4E, 0xAD, 0x32, 0xAD, 0x12, 0xB5, 0x32, +0xBD, 0x93, 0xCE, 0x15, 0xAD, 0x12, 0x94, 0x50, +0x9C, 0xB0, 0xA4, 0xB1, 0xAC, 0xF1, 0xB5, 0x32, +0xC5, 0xB5, 0xC5, 0xB5, 0xC5, 0xB4, 0xCD, 0xF5, +0xCD, 0xF5, 0xC5, 0xF5, 0xC5, 0xD5, 0xBD, 0xB4, +0xBD, 0xD4, 0xBD, 0xB4, 0xBD, 0xB4, 0xBD, 0xB4, +0xBD, 0xB4, 0xBD, 0x94, 0xB5, 0x73, 0xB5, 0x73, +0xB5, 0x52, 0xA4, 0xD1, 0xA4, 0xD0, 0xA4, 0xD0, +0xA4, 0xD0, 0x9C, 0xB0, 0x9C, 0xB0, 0x9C, 0x8F, +0xA4, 0xF1, 0xAD, 0x32, 0xB5, 0x31, 0xBD, 0x92, +0xB5, 0x52, 0x9C, 0x8F, 0xA4, 0xD1, 0xA4, 0xD0, +0x94, 0x6F, 0x9C, 0x8F, 0xAD, 0x11, 0xA4, 0xF0, +0xA5, 0x75, 0xAD, 0x76, 0x9D, 0x14, 0x94, 0xD3, +0x7B, 0xCF, 0x8C, 0x50, 0x94, 0xB0, 0x8C, 0x2F, +0x73, 0x6C, 0x9C, 0xB1, 0x7B, 0xCD, 0x7B, 0xCD, +0x6B, 0x4B, 0x4A, 0x68, 0x6B, 0x4C, 0x7B, 0xEE, +0x84, 0x0F, 0x94, 0x90, 0x7B, 0xCD, 0x83, 0xED, +0x8C, 0x4F, 0xA4, 0xF2, 0xB5, 0x73, 0xAD, 0x53, +0xAD, 0x32, 0x9C, 0x8F, 0xB4, 0xF0, 0xA4, 0x8E, +0xD6, 0x14, 0xD5, 0xF3, 0xD6, 0x13, 0xD6, 0x54, +0xD6, 0x34, 0xD6, 0x35, 0xC5, 0xF4, 0xBD, 0x93, +0xB5, 0x52, 0xA4, 0xAF, 0xBD, 0x93, 0xBD, 0x93, +0xAD, 0x11, 0xA4, 0xD0, 0x8C, 0x2E, 0x83, 0xCD, +0x94, 0x6F, 0x9C, 0x90, 0xAD, 0x10, 0xB5, 0x10, +0xBD, 0x71, 0xDE, 0x55, 0xB5, 0x10, 0xB4, 0xCF, +0x7B, 0x6A, 0x7B, 0x6B, 0x5A, 0x88, 0x4A, 0x06, +0x49, 0xE6, 0x4A, 0x27, 0x4A, 0x27, 0x62, 0xA9, +0x62, 0xA8, 0x6B, 0x0A, 0x73, 0x2A, 0x73, 0x4A, +0x7B, 0x4A, 0x73, 0x2A, 0x7B, 0x6A, 0x7B, 0x8A, +0x73, 0x09, 0x7B, 0x4A, 0x83, 0xAB, 0x9C, 0x4E, +0x8C, 0x0E, 0x4A, 0x48, 0x39, 0xE7, 0x42, 0x07, +0x31, 0xA6, 0x42, 0x07, 0x42, 0x08, 0x5A, 0xCB, +0x6B, 0x4D, 0x94, 0x92, 0xA5, 0x35, 0xB5, 0x96, +0xAD, 0x56, 0xA5, 0x35, 0xAD, 0x55, 0xC6, 0x38, +0xDE, 0xBA, 0x94, 0x50, 0x41, 0xE7, 0x7B, 0xAE, +0x94, 0x2E, 0xBD, 0x72, 0xBD, 0x51, 0xBD, 0x30, +0xBD, 0x51, 0xC5, 0x71, 0xC5, 0x91, 0xBD, 0x71, +0xC5, 0x72, 0xB5, 0x10, 0xB5, 0x10, 0x8B, 0xED, +0x21, 0x03, 0x21, 0x03, 0x63, 0x0B, 0x42, 0x07, +0x31, 0xA6, 0x4A, 0x48, 0x9C, 0xB2, 0x9C, 0x92, +0x9C, 0x71, 0x8B, 0xEF, 0xAC, 0xF2, 0xAC, 0xD2, +0x9C, 0x2F, 0x9C, 0x2F, 0x73, 0x0B, 0x94, 0x10, +0x83, 0xCF, 0x7B, 0x8E, 0xB5, 0x34, 0xBD, 0x75, +0xB5, 0x55, 0xCE, 0x38, 0xA4, 0xD2, 0xA5, 0x12, +0xBD, 0xB4, 0xBD, 0x93, 0x8C, 0x0D, 0xAC, 0xCF, +0xAC, 0xEF, 0xA4, 0xCF, 0xA4, 0xF0, 0x94, 0x4E, +0x83, 0xCC, 0x8C, 0x2D, 0x9C, 0xD0, 0xB5, 0x73, +0xAD, 0x52, 0xB5, 0xB5, 0xAD, 0x76, 0x9C, 0xF4, +0x83, 0xEF, 0x7B, 0x8C, 0x8B, 0xED, 0xB4, 0xF0, +0x94, 0x0D, 0x7B, 0xAC, 0x7B, 0xAC, 0x8C, 0x0D, +0x73, 0x6B, 0x73, 0x6B, 0x7B, 0xAC, 0x73, 0x4B, +0xA4, 0xF1, 0x8C, 0x0E, 0x94, 0x6F, 0xAD, 0x52, +0xA4, 0xD1, 0x83, 0xED, 0xAD, 0x53, 0xCE, 0x16, +0xC5, 0xD5, 0xC5, 0xF5, 0xB5, 0x74, 0xCE, 0x36, +0xBD, 0xD4, 0xA4, 0xF1, 0x9C, 0x90, 0x94, 0x6F, +0x9C, 0x90, 0xA4, 0xF1, 0xAD, 0x32, 0xCE, 0x36, +0xD6, 0x76, 0xCE, 0x36, 0xCE, 0x15, 0xA4, 0xD1, +0x8C, 0x2E, 0x7B, 0xAD, 0x73, 0x4B, 0x7B, 0x8C, +0x8B, 0xCD, 0x94, 0x0D, 0xA4, 0xF0, 0xAD, 0x10, +0x94, 0x2D, 0x8B, 0xEC, 0x94, 0x2D, 0x9C, 0x8F, +0x8C, 0x0D, 0x9C, 0x8F, 0x94, 0x8F, 0xA5, 0x11, +0x94, 0x4E, 0x7B, 0xCB, 0x8C, 0x0D, 0x8B, 0xED, +0x83, 0xEC, 0x7B, 0x8B, 0x94, 0x6E, 0xA4, 0xF0, +0x9C, 0xD0, 0xB5, 0x53, 0xA4, 0xF1, 0x7B, 0xAD, +0xA4, 0xF1, 0xBD, 0xD4, 0xBD, 0xD5, 0xAD, 0x53, +0x9C, 0xD1, 0x8C, 0x4F, 0x8C, 0x4F, 0xA4, 0xD1, +0x8C, 0x0E, 0x94, 0x6F, 0xA4, 0xF1, 0xB5, 0x73, +0xBD, 0xB4, 0x94, 0x90, 0x94, 0x90, 0x9C, 0xF1, +0x94, 0xB0, 0x9C, 0xB1, 0x7B, 0xCD, 0x83, 0xEE, +0x9C, 0xB0, 0xAD, 0x32, 0x73, 0x8C, 0x7B, 0xCD, +0x84, 0x0E, 0x9C, 0xF2, 0xA5, 0x12, 0xAD, 0x53, +0xAD, 0x53, 0xAD, 0x73, 0xB5, 0x74, 0xAD, 0x53, +0xAD, 0x33, 0xA4, 0xF1, 0xA4, 0xF2, 0x94, 0x70, +0x8C, 0x4F, 0x94, 0x6F, 0x9C, 0xB0, 0xA4, 0xF1, +0x94, 0x6F, 0x8C, 0x4F, 0x9C, 0xB1, 0x83, 0xEE, +0x8C, 0x2E, 0xAD, 0x12, 0x9C, 0xAF, 0xAD, 0x10, +0xAD, 0x10, 0x9C, 0x8F, 0xAC, 0xF1, 0xBD, 0x93, +0xBD, 0xB3, 0xBD, 0x93, 0xAD, 0x31, 0x94, 0x4E, +0x8C, 0x4E, 0x8C, 0x2E, 0x7B, 0xAC, 0x8C, 0x2E, +0x9C, 0xD0, 0x9C, 0xB0, 0xB5, 0x73, 0xC5, 0xF5, +0xB5, 0x73, 0xAD, 0x52, 0xAD, 0x11, 0xAD, 0x32, +0x9C, 0xB0, 0xB5, 0x52, 0x73, 0x4B, 0x5A, 0xA9, +0x73, 0x4B, 0x83, 0x8C, 0x7B, 0x8C, 0x83, 0xCD, +0x9C, 0x6F, 0xA4, 0xB0, 0xA4, 0xD1, 0xB5, 0x53, +0xB5, 0x53, 0xA4, 0xD1, 0x9C, 0xB0, 0x9C, 0xB0, +0xA4, 0xD0, 0xA4, 0xB0, 0x9C, 0x70, 0x9C, 0x90, +0xA4, 0xB1, 0xA4, 0xD1, 0xAC, 0xF1, 0xAD, 0x12, +0xA4, 0xF1, 0xB5, 0x32, 0xB5, 0x32, 0x94, 0x4F, +0x83, 0xED, 0x9C, 0x8F, 0xA4, 0xF1, 0xAD, 0x12, +0xB5, 0x53, 0xB5, 0x53, 0xB5, 0x32, 0xB5, 0x32, +0xAD, 0x11, 0xAD, 0x32, 0xB5, 0x52, 0xB5, 0x73, +0xA4, 0xF1, 0xB5, 0x73, 0xBD, 0x73, 0xBD, 0x94, +0xAD, 0x76, 0xB5, 0xD7, 0x9D, 0x14, 0x94, 0xD3, +0x7B, 0xCF, 0x84, 0x50, 0x84, 0x4F, 0x84, 0x2E, +0x9C, 0xD1, 0x84, 0x2F, 0x6B, 0x8C, 0x94, 0x90, +0x7B, 0xEE, 0x73, 0xAE, 0x8C, 0x70, 0x94, 0x91, +0x94, 0xB2, 0xA4, 0xF2, 0x94, 0x70, 0x9C, 0xD1, +0x7B, 0xEE, 0x9C, 0xB1, 0xBD, 0xD5, 0xAD, 0x53, +0xBD, 0x94, 0xA4, 0xAF, 0xB4, 0xF0, 0xAC, 0xCF, +0xDE, 0x55, 0xB4, 0xEF, 0xBD, 0x50, 0xC5, 0x91, +0xC5, 0xB2, 0xCD, 0xD3, 0xCD, 0xD3, 0xC5, 0xD3, +0xBD, 0x92, 0xC5, 0xD4, 0xCE, 0x35, 0xD6, 0x35, +0xC5, 0xD4, 0xCE, 0x15, 0xBD, 0x93, 0xAD, 0x32, +0xBD, 0xB4, 0xC5, 0xD4, 0xCD, 0xF4, 0xD6, 0x35, +0xCD, 0xF3, 0xDE, 0x75, 0xBD, 0x30, 0xB5, 0x10, +0xA4, 0xB0, 0x94, 0x6F, 0x7B, 0xCD, 0x7B, 0xAD, +0x84, 0x0F, 0x8C, 0x4F, 0x83, 0xEE, 0x8C, 0x2F, +0x7B, 0xCD, 0x83, 0xCD, 0x7B, 0x8C, 0x7B, 0xAD, +0x8C, 0x2E, 0x7B, 0x8C, 0x6B, 0x0A, 0x73, 0x6B, +0x7B, 0x8C, 0x8C, 0x0D, 0x9C, 0xB0, 0xA4, 0xD1, +0xAD, 0x12, 0x73, 0x4B, 0x4A, 0x27, 0x4A, 0x28, +0x4A, 0x48, 0x4A, 0x48, 0x39, 0xC6, 0x42, 0x28, +0x5A, 0xCB, 0x7B, 0xCF, 0x9C, 0xF4, 0xAD, 0x76, +0xAD, 0x55, 0x9C, 0xD3, 0x9C, 0xD4, 0xB5, 0xB7, +0xCE, 0x79, 0x7B, 0xAE, 0x42, 0x08, 0x39, 0xA6, +0x62, 0xCA, 0x83, 0xAC, 0x83, 0xAB, 0x94, 0x0D, +0xAC, 0xD0, 0xAC, 0xCF, 0xAC, 0xCF, 0x83, 0xAA, +0x94, 0x2C, 0x9C, 0x4D, 0x9C, 0x6E, 0xA4, 0x8F, +0x41, 0xE6, 0x5A, 0xCA, 0x7B, 0x8C, 0x31, 0x65, +0x39, 0xA6, 0x31, 0xA5, 0x42, 0x08, 0xA4, 0xF3, +0x7B, 0x6D, 0xAC, 0xF4, 0xA4, 0xF3, 0xA4, 0xB2, +0x7B, 0x6D, 0x39, 0x86, 0x4A, 0x28, 0x7B, 0xAE, +0x4A, 0x29, 0x5A, 0x8B, 0xBD, 0x96, 0xB5, 0x96, +0xCE, 0x59, 0xBD, 0xF8, 0xF7, 0x7D, 0xBD, 0xF7, +0x73, 0x6D, 0xBD, 0x94, 0xAD, 0x11, 0xBD, 0x30, +0xB5, 0x10, 0xAC, 0xCF, 0xAC, 0xEF, 0xAC, 0xEF, +0xB4, 0xCF, 0xB4, 0xEF, 0xAC, 0xCF, 0xA4, 0xAF, +0x9C, 0x6F, 0xBD, 0xB6, 0xBD, 0xD7, 0xA5, 0x14, +0xAC, 0xF2, 0xA4, 0xAF, 0xB5, 0x10, 0xB4, 0xEF, +0x94, 0x0D, 0x8B, 0xEC, 0x83, 0xEC, 0x8C, 0x0D, +0x7B, 0x8B, 0x7B, 0xAC, 0x7B, 0x8B, 0x94, 0x2E, +0xB5, 0x53, 0x73, 0x6C, 0x83, 0xCD, 0x9C, 0x90, +0x9C, 0xB0, 0x8C, 0x0E, 0xA4, 0xF1, 0xBD, 0xB4, +0xAD, 0x32, 0x94, 0x90, 0xA4, 0xD1, 0xCE, 0x16, +0xA5, 0x12, 0x83, 0xED, 0x8C, 0x0E, 0x8C, 0x2E, +0xA4, 0xD1, 0xB5, 0x53, 0xCE, 0x16, 0xC6, 0x15, +0xDE, 0x97, 0xD6, 0x76, 0xC5, 0xF5, 0x73, 0x6B, +0x83, 0xCD, 0x7B, 0x8D, 0x4A, 0x07, 0x6B, 0x2B, +0x83, 0x8C, 0x94, 0x4E, 0xAD, 0x11, 0xAC, 0xF0, +0xAC, 0xD0, 0xAD, 0x10, 0xB5, 0x72, 0xB5, 0x72, +0xAD, 0x31, 0xAD, 0x31, 0xAD, 0x32, 0xAD, 0x11, +0x94, 0x6E, 0x94, 0x4E, 0x94, 0x4E, 0x9C, 0x8F, +0x94, 0x2E, 0x83, 0xED, 0x7B, 0xAC, 0xA4, 0xF0, +0xA4, 0xD1, 0xAD, 0x12, 0x9C, 0x90, 0x63, 0x2B, +0xA5, 0x33, 0xBD, 0xD4, 0xBD, 0xB5, 0xAD, 0x53, +0xA5, 0x33, 0x94, 0x70, 0x94, 0x6F, 0x8C, 0x2F, +0x84, 0x0E, 0xA5, 0x12, 0xB5, 0xB4, 0xC5, 0xF5, +0xBD, 0xD4, 0xA5, 0x32, 0xAD, 0x53, 0xAD, 0x53, +0xA5, 0x32, 0xA5, 0x12, 0x94, 0x90, 0x8C, 0x70, +0x9C, 0x6F, 0xA4, 0xF1, 0x7B, 0xEE, 0x94, 0x90, +0x9C, 0xF2, 0xAD, 0x53, 0xAD, 0x53, 0xB5, 0xB4, +0xB5, 0xB4, 0xB5, 0xB4, 0xBD, 0xB5, 0xB5, 0xB4, +0xAD, 0x73, 0xB5, 0x73, 0xB5, 0x94, 0xA5, 0x12, +0x94, 0xB0, 0xAD, 0x33, 0xB5, 0x74, 0xBD, 0xD5, +0xAD, 0x33, 0x94, 0x90, 0x9C, 0xB1, 0x8C, 0x4F, +0x94, 0x6F, 0xAD, 0x32, 0xAD, 0x31, 0xAD, 0x31, +0xA4, 0xCF, 0x94, 0x6E, 0xB5, 0x72, 0xB5, 0x93, +0xBD, 0xD4, 0xBD, 0xD4, 0xBD, 0xB4, 0xA4, 0xF1, +0xAD, 0x53, 0xA5, 0x12, 0x8C, 0x6F, 0x94, 0x70, +0x9C, 0xD1, 0xA4, 0xF1, 0xC5, 0xD5, 0xCE, 0x36, +0xBD, 0xB4, 0xC5, 0xF4, 0xBD, 0x93, 0xB5, 0x73, +0x9C, 0xB0, 0xA4, 0xB0, 0x6A, 0xEA, 0x83, 0xCE, +0x7B, 0x8C, 0x8B, 0xED, 0x83, 0xED, 0x7B, 0xAC, +0x83, 0xAC, 0x9C, 0x6F, 0xA4, 0xF1, 0xB5, 0x73, +0xB5, 0x73, 0xBD, 0x94, 0xB5, 0x73, 0xB5, 0x53, +0xB5, 0x73, 0xBD, 0x93, 0xAD, 0x12, 0xA4, 0xF1, +0x94, 0x2F, 0x83, 0xCD, 0x94, 0x4F, 0x73, 0x6C, +0x62, 0xCA, 0x7B, 0xAD, 0x7B, 0x8C, 0x6B, 0x0B, +0x62, 0xA9, 0x9C, 0x90, 0x9C, 0xB0, 0xA4, 0xD1, +0xAD, 0x12, 0x9C, 0x90, 0x9C, 0xB0, 0x9C, 0x8F, +0x83, 0xED, 0x94, 0x4F, 0x94, 0x6F, 0x94, 0x4F, +0x8C, 0x0E, 0xB5, 0x53, 0xAC, 0xF1, 0xA4, 0xF1, +0xA5, 0x55, 0xAD, 0x76, 0x9D, 0x14, 0x94, 0xD3, +0x73, 0xCF, 0x84, 0x2F, 0x94, 0xB1, 0x9C, 0xD1, +0x9C, 0xF2, 0x84, 0x0E, 0x8C, 0x50, 0x63, 0x2B, +0x6B, 0x4C, 0x9C, 0xD2, 0x9C, 0xD2, 0x8C, 0x50, +0x7C, 0x0F, 0xAD, 0x33, 0x94, 0x91, 0xA4, 0xF2, +0x83, 0xEE, 0xB5, 0x94, 0xB5, 0x94, 0xA4, 0xF1, +0xBD, 0x93, 0x9C, 0x8F, 0xB5, 0x10, 0xAC, 0xCF, +0xD6, 0x13, 0xAC, 0xEF, 0x9C, 0x4D, 0xAC, 0xEF, +0xBD, 0x71, 0xC5, 0x92, 0xBD, 0x71, 0xC5, 0xB2, +0xB5, 0x51, 0xCE, 0x35, 0xCE, 0x35, 0xD6, 0x35, +0xCE, 0x15, 0xCE, 0x15, 0xC5, 0xF5, 0xAD, 0x12, +0xBD, 0x93, 0xCE, 0x14, 0xB5, 0x31, 0xAC, 0xCF, +0xB5, 0x10, 0xD6, 0x34, 0xAC, 0xCF, 0xB5, 0x10, +0xB5, 0x52, 0x84, 0x0E, 0x8C, 0x4F, 0xA4, 0xF2, +0xA4, 0xD1, 0xAD, 0x32, 0x7B, 0xCD, 0x94, 0x90, +0x94, 0x90, 0xA4, 0xF2, 0x8C, 0x50, 0x8C, 0x70, +0x8C, 0x4F, 0x8C, 0x2F, 0x8C, 0x4F, 0x9C, 0xB0, +0x8C, 0x2E, 0x9C, 0xB0, 0xB5, 0x93, 0xB5, 0x73, +0xB5, 0x73, 0xA4, 0xD1, 0x52, 0x68, 0x42, 0x07, +0x41, 0xE7, 0x41, 0xE7, 0x39, 0xC6, 0x31, 0xA6, +0x42, 0x49, 0x63, 0x2C, 0x8C, 0x51, 0xAD, 0x76, +0xAD, 0x76, 0x9C, 0xB3, 0x8C, 0x72, 0xB5, 0x96, +0xD6, 0x9A, 0xB5, 0x96, 0x6B, 0x4E, 0x4A, 0x29, +0x5A, 0x8A, 0x7B, 0x8D, 0x83, 0xCD, 0x7B, 0xCD, +0x7B, 0xAC, 0x8B, 0xED, 0xAC, 0xF0, 0x9C, 0x8F, +0x9C, 0xAF, 0xAD, 0x10, 0xAC, 0xCF, 0x9C, 0x4E, +0x7B, 0xAC, 0x73, 0x8C, 0x21, 0x03, 0x21, 0x03, +0x31, 0x85, 0x31, 0xA6, 0x29, 0x45, 0x5A, 0xCA, +0xA4, 0xD3, 0xAC, 0xF4, 0xCE, 0x38, 0x7B, 0x8D, +0x41, 0xE7, 0x29, 0x04, 0x29, 0x45, 0x6B, 0x2C, +0x7B, 0xCF, 0x7B, 0x8F, 0xB5, 0x76, 0xC5, 0xF8, +0xCE, 0x39, 0xB5, 0xB7, 0xCE, 0x9A, 0xEF, 0x7D, +0xA4, 0xF4, 0xBD, 0xB5, 0xE6, 0xF9, 0xD5, 0xF3, +0xDE, 0x54, 0xE6, 0x75, 0xDE, 0x54, 0xC5, 0x71, +0xCD, 0xB2, 0xDE, 0x34, 0xC5, 0x71, 0xBD, 0x30, +0xA4, 0xD0, 0xCE, 0x38, 0xA5, 0x14, 0xA5, 0x13, +0xA4, 0xB0, 0xAC, 0xCF, 0xB4, 0xEF, 0xB5, 0x10, +0xB5, 0x30, 0xBD, 0x51, 0xC5, 0x71, 0xCD, 0x92, +0xC5, 0x71, 0xC5, 0x71, 0xBD, 0x51, 0xC5, 0x93, +0xC5, 0xF5, 0xC5, 0xF6, 0xBD, 0xB5, 0xB5, 0x74, +0xAD, 0x33, 0xAD, 0x12, 0xA4, 0xF2, 0x9C, 0x90, +0xA4, 0xD1, 0xAD, 0x32, 0xAD, 0x12, 0xA4, 0xD1, +0x9C, 0x90, 0x94, 0x90, 0x94, 0x70, 0x8C, 0x2F, +0x8C, 0x2F, 0x83, 0xEE, 0x8C, 0x2E, 0x8C, 0x0E, +0x9C, 0x90, 0x94, 0x4F, 0x83, 0xED, 0x7B, 0x8C, +0x8C, 0x2F, 0x9C, 0x91, 0x94, 0x50, 0x83, 0xCE, +0x7B, 0x8D, 0x73, 0x6B, 0x7B, 0x8B, 0x7B, 0xAB, +0x8C, 0x0D, 0x9C, 0x8F, 0xA4, 0xCF, 0xA4, 0xD0, +0xB5, 0x52, 0xBD, 0xB3, 0xBD, 0xB3, 0xBD, 0x93, +0xB5, 0x72, 0xAD, 0x10, 0xAD, 0x10, 0xBD, 0x52, +0xAD, 0x10, 0xAD, 0x11, 0x94, 0x6E, 0x9C, 0xB0, +0xAD, 0x32, 0xAD, 0x12, 0x84, 0x0E, 0x63, 0x2B, +0xBD, 0xF5, 0xBD, 0xD4, 0xCE, 0x56, 0xBD, 0xD4, +0xAD, 0x73, 0x8C, 0x2F, 0x73, 0x8C, 0x7B, 0xAC, +0x8C, 0x2E, 0xA5, 0x12, 0xC5, 0xF5, 0xBD, 0xB4, +0xBD, 0xB4, 0xA5, 0x12, 0x9C, 0xF2, 0xB5, 0xB5, +0xAD, 0x73, 0xAD, 0x74, 0xAD, 0x53, 0xA4, 0xF1, +0x9C, 0x90, 0xA4, 0xD1, 0x8C, 0x4F, 0x9C, 0xD1, +0xA5, 0x12, 0xA5, 0x12, 0xA5, 0x32, 0xB5, 0x94, +0xC5, 0xF6, 0xBD, 0xD5, 0xBD, 0xB4, 0xBD, 0xD5, +0xBD, 0xD5, 0xBD, 0xF5, 0xC6, 0x16, 0xB5, 0x94, +0xB5, 0x94, 0xBD, 0xD5, 0xBD, 0xD5, 0xC6, 0x36, +0xBD, 0xF5, 0x9C, 0xF2, 0xA4, 0xF1, 0x94, 0x6F, +0x9C, 0xB0, 0xB5, 0x73, 0xB5, 0x52, 0xAD, 0x11, +0xAD, 0x32, 0xAD, 0x52, 0xC5, 0xF5, 0xC5, 0xD4, +0xBD, 0x93, 0xAD, 0x52, 0xBD, 0xB4, 0xAD, 0x12, +0xA4, 0xF1, 0x9C, 0xF1, 0x94, 0xB1, 0x9C, 0xD1, +0xAD, 0x74, 0xAD, 0x53, 0xC6, 0x36, 0xCE, 0x35, +0xBD, 0xD4, 0xC6, 0x15, 0xC5, 0xF5, 0xBD, 0xD4, +0x94, 0x90, 0xA4, 0xD1, 0x73, 0x4B, 0x8C, 0x2F, +0x83, 0xCD, 0x94, 0x4E, 0x83, 0xCD, 0x83, 0xCD, +0x94, 0x4F, 0x9C, 0xB0, 0xA4, 0xD0, 0xA4, 0xF1, +0x94, 0x6F, 0x83, 0xED, 0x83, 0xCD, 0x7B, 0xCC, +0x83, 0xED, 0x94, 0x4F, 0x94, 0x6F, 0x8C, 0x2E, +0x8C, 0x2E, 0x94, 0x4F, 0xA4, 0xD1, 0x8C, 0x2F, +0x73, 0x6C, 0x73, 0x4C, 0x4A, 0x28, 0x52, 0x48, +0x73, 0x4C, 0xAD, 0x12, 0x94, 0x6F, 0xAD, 0x12, +0xB5, 0x53, 0x9C, 0x90, 0xA4, 0xF1, 0xA4, 0xF1, +0x94, 0x6F, 0xAD, 0x11, 0xA4, 0xF1, 0xAD, 0x32, +0x94, 0x6F, 0xB5, 0x53, 0xB5, 0x73, 0x9C, 0xB0, +0xA5, 0x55, 0xA5, 0x35, 0x9D, 0x14, 0x94, 0xD3, +0x73, 0xCE, 0x84, 0x50, 0x94, 0x90, 0x94, 0x90, +0x9C, 0xD1, 0x9C, 0xB1, 0x94, 0x90, 0x84, 0x0E, +0x6B, 0x6C, 0x9C, 0xD2, 0x94, 0x71, 0x94, 0x90, +0x8C, 0x70, 0xAD, 0x54, 0x9C, 0xD1, 0xAD, 0x33, +0xBD, 0xB4, 0xBD, 0xD4, 0xB5, 0x73, 0xB5, 0x93, +0xC5, 0xD5, 0x9C, 0x6F, 0xB4, 0xF0, 0xA4, 0x8E, +0xD5, 0xF3, 0xBD, 0x51, 0xB4, 0xEF, 0x8B, 0xAA, +0x9C, 0x6E, 0xAC, 0xCF, 0xB5, 0x51, 0xC5, 0xB3, +0xC5, 0xB3, 0xD6, 0x35, 0xCE, 0x35, 0xCE, 0x15, +0xCD, 0xF4, 0xD6, 0x36, 0xCD, 0xF5, 0xBD, 0x72, +0xC5, 0xD4, 0xD6, 0x35, 0xC5, 0x92, 0xA4, 0xAE, +0x9C, 0x2D, 0xD5, 0xF3, 0xAC, 0xCE, 0xBD, 0x92, +0xBD, 0x93, 0xAD, 0x12, 0xAD, 0x32, 0xBD, 0xB5, +0xB5, 0x73, 0xBD, 0xB5, 0xB5, 0x53, 0xAD, 0x33, +0xB5, 0x73, 0xB5, 0x73, 0x9C, 0xD1, 0xA4, 0xF2, +0xB5, 0x53, 0xB5, 0x73, 0x7B, 0xCD, 0x9C, 0xD1, +0xAD, 0x32, 0xAD, 0x12, 0xBD, 0x93, 0xB5, 0x52, +0xC5, 0xD4, 0xA4, 0xD1, 0x7B, 0xCD, 0x42, 0x06, +0x39, 0xA6, 0x42, 0x07, 0x4A, 0x68, 0x42, 0x08, +0x4A, 0x49, 0x5A, 0xCB, 0x73, 0x8E, 0x8C, 0x71, +0x94, 0xB3, 0x84, 0x10, 0xA5, 0x34, 0xB5, 0x96, +0xA5, 0x14, 0xBD, 0xF7, 0xA5, 0x14, 0x94, 0x71, +0x9C, 0xB1, 0xA4, 0xD2, 0xAD, 0x33, 0xA5, 0x12, +0x7B, 0xCD, 0x6B, 0x4B, 0xAD, 0x11, 0xB5, 0x51, +0xA4, 0xCF, 0xBD, 0x92, 0xB5, 0x31, 0x9C, 0x6E, +0x94, 0x2E, 0x9C, 0x90, 0x6B, 0x4B, 0x5A, 0xAA, +0x6B, 0x2B, 0x41, 0xE7, 0x39, 0xE7, 0x29, 0x24, +0x4A, 0x28, 0x8C, 0x30, 0xAD, 0x13, 0x41, 0xE6, +0x18, 0xC2, 0x29, 0x45, 0x39, 0xA6, 0x4A, 0x49, +0x7B, 0xAE, 0x52, 0x8A, 0x6B, 0x2D, 0x84, 0x11, +0xAD, 0x56, 0xD6, 0x9B, 0xCE, 0x7A, 0xBD, 0xB7, +0x94, 0x71, 0x8C, 0x50, 0xCE, 0x17, 0xA4, 0xB0, +0xB5, 0x51, 0xC5, 0xB2, 0xBD, 0x51, 0xB4, 0xEF, +0x9C, 0x4C, 0xA4, 0xAE, 0xB5, 0x0F, 0xAC, 0xAF, +0x83, 0xEE, 0xB5, 0x95, 0x5A, 0xCB, 0x84, 0x10, +0x5A, 0xA9, 0x5A, 0x88, 0x62, 0xE9, 0x6B, 0x0A, +0x7B, 0x6B, 0x83, 0xAB, 0x94, 0x0D, 0xA4, 0x8F, +0xB5, 0x10, 0xAD, 0x0F, 0xA4, 0xAF, 0xA4, 0xAF, +0xA4, 0xD0, 0xA4, 0xD1, 0xAD, 0x32, 0xAD, 0x12, +0xB5, 0x33, 0xB5, 0x74, 0xBD, 0x94, 0xB5, 0x33, +0xB5, 0x73, 0xAD, 0x12, 0xB5, 0x33, 0xBD, 0xB4, +0xC5, 0xD5, 0xC5, 0xD5, 0xB5, 0x73, 0xB5, 0x94, +0xBD, 0xB5, 0xBD, 0x94, 0xBD, 0x93, 0xBD, 0x94, +0xBD, 0xB5, 0xBD, 0xB4, 0xBD, 0xB4, 0xC5, 0xD5, +0xC5, 0xB5, 0xC5, 0xD5, 0xC5, 0xF6, 0xC5, 0xF6, +0xBD, 0xD5, 0xB5, 0x53, 0xAD, 0x12, 0x9C, 0xB0, +0x94, 0x6F, 0x8C, 0x0E, 0x83, 0xEE, 0x8B, 0xEE, +0x83, 0xED, 0x83, 0xED, 0x8C, 0x0D, 0x8B, 0xED, +0x83, 0xCD, 0x7B, 0xAC, 0x83, 0xCC, 0x83, 0xCC, +0x7B, 0xAB, 0x8B, 0xED, 0x83, 0xCC, 0x83, 0xAC, +0xAD, 0x32, 0x9C, 0xB0, 0x8C, 0x4F, 0x84, 0x2E, +0x9C, 0xF1, 0xA4, 0xF1, 0xBD, 0xD4, 0xA4, 0xF1, +0xB5, 0x73, 0x7B, 0xAD, 0x6B, 0x6C, 0x73, 0x6C, +0x8C, 0x4F, 0xAD, 0x53, 0xCE, 0x36, 0xCE, 0x36, +0xC6, 0x16, 0xB5, 0x94, 0xB5, 0xB4, 0xBD, 0xF5, +0xC5, 0xF5, 0xBD, 0xD5, 0xA5, 0x32, 0x9C, 0xB0, +0x94, 0x6F, 0xA4, 0xD1, 0x9C, 0xB1, 0xA5, 0x12, +0xAD, 0x53, 0xAD, 0x53, 0x9C, 0xF2, 0xB5, 0x73, +0xB5, 0x94, 0xBD, 0xD5, 0xB5, 0x73, 0xB5, 0x74, +0xB5, 0x94, 0xBD, 0xB4, 0xBD, 0xD5, 0xB5, 0x94, +0xB5, 0x73, 0xBD, 0xB4, 0xBD, 0xD5, 0xC5, 0xF5, +0xBD, 0xB5, 0xA4, 0xF2, 0xA5, 0x32, 0x9C, 0xD1, +0x8C, 0x2F, 0xB5, 0x73, 0xAD, 0x31, 0xAD, 0x11, +0xAD, 0x52, 0xB5, 0x93, 0xBD, 0xB4, 0xBD, 0x93, +0xB5, 0x73, 0xAD, 0x52, 0xBD, 0xB4, 0xAD, 0x32, +0x9C, 0xB0, 0x8C, 0x4E, 0x7B, 0xCD, 0x94, 0x90, +0xB5, 0x94, 0xAD, 0x53, 0xC6, 0x36, 0xC6, 0x35, +0xBD, 0xB4, 0xC6, 0x15, 0xC5, 0xF4, 0xAD, 0x32, +0x94, 0x8F, 0xA5, 0x11, 0x8C, 0x0E, 0x94, 0x4F, +0x8C, 0x0E, 0x94, 0x4F, 0x8C, 0x2F, 0x94, 0x2F, +0x9C, 0x90, 0xA4, 0xF1, 0xA5, 0x11, 0xBD, 0xB4, +0xA4, 0xF1, 0x7B, 0xCC, 0x84, 0x0D, 0x83, 0xCD, +0x94, 0x6F, 0xA4, 0xD1, 0xB5, 0x93, 0x9C, 0xB0, +0x9C, 0xB0, 0xA4, 0xD1, 0xB5, 0x53, 0xA4, 0xF1, +0x7B, 0x8C, 0x7B, 0xAE, 0x6B, 0x0C, 0x7B, 0x8D, +0x94, 0x71, 0xB5, 0x94, 0x9C, 0xB1, 0xB5, 0x73, +0xB5, 0x52, 0xAC, 0xF1, 0xB5, 0x73, 0xBD, 0xB3, +0xA4, 0xD0, 0xC5, 0xB4, 0xBD, 0x93, 0xBD, 0x93, +0xA4, 0xD0, 0xBD, 0x94, 0xAD, 0x12, 0xA4, 0xD0, +0xA5, 0x55, 0xA5, 0x35, 0x9D, 0x14, 0x9C, 0xD3, +0x5A, 0xEB, 0x5A, 0xC9, 0x6B, 0x2B, 0x6B, 0x4B, +0x73, 0x8C, 0x7B, 0xCD, 0x84, 0x0E, 0x84, 0x0E, +0x84, 0x0E, 0x94, 0x90, 0x8C, 0x50, 0x94, 0x70, +0x94, 0x90, 0x9C, 0xD1, 0x9C, 0xF2, 0xA5, 0x12, +0xAD, 0x73, 0xB5, 0x93, 0xB5, 0x73, 0xBD, 0xB4, +0xA4, 0xD0, 0x94, 0x4D, 0xAC, 0xEF, 0x93, 0xEC, +0xCD, 0xB3, 0x9C, 0x4D, 0x94, 0x0C, 0x7B, 0x6A, +0x9C, 0x6F, 0x83, 0x8B, 0x73, 0x2A, 0x7B, 0x8B, +0xAC, 0xF0, 0xD6, 0x35, 0xD6, 0x56, 0xD6, 0x35, +0xD6, 0x55, 0xD6, 0x56, 0xC5, 0xB3, 0xC5, 0xB3, +0xC5, 0x92, 0xC5, 0xB3, 0xC5, 0xB3, 0xB5, 0x10, +0x83, 0x8A, 0xAC, 0xEF, 0xA4, 0x8E, 0xCD, 0xF4, +0xC5, 0xF4, 0xAD, 0x52, 0xA5, 0x12, 0xBD, 0x94, +0xBD, 0xB4, 0xBD, 0xB4, 0xA4, 0xF1, 0xBD, 0x94, +0xBD, 0xB4, 0xB5, 0x73, 0xA4, 0xD1, 0xA4, 0xF1, +0xB5, 0x74, 0x8C, 0x4F, 0x7B, 0xCD, 0xB5, 0x73, +0xBD, 0xB4, 0xB5, 0x73, 0xBD, 0x94, 0xBD, 0x93, +0xBD, 0xB4, 0x9C, 0x6F, 0xB5, 0x52, 0x62, 0xC9, +0x41, 0xE7, 0x39, 0xA6, 0x39, 0xE7, 0x42, 0x07, +0x42, 0x28, 0x4A, 0x48, 0x52, 0x89, 0x6B, 0x4D, +0x73, 0x6D, 0x94, 0x92, 0xA5, 0x34, 0xAD, 0x75, +0x9C, 0xD3, 0xCE, 0x59, 0xDE, 0xBB, 0xAD, 0x14, +0xB5, 0x54, 0xB5, 0x53, 0xB5, 0x74, 0xAD, 0x33, +0x83, 0xCE, 0x6B, 0x0B, 0xAD, 0x11, 0xB5, 0x31, +0xA4, 0xCF, 0xB5, 0x71, 0xBD, 0x72, 0xA4, 0x6E, +0xA4, 0xD0, 0xAC, 0xF1, 0xA4, 0xB0, 0x8C, 0x0E, +0x8B, 0xEE, 0x73, 0x2B, 0x39, 0xA6, 0x31, 0x85, +0x31, 0x85, 0x39, 0xA6, 0x62, 0xEA, 0x39, 0xA5, +0x29, 0x65, 0x39, 0xA6, 0x39, 0xE7, 0x4A, 0x69, +0x41, 0xE8, 0x52, 0x8A, 0x5A, 0xAB, 0x6B, 0x6E, +0xAD, 0x55, 0xCE, 0x59, 0x8C, 0x51, 0x6B, 0x2D, +0x7B, 0xAE, 0x8C, 0x30, 0x94, 0x71, 0xC5, 0xF7, +0xBD, 0x73, 0xCD, 0xF4, 0xC5, 0xB2, 0xC5, 0xB2, +0xA4, 0xAE, 0x9C, 0x4C, 0xAC, 0xEF, 0xA4, 0x8E, +0x8C, 0x2F, 0xB5, 0x96, 0x8C, 0x51, 0x8C, 0x51, +0x42, 0x07, 0x42, 0x07, 0x4A, 0x48, 0x4A, 0x48, +0x4A, 0x48, 0x52, 0x68, 0x52, 0x68, 0x5A, 0x89, +0x62, 0xEA, 0x73, 0x4B, 0x5A, 0xA8, 0x63, 0x0A, +0x62, 0xEA, 0x52, 0x88, 0x5A, 0xC9, 0x62, 0xEA, +0x83, 0xCD, 0x84, 0x0E, 0x94, 0x6F, 0x9C, 0x8F, +0x8C, 0x2E, 0x83, 0xAC, 0x83, 0xCD, 0x94, 0x70, +0xA4, 0xD1, 0xA4, 0xD1, 0xA4, 0xF2, 0xB5, 0x53, +0x9C, 0xD1, 0x94, 0x6F, 0x8C, 0x2E, 0x9C, 0x90, +0xA4, 0xF1, 0xAD, 0x12, 0xAD, 0x12, 0xAD, 0x12, +0xB5, 0x33, 0x94, 0x2F, 0x8C, 0x2E, 0x8C, 0x0E, +0x94, 0x8F, 0xA4, 0xF1, 0xA4, 0xF2, 0xB5, 0x73, +0xAD, 0x12, 0xAD, 0x33, 0xBD, 0x94, 0xBD, 0x94, +0xBD, 0x94, 0xB5, 0x94, 0xBD, 0x94, 0xBD, 0xB5, +0xC5, 0xD5, 0xBD, 0xB5, 0xBD, 0x94, 0xBD, 0x94, +0xAD, 0x32, 0x73, 0x8C, 0xB5, 0x74, 0xBD, 0xB5, +0xBD, 0xD5, 0xC5, 0xD5, 0xBD, 0xB4, 0xB5, 0x73, +0xAD, 0x32, 0xA4, 0xF1, 0xA4, 0xF1, 0x9C, 0xD1, +0xA5, 0x12, 0xA4, 0xF2, 0xA5, 0x12, 0xAD, 0x12, +0xA5, 0x12, 0xAD, 0x33, 0xAD, 0x32, 0xA4, 0xF1, +0xA5, 0x11, 0xA5, 0x12, 0xA4, 0xF1, 0xA4, 0xF1, +0xA4, 0xF1, 0xAD, 0x53, 0x8C, 0x2E, 0x7B, 0xAD, +0x8C, 0x4F, 0x8C, 0x2E, 0x9C, 0xD1, 0xB5, 0x94, +0xC5, 0xF6, 0xCE, 0x37, 0xC5, 0xF6, 0xBD, 0xB4, +0xB5, 0x93, 0xCE, 0x57, 0xCE, 0x36, 0xC6, 0x36, +0xC6, 0x16, 0xBD, 0xD5, 0xBD, 0xD5, 0xBD, 0xB4, +0xB5, 0x94, 0xAD, 0x53, 0xB5, 0x74, 0xBD, 0xB4, +0xA5, 0x12, 0xB5, 0x94, 0xBD, 0xB5, 0xA4, 0xF1, +0x7B, 0xAD, 0xA4, 0xF1, 0x9C, 0x8F, 0xA5, 0x11, +0xAD, 0x12, 0xCE, 0x36, 0xC6, 0x15, 0xBD, 0xB4, +0xB5, 0x93, 0xB5, 0x93, 0xBD, 0xD5, 0xAD, 0x53, +0xB5, 0x94, 0xAD, 0x32, 0x94, 0x6F, 0xAD, 0x53, +0xB5, 0x94, 0xAD, 0x53, 0xC6, 0x35, 0xC6, 0x35, +0xBD, 0xD4, 0xBD, 0xD4, 0xB5, 0x73, 0x9C, 0xB0, +0x94, 0x8F, 0xAD, 0x32, 0x94, 0x6F, 0x84, 0x0E, +0x9C, 0xD0, 0x9C, 0xB1, 0x94, 0x6F, 0xA4, 0xD1, +0x9C, 0xB0, 0xA4, 0xF1, 0x9C, 0xB0, 0xBD, 0xB4, +0xBD, 0xB4, 0xAD, 0x12, 0xA4, 0xD1, 0x9C, 0xD1, +0xAD, 0x12, 0xBD, 0xB4, 0xBD, 0xB4, 0xAD, 0x32, +0x9C, 0xD1, 0xA4, 0xD1, 0xB5, 0x52, 0xBD, 0x93, +0x7B, 0x8D, 0x62, 0xEB, 0x62, 0xEB, 0x73, 0x8D, +0x94, 0x71, 0xBD, 0xD6, 0xA4, 0xF2, 0xB5, 0x52, +0xB5, 0x32, 0xAC, 0xF1, 0xBD, 0x93, 0xC5, 0xB4, +0xAC, 0xF1, 0xC5, 0xB3, 0xCD, 0xF4, 0xC5, 0xF4, +0xAD, 0x11, 0xB5, 0x52, 0xAD, 0x32, 0xB5, 0x53, +0xA5, 0x55, 0xA5, 0x35, 0x9D, 0x14, 0x94, 0xD3, +0x73, 0xAD, 0x7B, 0x8B, 0x83, 0xCC, 0x8C, 0x0D, +0x94, 0x2D, 0x9C, 0x6E, 0x9C, 0x8E, 0x9C, 0x6E, +0x9C, 0x8F, 0xA4, 0x8F, 0xA4, 0x8F, 0xA4, 0x8F, +0x9C, 0x6E, 0x94, 0x2D, 0x94, 0x4E, 0x9C, 0x6F, +0xA4, 0xAF, 0xA4, 0xD0, 0xA4, 0xB0, 0x9C, 0xAF, +0x9C, 0x8E, 0xA4, 0x8E, 0xAC, 0xAE, 0x83, 0x8A, +0xA4, 0x6E, 0xA4, 0x6E, 0x8B, 0xCB, 0x8B, 0xCC, +0xA4, 0xAF, 0x73, 0x4A, 0x7B, 0x8C, 0x8C, 0x0D, +0xAC, 0xF0, 0xC5, 0xB3, 0xCD, 0xF4, 0xBD, 0x72, +0xBD, 0x72, 0xA4, 0xF0, 0xA4, 0xAF, 0xBD, 0x72, +0xC5, 0x92, 0xBD, 0x72, 0xB5, 0x31, 0xA4, 0x8E, +0x83, 0x8B, 0xAC, 0xEF, 0xAC, 0xAE, 0xBD, 0x72, +0xC5, 0xD4, 0xA4, 0xF1, 0x9C, 0xB0, 0x94, 0x6F, +0xA4, 0xD1, 0xAD, 0x32, 0x9C, 0xB0, 0xBD, 0xD4, +0xBD, 0x93, 0x9C, 0xB0, 0xBD, 0xB5, 0x9C, 0x90, +0xB5, 0x74, 0x9C, 0x90, 0x9C, 0xB0, 0xC5, 0xF5, +0xBD, 0xB4, 0xBD, 0xB4, 0xBD, 0xB4, 0xC5, 0xF5, +0xCE, 0x35, 0xAC, 0xD0, 0xC5, 0x72, 0x94, 0x4E, +0x52, 0x88, 0x39, 0xA6, 0x31, 0x85, 0x39, 0xC6, +0x39, 0xC6, 0x39, 0xC6, 0x4A, 0x69, 0x63, 0x2C, +0x84, 0x10, 0x9C, 0xD3, 0x9C, 0xD3, 0x94, 0x72, +0x84, 0x10, 0xBD, 0xD7, 0xD6, 0xBA, 0xCE, 0x58, +0xA4, 0xD2, 0xC5, 0xB5, 0xC5, 0xD6, 0xAD, 0x33, +0x83, 0xCE, 0x63, 0x0B, 0xA4, 0xD0, 0xB5, 0x31, +0xAD, 0x10, 0xB5, 0x51, 0xB5, 0x30, 0x9C, 0x6D, +0xA4, 0xD0, 0xA4, 0xD0, 0xA4, 0xD0, 0x9C, 0x6F, +0x73, 0x0A, 0x94, 0x0E, 0x9C, 0x90, 0x62, 0xCA, +0x31, 0x85, 0x31, 0x65, 0x31, 0x85, 0x29, 0x44, +0x31, 0xA6, 0x31, 0xA6, 0x39, 0xE7, 0x39, 0xE7, +0x42, 0x28, 0x6B, 0x2D, 0x63, 0x2D, 0x7B, 0xCF, +0x8C, 0x72, 0xA5, 0x35, 0x63, 0x2C, 0x52, 0x8A, +0x62, 0xCB, 0x7B, 0x6D, 0x7B, 0xAE, 0xD6, 0x9A, +0xCE, 0x37, 0xAD, 0x12, 0xA4, 0xD0, 0x94, 0x2D, +0x83, 0xEC, 0x94, 0x4D, 0xB5, 0x10, 0xA4, 0x8E, +0x94, 0x92, 0xB5, 0x96, 0x9C, 0xF4, 0x8C, 0x71, +0x42, 0x28, 0x4A, 0x49, 0x52, 0x89, 0x5A, 0xAA, +0x5A, 0xAA, 0x5A, 0xAA, 0x52, 0x69, 0x52, 0x69, +0x52, 0x89, 0x5A, 0xCA, 0x52, 0x89, 0x5A, 0xCA, +0x5A, 0xCA, 0x5A, 0xCA, 0x63, 0x0B, 0x62, 0xEB, +0x52, 0xA9, 0x5A, 0xEA, 0x94, 0x70, 0xA4, 0xF1, +0x94, 0x4F, 0x83, 0xED, 0x7B, 0xAD, 0x73, 0x8C, +0x83, 0xEE, 0x7B, 0xCD, 0x73, 0x8C, 0x7B, 0xAD, +0x83, 0xCD, 0x7B, 0xAD, 0x7B, 0x8C, 0x7B, 0x8C, +0x7B, 0xAC, 0x73, 0x4B, 0xA4, 0xD1, 0x9C, 0xB1, +0x7B, 0xAD, 0x6B, 0x0A, 0x7B, 0x8C, 0x8C, 0x2E, +0x83, 0xAD, 0x83, 0xEE, 0x8C, 0x0E, 0x94, 0x90, +0x94, 0x6F, 0x9C, 0x90, 0x8C, 0x4E, 0x94, 0x6F, +0x9C, 0xD0, 0x9C, 0xD1, 0x9C, 0xB1, 0xA4, 0xF1, +0x94, 0x70, 0xAD, 0x32, 0xAD, 0x12, 0x9C, 0xB1, +0x62, 0xEB, 0x4A, 0x49, 0x8C, 0x70, 0x94, 0x6F, +0x9C, 0x90, 0x9C, 0x90, 0xAD, 0x12, 0xA4, 0xF1, +0xA4, 0xD1, 0xA4, 0xF1, 0xB5, 0x53, 0xB5, 0x73, +0xC5, 0xF5, 0xBD, 0x94, 0xBD, 0x94, 0xB5, 0x73, +0xBD, 0x73, 0xBD, 0xB4, 0xBD, 0x94, 0xB5, 0x52, +0xB5, 0x73, 0xBD, 0x73, 0xC5, 0xB4, 0xC5, 0xB4, +0xBD, 0x94, 0xBD, 0x94, 0xC5, 0xD5, 0xC5, 0xF5, +0xCE, 0x16, 0xC5, 0xB4, 0xB5, 0x53, 0xAD, 0x12, +0xA4, 0xB1, 0xA4, 0xB1, 0xA4, 0xD0, 0x9C, 0xB0, +0x9C, 0xB0, 0x9C, 0xB0, 0xA4, 0xF1, 0xA4, 0xD1, +0x9C, 0xB0, 0x9C, 0xB0, 0xA4, 0xF1, 0xAD, 0x32, +0xA4, 0xF1, 0x8C, 0x2E, 0x94, 0x6F, 0x9C, 0x90, +0x9C, 0xB1, 0xAD, 0x33, 0xB5, 0x53, 0x84, 0x0E, +0x83, 0xEE, 0xBD, 0xB5, 0xAD, 0x32, 0x9C, 0xB0, +0x8C, 0x2E, 0xAD, 0x32, 0x83, 0xED, 0x9C, 0xD0, +0xBD, 0xD4, 0xCE, 0x36, 0xC6, 0x15, 0xAD, 0x52, +0xCE, 0x36, 0xCE, 0x36, 0xB5, 0x94, 0xC6, 0x16, +0xC5, 0xF6, 0xC5, 0xF5, 0xD6, 0x97, 0xC6, 0x15, +0xC6, 0x15, 0xCE, 0x36, 0xBD, 0xB4, 0x94, 0x8F, +0x9C, 0xB0, 0xA4, 0xF1, 0x94, 0x6F, 0xA4, 0xF1, +0x9C, 0xD1, 0xAD, 0x32, 0xB5, 0x73, 0xB5, 0x73, +0xB5, 0x94, 0xC5, 0xF5, 0xBD, 0xD5, 0xC5, 0xF5, +0xCE, 0x36, 0xC5, 0xF5, 0xBD, 0xB4, 0xB5, 0x73, +0xBD, 0xB4, 0xC5, 0xF5, 0xC5, 0xF5, 0xBD, 0xB4, +0xBD, 0x94, 0xBD, 0x94, 0xC5, 0xD4, 0xC5, 0xD4, +0x83, 0xCD, 0x8C, 0x0F, 0x62, 0xEB, 0x6B, 0x6D, +0x94, 0x91, 0xC6, 0x17, 0xB5, 0x54, 0xAD, 0x32, +0xB5, 0x32, 0xB5, 0x32, 0xBD, 0x93, 0xC5, 0x93, +0xBD, 0x73, 0xD6, 0x35, 0xCE, 0x14, 0xC5, 0xF4, +0xA4, 0xF1, 0xAC, 0xF1, 0xAD, 0x32, 0xB5, 0x52, +0xA5, 0x55, 0xA5, 0x35, 0x9D, 0x14, 0x94, 0xB3, +0x6B, 0x4C, 0x5A, 0x67, 0x5A, 0x67, 0x6A, 0xC8, +0x72, 0xE9, 0x7B, 0x29, 0x7B, 0x4A, 0x7B, 0x4A, +0x83, 0xAB, 0x8B, 0xCC, 0x94, 0x0C, 0x9C, 0x2D, +0xA4, 0x8E, 0xA4, 0x8E, 0xA4, 0x8F, 0xA4, 0x6E, +0x9C, 0x4E, 0x9C, 0x6E, 0x9C, 0x6E, 0xA4, 0xAF, +0xAC, 0xAF, 0xA4, 0x8E, 0xAC, 0xCF, 0xB5, 0x10, +0xB4, 0xEF, 0xB4, 0xCF, 0xB4, 0xF0, 0xAC, 0xEF, +0xAC, 0xCF, 0xB4, 0xF0, 0xB4, 0xEF, 0xAC, 0xAE, +0xA4, 0x8E, 0xA4, 0x8E, 0xA4, 0x6D, 0x9C, 0x2C, +0x94, 0x2C, 0x93, 0xEC, 0x8B, 0xEC, 0x94, 0x2D, +0x8B, 0xCC, 0x83, 0x8B, 0x83, 0x6A, 0x8B, 0xAA, +0x72, 0xE8, 0x94, 0x0D, 0xAC, 0xCF, 0x9C, 0x2D, +0x8B, 0xEC, 0x73, 0x2A, 0x8B, 0xED, 0x73, 0x2A, +0x62, 0xA9, 0x62, 0xC9, 0x73, 0x4B, 0x7B, 0x6B, +0x73, 0x2A, 0x62, 0xC9, 0x83, 0xEE, 0x73, 0x4A, +0x83, 0xCC, 0x83, 0xCC, 0x9C, 0x6F, 0xAD, 0x11, +0xAC, 0xF1, 0xAC, 0xF1, 0xAD, 0x31, 0xB5, 0x52, +0xAD, 0x11, 0xAC, 0xCF, 0xC5, 0x71, 0x9C, 0x4D, +0x8C, 0x0E, 0x42, 0x07, 0x39, 0xA6, 0x42, 0x07, +0x42, 0x28, 0x42, 0x28, 0x4A, 0x69, 0x52, 0x89, +0x63, 0x0C, 0x7B, 0xAE, 0x9C, 0xB2, 0x83, 0xEF, +0x9C, 0xD3, 0xB5, 0x96, 0xBD, 0xB7, 0xCE, 0x59, +0x94, 0x51, 0xA4, 0xF3, 0xEF, 0x3C, 0xDE, 0xDB, +0xBD, 0xB6, 0x7B, 0xCE, 0xA4, 0xD1, 0xBD, 0x93, +0xC5, 0xD3, 0xBD, 0xB3, 0xB5, 0x10, 0x9C, 0x2C, +0xB5, 0x10, 0xB5, 0x11, 0xAC, 0xF0, 0xB4, 0xF1, +0x94, 0x0E, 0x8B, 0xED, 0x94, 0x2E, 0x73, 0x4B, +0x31, 0xA5, 0x39, 0xC6, 0x31, 0x85, 0x29, 0x64, +0x31, 0x85, 0x39, 0xC6, 0x39, 0xE7, 0x42, 0x28, +0x62, 0xEB, 0x6B, 0x6D, 0x7B, 0xCF, 0x63, 0x0C, +0x63, 0x2D, 0x8C, 0x72, 0x6B, 0x2D, 0x39, 0x86, +0x41, 0xE7, 0x52, 0x49, 0x73, 0x6D, 0xAD, 0x35, +0xDE, 0xBA, 0xE6, 0xDB, 0xCE, 0x38, 0x83, 0xEE, +0x83, 0xED, 0x9C, 0x8F, 0xBD, 0x30, 0xA4, 0x8F, +0xB5, 0x75, 0xAD, 0x76, 0x9C, 0xF4, 0x8C, 0x51, +0x6B, 0x4D, 0x6B, 0x2C, 0x62, 0xEB, 0x63, 0x0B, +0x63, 0x2B, 0x63, 0x0B, 0x62, 0xEA, 0x6B, 0x4B, +0x6B, 0x6C, 0x73, 0x8D, 0x63, 0x2B, 0x6B, 0x4C, +0x6B, 0x6C, 0x73, 0x8D, 0x73, 0xAE, 0x7B, 0xCE, +0x83, 0xEE, 0x83, 0xEE, 0x9C, 0xD1, 0xAD, 0x12, +0xB5, 0x32, 0xA4, 0xF1, 0xA4, 0xF1, 0xA5, 0x12, +0xB5, 0x93, 0xB5, 0x94, 0x9C, 0xD1, 0xAD, 0x12, +0xA4, 0xF1, 0x94, 0x2E, 0x9C, 0x8F, 0xA4, 0xD1, +0xA4, 0xB1, 0x83, 0xEE, 0xCE, 0x57, 0xDE, 0xB8, +0xCD, 0xF5, 0xBD, 0x94, 0xA4, 0xD0, 0xB5, 0x52, +0xA4, 0xB0, 0xAC, 0xF1, 0x9C, 0xB0, 0xB5, 0x53, +0xAD, 0x32, 0xAD, 0x32, 0xAD, 0x32, 0xAD, 0x12, +0xB5, 0x73, 0xAD, 0x32, 0xA4, 0xF2, 0xA4, 0xF1, +0xA4, 0xD1, 0xA4, 0xF1, 0x8C, 0x2E, 0x5A, 0xCB, +0x4A, 0x6A, 0x52, 0xAB, 0x94, 0x91, 0xA5, 0x12, +0x9C, 0x90, 0xAD, 0x12, 0xC5, 0xD5, 0xBD, 0x94, +0xB5, 0x52, 0xB5, 0x53, 0xAD, 0x32, 0xA4, 0xD1, +0x9C, 0x90, 0x8C, 0x0D, 0x94, 0x4E, 0x9C, 0x8F, +0xA4, 0xD0, 0x94, 0x4E, 0x94, 0x6F, 0x83, 0xEC, +0x94, 0x6E, 0xA4, 0xD0, 0xAC, 0xF0, 0xB5, 0x10, +0xAD, 0x10, 0xA4, 0xCF, 0x8C, 0x2D, 0x94, 0x2E, +0x8C, 0x2E, 0x8C, 0x0E, 0x8C, 0x0E, 0x94, 0x4F, +0x9C, 0x90, 0x9C, 0x90, 0x9C, 0xB0, 0xB5, 0x53, +0xBD, 0x73, 0xB5, 0x53, 0xAD, 0x32, 0xB5, 0x52, +0xB5, 0x53, 0xB5, 0x73, 0xB5, 0x53, 0xB5, 0x53, +0xAD, 0x12, 0xB5, 0x53, 0xA5, 0x12, 0xB5, 0x53, +0xC5, 0xB4, 0xBD, 0x94, 0xB5, 0x53, 0xBD, 0xB4, +0xAD, 0x32, 0xA4, 0xF1, 0xA4, 0xF1, 0xAD, 0x12, +0xA4, 0xD1, 0xA4, 0xF2, 0x94, 0x70, 0xA4, 0xF1, +0xA4, 0xF1, 0xA4, 0xF1, 0xA4, 0xD0, 0x9C, 0xD0, +0xA4, 0xD1, 0xA4, 0xF1, 0xAD, 0x12, 0xAD, 0x32, +0xA5, 0x11, 0xA5, 0x11, 0xA4, 0xD0, 0x94, 0x4F, +0x94, 0x6F, 0x9C, 0x90, 0x83, 0xED, 0x6B, 0x2A, +0x94, 0x6F, 0xA5, 0x12, 0xB5, 0x73, 0xA4, 0xF1, +0x94, 0x90, 0xB5, 0x94, 0xBD, 0xB4, 0xBD, 0x94, +0xC6, 0x16, 0xCE, 0x57, 0xCE, 0x36, 0xCE, 0x36, +0xCE, 0x36, 0xCE, 0x36, 0xCE, 0x36, 0xCE, 0x36, +0xCE, 0x36, 0xD6, 0x56, 0xD6, 0x57, 0xCE, 0x36, +0xCE, 0x56, 0xD6, 0x76, 0xD6, 0x77, 0xCE, 0x15, +0x83, 0xCD, 0xA4, 0xF2, 0x7B, 0xAE, 0x8C, 0x51, +0xAD, 0x55, 0xCE, 0x79, 0xC5, 0xD5, 0xBD, 0x94, +0xB5, 0x32, 0xBD, 0x73, 0xD6, 0x15, 0xD6, 0x35, +0xCD, 0xD3, 0xD6, 0x55, 0xD6, 0x35, 0xCD, 0xF4, +0xA4, 0xF0, 0xAD, 0x11, 0xC5, 0xF4, 0xBD, 0x93, +0xA5, 0x55, 0xA5, 0x35, 0x9D, 0x14, 0x94, 0xB2, +0x8C, 0x0F, 0x7B, 0x6B, 0x7B, 0x6B, 0x83, 0xAC, +0x94, 0x2D, 0x8B, 0xCC, 0x7B, 0x4B, 0x83, 0x6B, +0x8B, 0xCC, 0x83, 0x6B, 0x83, 0xAC, 0x83, 0xAC, +0x8B, 0xEC, 0x9C, 0x2D, 0x9C, 0x4D, 0x9C, 0x4D, +0x7B, 0x6A, 0x83, 0xCC, 0x7B, 0x8B, 0x6B, 0x09, +0x6A, 0xE9, 0x6A, 0xE9, 0x7B, 0x6A, 0x73, 0x09, +0x7B, 0x4A, 0x83, 0x6A, 0x8B, 0xCB, 0x94, 0x0C, +0x9C, 0x2C, 0xA4, 0x6D, 0x9C, 0x2C, 0x9C, 0x2C, +0xA4, 0x6D, 0xA4, 0x8E, 0x9C, 0x2D, 0xA4, 0x8E, +0xB4, 0xCF, 0xB4, 0xEF, 0xB4, 0xEF, 0xA4, 0x8E, +0x9C, 0x4D, 0xA4, 0x8E, 0xA4, 0x8E, 0x9C, 0x6D, +0x9C, 0x4D, 0x9C, 0x2D, 0xA4, 0x8E, 0xAC, 0xCF, +0xA4, 0x8E, 0x9C, 0x6F, 0x9C, 0x6E, 0x9C, 0x4E, +0x9C, 0x6F, 0x9C, 0x4F, 0x9C, 0x6E, 0x9C, 0x6E, +0xA4, 0xCF, 0xA4, 0xB0, 0x9C, 0x6E, 0xA4, 0x6F, +0x94, 0x0D, 0x94, 0x0D, 0x9C, 0x6E, 0x9C, 0x6E, +0x94, 0x0D, 0x8B, 0xEC, 0x83, 0xAB, 0x73, 0x4A, +0x73, 0x29, 0x7B, 0x6A, 0xAC, 0xCF, 0x94, 0x0D, +0x83, 0xAC, 0x62, 0xEA, 0x42, 0x07, 0x4A, 0x48, +0x4A, 0x48, 0x42, 0x07, 0x4A, 0x69, 0x52, 0xAA, +0x5A, 0xAA, 0x7B, 0xCF, 0x73, 0x6D, 0x84, 0x30, +0x9C, 0xF3, 0xAD, 0x55, 0xB5, 0x96, 0xBD, 0xB7, +0x8C, 0x51, 0x62, 0xEC, 0xA5, 0x14, 0xBD, 0xB7, +0xBD, 0x96, 0x94, 0x50, 0xBD, 0xB4, 0xCE, 0x34, +0xC5, 0xF4, 0xBD, 0xB3, 0xB5, 0x10, 0xA4, 0x6D, +0xCD, 0xD3, 0xD5, 0xD3, 0xCD, 0xB3, 0xCD, 0xB3, +0x9C, 0x2E, 0x83, 0xAC, 0x7B, 0x6B, 0x6B, 0x0A, +0x5A, 0xA9, 0x39, 0xC6, 0x41, 0xE7, 0x31, 0x85, +0x31, 0xA6, 0x39, 0xC6, 0x42, 0x07, 0x52, 0x89, +0x73, 0x8D, 0x52, 0xAA, 0x5A, 0xEB, 0x39, 0xE7, +0x6B, 0x4D, 0x84, 0x31, 0x6B, 0x4D, 0x31, 0x85, +0x41, 0xE7, 0x42, 0x08, 0x4A, 0x28, 0x39, 0xA7, +0x52, 0x8A, 0x6B, 0x2D, 0xDE, 0xBB, 0xD6, 0x79, +0x94, 0x70, 0x9C, 0x6F, 0xBD, 0x51, 0xA4, 0xAF, +0xBD, 0xF6, 0xA5, 0x35, 0x8C, 0x72, 0x9C, 0xB1, +0xAD, 0x32, 0xAD, 0x11, 0xA4, 0xF1, 0x9C, 0xB0, +0x94, 0x6F, 0x8C, 0x2E, 0x8C, 0x4F, 0x8C, 0x2E, +0x8C, 0x2E, 0x9C, 0xB0, 0x8C, 0x4F, 0x83, 0xED, +0x83, 0xEE, 0x83, 0xEE, 0x8C, 0x0E, 0x8C, 0x4F, +0x9C, 0xB0, 0xA4, 0xF1, 0xAD, 0x32, 0xAD, 0x11, +0xC5, 0xB3, 0xC5, 0xB3, 0xB5, 0x72, 0xA5, 0x11, +0xA4, 0xF1, 0xB5, 0x73, 0xA4, 0xD1, 0xBD, 0x93, +0xCD, 0xD4, 0xCD, 0xD3, 0xBD, 0x72, 0xBD, 0x52, +0xAC, 0xF1, 0x41, 0xE7, 0x6B, 0x6C, 0x9C, 0xB1, +0xBD, 0xB4, 0xCE, 0x36, 0xB5, 0x51, 0xA4, 0xD0, +0xB5, 0x11, 0xC5, 0x93, 0x9C, 0x90, 0xB5, 0x73, +0xB5, 0x53, 0xA4, 0xF1, 0xAD, 0x52, 0xB5, 0x94, +0xB5, 0x74, 0xB5, 0x74, 0xBD, 0x94, 0xBD, 0x94, +0xB5, 0x73, 0x9C, 0xB1, 0x5A, 0xCA, 0x4A, 0x4A, +0x4A, 0x6A, 0x4A, 0x6A, 0x8C, 0x50, 0x9C, 0xB1, +0x8C, 0x4F, 0x9C, 0xB0, 0xA4, 0xF1, 0xAD, 0x32, +0xB5, 0x52, 0xAD, 0x32, 0xBD, 0xB4, 0xB5, 0x52, +0xA4, 0xD1, 0xAD, 0x11, 0xBD, 0xB3, 0xB5, 0x72, +0xBD, 0x93, 0xA4, 0xD0, 0x9C, 0x8F, 0x9C, 0xB0, +0xB5, 0x52, 0xAC, 0xF0, 0xB5, 0x30, 0xBD, 0x71, +0xAD, 0x30, 0xB5, 0x51, 0xB5, 0x72, 0xB5, 0x72, +0xA4, 0xF0, 0x94, 0x6E, 0x94, 0x6E, 0x8C, 0x2D, +0x94, 0x6F, 0x83, 0xCC, 0x73, 0x4B, 0xA4, 0xD1, +0xB5, 0x53, 0xBD, 0x94, 0x83, 0xCD, 0x9C, 0x90, +0xAD, 0x12, 0x94, 0x70, 0x94, 0x2F, 0x94, 0x6F, +0x8C, 0x2F, 0x94, 0x4F, 0x83, 0xED, 0x8C, 0x0E, +0x94, 0x2F, 0x9C, 0x90, 0x9C, 0x70, 0x8C, 0x2F, +0x8C, 0x2E, 0x94, 0x6F, 0x9C, 0xB0, 0xA4, 0xD1, +0xAC, 0xF1, 0xB5, 0x53, 0xBD, 0x73, 0xB5, 0x32, +0xA4, 0xB0, 0x94, 0x4F, 0xA4, 0xD0, 0xA4, 0xD0, +0xA4, 0xD0, 0x9C, 0x90, 0x9C, 0x90, 0x9C, 0x8F, +0x94, 0x6F, 0x94, 0x4E, 0x9C, 0x90, 0xA4, 0xF1, +0xA4, 0xD0, 0xAD, 0x12, 0xAD, 0x11, 0xAD, 0x11, +0xAD, 0x12, 0xAD, 0x32, 0xAD, 0x12, 0xAD, 0x32, +0x9C, 0xB0, 0xA4, 0xF1, 0xA4, 0xD1, 0xAD, 0x32, +0xAD, 0x32, 0xAD, 0x32, 0xAC, 0xF1, 0xA4, 0xD1, +0x9C, 0xB0, 0x9C, 0xB0, 0x9C, 0xB0, 0xA4, 0xF1, +0xA4, 0xF2, 0xCE, 0x16, 0xDE, 0x99, 0xDE, 0x99, +0xAD, 0x33, 0xAD, 0x32, 0xB5, 0x73, 0xAD, 0x53, +0x83, 0xCE, 0xAD, 0x54, 0x94, 0x71, 0x73, 0x8E, +0x63, 0x2D, 0x8C, 0x51, 0xCE, 0x17, 0xC5, 0xD4, +0xC5, 0x94, 0xBD, 0x73, 0xCD, 0xF5, 0xC5, 0xB4, +0xBD, 0x72, 0xC5, 0xB3, 0xC5, 0x72, 0xAC, 0xD0, +0xA4, 0x8F, 0xB5, 0x52, 0xCD, 0xF5, 0xB5, 0x73, +0xA5, 0x55, 0xA5, 0x34, 0x9D, 0x14, 0x94, 0xB2, +0x94, 0x70, 0x8B, 0xED, 0x94, 0x2E, 0xAC, 0xF1, +0x83, 0x8B, 0x94, 0x4E, 0xAC, 0xF0, 0xAD, 0x11, +0xB5, 0x11, 0xAD, 0x11, 0xB5, 0x32, 0xA4, 0xAF, +0xB5, 0x31, 0xB5, 0x10, 0xAC, 0xAE, 0xA4, 0x6E, +0x94, 0x4E, 0x9C, 0xB0, 0x94, 0x90, 0xA4, 0xF1, +0x9C, 0xB1, 0x8C, 0x2E, 0x8C, 0x0D, 0x8C, 0x2E, +0x8C, 0x2E, 0x8C, 0x2E, 0x9C, 0x8F, 0x94, 0x4E, +0x9C, 0x4E, 0xA4, 0xAF, 0x9C, 0x4D, 0xA4, 0xAE, +0xA4, 0x8E, 0xAC, 0xCF, 0xA4, 0xAF, 0xAC, 0xF0, +0xAC, 0xD0, 0x9C, 0x6E, 0xA4, 0x8E, 0xAC, 0xCF, +0xC5, 0x92, 0xBD, 0x31, 0xB5, 0x10, 0xBD, 0x51, +0xA4, 0x8E, 0x94, 0x0D, 0x94, 0x0C, 0xA4, 0x6D, +0x9C, 0x2D, 0xA4, 0x6E, 0xA4, 0x8E, 0x94, 0x0D, +0x8B, 0xAB, 0x83, 0xAC, 0x8B, 0xCC, 0x94, 0x0D, +0x9C, 0x4D, 0xA4, 0x8F, 0x9C, 0x4D, 0x8B, 0xAB, +0x93, 0xEC, 0x9C, 0x4D, 0xB5, 0x10, 0xB5, 0x10, +0xA4, 0xAF, 0xA4, 0x6E, 0x9C, 0x6E, 0x9C, 0x2D, +0x94, 0x2D, 0x9C, 0x6E, 0xAC, 0xAE, 0xAC, 0xCF, +0xA4, 0x8E, 0x8C, 0x0D, 0x4A, 0x48, 0x39, 0xC6, +0x39, 0xA6, 0x39, 0xC6, 0x4A, 0x28, 0x52, 0x89, +0x52, 0x8A, 0x5A, 0xCA, 0x5A, 0xCB, 0x9C, 0xB2, +0x9C, 0xB2, 0xA5, 0x14, 0xAD, 0x76, 0xB5, 0x76, +0x84, 0x30, 0x41, 0xE8, 0x5A, 0x8A, 0x5A, 0xAB, +0x4A, 0x49, 0x63, 0x0B, 0xB5, 0x73, 0x8C, 0x2D, +0x7B, 0xAB, 0x7B, 0x8A, 0x9C, 0x4D, 0x8B, 0xEB, +0x9C, 0x4D, 0xA4, 0x8E, 0x9C, 0x6E, 0x83, 0x8B, +0x62, 0xA8, 0x83, 0xAC, 0x73, 0x4B, 0x6A, 0xEA, +0x8C, 0x0E, 0x9C, 0x6F, 0xA4, 0x8F, 0x73, 0x6B, +0x39, 0xC6, 0x29, 0x65, 0x39, 0xC7, 0x42, 0x07, +0x52, 0x69, 0x31, 0xA6, 0x39, 0xC7, 0x52, 0xAA, +0x73, 0x8E, 0x7B, 0xEF, 0x7B, 0xAE, 0x39, 0xA6, +0x52, 0x8A, 0x52, 0xAA, 0x7B, 0xCF, 0x73, 0xAE, +0x5A, 0xCB, 0x39, 0xC8, 0x63, 0x0D, 0xBD, 0xF7, +0xDE, 0xDA, 0xAD, 0x11, 0xB5, 0x30, 0xB5, 0x11, +0xCE, 0x58, 0xAD, 0x55, 0x8C, 0x72, 0xBD, 0x94, +0xD6, 0x75, 0xDE, 0x75, 0xD6, 0x55, 0xDE, 0x96, +0xD6, 0x55, 0xCD, 0xF4, 0xD6, 0x55, 0xDE, 0x75, +0xD6, 0x34, 0xCD, 0xF4, 0xB5, 0x52, 0xA4, 0xF1, +0x7B, 0x8C, 0x94, 0x6F, 0xB5, 0x53, 0xBD, 0x93, +0xA4, 0xF1, 0xAD, 0x32, 0xB5, 0x53, 0xAD, 0x11, +0xC5, 0xB3, 0xBD, 0x93, 0xBD, 0x73, 0xB5, 0x73, +0xAD, 0x52, 0xC5, 0xF5, 0xB5, 0x53, 0xB5, 0x31, +0xAC, 0xCF, 0xCD, 0xB3, 0xCD, 0x92, 0xCD, 0xB3, +0xCD, 0xD4, 0x52, 0x69, 0x39, 0xE8, 0x4A, 0x49, +0x73, 0x6D, 0xA4, 0xF1, 0x94, 0x4E, 0xAC, 0xF0, +0xC5, 0x73, 0xC5, 0x73, 0xA4, 0xB0, 0xAD, 0x32, +0xBD, 0xD5, 0xC5, 0xD5, 0xC5, 0xF5, 0xCE, 0x36, +0xC6, 0x16, 0xBD, 0xD5, 0xAD, 0x32, 0x94, 0x4F, +0x73, 0x8D, 0x52, 0x8A, 0x39, 0xE8, 0x41, 0xE9, +0x42, 0x09, 0x3A, 0x08, 0x83, 0xEF, 0x9C, 0xD1, +0x8C, 0x2F, 0x94, 0x6F, 0x9C, 0xB0, 0x9C, 0x90, +0x94, 0x6F, 0x9C, 0xB0, 0xA4, 0xF1, 0xB5, 0x73, +0x9C, 0xD0, 0xAD, 0x11, 0xB5, 0x93, 0xBD, 0xB3, +0xC5, 0xF5, 0xB5, 0x52, 0xAD, 0x11, 0xB5, 0x52, +0xB5, 0x51, 0xAD, 0x10, 0xB5, 0x30, 0xAD, 0x0F, +0xA4, 0xCF, 0xAD, 0x30, 0xB5, 0x72, 0xB5, 0x92, +0xBD, 0xB3, 0x9C, 0xAF, 0xB5, 0x51, 0xB5, 0x51, +0xBD, 0x93, 0xAD, 0x11, 0x8C, 0x0D, 0xB5, 0x53, +0xBD, 0x74, 0x9C, 0xB0, 0x94, 0x4F, 0x94, 0x4F, +0x83, 0xCD, 0x7B, 0x8C, 0x83, 0xAD, 0x94, 0x4F, +0x8C, 0x2E, 0x8C, 0x0E, 0x7B, 0x8C, 0x7B, 0x6C, +0x6B, 0x2B, 0x83, 0xEE, 0x9C, 0xB0, 0x9C, 0x90, +0x94, 0x70, 0x94, 0x4F, 0x8C, 0x0E, 0x7B, 0xAC, +0x7B, 0x8C, 0x8C, 0x2E, 0x83, 0xCD, 0x83, 0xCD, +0xA4, 0xD1, 0x9C, 0xB1, 0x8C, 0x0E, 0x94, 0x4F, +0x5A, 0xA8, 0x83, 0xCD, 0x8C, 0x2E, 0xA4, 0xD0, +0xBD, 0x93, 0xB5, 0x52, 0xAD, 0x32, 0xAD, 0x11, +0xA4, 0xF0, 0xB5, 0x32, 0xAC, 0xF1, 0xAD, 0x32, +0x9C, 0x6F, 0x9C, 0x6F, 0xA4, 0xD0, 0xB5, 0x32, +0xBD, 0x93, 0xAD, 0x31, 0xAC, 0xF1, 0xBD, 0x93, +0xBD, 0x93, 0xB5, 0x32, 0xB5, 0x73, 0xBD, 0x73, +0xBD, 0x73, 0xBD, 0x94, 0xBD, 0x94, 0xAD, 0x33, +0xCE, 0x58, 0xCE, 0x18, 0xC6, 0x38, 0xDE, 0xDB, +0xBD, 0xB6, 0xA4, 0xF2, 0xA4, 0xD1, 0x9C, 0xD1, +0xAD, 0x33, 0xC5, 0xD6, 0x8C, 0x50, 0x41, 0xE8, +0x39, 0xE8, 0x63, 0x2D, 0xB5, 0x75, 0xAD, 0x12, +0xA4, 0xB0, 0xA4, 0xB0, 0x9C, 0x90, 0x9C, 0x90, +0x9C, 0x8F, 0x9C, 0x8F, 0x9C, 0x6E, 0x94, 0x4E, +0xA4, 0xD1, 0xAC, 0xF1, 0x9C, 0x90, 0x94, 0x6F, +0xA5, 0x75, 0xA5, 0x35, 0x9D, 0x14, 0x94, 0xB2, +0x9C, 0x90, 0x8C, 0x0D, 0x9C, 0x8F, 0xA4, 0xD0, +0x94, 0x2D, 0xB5, 0x31, 0xB5, 0x31, 0xB5, 0x51, +0xB5, 0x52, 0xB5, 0x52, 0xB5, 0x52, 0xBD, 0x92, +0xC5, 0xB3, 0xBD, 0x72, 0xAC, 0xCF, 0xA4, 0x8E, +0xA4, 0xD0, 0x9C, 0xB0, 0x8C, 0x4F, 0x94, 0x6F, +0x9C, 0xB1, 0x9C, 0xD0, 0x94, 0x4E, 0xA4, 0xD1, +0xB5, 0x73, 0xAD, 0x11, 0xA4, 0xF0, 0x94, 0x6F, +0x9C, 0x8F, 0xAC, 0xF1, 0xAD, 0x31, 0xBD, 0x93, +0xB5, 0x72, 0xBD, 0x73, 0xAD, 0x11, 0xB5, 0x73, +0xBD, 0x73, 0xA4, 0xD0, 0x9C, 0x6D, 0xAC, 0xAE, +0xC5, 0xB2, 0xAC, 0xEF, 0xC5, 0x92, 0xBD, 0x31, +0xB5, 0x10, 0xAC, 0xF0, 0xA4, 0x8E, 0xA4, 0x8E, +0x94, 0x0C, 0x94, 0x0D, 0x94, 0x2D, 0x94, 0x2D, +0x8B, 0xCC, 0x83, 0xAC, 0x94, 0x2E, 0x9C, 0x6E, +0x9C, 0x8E, 0xAC, 0xF0, 0xAC, 0xF0, 0x9C, 0x8E, +0x8B, 0xEC, 0x93, 0xEC, 0x94, 0x0C, 0xA4, 0x6D, +0xB5, 0x10, 0xB5, 0x10, 0xB5, 0x10, 0xA4, 0xAF, +0x83, 0x8B, 0x7B, 0x6A, 0x94, 0x0C, 0x94, 0x0C, +0x94, 0x2D, 0x9C, 0x8F, 0x7B, 0xAD, 0x4A, 0x28, +0x39, 0xE7, 0x31, 0x85, 0x41, 0xE7, 0x41, 0xE7, +0x41, 0xE7, 0x4A, 0x48, 0x6B, 0x2C, 0x83, 0xEF, +0x7B, 0xEF, 0x9C, 0xD3, 0x8C, 0x71, 0x9C, 0xD3, +0xA4, 0xF3, 0x5A, 0xAB, 0x6B, 0x2D, 0x6B, 0x4D, +0x31, 0x66, 0x42, 0x28, 0xAD, 0x13, 0xAD, 0x12, +0xAC, 0xF0, 0xAC, 0xCF, 0xAC, 0xEF, 0xAC, 0xAE, +0x9C, 0x4D, 0x9C, 0x2D, 0x93, 0xEC, 0x8B, 0xED, +0x9C, 0x4E, 0xA4, 0x8F, 0x9C, 0x6E, 0xB5, 0x11, +0xC5, 0x92, 0xC5, 0x71, 0xC5, 0x71, 0xB4, 0xF0, +0xA4, 0x8F, 0x6B, 0x0B, 0x5A, 0xEB, 0x39, 0xE7, +0x31, 0x86, 0x31, 0xA6, 0x42, 0x07, 0x4A, 0x49, +0x63, 0x0C, 0x39, 0xE7, 0x31, 0x86, 0x5A, 0xAB, +0x6B, 0x4D, 0x6B, 0x6D, 0x94, 0xD2, 0xA5, 0x34, +0x73, 0x6E, 0x52, 0x8A, 0x42, 0x29, 0x94, 0x92, +0x8C, 0x30, 0xBD, 0x94, 0xB5, 0x31, 0xA4, 0xD0, +0xCE, 0x38, 0xAD, 0x35, 0x94, 0x92, 0xB5, 0x73, +0xCD, 0xF4, 0xC5, 0xD3, 0xBD, 0x92, 0xCD, 0xF3, +0xD6, 0x34, 0xD6, 0x55, 0xE6, 0xB6, 0xDE, 0x96, +0xDE, 0x75, 0xDE, 0x96, 0xD6, 0x15, 0xB5, 0x31, +0xAD, 0x31, 0xB5, 0x32, 0xCD, 0xF4, 0xD6, 0x35, +0xCE, 0x36, 0xBD, 0x93, 0xBD, 0x94, 0xB5, 0x52, +0xC5, 0xB3, 0xBD, 0x92, 0xBD, 0xB3, 0xBD, 0xB4, +0xC5, 0xD4, 0xBD, 0xD4, 0xB5, 0x72, 0xC5, 0xB3, +0xCD, 0xD3, 0xCD, 0x92, 0xCD, 0xB3, 0xCD, 0xB3, +0xC5, 0x93, 0x83, 0xCE, 0x42, 0x08, 0x42, 0x09, +0x42, 0x08, 0x4A, 0x49, 0x73, 0x6C, 0xA4, 0xB0, +0xBD, 0x52, 0xBD, 0x51, 0xA4, 0xF0, 0x9C, 0x8F, +0xAD, 0x32, 0xA4, 0xF2, 0x9C, 0xD1, 0x94, 0x90, +0x7B, 0xCE, 0x52, 0x69, 0x39, 0xE7, 0x39, 0xC7, +0x31, 0x87, 0x29, 0x46, 0x29, 0x46, 0x31, 0x87, +0x39, 0xA7, 0x39, 0xC7, 0x7B, 0xCE, 0x8C, 0x6F, +0x8C, 0x2E, 0x8C, 0x2E, 0x8C, 0x2E, 0x8C, 0x2E, +0x8C, 0x4E, 0x9C, 0xB0, 0xA5, 0x11, 0xB5, 0x73, +0xA4, 0xF1, 0xB5, 0x52, 0xC5, 0xF4, 0xC5, 0xD4, +0xBD, 0xD4, 0xB5, 0x52, 0xB5, 0x52, 0xAD, 0x32, +0xBD, 0xB3, 0xB5, 0x71, 0xBD, 0x71, 0xAD, 0x10, +0xB5, 0x71, 0xB5, 0x72, 0xB5, 0x52, 0xC5, 0xD4, +0xCE, 0x15, 0xAD, 0x31, 0xB5, 0x71, 0xB5, 0x51, +0xC5, 0xD3, 0xBD, 0xB3, 0xA4, 0xF0, 0xBD, 0x94, +0xBD, 0x73, 0x9C, 0xB0, 0xBD, 0x94, 0xBD, 0xB4, +0xB5, 0x53, 0xAD, 0x33, 0x9C, 0xB0, 0xA4, 0xF1, +0xAD, 0x53, 0xAD, 0x52, 0xA4, 0xF1, 0x8C, 0x2F, +0x83, 0xCE, 0xA4, 0xF1, 0xAD, 0x32, 0xBD, 0x93, +0xAD, 0x32, 0x9C, 0x90, 0x9C, 0xB0, 0x94, 0x6F, +0x6B, 0x2A, 0x8C, 0x2E, 0x73, 0x6B, 0x9C, 0xB1, +0xAD, 0x53, 0x94, 0x70, 0xA4, 0xD1, 0xA4, 0xD1, +0x6B, 0x2B, 0x83, 0xCD, 0x7B, 0x8B, 0x7B, 0xAC, +0x8C, 0x0D, 0x83, 0xED, 0x83, 0xEC, 0x83, 0xCC, +0x83, 0xCC, 0x83, 0xED, 0x8C, 0x2E, 0xA4, 0xF0, +0x8C, 0x0D, 0x83, 0xCD, 0x8B, 0xED, 0x8C, 0x0D, +0x83, 0xCC, 0x83, 0xCC, 0xAC, 0xF0, 0xBD, 0x72, +0xA4, 0xB0, 0xA4, 0xB0, 0xA4, 0xB0, 0x94, 0x4E, +0xA4, 0xF1, 0xAD, 0x32, 0xBD, 0x73, 0xB5, 0x54, +0xC6, 0x18, 0xC5, 0xF8, 0xE7, 0x1C, 0xE7, 0x3C, +0xC6, 0x38, 0xBD, 0xD6, 0xB5, 0x54, 0xB5, 0x73, +0xB5, 0x74, 0xB5, 0x74, 0x94, 0x91, 0x52, 0x8A, +0x5A, 0xCB, 0x73, 0xAF, 0xAD, 0x54, 0xB5, 0x74, +0xBD, 0x73, 0xB5, 0x52, 0xB5, 0x53, 0xB5, 0x53, +0xB5, 0x53, 0xB5, 0x32, 0xB5, 0x52, 0xB5, 0x52, +0xB5, 0x73, 0xBD, 0x73, 0xB5, 0x53, 0xB5, 0x52, +0xB5, 0xD5, 0xA5, 0x55, 0x9D, 0x14, 0x94, 0xD2, +0x94, 0x70, 0x7B, 0x6B, 0x9C, 0x8F, 0xA4, 0xAF, +0xA4, 0xF0, 0xB5, 0x31, 0x8C, 0x0D, 0xA4, 0xCF, +0xBD, 0x93, 0xB5, 0x52, 0xAD, 0x31, 0xBD, 0x72, +0xBD, 0x93, 0xC5, 0x93, 0xAC, 0xCF, 0xA4, 0x8E, +0xB5, 0x31, 0xA5, 0x11, 0x9C, 0xB0, 0x94, 0x70, +0xA4, 0xD1, 0x9C, 0xB0, 0x94, 0x8F, 0xBD, 0x93, +0xBD, 0xB4, 0xBD, 0xB4, 0xB5, 0x52, 0xA4, 0xD0, +0x9C, 0x8F, 0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x31, +0x9C, 0xAF, 0xAD, 0x31, 0xC5, 0xD4, 0xBD, 0x93, +0xC5, 0xD4, 0xAD, 0x11, 0xA4, 0x8E, 0xAC, 0xCF, +0xCD, 0xD3, 0xCD, 0xD3, 0xCD, 0xD3, 0xCD, 0xB2, +0xCD, 0xD3, 0xBD, 0x72, 0xBD, 0x51, 0xB5, 0x30, +0xA4, 0xCF, 0xA4, 0xAF, 0xAC, 0xF0, 0xBD, 0x51, +0xBD, 0x72, 0xBD, 0x52, 0xB5, 0x11, 0xA4, 0xAF, +0xB5, 0x10, 0xB5, 0x31, 0xBD, 0x51, 0xB5, 0x30, +0xBD, 0x51, 0xA4, 0x6E, 0x83, 0x8A, 0x9C, 0x4D, +0xAC, 0xD0, 0xAC, 0xCF, 0xAC, 0xCF, 0xAC, 0xF0, +0x94, 0x0D, 0x9C, 0x4D, 0x9C, 0x4E, 0xA4, 0x6E, +0x94, 0x0D, 0xA4, 0x8F, 0x94, 0x2F, 0x52, 0x68, +0x39, 0xA6, 0x29, 0x44, 0x41, 0xE7, 0x52, 0x69, +0x5A, 0xAA, 0x52, 0x8A, 0x62, 0xEB, 0x73, 0x8D, +0x94, 0x92, 0x94, 0xB2, 0x83, 0xF0, 0xA5, 0x14, +0xA4, 0xF4, 0x8C, 0x51, 0x8C, 0x52, 0x84, 0x10, +0x4A, 0x49, 0x29, 0x25, 0x52, 0x8A, 0x5A, 0xAA, +0x73, 0x2B, 0x6B, 0x0A, 0x73, 0x2A, 0x73, 0x4B, +0x7B, 0x6B, 0x73, 0x4B, 0x6B, 0x0A, 0x7B, 0x6B, +0x94, 0x0D, 0xA4, 0x6E, 0xA4, 0x8E, 0xA4, 0xAF, +0xA4, 0x8E, 0xA4, 0x8E, 0xA4, 0x8E, 0x9C, 0x4D, +0x94, 0x0D, 0x6B, 0x2B, 0x42, 0x07, 0x21, 0x24, +0x19, 0x04, 0x21, 0x24, 0x39, 0xE7, 0x4A, 0x48, +0x3A, 0x07, 0x29, 0x65, 0x39, 0xE7, 0x5A, 0xCB, +0x73, 0x8E, 0x8C, 0x71, 0xC6, 0x38, 0x9C, 0xD2, +0x63, 0x2D, 0x8C, 0x72, 0x73, 0x8F, 0x63, 0x0C, +0x84, 0x10, 0x8C, 0x30, 0xCD, 0xF6, 0xBD, 0x95, +0xC6, 0x18, 0xA5, 0x35, 0x94, 0x71, 0x94, 0x4F, +0x9C, 0x4E, 0xA4, 0x6E, 0xA4, 0x8E, 0xA4, 0x6D, +0x9C, 0x6D, 0x9C, 0x2C, 0x93, 0xEC, 0x94, 0x0D, +0xA4, 0x8E, 0xAC, 0xCF, 0xBD, 0x31, 0xAC, 0xD0, +0xA4, 0xD0, 0xB5, 0x52, 0xAD, 0x11, 0xAC, 0xF0, +0xCD, 0xF5, 0xBD, 0x73, 0xB5, 0x73, 0x9C, 0x8F, +0x9C, 0xB0, 0xB5, 0x52, 0xAD, 0x11, 0xBD, 0xB4, +0xB5, 0x73, 0xC5, 0xF5, 0xBD, 0x72, 0xDE, 0x55, +0xD5, 0xF4, 0xCD, 0xB3, 0xE6, 0x55, 0xDE, 0x55, +0xD6, 0x14, 0xB5, 0x53, 0x52, 0x69, 0x39, 0xC8, +0x39, 0xC7, 0x41, 0xE8, 0x39, 0xC8, 0x41, 0xC7, +0x5A, 0x89, 0x5A, 0x88, 0x4A, 0x07, 0x39, 0xC6, +0x39, 0x86, 0x31, 0x65, 0x29, 0x45, 0x29, 0x45, +0x29, 0x66, 0x31, 0x87, 0x29, 0x66, 0x29, 0x25, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x29, 0x26, +0x29, 0x46, 0x31, 0x86, 0x52, 0x89, 0x7B, 0xAD, +0x8C, 0x0E, 0x94, 0x4F, 0x7B, 0xCC, 0x84, 0x0D, +0xA4, 0xF1, 0xAD, 0x32, 0x8C, 0x2E, 0xBD, 0x94, +0xA4, 0xF1, 0xAD, 0x52, 0xC5, 0xF4, 0xBD, 0xD4, +0xC6, 0x15, 0xC5, 0xD4, 0xBD, 0x93, 0xB5, 0x52, +0xBD, 0xB3, 0xB5, 0x92, 0xBD, 0x92, 0xBD, 0x92, +0xC5, 0xD3, 0xC5, 0xF4, 0xCE, 0x15, 0xBD, 0x93, +0xC5, 0xF4, 0xBD, 0x93, 0xBD, 0x92, 0xBD, 0xB3, +0xB5, 0x72, 0xC5, 0xF4, 0xA4, 0xF0, 0xC5, 0xB4, +0xB5, 0x53, 0xAD, 0x11, 0xBD, 0xB4, 0xC5, 0xF5, +0xCE, 0x15, 0xC6, 0x15, 0xAD, 0x32, 0xAD, 0x52, +0xC5, 0xF5, 0xAD, 0x32, 0xBD, 0xB4, 0x94, 0x4F, +0xAD, 0x12, 0xBD, 0xB4, 0xBD, 0xB4, 0xB5, 0x93, +0xBD, 0xB4, 0xA4, 0xD1, 0xAD, 0x32, 0xAD, 0x32, +0x7B, 0x8C, 0x8C, 0x2E, 0x94, 0x70, 0x94, 0x6F, +0xAD, 0x33, 0x9C, 0x90, 0x83, 0xEE, 0xB5, 0x53, +0x7B, 0xCD, 0x9C, 0xB0, 0x9C, 0xB0, 0x9C, 0x90, +0xA4, 0xF1, 0x8C, 0x2E, 0x8C, 0x2E, 0x94, 0x8F, +0x94, 0x8F, 0x7B, 0xCD, 0x8C, 0x0E, 0x94, 0x6F, +0x9C, 0x8F, 0xA4, 0xF1, 0x94, 0x4E, 0x83, 0xED, +0x9C, 0x8F, 0x9C, 0xB0, 0xAC, 0xF0, 0xC5, 0x93, +0xA4, 0xD0, 0xBD, 0x94, 0xB5, 0x53, 0x94, 0x6F, +0xAD, 0x53, 0xB5, 0x94, 0xCE, 0x36, 0xBD, 0xD6, +0xBD, 0xD7, 0xD6, 0xBB, 0xCE, 0x7A, 0xB5, 0x56, +0xB5, 0x76, 0xEF, 0x3C, 0xCE, 0x37, 0xCE, 0x36, +0xCD, 0xF6, 0xC5, 0xD5, 0xAD, 0x53, 0x73, 0x6D, +0x63, 0x2D, 0x7B, 0xAF, 0x8C, 0x30, 0xB5, 0x94, +0x94, 0x4F, 0xAC, 0xF1, 0xA4, 0xB0, 0xA4, 0xB0, +0xBD, 0x93, 0xAD, 0x12, 0xAD, 0x11, 0x9C, 0x6F, +0x8C, 0x0D, 0xB5, 0x32, 0xBD, 0x73, 0xAD, 0x11, +0x95, 0x2F, 0xA5, 0x94, 0x9D, 0x34, 0x94, 0xB2, +0x94, 0x4F, 0x83, 0xAB, 0xA4, 0x8F, 0xA4, 0xAF, +0xB5, 0x52, 0xB5, 0x32, 0x8C, 0x0D, 0x94, 0x2D, +0xB5, 0x52, 0xB5, 0x31, 0xAD, 0x11, 0xBD, 0x72, +0xC5, 0x93, 0xC5, 0x92, 0xA4, 0x6E, 0xA4, 0x8E, +0xAD, 0x31, 0xB5, 0x73, 0xAD, 0x12, 0x94, 0x70, +0x94, 0x70, 0x9C, 0x90, 0xAD, 0x32, 0xB5, 0x73, +0xB5, 0x72, 0xCD, 0xF5, 0xB5, 0x52, 0xB5, 0x32, +0xAD, 0x12, 0xA4, 0xF1, 0x9C, 0xB0, 0x9C, 0xD0, +0x9C, 0x8F, 0xB5, 0x52, 0xAD, 0x11, 0xBD, 0xB4, +0xB5, 0x72, 0xA4, 0x8F, 0xAC, 0xAE, 0xAC, 0xAE, +0xDE, 0x35, 0xCD, 0xD3, 0xCD, 0xD3, 0xCD, 0xD2, +0xCD, 0xF3, 0xD5, 0xF3, 0xC5, 0xB2, 0xC5, 0x71, +0xC5, 0xB2, 0xD5, 0xF3, 0xCD, 0xB2, 0xD6, 0x34, +0xCD, 0xD3, 0xCD, 0xB3, 0xCD, 0xB3, 0xC5, 0x92, +0xCD, 0xD2, 0xCD, 0xB2, 0xCD, 0x92, 0xCD, 0xB2, +0xC5, 0x71, 0xBD, 0x31, 0x9C, 0x2C, 0xA4, 0x6D, +0xC5, 0x72, 0xAC, 0xCF, 0x93, 0xEB, 0xB5, 0x30, +0xBD, 0x51, 0xA4, 0x8E, 0x9C, 0x2D, 0x94, 0x0C, +0xA4, 0xCF, 0x8B, 0xED, 0x7B, 0x8C, 0x52, 0x89, +0x31, 0xA6, 0x29, 0x44, 0x42, 0x07, 0x52, 0x89, +0x4A, 0x28, 0x42, 0x07, 0x5A, 0xAA, 0x6B, 0x4C, +0x84, 0x10, 0x8C, 0x71, 0x8C, 0x31, 0x94, 0x72, +0xAD, 0x35, 0xB5, 0x97, 0xA4, 0xF4, 0x94, 0x71, +0x6B, 0x4D, 0x42, 0x08, 0x52, 0x69, 0x4A, 0x28, +0x7B, 0xAD, 0x73, 0x8D, 0x5A, 0xCA, 0x5A, 0xCA, +0x52, 0xA9, 0x52, 0x89, 0x52, 0x89, 0x7B, 0xAC, +0x8C, 0x0D, 0x8C, 0x0D, 0x6B, 0x2A, 0x5A, 0x88, +0x52, 0x68, 0x52, 0x48, 0x52, 0x89, 0x52, 0x88, +0x52, 0x48, 0x52, 0x69, 0x62, 0xEB, 0x5A, 0xCA, +0x39, 0xE7, 0x29, 0x44, 0x39, 0xC7, 0x39, 0xE7, +0x29, 0x65, 0x42, 0x28, 0x4A, 0x48, 0x52, 0x69, +0x63, 0x2C, 0x8C, 0x50, 0x8C, 0x50, 0x8C, 0x71, +0x8C, 0x51, 0x9D, 0x15, 0xA5, 0x35, 0xAD, 0x56, +0xAD, 0x35, 0xBD, 0xB6, 0xCE, 0x17, 0xC5, 0xD7, +0xC6, 0x38, 0xAD, 0x35, 0x8C, 0x71, 0x9C, 0x6F, +0xA4, 0xAF, 0x94, 0x0C, 0xA4, 0x8E, 0xA4, 0x8E, +0x9C, 0x6D, 0x9C, 0x4D, 0x9C, 0x6D, 0xA4, 0x8E, +0xB4, 0xF0, 0xBD, 0x51, 0xBD, 0x50, 0xC5, 0x92, +0xC5, 0xD4, 0xC5, 0xD4, 0xC5, 0xD4, 0xB5, 0x52, +0xBD, 0x72, 0xC5, 0xD4, 0xC5, 0xD5, 0xBD, 0x94, +0xBD, 0xB4, 0xB5, 0x73, 0xAD, 0x32, 0xAD, 0x12, +0xAC, 0xF1, 0xAD, 0x11, 0xA4, 0xD1, 0xA4, 0xF1, +0xA4, 0xD0, 0xA4, 0xB0, 0xA4, 0xB0, 0x9C, 0x90, +0x9C, 0x6F, 0x8C, 0x2F, 0x62, 0xEB, 0x29, 0x46, +0x31, 0x87, 0x31, 0x87, 0x39, 0xA7, 0x29, 0x45, +0x21, 0x04, 0x21, 0x04, 0x21, 0x05, 0x21, 0x05, +0x21, 0x25, 0x29, 0x25, 0x21, 0x25, 0x20, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x29, 0x26, 0x31, 0x66, 0x42, 0x08, +0x6B, 0x2B, 0x8C, 0x2E, 0x84, 0x0D, 0x9C, 0xB0, +0xB5, 0x73, 0xAD, 0x52, 0x8C, 0x4E, 0xBD, 0xD4, +0xA4, 0xD0, 0xBD, 0xB3, 0xC5, 0xF4, 0xBD, 0xD4, +0xCE, 0x35, 0xC5, 0xF4, 0xC6, 0x15, 0xBD, 0x93, +0xC5, 0xF4, 0xBD, 0xB2, 0xC5, 0xB3, 0xC5, 0xD3, +0xCE, 0x14, 0x9C, 0xD0, 0xAD, 0x32, 0xB5, 0x53, +0xC5, 0xF4, 0xB5, 0x93, 0xB5, 0x72, 0xCE, 0x34, +0xB5, 0x72, 0xC5, 0xF4, 0xA4, 0xD0, 0xC5, 0xB5, +0xB5, 0x53, 0xA4, 0xF1, 0xC5, 0xD4, 0xCE, 0x36, +0xBD, 0xB4, 0xC5, 0xD4, 0xB5, 0x73, 0xC5, 0xF5, +0xCE, 0x16, 0xC5, 0xF5, 0xC5, 0xF5, 0xAD, 0x12, +0xBD, 0xB4, 0xC5, 0xF5, 0xB5, 0x73, 0xB5, 0x73, +0xB5, 0x93, 0xAD, 0x52, 0xBD, 0x93, 0xBD, 0x94, +0x7B, 0xAD, 0x9C, 0x90, 0x9C, 0xB1, 0x9C, 0x90, +0xAD, 0x32, 0x94, 0x90, 0x52, 0x68, 0x8C, 0x2E, +0x5A, 0xC9, 0x5A, 0xC9, 0x62, 0xEA, 0x62, 0xEA, +0x94, 0x6F, 0xA4, 0xD1, 0x94, 0x8F, 0xA4, 0xD1, +0x9C, 0x90, 0x83, 0xED, 0x9C, 0xB0, 0xAD, 0x32, +0xAD, 0x32, 0xB5, 0x52, 0xA4, 0xD0, 0x8C, 0x0E, +0xAD, 0x32, 0xA4, 0xD1, 0x9C, 0x6F, 0xB5, 0x52, +0xAD, 0x11, 0xB5, 0x53, 0xB5, 0x32, 0xA4, 0xF1, +0xB5, 0x94, 0xB5, 0x94, 0xC5, 0xF6, 0xCE, 0x38, +0xD6, 0x9A, 0xC6, 0x39, 0x8C, 0x72, 0xBD, 0xF8, +0xE6, 0xFC, 0xD6, 0xBA, 0xBD, 0xF7, 0x9C, 0xD2, +0x9C, 0xB1, 0xCE, 0x36, 0xC6, 0x16, 0x7B, 0xCE, +0x62, 0xEB, 0x73, 0x8E, 0x8C, 0x30, 0xBD, 0xD6, +0xAD, 0x12, 0xB5, 0x52, 0x9C, 0x8F, 0xAD, 0x11, +0xBD, 0xB4, 0xA4, 0xF1, 0xA4, 0xF0, 0xAD, 0x10, +0xA4, 0xD0, 0xD6, 0x56, 0xD6, 0x35, 0xBD, 0xB3, +0xA5, 0xB2, 0x9D, 0x54, 0x9D, 0x14, 0x94, 0xB2, +0x7B, 0xAC, 0x7B, 0x6A, 0x83, 0xAC, 0x94, 0x4E, +0xAC, 0xF1, 0xAC, 0xF1, 0xAD, 0x11, 0xA4, 0xD0, +0xAD, 0x11, 0xBD, 0x72, 0xBD, 0x73, 0xC5, 0xD4, +0xBD, 0x72, 0xCD, 0xD3, 0xAC, 0xCF, 0xAC, 0xCF, +0x83, 0xAB, 0xB5, 0x52, 0xA5, 0x11, 0x8C, 0x0E, +0x94, 0x90, 0xAD, 0x12, 0xA4, 0xD1, 0x9C, 0xAF, +0xC5, 0xD4, 0xC5, 0xD4, 0xA4, 0xD0, 0xC5, 0xF5, +0xBD, 0x93, 0xAD, 0x32, 0xA4, 0xF1, 0xA4, 0xF1, +0x9C, 0xD0, 0xBD, 0x94, 0xB5, 0x73, 0xBD, 0x93, +0xC5, 0xB4, 0x94, 0x2D, 0xBD, 0x30, 0xAC, 0xCE, +0xC5, 0x92, 0xBD, 0x10, 0xCD, 0xD2, 0xCD, 0xB2, +0xCD, 0xD2, 0xD5, 0xF3, 0xD6, 0x13, 0xCD, 0xD2, +0xCD, 0xD2, 0xD5, 0xD3, 0xCD, 0xB2, 0xD6, 0x13, +0xCD, 0xB2, 0xD5, 0xF3, 0xD5, 0xF3, 0xD5, 0xF3, +0xCD, 0xB2, 0xCD, 0x92, 0xCD, 0x91, 0xCD, 0x92, +0xC5, 0x51, 0xC5, 0x30, 0xAC, 0x8E, 0xAC, 0x8D, +0xBD, 0x51, 0xB5, 0x10, 0xBD, 0x31, 0xBD, 0x51, +0x94, 0x2D, 0xBD, 0x31, 0xAC, 0xAF, 0xA4, 0x8F, +0xAC, 0xF0, 0x94, 0x4E, 0x94, 0x6F, 0x8C, 0x0E, +0x52, 0x48, 0x31, 0xA6, 0x39, 0xC6, 0x31, 0x65, +0x39, 0xC6, 0x4A, 0x48, 0x52, 0x89, 0x52, 0x89, +0x6B, 0x4D, 0x73, 0xAE, 0x94, 0x71, 0x94, 0x92, +0xA5, 0x35, 0xA4, 0xF4, 0x7B, 0x8E, 0x83, 0xCF, +0x73, 0x8E, 0x62, 0xEB, 0x4A, 0x69, 0x4A, 0x49, +0x7B, 0xAE, 0xAD, 0x13, 0x84, 0x0F, 0x73, 0x8D, +0x6B, 0x4C, 0x6B, 0x6D, 0x73, 0x6D, 0x8C, 0x4F, +0x94, 0x4E, 0x8C, 0x0D, 0x83, 0xCD, 0x7B, 0xAD, +0x73, 0xAD, 0x73, 0xAD, 0x83, 0xEE, 0x73, 0x6C, +0x6B, 0x4C, 0x73, 0x6C, 0x8C, 0x2F, 0x94, 0x90, +0x8C, 0x4F, 0x4A, 0x68, 0x31, 0xA6, 0x39, 0xE7, +0x31, 0x85, 0x39, 0xE7, 0x42, 0x07, 0x4A, 0x49, +0x5A, 0xCA, 0x5A, 0xCA, 0x6B, 0x6D, 0x7B, 0xEF, +0x94, 0xB3, 0x9C, 0xD4, 0xAD, 0x55, 0x8C, 0x52, +0x7B, 0xAF, 0x73, 0x6E, 0xA5, 0x14, 0xBD, 0xD7, +0xCE, 0x39, 0xB5, 0x96, 0x94, 0x72, 0x8C, 0x0E, +0x9C, 0x8F, 0x8B, 0xEC, 0xAD, 0x10, 0x7B, 0x8B, +0x6B, 0x29, 0x83, 0xEC, 0x8C, 0x0C, 0x8B, 0xED, +0x8B, 0xEC, 0xAC, 0xCF, 0xB5, 0x30, 0xBD, 0x52, +0xC5, 0xB4, 0x94, 0x4F, 0x94, 0x4E, 0x9C, 0xB0, +0xA4, 0xF0, 0xA4, 0xD0, 0xA4, 0xF1, 0xA4, 0xD1, +0xA4, 0xD1, 0xA4, 0xB0, 0xA4, 0xD1, 0xAC, 0xF1, +0xAC, 0xF1, 0xA4, 0xF1, 0xAD, 0x32, 0xAD, 0x12, +0xAD, 0x32, 0xAD, 0x12, 0xAD, 0x32, 0xB5, 0x33, +0xB5, 0x53, 0xAC, 0xF2, 0x83, 0xCE, 0x31, 0x66, +0x29, 0x46, 0x29, 0x66, 0x29, 0x66, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x20, 0xE5, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x25, 0x29, 0x45, +0x4A, 0x49, 0x83, 0xEE, 0x84, 0x0D, 0x8C, 0x2E, +0x94, 0x6F, 0x94, 0x6F, 0x8C, 0x0E, 0xAD, 0x32, +0x8C, 0x2E, 0xA4, 0xD1, 0xB5, 0x73, 0xA4, 0xF1, +0x94, 0x6F, 0x94, 0x6F, 0xC5, 0xF5, 0xC5, 0xD4, +0xC5, 0xD4, 0xC5, 0xD3, 0xBD, 0xB3, 0xBD, 0xB2, +0xBD, 0xB3, 0x8C, 0x2F, 0xAD, 0x74, 0xB5, 0x94, +0xCE, 0x35, 0xC5, 0xD4, 0xBD, 0xB3, 0xBD, 0x93, +0xBD, 0x93, 0xB5, 0x72, 0xA4, 0xF1, 0xC5, 0xD4, +0xA4, 0xD1, 0xA4, 0xF1, 0xB5, 0x73, 0xD6, 0x56, +0xC5, 0xD5, 0xBD, 0xB4, 0xCE, 0x36, 0xCE, 0x36, +0xC5, 0xF5, 0xCE, 0x36, 0xB5, 0x73, 0xAD, 0x11, +0xBD, 0xB4, 0xCE, 0x15, 0xBD, 0xB3, 0xCE, 0x15, +0xDE, 0x97, 0xBD, 0xB4, 0xBD, 0xB4, 0xC5, 0xD5, +0x83, 0xEE, 0x9C, 0xB0, 0x9C, 0x90, 0xA4, 0xD1, +0xAD, 0x32, 0x8C, 0x2E, 0x5A, 0xC9, 0xAD, 0x33, +0xA4, 0xF1, 0x52, 0x89, 0x4A, 0x48, 0x73, 0x8D, +0x9C, 0xB0, 0x9C, 0xD1, 0xA4, 0xF1, 0x94, 0x8F, +0xA4, 0xF1, 0xAD, 0x12, 0xAD, 0x32, 0xCE, 0x15, +0xB5, 0x53, 0xCE, 0x36, 0xBD, 0x94, 0xA4, 0xD1, +0xBD, 0xB4, 0x6B, 0x2B, 0x4A, 0x27, 0x6B, 0x2B, +0x9C, 0xB0, 0xB5, 0x32, 0xAD, 0x12, 0xA4, 0xF1, +0xBD, 0xD4, 0x9C, 0xB1, 0x73, 0x8E, 0xA5, 0x14, +0xCE, 0x3A, 0xCE, 0x7A, 0xCE, 0x7A, 0xDE, 0xDB, +0xCE, 0x7A, 0x8C, 0x31, 0xAD, 0x35, 0xB5, 0x96, +0xBD, 0xD6, 0xCE, 0x37, 0xB5, 0x74, 0x73, 0x8D, +0x4A, 0x49, 0x52, 0x8A, 0x7B, 0xCF, 0x94, 0x91, +0xAD, 0x12, 0xAD, 0x32, 0x9C, 0xB0, 0xB5, 0x53, +0xC5, 0xD4, 0xCE, 0x35, 0xCE, 0x15, 0xC5, 0xD4, +0xC5, 0xF4, 0xD6, 0x76, 0xCE, 0x55, 0xBD, 0xB3, +0xA5, 0x93, 0xA5, 0x54, 0x9C, 0xF3, 0x94, 0x71, +0x62, 0xC9, 0x6A, 0xE9, 0x73, 0x2A, 0x7B, 0x6B, +0x8B, 0xCB, 0x94, 0x2C, 0x94, 0x2D, 0x9C, 0x4E, +0xA4, 0x8E, 0xA4, 0xCF, 0x9C, 0x4D, 0xAC, 0xCF, +0x9C, 0x6E, 0xAC, 0xCF, 0xB4, 0xEF, 0xB5, 0x10, +0x94, 0x2D, 0x94, 0x4E, 0x9C, 0xB0, 0x84, 0x0E, +0x8C, 0x2E, 0x9C, 0xB0, 0x9C, 0xB0, 0xBD, 0xD4, +0xD6, 0x56, 0xCE, 0x35, 0xC5, 0xD4, 0xBD, 0xB3, +0xBD, 0xD4, 0xBD, 0xB3, 0xAD, 0x32, 0xAD, 0x11, +0xAD, 0x32, 0xBD, 0xD4, 0xC5, 0xD4, 0xC5, 0xD4, +0xC5, 0xB4, 0x73, 0x2A, 0xAC, 0xCF, 0xA4, 0x6D, +0xC5, 0x70, 0xB5, 0x0F, 0xCD, 0x92, 0xAC, 0x8E, +0xAC, 0x8E, 0xB5, 0x0F, 0xBD, 0x30, 0xCD, 0xB2, +0xCD, 0xB2, 0xCD, 0x92, 0xC5, 0x71, 0xCD, 0x92, +0xC5, 0x71, 0xC5, 0x51, 0xBD, 0x30, 0xBD, 0x30, +0xC5, 0x71, 0xC5, 0x30, 0xC5, 0x30, 0xBD, 0x10, +0xC5, 0x30, 0xBD, 0x10, 0xBC, 0xEF, 0xAC, 0xAE, +0x94, 0x0C, 0xC5, 0x91, 0xCD, 0xD3, 0xBD, 0x71, +0xBD, 0x31, 0xCD, 0xB2, 0xBD, 0x51, 0xBD, 0x51, +0xB5, 0x11, 0xB5, 0x11, 0xAD, 0x10, 0xC5, 0xB3, +0x8B, 0xEE, 0x52, 0x48, 0x41, 0xE7, 0x31, 0xA5, +0x39, 0xC6, 0x39, 0xC6, 0x41, 0xE7, 0x52, 0x69, +0x62, 0xEB, 0x7B, 0xEF, 0x84, 0x30, 0x8C, 0x71, +0x8C, 0x31, 0xAD, 0x14, 0x94, 0x51, 0x73, 0x6D, +0x73, 0x6D, 0x63, 0x0C, 0x4A, 0x49, 0x39, 0xE7, +0x7B, 0x8D, 0xAD, 0x33, 0xAD, 0x34, 0x7B, 0xCE, +0x73, 0xAE, 0x7B, 0xCE, 0x6B, 0x6D, 0x94, 0x6F, +0x94, 0x6F, 0x9C, 0xB0, 0x94, 0x90, 0x94, 0x70, +0x8C, 0x70, 0x8C, 0x4F, 0x83, 0xCE, 0x7B, 0xCE, +0x7B, 0xCE, 0x73, 0x8C, 0x73, 0x8C, 0x7B, 0xCD, +0x7B, 0xEE, 0x63, 0x2B, 0x63, 0x0B, 0x42, 0x07, +0x42, 0x07, 0x4A, 0x28, 0x42, 0x07, 0x42, 0x28, +0x52, 0xAA, 0x5A, 0xEB, 0x63, 0x0C, 0x8C, 0x71, +0x94, 0xB3, 0x94, 0x92, 0x73, 0xAF, 0x63, 0x0C, +0x84, 0x10, 0x52, 0x6A, 0x63, 0x0D, 0xB5, 0xB7, +0xD6, 0xBB, 0xCE, 0x59, 0xC6, 0x18, 0xBD, 0x95, +0x83, 0xED, 0x9C, 0xB0, 0xAD, 0x52, 0xA4, 0xD1, +0x8C, 0x4E, 0x94, 0x4E, 0x94, 0x6E, 0x8C, 0x2E, +0x8C, 0x0E, 0x83, 0xED, 0xAD, 0x31, 0xB5, 0x52, +0xB5, 0x32, 0x94, 0x2E, 0x8C, 0x0D, 0xA4, 0xF1, +0x8C, 0x2E, 0x83, 0xED, 0x83, 0xED, 0x94, 0x4E, +0x9C, 0x8F, 0x8C, 0x2E, 0x9C, 0x6F, 0x94, 0x4E, +0x8C, 0x2E, 0x7B, 0x8C, 0x83, 0xAD, 0x83, 0xCC, +0x7B, 0xAC, 0x7B, 0xAC, 0x83, 0xAC, 0x83, 0xED, +0x94, 0x6F, 0x8C, 0x0E, 0x83, 0xEE, 0x52, 0x69, +0x21, 0x25, 0x29, 0x46, 0x29, 0x46, 0x29, 0x25, +0x21, 0x05, 0x18, 0xE4, 0x18, 0xE4, 0x21, 0x05, +0x18, 0xE4, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, +0x18, 0xC4, 0x18, 0xE4, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x18, 0xE4, 0x4A, 0x49, 0x6B, 0x4D, +0x41, 0xE8, 0x5A, 0xAA, 0x84, 0x0E, 0x7B, 0x8C, +0x5A, 0x89, 0x52, 0x68, 0x62, 0xEA, 0x83, 0xED, +0xA4, 0xD1, 0xAD, 0x53, 0xAD, 0x54, 0xB5, 0x74, +0xB5, 0x74, 0xAD, 0x33, 0xA4, 0xF1, 0xA4, 0xB0, +0x9C, 0x8F, 0x9C, 0x8F, 0x9C, 0xAF, 0xA4, 0xB0, +0xA4, 0xF0, 0x9C, 0x90, 0x9C, 0xD1, 0xA5, 0x11, +0x9C, 0x90, 0xA4, 0xF1, 0xAD, 0x11, 0xAD, 0x11, +0x9C, 0xB0, 0x9C, 0x8F, 0x9C, 0x8F, 0x9C, 0x8F, +0x8C, 0x2E, 0x7B, 0x8C, 0x6B, 0x4B, 0x84, 0x0E, +0xAD, 0x12, 0xBD, 0x73, 0xD6, 0x36, 0xCD, 0xF5, +0xC5, 0xD4, 0xCE, 0x15, 0xC5, 0xB4, 0xB5, 0x73, +0xC5, 0xD4, 0xCE, 0x15, 0xB5, 0x72, 0xBD, 0xB3, +0xCE, 0x35, 0xCE, 0x15, 0xCE, 0x35, 0xAD, 0x11, +0x7B, 0x8C, 0x94, 0x6F, 0x94, 0x6F, 0x9C, 0xB0, +0xAD, 0x12, 0x83, 0xCD, 0x9C, 0xD1, 0xC5, 0xF5, +0xC5, 0xD4, 0xBD, 0xB4, 0xAD, 0x32, 0xAD, 0x12, +0xA4, 0xD1, 0x94, 0x4F, 0xA4, 0xD1, 0x8C, 0x2E, +0x94, 0x4F, 0x9C, 0x8F, 0xAD, 0x11, 0xBD, 0x73, +0xBD, 0x73, 0xC5, 0xB4, 0xB5, 0x73, 0xAD, 0x32, +0xB5, 0x53, 0x52, 0x69, 0x4A, 0x69, 0x6B, 0x2B, +0x9C, 0xB1, 0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x53, +0xB5, 0x73, 0x9C, 0xB1, 0x4A, 0x49, 0x73, 0x8E, +0xA5, 0x35, 0xB5, 0x76, 0xBD, 0xB8, 0xD6, 0x7B, +0xDE, 0xDC, 0xDE, 0xDC, 0xD6, 0x9A, 0xBD, 0xD7, +0xBD, 0xD6, 0xCE, 0x57, 0xCE, 0x56, 0x8C, 0x4F, +0x52, 0x8A, 0x63, 0x2C, 0x7B, 0xCF, 0x7B, 0xCF, +0x8C, 0x2F, 0xB5, 0x52, 0xA4, 0xB0, 0xB5, 0x53, +0xBD, 0xB4, 0xCE, 0x35, 0xCE, 0x15, 0xAD, 0x31, +0xAD, 0x31, 0xC5, 0xF4, 0xCE, 0x55, 0xBD, 0xD4, +0xAD, 0xD5, 0xAE, 0x16, 0xB6, 0x16, 0xB5, 0xF6, +0x9D, 0x12, 0x7B, 0x8C, 0x7B, 0x4B, 0x83, 0xCC, +0x8B, 0xCB, 0x83, 0xAB, 0x94, 0x0C, 0x93, 0xEC, +0x9C, 0x2D, 0x9C, 0x4D, 0xA4, 0x8E, 0xA4, 0x8E, +0xAC, 0xCF, 0xB4, 0xF0, 0xBD, 0x30, 0xBD, 0x51, +0xBD, 0x30, 0xB5, 0x10, 0xAC, 0xD0, 0xA4, 0xD0, +0xA4, 0xD0, 0x9C, 0x8F, 0x9C, 0x8F, 0xA4, 0xCF, +0xA4, 0xCF, 0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0xCF, +0xAC, 0xF0, 0xA4, 0xD0, 0x9C, 0xAF, 0x9C, 0x8F, +0xA4, 0xF0, 0xB5, 0x52, 0xBD, 0x93, 0xB5, 0x52, +0x94, 0x4E, 0x9C, 0x4D, 0xB5, 0x10, 0xAC, 0x8D, +0x94, 0x0C, 0x9C, 0x4C, 0xB4, 0xCF, 0xAC, 0xAE, +0xB4, 0xCE, 0xB4, 0xCE, 0xAC, 0x8E, 0xB4, 0xEF, +0xC5, 0x71, 0xAC, 0xAE, 0x9C, 0x0C, 0xAC, 0x8E, +0x9C, 0x4D, 0xB4, 0xEF, 0xC5, 0x71, 0xAC, 0x8E, +0xC5, 0x31, 0xAC, 0x8E, 0xAC, 0x6D, 0xAC, 0x6D, +0xB4, 0xCF, 0x93, 0xAB, 0xAC, 0x8E, 0xB4, 0xCF, +0x83, 0x8A, 0x83, 0xCB, 0xBD, 0x72, 0xD5, 0xF3, +0xD5, 0xF4, 0xC5, 0x71, 0xBD, 0x51, 0xC5, 0x92, +0xB5, 0x11, 0xB5, 0x31, 0xC5, 0x92, 0xC5, 0xB4, +0xCD, 0xD5, 0x83, 0xCD, 0x31, 0x85, 0x31, 0x65, +0x39, 0xC6, 0x39, 0xC6, 0x42, 0x07, 0x4A, 0x48, +0x52, 0x8A, 0x5A, 0xCB, 0x7B, 0xEF, 0x83, 0xEF, +0x83, 0xEF, 0x9C, 0x71, 0x8B, 0xEF, 0x83, 0xEF, +0x6B, 0x2D, 0x6B, 0x4D, 0x4A, 0x69, 0x31, 0xA6, +0x5A, 0xAA, 0x8C, 0x30, 0xB5, 0x74, 0x84, 0x2F, +0x7B, 0xEE, 0x7B, 0xCF, 0x63, 0x0B, 0x9C, 0x90, +0x94, 0x6F, 0xB5, 0x52, 0xAD, 0x12, 0x9C, 0xB1, +0x9C, 0xB0, 0x9C, 0xD1, 0x94, 0x70, 0x9C, 0xB1, +0x94, 0x90, 0x94, 0x6F, 0x9C, 0xB0, 0x9C, 0xB0, +0x84, 0x0E, 0x83, 0xEE, 0x84, 0x0F, 0x73, 0xAE, +0x5A, 0xAA, 0x42, 0x07, 0x42, 0x28, 0x42, 0x07, +0x52, 0x89, 0x5A, 0xCA, 0x4A, 0x69, 0x6B, 0x6D, +0x7B, 0xCF, 0x7B, 0xAF, 0x52, 0x8A, 0x4A, 0x29, +0x5A, 0xCB, 0x6B, 0x4D, 0x94, 0xB3, 0xC6, 0x19, +0xC6, 0x39, 0x7B, 0xF0, 0x9C, 0xB2, 0xB5, 0x33, +0x83, 0xCD, 0x9C, 0xB0, 0xA5, 0x11, 0xAD, 0x32, +0x8C, 0x2E, 0x8C, 0x2E, 0xA4, 0xD0, 0x94, 0x4E, +0x94, 0x4F, 0x83, 0xCD, 0xB5, 0x73, 0xBD, 0x73, +0xB5, 0x52, 0x7B, 0x6B, 0x8C, 0x2E, 0xB5, 0x52, +0xAD, 0x31, 0x9C, 0x8F, 0x8C, 0x4D, 0xAD, 0x10, +0xAD, 0x11, 0xAD, 0x31, 0xB5, 0x52, 0xBD, 0xB3, +0xB5, 0x52, 0x9C, 0xB0, 0x9C, 0xB0, 0x9C, 0x90, +0xB5, 0x53, 0x9C, 0x6F, 0xB5, 0x32, 0x9C, 0xB0, +0xA4, 0xD0, 0x9C, 0x90, 0x73, 0x6C, 0x7B, 0xAE, +0x21, 0x05, 0x21, 0x25, 0x21, 0x05, 0x18, 0xE4, +0x10, 0xA3, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x10, 0xA3, 0x18, 0xA3, 0x21, 0x05, 0x18, 0xC4, +0x10, 0xA3, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC3, +0x18, 0xA3, 0x18, 0xC4, 0x18, 0xE4, 0x21, 0x05, +0x20, 0xE5, 0x18, 0xC4, 0x62, 0xEC, 0xB5, 0x55, +0x94, 0x71, 0x4A, 0x29, 0x31, 0x86, 0x31, 0x66, +0x29, 0x46, 0x29, 0x25, 0x29, 0x25, 0x31, 0x66, +0x5A, 0xA9, 0x7B, 0xAE, 0x94, 0x71, 0xA4, 0xF2, +0xAD, 0x33, 0xAD, 0x33, 0xAD, 0x32, 0xB5, 0x53, +0xBD, 0x94, 0xC5, 0xD4, 0xC5, 0x94, 0xC5, 0xB4, +0xCD, 0xF5, 0xCE, 0x16, 0xCD, 0xF5, 0xBD, 0xB4, +0xBD, 0x94, 0x9C, 0xD1, 0xA4, 0xD1, 0x9C, 0xB0, +0x8C, 0x0E, 0x7B, 0xAD, 0x83, 0xED, 0x83, 0xCD, +0xA4, 0xD0, 0xA4, 0xD1, 0x9C, 0x90, 0x9C, 0x90, +0x9C, 0x90, 0x94, 0x4F, 0x8C, 0x2E, 0x8C, 0x0E, +0x83, 0xED, 0x83, 0xED, 0x8B, 0xEE, 0x7B, 0xAD, +0x83, 0xED, 0x8C, 0x2E, 0x8C, 0x0E, 0x94, 0x4E, +0xA4, 0xD0, 0xA4, 0xF1, 0x9C, 0x90, 0x8C, 0x2E, +0x8C, 0x2E, 0x94, 0x4F, 0x8C, 0x2E, 0x94, 0x6F, +0x94, 0x90, 0x73, 0x4B, 0xAD, 0x12, 0xAD, 0x11, +0xB5, 0x52, 0xB5, 0x72, 0xAD, 0x32, 0x9C, 0xB0, +0x94, 0x6F, 0x8C, 0x2E, 0x7B, 0xAC, 0x83, 0xED, +0x94, 0x4E, 0x9C, 0xB0, 0xB5, 0x52, 0xC5, 0xB3, +0xC5, 0xB4, 0xC5, 0xB4, 0xB5, 0x52, 0xA4, 0xD0, +0xA4, 0xD0, 0x6B, 0x2B, 0x73, 0x6C, 0x83, 0xCE, +0xA4, 0xD1, 0xB5, 0x52, 0xB5, 0x73, 0xB5, 0x93, +0xC6, 0x15, 0xCE, 0x77, 0xA5, 0x33, 0x63, 0x2C, +0x84, 0x10, 0xAD, 0x56, 0xA4, 0xF5, 0xC6, 0x19, +0xDE, 0xDC, 0xA4, 0xF4, 0x9C, 0xB3, 0x9C, 0xB3, +0x9C, 0x92, 0xC5, 0xD6, 0xCE, 0x36, 0x7B, 0xAD, +0x4A, 0x69, 0x5A, 0xCB, 0x73, 0x8D, 0x6B, 0x4C, +0x8C, 0x2F, 0xB5, 0x32, 0xA4, 0xF1, 0xB5, 0x73, +0xB5, 0x73, 0xC5, 0xF4, 0xCE, 0x15, 0xBD, 0xB3, +0xBD, 0xB3, 0xCE, 0x35, 0xD6, 0x55, 0xBD, 0xD4, +0xB6, 0x55, 0xBE, 0xD8, 0xC6, 0xF8, 0xCE, 0xF8, +0xC6, 0xB8, 0xB5, 0xD5, 0x83, 0xED, 0x6B, 0x29, +0x6B, 0x2A, 0x73, 0x4A, 0x7B, 0x8B, 0x6B, 0x09, +0x73, 0x2A, 0x83, 0xCC, 0x7B, 0x6A, 0x73, 0x4A, +0x62, 0xC8, 0x5A, 0x87, 0x6A, 0xE9, 0x73, 0x4A, +0x8B, 0xEC, 0x93, 0xEC, 0x8B, 0xEC, 0x9C, 0x4E, +0x9C, 0x4E, 0xA4, 0x8F, 0xAC, 0xAF, 0xAC, 0xAF, +0xB5, 0x10, 0xB5, 0x10, 0xB4, 0xEF, 0xAC, 0xCF, +0xAC, 0xCF, 0xAC, 0xCF, 0xA4, 0xAF, 0xAC, 0xCF, +0xAC, 0xAF, 0xA4, 0x8F, 0xA4, 0x8E, 0xA4, 0x8E, +0xAC, 0xCF, 0xB5, 0x10, 0xB5, 0x0F, 0xAC, 0xCE, +0xAC, 0xCF, 0xAC, 0xAE, 0xA4, 0x6D, 0xA4, 0x4D, +0x9C, 0x0C, 0x93, 0xEB, 0x93, 0xCB, 0x94, 0x0C, +0x9C, 0x2C, 0xA4, 0x4D, 0xA4, 0x8E, 0xA4, 0x8E, +0x9C, 0x2C, 0xA4, 0x4D, 0xA4, 0x6D, 0xA4, 0x4C, +0xA4, 0x6D, 0x9B, 0xEB, 0xAC, 0x8D, 0xAC, 0xAE, +0xB4, 0xAE, 0xA4, 0x4D, 0xA4, 0x2C, 0xBD, 0x0F, +0xB4, 0xCF, 0x7B, 0x4A, 0x73, 0x09, 0x83, 0x8A, +0x94, 0x0C, 0x8B, 0xCB, 0x9C, 0x2D, 0xAC, 0xAF, +0xA4, 0xAF, 0xC5, 0x93, 0xB5, 0x31, 0xC5, 0xD3, +0xCE, 0x14, 0xA4, 0xD0, 0x63, 0x0A, 0x31, 0xA5, +0x39, 0xA6, 0x39, 0xC6, 0x42, 0x07, 0x41, 0xE7, +0x39, 0xC7, 0x52, 0x8A, 0x6B, 0x4D, 0x5A, 0xCB, +0x4A, 0x28, 0x4A, 0x08, 0x41, 0xC7, 0x5A, 0xCB, +0x4A, 0x49, 0x63, 0x0C, 0x52, 0x6A, 0x29, 0x65, +0x31, 0x66, 0x7B, 0xAE, 0x8C, 0x0F, 0x84, 0x0F, +0x7B, 0xEF, 0x73, 0xAE, 0x63, 0x0B, 0xA4, 0xF2, +0x94, 0x4E, 0xB5, 0x52, 0xBD, 0x73, 0xBD, 0x93, +0xB5, 0x32, 0xAD, 0x11, 0xAD, 0x12, 0xB5, 0x73, +0xAD, 0x32, 0xAD, 0x11, 0xB5, 0x73, 0xB5, 0x32, +0xA4, 0xD1, 0xA5, 0x11, 0x9C, 0x90, 0x9C, 0xB0, +0x7B, 0x8D, 0x73, 0x8D, 0x39, 0xA6, 0x39, 0xE6, +0x42, 0x27, 0x42, 0x28, 0x4A, 0x68, 0x63, 0x0B, +0x5A, 0xCA, 0x63, 0x0B, 0x52, 0x69, 0x41, 0xE8, +0x42, 0x08, 0x8C, 0x51, 0xA4, 0xF4, 0xC6, 0x19, +0x9C, 0xB4, 0x5A, 0xAC, 0xA5, 0x14, 0xB5, 0x75, +0xC5, 0xB5, 0xA4, 0xB1, 0x94, 0x4F, 0xAD, 0x12, +0x94, 0x2E, 0x8C, 0x2E, 0x9C, 0x90, 0x94, 0x4E, +0x94, 0x6F, 0x7B, 0xAC, 0x94, 0x6F, 0xB5, 0x72, +0xB5, 0x52, 0x6B, 0x0A, 0x8C, 0x2E, 0xA4, 0xD0, +0x94, 0x6F, 0x94, 0x2E, 0x94, 0x6F, 0x94, 0x6E, +0xA4, 0xAF, 0xAC, 0xF1, 0x9C, 0xAF, 0x9C, 0x8F, +0x9C, 0x8F, 0x94, 0x6F, 0x9C, 0xB0, 0xA4, 0xD0, +0xB5, 0x73, 0x94, 0x4F, 0x9C, 0x90, 0xAC, 0xF1, +0xB5, 0x72, 0xA4, 0xF1, 0x7B, 0xAD, 0x8C, 0x30, +0x21, 0x04, 0x18, 0xE4, 0x20, 0xE4, 0x18, 0xC4, +0x10, 0xA3, 0x10, 0xC4, 0x18, 0xE4, 0x10, 0xC4, +0x10, 0x83, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xA4, +0x18, 0xC4, 0x18, 0xC3, 0x18, 0xC4, 0x18, 0xC3, +0x10, 0xA4, 0x10, 0xA3, 0x18, 0xA3, 0x18, 0xC4, +0x18, 0xC4, 0x10, 0xA4, 0x10, 0xA3, 0x29, 0x45, +0x42, 0x08, 0x21, 0x05, 0x21, 0x05, 0x21, 0x04, +0x20, 0xE4, 0x18, 0xC4, 0x18, 0xC3, 0x20, 0xE4, +0x29, 0x45, 0x31, 0x87, 0x42, 0x08, 0x52, 0x8A, +0x7B, 0xAE, 0x94, 0x50, 0x9C, 0xB1, 0x83, 0xEE, +0x8B, 0xEE, 0x83, 0xEE, 0x7B, 0xAD, 0x7B, 0xAD, +0x73, 0x8D, 0x83, 0xEE, 0x94, 0x50, 0x94, 0x90, +0x94, 0x50, 0x7B, 0xCE, 0x73, 0x6D, 0x6B, 0x4D, +0x63, 0x0C, 0x5A, 0xCB, 0x5A, 0xAA, 0x62, 0xEB, +0x7B, 0x8D, 0x73, 0x4C, 0x7B, 0x6C, 0x94, 0x2F, +0x9C, 0xB0, 0xAD, 0x12, 0xB5, 0x33, 0xB5, 0x33, +0xB5, 0x33, 0xB5, 0x33, 0xAD, 0x32, 0xB5, 0x53, +0xB5, 0x53, 0xAD, 0x12, 0xAD, 0x32, 0xA4, 0xF1, +0xA4, 0xD1, 0xB5, 0x73, 0xBD, 0x73, 0xBD, 0x94, +0xBD, 0x94, 0xC5, 0xB4, 0xB5, 0x32, 0xBD, 0x94, +0xA4, 0xD1, 0x83, 0xEE, 0x8C, 0x0E, 0x83, 0xED, +0x83, 0xED, 0x8C, 0x0E, 0x8C, 0x0E, 0x83, 0xEE, +0x8B, 0xEE, 0x94, 0x6F, 0xA4, 0xB1, 0x94, 0x6F, +0x8C, 0x0E, 0x7B, 0xCC, 0x83, 0xAC, 0x83, 0xCD, +0x94, 0x0F, 0x9C, 0x6F, 0x94, 0x4F, 0x94, 0x4F, +0x83, 0xED, 0x94, 0x4F, 0x7B, 0x8C, 0x7B, 0x8C, +0xAD, 0x32, 0xA4, 0xF1, 0xB5, 0x52, 0xBD, 0xD4, +0xBD, 0xB4, 0xBD, 0xD4, 0xC6, 0x15, 0x8C, 0x4F, +0x6B, 0x4D, 0x84, 0x31, 0x83, 0xF0, 0xBD, 0xF8, +0xA4, 0xF4, 0x7B, 0xAF, 0xA4, 0xD3, 0xBD, 0x76, +0x7B, 0x8E, 0xC6, 0x17, 0xCE, 0x78, 0x63, 0x2C, +0x5A, 0xCA, 0x63, 0x0C, 0x63, 0x0B, 0x52, 0xAA, +0x5A, 0xAA, 0x8C, 0x2F, 0x94, 0x4E, 0xAD, 0x32, +0xAD, 0x11, 0xC5, 0xF4, 0xC5, 0xF4, 0xA4, 0xD0, +0xA4, 0xF0, 0xCE, 0x14, 0xD6, 0x55, 0xC5, 0xF4, +0xA5, 0xF1, 0xA5, 0xB4, 0x95, 0x32, 0x84, 0x50, +0x3A, 0x07, 0x5A, 0xC9, 0x6B, 0x29, 0x73, 0x6A, +0x83, 0xCC, 0x94, 0x4E, 0x94, 0x6E, 0x8C, 0x2D, +0x8C, 0x0D, 0x9C, 0x8F, 0xA4, 0xD0, 0x9C, 0x8F, +0x94, 0x6F, 0x7B, 0x8C, 0x7B, 0xAC, 0x73, 0x4B, +0x7B, 0xAB, 0x83, 0xAB, 0x83, 0xCC, 0x94, 0x0D, +0x8B, 0xCC, 0x83, 0xAB, 0xA4, 0x8F, 0x9C, 0x2D, +0x9C, 0x4D, 0xA4, 0x6D, 0x9C, 0x4D, 0x83, 0xAB, +0x7B, 0x6A, 0x94, 0x0C, 0x83, 0xCB, 0x73, 0x2A, +0x73, 0x29, 0x83, 0xCB, 0x94, 0x0D, 0x9C, 0x2D, +0x8B, 0xCC, 0x9C, 0x4D, 0xB4, 0xEF, 0xB5, 0x10, +0xAC, 0xAE, 0xA4, 0x8E, 0xAC, 0xAE, 0xA4, 0x4D, +0xAC, 0x8E, 0xAC, 0xCF, 0xB4, 0xF0, 0x8B, 0xEC, +0x93, 0xEC, 0x9C, 0x2D, 0x9C, 0x2C, 0xAC, 0xAF, +0xAC, 0xCF, 0xAC, 0xAE, 0xAC, 0xCF, 0xAC, 0x8E, +0xAC, 0x8E, 0xAC, 0x8E, 0xA4, 0x8E, 0xAC, 0x8E, +0xAC, 0x8E, 0xAC, 0xAE, 0xB4, 0xCF, 0xBD, 0x30, +0xBD, 0x10, 0xB4, 0xF0, 0xB4, 0xF0, 0x9C, 0x4E, +0x94, 0x2D, 0x94, 0x2D, 0x8B, 0xEC, 0x8B, 0xEC, +0x94, 0x0D, 0xA4, 0x6E, 0xAC, 0xAE, 0x94, 0x0C, +0x9C, 0x4D, 0xA4, 0x8F, 0x94, 0x2E, 0x4A, 0x28, +0x39, 0xA6, 0x39, 0xC6, 0x39, 0xA6, 0x39, 0xC6, +0x4A, 0x28, 0x52, 0x69, 0x52, 0x8A, 0x42, 0x08, +0x39, 0xC7, 0x39, 0xC7, 0x31, 0x86, 0x39, 0xA6, +0x31, 0x86, 0x6B, 0x2D, 0x5A, 0xCB, 0x42, 0x08, +0x4A, 0x28, 0xAD, 0x34, 0xA4, 0xD2, 0x9C, 0xB1, +0x9C, 0xB1, 0x94, 0x71, 0x8C, 0x4F, 0xB5, 0x53, +0x94, 0x2D, 0xAD, 0x11, 0xBD, 0x52, 0xC5, 0xB3, +0xC5, 0xB3, 0xC5, 0x92, 0xBD, 0x51, 0xBD, 0x52, +0xBD, 0x52, 0xBD, 0x51, 0xB5, 0x11, 0xAC, 0xF1, +0xA4, 0xAF, 0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x11, +0xA4, 0xD0, 0xAD, 0x11, 0x6B, 0x2A, 0x39, 0xA5, +0x39, 0xC6, 0x39, 0xE6, 0x4A, 0x48, 0x42, 0x07, +0x41, 0xE7, 0x52, 0x69, 0x4A, 0x48, 0x31, 0xA6, +0x4A, 0x69, 0x84, 0x10, 0x9C, 0xD4, 0xC6, 0x39, +0xA5, 0x35, 0x7B, 0xD0, 0xBD, 0xD7, 0xAD, 0x55, +0xC5, 0xB6, 0xCD, 0xB5, 0xB5, 0x33, 0x8C, 0x0E, +0xA4, 0xF1, 0xBD, 0xF6, 0xB5, 0x53, 0x94, 0x70, +0xA4, 0xF1, 0x7B, 0xAC, 0x8C, 0x0D, 0xB5, 0x52, +0xAD, 0x12, 0x5A, 0xA9, 0x9C, 0x6F, 0xAC, 0xF0, +0x9C, 0xAF, 0x9C, 0x8F, 0x94, 0x6E, 0x9C, 0x6F, +0xA4, 0xF0, 0xAD, 0x10, 0xA4, 0xD0, 0x9C, 0xAF, +0x94, 0x6E, 0x94, 0x4E, 0x8C, 0x2E, 0x8C, 0x4E, +0x94, 0x4E, 0x8C, 0x2E, 0x8C, 0x0D, 0xA4, 0xF0, +0x94, 0x4E, 0x8C, 0x2E, 0x7B, 0xCD, 0x94, 0x91, +0x29, 0x66, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xC4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC4, 0x10, 0xC3, 0x10, 0xA3, +0x10, 0xC4, 0x10, 0xC4, 0x18, 0xE4, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xA4, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x18, 0xE4, +0x20, 0xE4, 0x20, 0xE5, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, +0x21, 0x04, 0x29, 0x25, 0x29, 0x66, 0x29, 0x66, +0x39, 0xC7, 0x52, 0x6A, 0x6B, 0x4D, 0x7B, 0xAE, +0x9C, 0xB2, 0xA4, 0xF2, 0x8C, 0x2F, 0x8C, 0x50, +0x7B, 0xCE, 0x7B, 0xAE, 0x73, 0x8D, 0x6B, 0x2C, +0x63, 0x0C, 0x5A, 0xAB, 0x52, 0x6A, 0x52, 0x6A, +0x52, 0x6A, 0x5A, 0x8B, 0x5A, 0xAB, 0x5A, 0x8B, +0x5A, 0xAB, 0x5A, 0xAA, 0x5A, 0xCB, 0x73, 0x6D, +0x8C, 0x2F, 0x8C, 0x0E, 0x94, 0x2F, 0x9C, 0xB0, +0x94, 0x70, 0x94, 0x2F, 0x83, 0xED, 0x8C, 0x2E, +0xA4, 0xD1, 0x9C, 0x70, 0x94, 0x4F, 0x9C, 0x90, +0x9C, 0x70, 0xAD, 0x11, 0xBD, 0x72, 0xBD, 0x73, +0xB5, 0x11, 0xAC, 0xF1, 0xB5, 0x32, 0xBD, 0x94, +0xB5, 0x53, 0xA4, 0xD1, 0x9C, 0xB0, 0xA4, 0xF1, +0xBD, 0x94, 0xBD, 0x73, 0xC5, 0xD5, 0xCD, 0xF6, +0xCE, 0x16, 0xCE, 0x16, 0xD6, 0x57, 0xC5, 0xD5, +0xC5, 0xD5, 0xBD, 0x94, 0xC5, 0xD5, 0xC5, 0xD5, +0xC5, 0xD4, 0xC5, 0xB4, 0xC5, 0xD5, 0xC5, 0xD5, +0xC5, 0xD4, 0xBD, 0x94, 0xB5, 0x53, 0xB5, 0x53, +0xB5, 0x53, 0xAD, 0x32, 0xAC, 0xF1, 0xA4, 0xB0, +0x94, 0x6F, 0xA4, 0xB0, 0x9C, 0xB0, 0x94, 0x70, +0x7B, 0xAD, 0x6B, 0x4D, 0x8C, 0x51, 0xBD, 0xF7, +0x84, 0x10, 0xAD, 0x35, 0x8C, 0x51, 0xBD, 0x96, +0x94, 0x51, 0xCE, 0x59, 0xD6, 0xBA, 0x73, 0xAF, +0x4A, 0x49, 0x5A, 0xCA, 0x52, 0xAA, 0x5A, 0xEB, +0x6B, 0x2C, 0xAD, 0x13, 0x8C, 0x2E, 0x9C, 0xB0, +0xB5, 0x73, 0xB5, 0x93, 0xB5, 0x72, 0x9C, 0x8F, +0x94, 0x4E, 0xC5, 0xD4, 0xC5, 0xF4, 0xC5, 0xD4, +0x9D, 0xD0, 0x9D, 0x72, 0x9D, 0x73, 0x84, 0x50, +0x7C, 0x2F, 0x94, 0xD0, 0x6B, 0x4A, 0x83, 0xCC, +0x94, 0x6F, 0x94, 0x6F, 0x9C, 0x8F, 0x83, 0xED, +0xA4, 0xF0, 0xA4, 0xD0, 0xA4, 0xF0, 0xA4, 0xD0, +0x9C, 0xAF, 0x9C, 0x8F, 0x9C, 0xAF, 0x94, 0x2E, +0x94, 0x6E, 0x94, 0x4E, 0xA4, 0xD0, 0x9C, 0x6F, +0x94, 0x6F, 0x83, 0xCC, 0xA4, 0xCF, 0xA4, 0xAF, +0x9C, 0x8E, 0xAD, 0x10, 0xAC, 0xF0, 0xAD, 0x11, +0x9C, 0x8F, 0x94, 0x4E, 0x9C, 0xB0, 0x94, 0x6F, +0x73, 0x6B, 0x94, 0x4E, 0x8C, 0x2E, 0x8C, 0x0D, +0x7B, 0x6B, 0x73, 0x29, 0x83, 0x6A, 0x83, 0x6A, +0x83, 0x8A, 0x83, 0x8A, 0x83, 0xAB, 0x9C, 0x6E, +0x83, 0x8B, 0x8B, 0xEC, 0xB5, 0x10, 0x9C, 0x8E, +0x9C, 0xD0, 0xA4, 0xD0, 0xA4, 0xD0, 0xAD, 0x11, +0xA4, 0xF0, 0xAD, 0x11, 0xAD, 0x11, 0xA4, 0xCF, +0x9C, 0x8E, 0x9C, 0x4D, 0xA4, 0x8E, 0x9C, 0x6E, +0x9C, 0x6E, 0x9C, 0x4E, 0x8B, 0xEC, 0x94, 0x0C, +0x8B, 0xCB, 0x8B, 0xCB, 0x8B, 0xCC, 0x8B, 0xCB, +0x9C, 0x4D, 0xAC, 0xEF, 0xC5, 0x92, 0xCD, 0xB3, +0xC5, 0x71, 0xB4, 0xF0, 0xBD, 0x10, 0xAC, 0xCF, +0xB4, 0xEF, 0xB5, 0x10, 0xAC, 0xD0, 0x73, 0x4B, +0x31, 0x85, 0x41, 0xE7, 0x41, 0xE7, 0x42, 0x08, +0x4A, 0x48, 0x42, 0x08, 0x4A, 0x48, 0x39, 0xA6, +0x29, 0x44, 0x29, 0x24, 0x31, 0x65, 0x4A, 0x28, +0x6B, 0x4D, 0x94, 0x72, 0x73, 0x8E, 0x52, 0x8A, +0x7B, 0x8D, 0x73, 0x4C, 0x62, 0xCA, 0x6B, 0x2B, +0x84, 0x0F, 0x9C, 0x90, 0xB5, 0x52, 0xC5, 0x93, +0xA4, 0x8E, 0x9C, 0x6E, 0x9C, 0x4E, 0x9C, 0x6E, +0xAC, 0xCF, 0xBD, 0x30, 0xC5, 0x71, 0xCD, 0xD2, +0xCD, 0x92, 0xC5, 0x51, 0xBD, 0x50, 0xBD, 0x51, +0xCD, 0xB2, 0xCD, 0xB3, 0xC5, 0x72, 0xAC, 0xF0, +0xAD, 0x11, 0xB5, 0x51, 0xAC, 0xF0, 0x6A, 0xE9, +0x29, 0x64, 0x31, 0xA5, 0x42, 0x07, 0x39, 0xA5, +0x39, 0xA6, 0x42, 0x07, 0x42, 0x07, 0x39, 0xC7, +0x5A, 0xAA, 0x73, 0xAE, 0x94, 0xB3, 0xC6, 0x19, +0x94, 0x93, 0x84, 0x10, 0xBD, 0xF8, 0xAD, 0x56, +0xAD, 0x35, 0xA4, 0xD3, 0xD6, 0x38, 0x9C, 0x50, +0x52, 0x8A, 0x8C, 0x51, 0xB5, 0x95, 0x8C, 0x4F, +0xB5, 0x53, 0x8C, 0x4E, 0x94, 0x4F, 0xB5, 0x73, +0xB5, 0x53, 0x52, 0x68, 0xA4, 0xD1, 0xA4, 0xF0, +0xAD, 0x31, 0xAC, 0xF0, 0x9C, 0xAF, 0x9C, 0x8F, +0xAD, 0x31, 0xB5, 0x51, 0xB5, 0x52, 0xA4, 0xD0, +0xA4, 0xB0, 0xA4, 0xD0, 0xA4, 0xD1, 0x8C, 0x4E, +0x94, 0x6F, 0x84, 0x0E, 0x8C, 0x4E, 0xAD, 0x11, +0x9C, 0x6F, 0x94, 0x2F, 0x94, 0x2F, 0x94, 0x50, +0x39, 0xA7, 0x21, 0x05, 0x18, 0xC4, 0x18, 0xE4, +0x19, 0x05, 0x18, 0xE4, 0x10, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xC3, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xC4, 0x20, 0xE5, 0x49, 0x46, 0x71, 0xA8, +0x59, 0x86, 0x21, 0x04, 0x21, 0x05, 0x21, 0x05, +0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC3, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xE4, 0x21, 0x25, 0x29, 0x46, 0x29, 0x66, +0x39, 0xA7, 0x31, 0xA7, 0x39, 0xE8, 0x4A, 0x29, +0x62, 0xEC, 0x7B, 0xAE, 0x6B, 0x4D, 0x62, 0xEC, +0x5A, 0xAB, 0x52, 0x6A, 0x52, 0x4A, 0x4A, 0x29, +0x4A, 0x09, 0x41, 0xE8, 0x41, 0xC8, 0x41, 0xC8, +0x41, 0xC8, 0x4A, 0x09, 0x52, 0x8B, 0x5A, 0xAB, +0x52, 0x8B, 0x52, 0x8B, 0x5A, 0xAB, 0x73, 0x6D, +0x9C, 0xD2, 0xB5, 0x74, 0xB5, 0x74, 0xBD, 0xB4, +0xA4, 0xF2, 0x94, 0x70, 0xA4, 0xF2, 0x9C, 0xD1, +0x9C, 0xD1, 0xA4, 0xF2, 0x8C, 0x2F, 0x83, 0xEE, +0xAD, 0x32, 0xBD, 0xB3, 0xC5, 0xD3, 0xC5, 0xB3, +0xAD, 0x11, 0xA4, 0xF0, 0x9C, 0xAF, 0x9C, 0x8F, +0xAD, 0x11, 0xB5, 0x52, 0x9C, 0xB0, 0xA4, 0xD0, +0xAD, 0x11, 0xAC, 0xF1, 0xA4, 0xB0, 0x9C, 0x8F, +0xAD, 0x32, 0xA4, 0xD0, 0x94, 0x6F, 0x94, 0x4E, +0x8C, 0x0E, 0xAC, 0xF1, 0xB5, 0x32, 0xB5, 0x32, +0xB5, 0x11, 0xAC, 0xF1, 0xA4, 0xD0, 0xAD, 0x11, +0xA4, 0xB0, 0xAC, 0xD0, 0xAC, 0xD0, 0xB5, 0x32, +0xAC, 0xD0, 0xAC, 0xF1, 0xA4, 0xB0, 0xB5, 0x11, +0xBD, 0x73, 0xBD, 0x73, 0xB5, 0x52, 0xBD, 0x93, +0xB5, 0x33, 0x6B, 0x2C, 0x73, 0xAF, 0x8C, 0x72, +0xB5, 0x96, 0xB5, 0x56, 0x83, 0xEF, 0xB5, 0x55, +0xCE, 0x7A, 0xD6, 0xDB, 0xEF, 0x5D, 0xD6, 0xBA, +0x73, 0x8E, 0x52, 0xAA, 0x52, 0xAA, 0x63, 0x2C, +0x7B, 0xEF, 0xB5, 0x54, 0xAD, 0x33, 0xA4, 0xD1, +0x94, 0x6F, 0x9C, 0x6F, 0x94, 0x6F, 0x8C, 0x2E, +0x8C, 0x2E, 0x94, 0x4F, 0x94, 0x4F, 0x8C, 0x0E, +0x95, 0xAE, 0x9D, 0x70, 0x9D, 0x52, 0x9D, 0x52, +0x9D, 0x32, 0x6B, 0x6B, 0x94, 0x8F, 0xBD, 0xF4, +0xCE, 0x95, 0xBD, 0xF4, 0x9C, 0x8F, 0x6B, 0x2A, +0xAD, 0x52, 0xA4, 0xD0, 0xAD, 0x11, 0xAD, 0x31, +0xAD, 0x31, 0xAD, 0x31, 0xB5, 0x52, 0xAD, 0x11, +0xAD, 0x11, 0xA4, 0xD0, 0xBD, 0x93, 0xAD, 0x31, +0xAC, 0xF0, 0x94, 0x2D, 0xA4, 0xAF, 0xAD, 0x10, +0xB5, 0x31, 0xBD, 0x72, 0xB5, 0x72, 0xAD, 0x32, +0xAD, 0x12, 0xB5, 0x53, 0xB5, 0x73, 0xAD, 0x12, +0x94, 0x4F, 0x9C, 0x90, 0x9C, 0xD0, 0x9C, 0x90, +0xAD, 0x11, 0x7B, 0x8C, 0x7B, 0x6B, 0x62, 0xC8, +0x83, 0xAC, 0xA4, 0xB0, 0x8B, 0xED, 0x94, 0x4E, +0x94, 0x2E, 0x83, 0xAB, 0xB5, 0x10, 0xAD, 0x11, +0xB5, 0x93, 0xB5, 0x53, 0xAD, 0x32, 0xB5, 0x73, +0xBD, 0xB4, 0xB5, 0x53, 0xA5, 0x11, 0xAD, 0x32, +0x9C, 0xD0, 0x9C, 0xD0, 0xA4, 0xF1, 0x9C, 0xB0, +0xA4, 0xF1, 0xAD, 0x52, 0x9C, 0xB0, 0x8C, 0x0D, +0x9C, 0x8F, 0xA4, 0xD0, 0xA4, 0xF1, 0x9C, 0x8F, +0xA4, 0xD0, 0xA4, 0x8E, 0xB4, 0xF0, 0xAC, 0xCF, +0xBD, 0x51, 0xBD, 0x51, 0xB5, 0x30, 0xAC, 0xEF, +0xA4, 0xAF, 0xBD, 0x52, 0x8C, 0x0D, 0x8C, 0x2E, +0x4A, 0x48, 0x41, 0xE7, 0x39, 0xC6, 0x39, 0xA6, +0x41, 0xE7, 0x52, 0x69, 0x4A, 0x48, 0x41, 0xE7, +0x29, 0x45, 0x31, 0x65, 0x39, 0xA6, 0x52, 0x69, +0x84, 0x10, 0xAD, 0x55, 0x83, 0xEF, 0x4A, 0x48, +0x5A, 0xAA, 0x31, 0x45, 0x29, 0x45, 0x41, 0xE7, +0x5A, 0x89, 0xA4, 0xB0, 0xBD, 0x31, 0xBD, 0x50, +0xCD, 0x92, 0xCD, 0xB2, 0xCD, 0xB2, 0xCD, 0xB2, +0xCD, 0xB2, 0xC5, 0x92, 0xC5, 0x51, 0xBD, 0x30, +0xC5, 0x71, 0xC5, 0x71, 0xBD, 0x10, 0xBD, 0x30, +0xBD, 0x31, 0xBD, 0x10, 0xB4, 0xEF, 0xB4, 0xEF, +0xAC, 0xEF, 0xAC, 0xCF, 0xB5, 0x10, 0xAC, 0xF0, +0x62, 0xC9, 0x29, 0x64, 0x39, 0xA5, 0x39, 0xA5, +0x39, 0xC6, 0x41, 0xE7, 0x42, 0x28, 0x42, 0x08, +0x52, 0x8A, 0x6B, 0x4D, 0xA5, 0x35, 0xBD, 0xD7, +0x84, 0x11, 0x7B, 0xD0, 0xA5, 0x35, 0xBD, 0xF8, +0x94, 0x93, 0x73, 0x6D, 0xBD, 0x95, 0x9C, 0x71, +0xB5, 0x35, 0x9C, 0xB2, 0x9C, 0xF3, 0x5A, 0xCB, +0x94, 0x70, 0x8C, 0x4E, 0x9C, 0xB0, 0xBD, 0x94, +0xB5, 0x32, 0x8B, 0xEE, 0xA4, 0xF1, 0xAC, 0xF0, +0xB5, 0x52, 0xBD, 0x72, 0xBD, 0x93, 0xB5, 0x31, +0xBD, 0x72, 0xB5, 0x51, 0xB5, 0x52, 0xBD, 0x72, +0xBD, 0x93, 0xB5, 0x32, 0xB5, 0x52, 0xB5, 0x73, +0xAD, 0x11, 0x9C, 0xB0, 0xA5, 0x12, 0xAD, 0x32, +0xA4, 0xB0, 0x94, 0x4F, 0x83, 0xCD, 0x6B, 0x2B, +0x21, 0x04, 0x18, 0xC4, 0x10, 0xA3, 0x18, 0xC4, +0x18, 0xE4, 0x10, 0xC3, 0x10, 0xA3, 0x10, 0xC3, +0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC4, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC4, +0x10, 0xC4, 0x30, 0xE5, 0x71, 0x87, 0xA1, 0xE9, +0xA2, 0x8A, 0x31, 0x04, 0x20, 0xE5, 0x21, 0x05, +0x20, 0xE4, 0x18, 0xC3, 0x10, 0xA3, 0x10, 0xA3, +0x18, 0xA3, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC3, +0x18, 0xC4, 0x21, 0x04, 0x29, 0x45, 0x29, 0x66, +0x29, 0x66, 0x31, 0x67, 0x31, 0x87, 0x39, 0xA7, +0x41, 0xE8, 0x4A, 0x29, 0x52, 0x6A, 0x52, 0x8B, +0x4A, 0x4A, 0x4A, 0x09, 0x41, 0xE8, 0x39, 0xC8, +0x39, 0x87, 0x39, 0x87, 0x31, 0x66, 0x31, 0x66, +0x31, 0x86, 0x31, 0x87, 0x39, 0xC8, 0x41, 0xE8, +0x4A, 0x4A, 0x52, 0x8B, 0x52, 0xAB, 0x5A, 0xCC, +0x62, 0xEC, 0x73, 0x8E, 0x94, 0x91, 0xB5, 0x74, +0xBD, 0x94, 0xB5, 0x74, 0xB5, 0x74, 0xAD, 0x33, +0xAD, 0x53, 0xAD, 0x53, 0x9C, 0x90, 0x84, 0x2E, +0xB5, 0x93, 0xBD, 0xB3, 0xBD, 0x72, 0xCD, 0xF4, +0xBD, 0xB4, 0xBD, 0xD4, 0xAD, 0x12, 0xAD, 0x12, +0xB5, 0x53, 0xB5, 0x93, 0xBD, 0x92, 0xBD, 0x72, +0xAD, 0x11, 0xAD, 0x31, 0xB5, 0x73, 0xA4, 0xF1, +0xAD, 0x52, 0xAD, 0x52, 0xA5, 0x11, 0x94, 0x6F, +0x7B, 0x6C, 0xCD, 0xF5, 0xCE, 0x15, 0xCD, 0xF4, +0xAC, 0xD0, 0xBD, 0x52, 0x8C, 0x0D, 0xA4, 0x8F, +0xA4, 0xAF, 0xAC, 0xF0, 0xBD, 0x52, 0xBD, 0x72, +0xB5, 0x52, 0xC5, 0xB3, 0xBD, 0x72, 0xAC, 0xF1, +0x7B, 0x6B, 0x8C, 0x2E, 0xA4, 0xD0, 0xA4, 0xB0, +0xC5, 0xB4, 0xA4, 0xF2, 0x52, 0xAA, 0x7B, 0xF0, +0xB5, 0x76, 0x73, 0x8E, 0x94, 0x92, 0xCE, 0x39, +0xDE, 0xDB, 0xC6, 0x18, 0x94, 0xB3, 0xB5, 0x96, +0xBD, 0xD7, 0x73, 0xAE, 0x5A, 0xEB, 0x6B, 0x4D, +0x7B, 0xEF, 0xA5, 0x13, 0xAD, 0x33, 0xAD, 0x12, +0xB5, 0x73, 0xBD, 0x73, 0xBD, 0x73, 0xB5, 0x53, +0xC5, 0xB4, 0xBD, 0x73, 0xBD, 0x73, 0xBD, 0x94, +0x85, 0x0A, 0x9D, 0xAF, 0x95, 0x30, 0x8C, 0xCF, +0x4A, 0x87, 0x6B, 0x4A, 0x84, 0x2D, 0x9D, 0x2E, +0x9D, 0xAD, 0xC6, 0x93, 0xB5, 0x92, 0xA4, 0xCF, +0xAD, 0x30, 0x84, 0x0C, 0xB5, 0x52, 0xB5, 0x52, +0xAD, 0x11, 0xAD, 0x31, 0xB5, 0x52, 0xB5, 0x32, +0xB5, 0x32, 0xAD, 0x31, 0xC5, 0xD4, 0xB5, 0x51, +0xB5, 0x31, 0xAD, 0x11, 0xAC, 0xF0, 0xB5, 0x31, +0xC5, 0x92, 0xCD, 0xF4, 0xBD, 0x93, 0xB5, 0x53, +0xBD, 0x73, 0xBD, 0xB4, 0xAD, 0x12, 0xAD, 0x32, +0xB5, 0x32, 0x8C, 0x2E, 0x94, 0x6F, 0xAD, 0x52, +0xB5, 0x52, 0x9C, 0xB0, 0x94, 0x4E, 0x6A, 0xE9, +0x83, 0xED, 0x73, 0x6A, 0x9C, 0x8F, 0x9C, 0x6F, +0x9C, 0xB0, 0x9C, 0x8F, 0xB5, 0x31, 0xB5, 0x73, +0xC5, 0xF5, 0xBD, 0xB4, 0xAD, 0x53, 0xB5, 0x94, +0xBD, 0xB4, 0xAD, 0x53, 0xB5, 0x94, 0xAD, 0x52, +0xA5, 0x11, 0xAD, 0x32, 0xAD, 0x53, 0xA5, 0x11, +0xAD, 0x53, 0xB5, 0x94, 0xB5, 0x73, 0xA4, 0xF1, +0xBD, 0xB4, 0xBD, 0xB4, 0xB5, 0x93, 0xAD, 0x52, +0xC5, 0xF5, 0xA4, 0xAF, 0xA4, 0x8E, 0xAC, 0xD0, +0xBD, 0x72, 0xD6, 0x14, 0xCD, 0xF4, 0xCD, 0xF4, +0xCD, 0xD3, 0xCD, 0xF4, 0x9C, 0x90, 0x9C, 0xB0, +0x7B, 0xCE, 0x4A, 0x48, 0x41, 0xE7, 0x39, 0xC7, +0x39, 0xC7, 0x4A, 0x28, 0x42, 0x08, 0x41, 0xE7, +0x4A, 0x28, 0x5A, 0xAA, 0x52, 0x8A, 0x62, 0xEB, +0x94, 0x71, 0xB5, 0x75, 0x7B, 0xCF, 0x5A, 0xCB, +0x4A, 0x48, 0x39, 0x86, 0x4A, 0x49, 0x5A, 0xCA, +0x41, 0xC6, 0x83, 0xCD, 0x94, 0x2D, 0x8B, 0xCB, +0x9C, 0x6D, 0x9C, 0x4D, 0xA4, 0x6E, 0xBD, 0x10, +0xC5, 0x71, 0x94, 0x0C, 0xA4, 0x8E, 0x94, 0x0C, +0x94, 0x2D, 0x94, 0x2C, 0x94, 0x0C, 0x94, 0x2D, +0x9C, 0x6E, 0xA4, 0x8E, 0xA4, 0x8E, 0x94, 0x2D, +0x9C, 0x4D, 0xA4, 0x8E, 0xB5, 0x10, 0xAC, 0xF0, +0x5A, 0xA8, 0x21, 0x03, 0x21, 0x23, 0x39, 0xA5, +0x42, 0x07, 0x39, 0xC6, 0x42, 0x07, 0x41, 0xE7, +0x42, 0x08, 0x5A, 0xEB, 0xC6, 0x18, 0xB5, 0x76, +0x8C, 0x72, 0x73, 0x8F, 0x9C, 0xF4, 0xB5, 0x96, +0x84, 0x10, 0x7B, 0xCF, 0x6B, 0x0C, 0x39, 0xA6, +0xC5, 0xF7, 0xD6, 0x79, 0xAD, 0x34, 0x7B, 0xEF, +0x73, 0x6C, 0x8B, 0xED, 0x94, 0x2E, 0xAD, 0x11, +0xAC, 0xF1, 0x9C, 0xB0, 0x9C, 0x90, 0x9C, 0xB0, +0xAC, 0xF0, 0xAC, 0xF0, 0xB5, 0x11, 0x9C, 0x8E, +0x9C, 0x8F, 0x9C, 0x6F, 0x9C, 0x8F, 0xA4, 0xD0, +0xA4, 0xD0, 0xA4, 0xAF, 0x9C, 0x8F, 0xAC, 0xF1, +0xBD, 0x94, 0xBD, 0x94, 0xBD, 0x94, 0xB5, 0x73, +0xA4, 0xF1, 0x94, 0x6F, 0x7B, 0x8D, 0x52, 0x49, +0x18, 0xC4, 0x18, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC4, +0x10, 0xC4, 0x10, 0xC4, 0x18, 0xE4, 0x10, 0xC4, +0x10, 0xC4, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xA3, 0x49, 0x26, 0x79, 0x47, 0xAA, 0x4A, +0x79, 0xA8, 0x28, 0xE4, 0x18, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x18, 0xC3, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xE4, 0x20, 0xE5, 0x21, 0x05, 0x21, 0x25, +0x29, 0x46, 0x29, 0x66, 0x31, 0x87, 0x39, 0xA7, +0x39, 0xC8, 0x39, 0xC8, 0x39, 0xE8, 0x4A, 0x09, +0x42, 0x09, 0x41, 0xC8, 0x39, 0xC8, 0x31, 0x87, +0x31, 0x87, 0x31, 0x87, 0x29, 0x66, 0x29, 0x46, +0x29, 0x46, 0x29, 0x46, 0x29, 0x66, 0x31, 0x87, +0x39, 0xA7, 0x39, 0xC8, 0x42, 0x29, 0x4A, 0x4A, +0x4A, 0x2A, 0x4A, 0x4A, 0x52, 0x8B, 0x63, 0x2D, +0x83, 0xEF, 0x9C, 0xD2, 0xB5, 0x74, 0xB5, 0x94, +0xB5, 0xB5, 0xAD, 0x53, 0x94, 0x70, 0x94, 0x6F, +0xBD, 0xB4, 0xCD, 0xF4, 0xBD, 0x92, 0xC5, 0xF4, +0xB5, 0x52, 0xB5, 0x73, 0xAD, 0x53, 0xBD, 0xB4, +0xB5, 0x73, 0xB5, 0x73, 0xAD, 0x51, 0xBD, 0x92, +0xBD, 0x72, 0xB5, 0x51, 0xB5, 0x93, 0xAD, 0x32, +0xC6, 0x16, 0xBD, 0xD5, 0xBD, 0xF5, 0xB5, 0x73, +0x9C, 0xD0, 0xCD, 0xF4, 0xCE, 0x35, 0xCE, 0x15, +0xA4, 0xB0, 0xBD, 0x73, 0x94, 0x6F, 0x94, 0x0D, +0x9C, 0x4E, 0xAD, 0x11, 0xAC, 0xF0, 0xAC, 0xF0, +0xBD, 0xB3, 0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x11, +0x8C, 0x0D, 0xA4, 0xF0, 0xAD, 0x11, 0xAD, 0x11, +0xBD, 0x93, 0xC5, 0xB4, 0x94, 0x70, 0x5A, 0xCB, +0x8C, 0x51, 0x73, 0xAF, 0x7B, 0xCF, 0xB5, 0x96, +0x83, 0xF0, 0x5A, 0xCC, 0x73, 0x6E, 0x84, 0x30, +0x94, 0xB2, 0x8C, 0x51, 0x62, 0xEC, 0x6B, 0x4D, +0x7B, 0xEF, 0x9C, 0xF3, 0xC5, 0xF6, 0xC5, 0xF4, +0xC5, 0xF4, 0xC5, 0xF4, 0xB5, 0x73, 0xBD, 0xB3, +0xC5, 0xB4, 0xBD, 0x72, 0xBD, 0x93, 0xAD, 0x11, +0x74, 0xE9, 0x7C, 0xEC, 0x85, 0x0F, 0x84, 0x8F, +0x39, 0xE6, 0x52, 0x88, 0x73, 0xAB, 0x7C, 0x2A, +0x74, 0x47, 0x9D, 0x8B, 0xBE, 0x30, 0xB5, 0xB0, +0x94, 0x8C, 0x94, 0x6D, 0xA4, 0xAF, 0xB5, 0x52, +0xAD, 0x31, 0xAD, 0x11, 0xB5, 0x31, 0xB5, 0x52, +0xB5, 0x32, 0xBD, 0x73, 0xC5, 0xB3, 0xB5, 0x51, +0xAD, 0x31, 0x9C, 0x6E, 0xAC, 0xF0, 0xB5, 0x10, +0xBD, 0x92, 0xC5, 0xB3, 0xC5, 0xB4, 0xC5, 0xB4, +0xC5, 0xD4, 0xC5, 0xD5, 0xBD, 0xB4, 0xBD, 0xD5, +0xA4, 0xD1, 0x94, 0x4F, 0xAD, 0x32, 0xBD, 0xB4, +0xAD, 0x11, 0xB5, 0x73, 0xAD, 0x32, 0xAD, 0x32, +0xA4, 0xD0, 0x8C, 0x2E, 0xA4, 0xF1, 0x9C, 0x6F, +0x9C, 0xB0, 0x9C, 0xAF, 0xB5, 0x10, 0xBD, 0xB3, +0xBD, 0xD5, 0xB5, 0x94, 0xBD, 0xD4, 0xBD, 0xB4, +0xBD, 0xD5, 0xB5, 0x74, 0xC5, 0xF5, 0xBD, 0xB4, +0xB5, 0x73, 0xBD, 0xD5, 0xBD, 0xD5, 0xB5, 0x94, +0xB5, 0xB4, 0xBD, 0xD5, 0xBD, 0xB4, 0xA5, 0x11, +0xAD, 0x32, 0xAD, 0x32, 0xAD, 0x32, 0xB5, 0x73, +0xC5, 0xF5, 0xA4, 0xCF, 0xA4, 0x8E, 0xB5, 0x52, +0xBD, 0x93, 0xCD, 0xF4, 0xCD, 0xF4, 0xCD, 0xD3, +0xCD, 0xD3, 0xCD, 0xF4, 0x9C, 0xB0, 0x8C, 0x4F, +0x84, 0x0E, 0x73, 0x6D, 0x41, 0xE7, 0x39, 0xA6, +0x29, 0x44, 0x39, 0xC6, 0x39, 0xC6, 0x52, 0x69, +0x52, 0x89, 0x5A, 0xAA, 0x63, 0x0C, 0x73, 0x8D, +0x94, 0x91, 0x8C, 0x30, 0x7B, 0xAE, 0x6B, 0x2C, +0x42, 0x07, 0x39, 0xA6, 0x39, 0xC7, 0x42, 0x08, +0x4A, 0x28, 0xA4, 0xF1, 0xB5, 0x31, 0x9C, 0x6E, +0xAC, 0xF0, 0xB5, 0x31, 0xA4, 0xAF, 0xAC, 0xF0, +0xC5, 0x72, 0x94, 0x0C, 0xA4, 0xAF, 0xAC, 0xF0, +0xAD, 0x31, 0xA4, 0xAF, 0xAD, 0x11, 0xAD, 0x11, +0xA4, 0xD0, 0xA4, 0xD0, 0xAC, 0xF0, 0x9C, 0xB0, +0x84, 0x0D, 0x94, 0x6F, 0xA4, 0xF0, 0xAD, 0x11, +0xB5, 0x73, 0x73, 0x6C, 0x4A, 0x48, 0x63, 0x2B, +0x29, 0x64, 0x42, 0x27, 0x42, 0x07, 0x39, 0xC6, +0x84, 0x10, 0x94, 0xB3, 0xD6, 0x7A, 0xA5, 0x35, +0x8C, 0x51, 0x8C, 0x52, 0x9C, 0xF4, 0x8C, 0x52, +0x7B, 0xAF, 0x84, 0x10, 0xC5, 0xD7, 0x62, 0xCB, +0x62, 0xEC, 0x84, 0x10, 0x9C, 0xD3, 0xAD, 0x34, +0xA4, 0xD2, 0xAC, 0xD0, 0xA4, 0xB0, 0xB5, 0x53, +0xB5, 0x73, 0xC5, 0xB4, 0xC5, 0xD5, 0xC5, 0xD5, +0xC5, 0xB4, 0xBD, 0x94, 0xB5, 0x52, 0xB5, 0x53, +0xC5, 0xD5, 0xC5, 0xB4, 0xC5, 0xB4, 0xBD, 0x93, +0xBD, 0x94, 0xC5, 0xB4, 0xBD, 0x94, 0xBD, 0x94, +0xB5, 0x53, 0xB5, 0x32, 0xAD, 0x12, 0xAD, 0x32, +0xAD, 0x12, 0xAD, 0x53, 0x9C, 0x90, 0x41, 0xE7, +0x20, 0xE4, 0x18, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xC3, 0x10, 0xC3, 0x10, 0xC4, 0x10, 0xA3, +0x10, 0xC4, 0x18, 0xC4, 0x10, 0xC4, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xE4, 0x21, 0x05, 0x18, 0xE4, +0x20, 0xA3, 0x61, 0x87, 0x71, 0x26, 0x89, 0xE9, +0x30, 0x83, 0x20, 0xC4, 0x18, 0xC3, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x18, 0xC4, 0x18, 0xE4, +0x18, 0xE4, 0x21, 0x05, 0x21, 0x05, 0x29, 0x25, +0x29, 0x46, 0x29, 0x66, 0x31, 0x87, 0x31, 0xA7, +0x39, 0xC8, 0x39, 0xC8, 0x31, 0xA7, 0x39, 0xA8, +0x39, 0xC8, 0x39, 0xC8, 0x31, 0x87, 0x31, 0x87, +0x31, 0x66, 0x29, 0x66, 0x29, 0x66, 0x29, 0x66, +0x29, 0x66, 0x29, 0x46, 0x29, 0x46, 0x21, 0x25, +0x29, 0x46, 0x29, 0x46, 0x31, 0x87, 0x31, 0xA7, +0x39, 0xC8, 0x4A, 0x4A, 0x4A, 0x6A, 0x52, 0x6B, +0x5A, 0xAB, 0x63, 0x0C, 0x7B, 0xCF, 0xA4, 0xF3, +0xBD, 0xB5, 0xBD, 0xD5, 0xA5, 0x12, 0x94, 0x90, +0xBD, 0x94, 0xCE, 0x14, 0xBD, 0x72, 0xC5, 0xD4, +0xAD, 0x52, 0xAD, 0x32, 0xB5, 0x94, 0xBD, 0xD5, +0xBD, 0xD5, 0xBD, 0xB4, 0xB5, 0x52, 0xBD, 0xB3, +0xB5, 0x51, 0xB5, 0x31, 0xAD, 0x31, 0xAD, 0x52, +0xC6, 0x15, 0xBD, 0xB5, 0xB5, 0xB4, 0xB5, 0x93, +0xA4, 0xF1, 0xC5, 0xF4, 0xCE, 0x14, 0xC5, 0xD4, +0xA4, 0xB0, 0xBD, 0x93, 0x94, 0x4F, 0xAC, 0xD0, +0xAC, 0xF0, 0xBD, 0x93, 0xAD, 0x31, 0xBD, 0x73, +0xCE, 0x15, 0xA4, 0xF0, 0xAD, 0x11, 0xB5, 0x52, +0xA4, 0xD0, 0xA4, 0xF1, 0xA4, 0xD0, 0xAD, 0x32, +0xC5, 0xF5, 0xC5, 0xD4, 0xC5, 0xF5, 0x6B, 0x4C, +0x62, 0xEC, 0x4A, 0x29, 0x52, 0x69, 0x63, 0x0C, +0x6B, 0x4D, 0x5A, 0xCB, 0x6B, 0x2D, 0x73, 0x8E, +0x84, 0x10, 0xAD, 0x76, 0x6B, 0x6E, 0x73, 0xAF, +0x84, 0x10, 0x9C, 0xF3, 0xBD, 0xB5, 0xC5, 0xD4, +0xC6, 0x14, 0xBD, 0xB3, 0xAD, 0x11, 0xC5, 0xD3, +0xCE, 0x35, 0xCE, 0x15, 0xCE, 0x35, 0xC5, 0xF4, +0x74, 0xAA, 0x8D, 0x4F, 0x9D, 0x71, 0x7C, 0x4D, +0x63, 0x49, 0x52, 0xE8, 0x5A, 0xC8, 0x63, 0x29, +0x5B, 0x26, 0x7C, 0x68, 0x84, 0x87, 0x95, 0x2B, +0xAD, 0xB0, 0xAD, 0x90, 0x8C, 0x6C, 0x9C, 0x8F, +0x9C, 0x8F, 0x9C, 0x8E, 0x9C, 0xAF, 0xAD, 0x11, +0xB5, 0x32, 0xBD, 0x93, 0xB5, 0x52, 0xBD, 0x93, +0xB5, 0x52, 0x83, 0xCB, 0xB5, 0x10, 0xB5, 0x30, +0xC5, 0xD3, 0xCE, 0x15, 0xD6, 0x35, 0xCE, 0x15, +0xCE, 0x35, 0xCE, 0x35, 0xC5, 0xF5, 0xCE, 0x16, +0x8C, 0x0E, 0xC5, 0xD5, 0xC5, 0xD5, 0xBD, 0xB4, +0xB5, 0x94, 0xB5, 0x94, 0xB5, 0x73, 0xBD, 0x94, +0xBD, 0x94, 0xB5, 0x73, 0xAD, 0x32, 0xA4, 0xB0, +0xA4, 0xD0, 0xA4, 0xF0, 0xB5, 0x31, 0xC5, 0xF4, +0xC5, 0xF6, 0xB5, 0x94, 0xC6, 0x16, 0xBD, 0xD5, +0xBD, 0xD5, 0xC5, 0xF6, 0xC6, 0x16, 0xC6, 0x36, +0xC6, 0x15, 0xC5, 0xF5, 0xBD, 0xD5, 0xB5, 0xB4, +0xC6, 0x16, 0xBD, 0xD5, 0xBD, 0xD5, 0xBD, 0xD5, +0xC6, 0x16, 0xC6, 0x15, 0xB5, 0x73, 0xBD, 0xB4, +0xBD, 0x93, 0xB5, 0x10, 0xA4, 0x8E, 0xAD, 0x11, +0xC5, 0xD4, 0xCD, 0xF4, 0xD5, 0xF4, 0xCD, 0xD3, +0xCD, 0xF3, 0xD6, 0x15, 0xA4, 0xD1, 0x9C, 0xD1, +0x8C, 0x2F, 0x94, 0x71, 0x52, 0x89, 0x41, 0xE7, +0x39, 0xC6, 0x39, 0xA6, 0x41, 0xE7, 0x4A, 0x28, +0x4A, 0x49, 0x63, 0x0B, 0x6B, 0x4C, 0x6B, 0x4C, +0x73, 0x8E, 0x7B, 0xCE, 0x8C, 0x51, 0x73, 0x8E, +0x5A, 0xAA, 0x52, 0x69, 0x8C, 0x71, 0x7B, 0xAE, +0x52, 0x69, 0xA4, 0xF1, 0xC5, 0xD4, 0xAC, 0xF0, +0x9C, 0xAF, 0xAD, 0x31, 0xCD, 0xF5, 0xA4, 0xAF, +0xBD, 0x51, 0x94, 0x4D, 0xAC, 0xF0, 0xA4, 0xD0, +0xA4, 0xD0, 0xA4, 0xF1, 0xAD, 0x32, 0xB5, 0x52, +0xB5, 0x52, 0xAD, 0x31, 0xAD, 0x11, 0xB5, 0x73, +0xAD, 0x52, 0xB5, 0x73, 0xAD, 0x52, 0xB5, 0x73, +0xBD, 0xB4, 0xB5, 0x73, 0xA5, 0x12, 0x63, 0x0B, +0x18, 0xE3, 0x29, 0x64, 0x31, 0xA5, 0x4A, 0x69, +0x94, 0xB2, 0xC6, 0x39, 0xC5, 0xF8, 0xA4, 0xF4, +0x84, 0x11, 0x84, 0x31, 0x7B, 0xCF, 0x7B, 0xD0, +0x73, 0x6E, 0x94, 0x72, 0xCE, 0x38, 0xB5, 0x55, +0x52, 0x49, 0x4A, 0x28, 0x5A, 0xAA, 0x5A, 0x8A, +0xA4, 0xF2, 0xBD, 0x52, 0x9C, 0x6E, 0xAD, 0x11, +0xB5, 0x52, 0xB5, 0x52, 0xA4, 0xD0, 0xA4, 0xB0, +0xBD, 0x73, 0x9C, 0x8F, 0xA4, 0xD0, 0xB5, 0x31, +0xAD, 0x11, 0xAD, 0x11, 0xA4, 0xD0, 0xA4, 0xB0, +0xA4, 0xD0, 0xA4, 0xB0, 0xA4, 0xB0, 0xAD, 0x12, +0xA4, 0xF1, 0x9C, 0xB0, 0xA4, 0xD0, 0xAD, 0x12, +0xB5, 0x53, 0xB5, 0x73, 0x94, 0x4F, 0x31, 0x86, +0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC3, +0x10, 0xC4, 0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC4, 0x10, 0xA3, +0x38, 0xE4, 0x71, 0x46, 0x89, 0xA8, 0x61, 0x46, +0x20, 0xA3, 0x18, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x18, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x18, 0xA3, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xE4, 0x21, 0x05, 0x21, 0x05, 0x21, 0x25, +0x21, 0x05, 0x21, 0x25, 0x21, 0x25, 0x29, 0x46, +0x31, 0xA7, 0x39, 0xC8, 0x39, 0xC8, 0x31, 0x87, +0x31, 0x87, 0x31, 0x87, 0x31, 0x66, 0x29, 0x46, +0x31, 0x66, 0x31, 0x87, 0x31, 0x66, 0x29, 0x66, +0x29, 0x46, 0x29, 0x46, 0x29, 0x46, 0x29, 0x46, +0x21, 0x25, 0x21, 0x05, 0x29, 0x46, 0x31, 0x87, +0x39, 0xC8, 0x39, 0xC8, 0x41, 0xE9, 0x4A, 0x29, +0x52, 0x8B, 0x52, 0x8B, 0x52, 0x8B, 0x5A, 0xCC, +0x73, 0x8E, 0x94, 0x91, 0x94, 0x91, 0x94, 0x90, +0xBD, 0x73, 0xC5, 0xF4, 0xBD, 0x92, 0xC5, 0xD4, +0xBD, 0xD4, 0xBD, 0xB4, 0xBD, 0xB4, 0xBD, 0xD4, +0xC6, 0x16, 0xBD, 0xB4, 0xB5, 0x93, 0xC5, 0xB3, +0xC5, 0xD3, 0xC5, 0xF4, 0xB5, 0x93, 0xB5, 0x73, +0xC5, 0xF5, 0xC5, 0xF5, 0xB5, 0x94, 0xBD, 0xB4, +0xB5, 0x52, 0xC5, 0xD4, 0xCE, 0x35, 0xBD, 0xD3, +0xAD, 0x11, 0xC5, 0xB4, 0x94, 0x2E, 0xA4, 0xAF, +0xB5, 0x51, 0xC5, 0xD4, 0xCE, 0x15, 0xD6, 0x35, +0xCE, 0x15, 0xB5, 0x72, 0xBD, 0xB3, 0xCE, 0x15, +0xC5, 0xF4, 0xBD, 0xB4, 0xB5, 0x53, 0xAD, 0x52, +0xC5, 0xF4, 0xC5, 0xD4, 0xC5, 0xB4, 0xAD, 0x32, +0x6B, 0x0B, 0x52, 0x8A, 0x5A, 0xAA, 0x84, 0x10, +0x8C, 0x51, 0x39, 0xC7, 0x4A, 0x4A, 0x8C, 0x31, +0x84, 0x10, 0xC5, 0xF8, 0x9C, 0xB3, 0x84, 0x31, +0x8C, 0x51, 0x6B, 0x4D, 0xAD, 0x13, 0xCE, 0x15, +0xCE, 0x35, 0xBD, 0xD3, 0xB5, 0x72, 0xC5, 0xD4, +0xCE, 0x34, 0xD6, 0x55, 0xC5, 0xF3, 0xC5, 0xF4, +0x7D, 0x0C, 0x7C, 0xEC, 0x6C, 0x4B, 0x7C, 0x8B, +0x84, 0x8C, 0x8C, 0x8C, 0x84, 0x0B, 0x8C, 0x0C, +0x94, 0x6D, 0x94, 0xCC, 0x7C, 0x68, 0x5B, 0x84, +0x63, 0xE5, 0x7C, 0x68, 0x9C, 0xEC, 0x9C, 0x6D, +0x94, 0x2D, 0x94, 0x2D, 0x94, 0x2D, 0x94, 0x2D, +0x94, 0x2D, 0x9C, 0x6E, 0x9C, 0x6E, 0x9C, 0x6E, +0x8B, 0xEC, 0x7B, 0x6A, 0xB5, 0x10, 0x8B, 0xCB, +0x94, 0x4D, 0xA4, 0xAF, 0xA4, 0xD0, 0xA4, 0x8F, +0xA4, 0xB0, 0xAD, 0x11, 0xB5, 0x32, 0xB5, 0x73, +0xB5, 0x53, 0xB5, 0x93, 0xB5, 0x73, 0xBD, 0x94, +0xC5, 0xF5, 0xCE, 0x15, 0xCE, 0x16, 0xCE, 0x36, +0xC5, 0xD5, 0xC5, 0xD5, 0xB5, 0x73, 0xA4, 0xF1, +0xA4, 0xF1, 0xB5, 0x31, 0xBD, 0x51, 0xBD, 0xB4, +0xCE, 0x57, 0xBD, 0xF5, 0xC6, 0x16, 0xCE, 0x57, +0xCE, 0x36, 0xC6, 0x36, 0xCE, 0x36, 0xC6, 0x16, +0xC6, 0x16, 0xC6, 0x16, 0xC5, 0xF5, 0xBD, 0xF5, +0xC6, 0x16, 0xBD, 0xD5, 0xC5, 0xF5, 0xBD, 0xD5, +0xBD, 0xB4, 0xC5, 0xF5, 0xB5, 0x73, 0xB5, 0x73, +0xBD, 0xB4, 0xAD, 0x10, 0x9C, 0x6E, 0x94, 0x4E, +0xC5, 0xD4, 0xCD, 0xD3, 0xDE, 0x35, 0xCD, 0xF4, +0xCD, 0xB3, 0xD6, 0x15, 0xAD, 0x12, 0xAD, 0x33, +0x9C, 0xF2, 0x9C, 0xF2, 0x8C, 0x50, 0x4A, 0x28, +0x42, 0x07, 0x4A, 0x28, 0x41, 0xE7, 0x4A, 0x48, +0x5A, 0xCA, 0x5A, 0xEB, 0x5A, 0xCA, 0x5A, 0xCB, +0x62, 0xEB, 0x83, 0xEF, 0x94, 0x92, 0x8C, 0x30, +0x7B, 0xCF, 0x6B, 0x2D, 0x9C, 0xB3, 0x83, 0xF0, +0x62, 0xEB, 0x83, 0xEE, 0xCE, 0x35, 0xC5, 0xD4, +0xA5, 0x11, 0xBD, 0xB3, 0xCE, 0x15, 0x9C, 0x8F, +0xB5, 0x51, 0x7B, 0x6A, 0x94, 0x6F, 0xAD, 0x11, +0xAD, 0x11, 0xC5, 0xD4, 0xC6, 0x15, 0xC5, 0xF5, +0xCE, 0x36, 0xBD, 0xD4, 0xBD, 0xD4, 0xBD, 0xB4, +0xBD, 0xB4, 0xBD, 0xB4, 0xCE, 0x56, 0xC5, 0xD5, +0xBD, 0xD4, 0xBD, 0xD4, 0xB5, 0x94, 0x8C, 0x50, +0x4A, 0x49, 0x42, 0x28, 0x29, 0x44, 0x39, 0xE7, +0x7B, 0xCF, 0xB5, 0x96, 0xAD, 0x55, 0x9C, 0xD4, +0x73, 0x8F, 0x52, 0xAB, 0x63, 0x2D, 0x73, 0x6E, +0x73, 0x6E, 0x73, 0x6E, 0xB5, 0x96, 0xBD, 0x96, +0x7B, 0xAE, 0x62, 0xEB, 0x39, 0xA6, 0x62, 0xEB, +0x9C, 0x91, 0xB5, 0x52, 0xA4, 0xB0, 0xC5, 0xB3, +0xC5, 0xD3, 0xC5, 0xB3, 0xB5, 0x52, 0x9C, 0x90, +0xB5, 0x52, 0xC5, 0xB3, 0xC5, 0xD3, 0xCD, 0xD3, +0xDE, 0x75, 0xC5, 0xB3, 0xBD, 0x72, 0xBD, 0x92, +0xD6, 0x14, 0xC5, 0x93, 0xA4, 0xB0, 0xA4, 0xF0, +0xAC, 0xF0, 0x9C, 0x8F, 0x9C, 0x6F, 0xBD, 0x73, +0xB5, 0x53, 0xAD, 0x12, 0x7B, 0xAD, 0x29, 0x45, +0x21, 0x04, 0x18, 0xE4, 0x18, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x08, 0x83, 0x10, 0xA3, 0x18, 0xC4, +0x10, 0xC3, 0x10, 0xC3, 0x10, 0xC3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x20, 0x83, +0x61, 0x26, 0x81, 0x67, 0x91, 0xE9, 0x38, 0xA3, +0x18, 0xA3, 0x18, 0xA3, 0x18, 0xA3, 0x18, 0xA3, +0x18, 0xA3, 0x10, 0xA3, 0x18, 0xA3, 0x18, 0xA3, +0x18, 0xA3, 0x18, 0xC3, 0x18, 0xC3, 0x18, 0xE4, +0x20, 0xE4, 0x21, 0x05, 0x21, 0x05, 0x21, 0x25, +0x29, 0x25, 0x29, 0x46, 0x29, 0x46, 0x31, 0x66, +0x31, 0x87, 0x39, 0xA7, 0x31, 0xA7, 0x31, 0x87, +0x31, 0x66, 0x29, 0x25, 0x21, 0x25, 0x21, 0x05, +0x21, 0x25, 0x29, 0x46, 0x29, 0x46, 0x21, 0x25, +0x29, 0x46, 0x29, 0x25, 0x29, 0x25, 0x29, 0x25, +0x29, 0x25, 0x29, 0x46, 0x29, 0x46, 0x29, 0x46, +0x31, 0x87, 0x31, 0xA7, 0x31, 0x87, 0x31, 0xA7, +0x41, 0xE8, 0x4A, 0x29, 0x4A, 0x4A, 0x4A, 0x4A, +0x4A, 0x6A, 0x52, 0xAB, 0x63, 0x2C, 0x84, 0x0F, +0xB5, 0x53, 0xC5, 0xF4, 0xCE, 0x14, 0xCE, 0x15, +0xCE, 0x36, 0xC5, 0xF5, 0xB5, 0x73, 0xB5, 0xB4, +0xC6, 0x36, 0xBD, 0xB4, 0xC6, 0x15, 0xCE, 0x55, +0xCE, 0x35, 0xD6, 0x76, 0xBD, 0xB4, 0xB5, 0x94, +0xBD, 0xD5, 0xBD, 0xD4, 0xB5, 0x94, 0xB5, 0x94, +0xBD, 0x93, 0xBD, 0x93, 0xD6, 0x76, 0xC5, 0xD4, +0xB5, 0x52, 0xC5, 0xB3, 0x94, 0x0E, 0x7B, 0x6B, +0x94, 0x4E, 0xBD, 0xB3, 0xB5, 0x92, 0xC5, 0xD3, +0xAD, 0x11, 0xAC, 0xF0, 0xB5, 0x52, 0xC5, 0xD3, +0xC5, 0xF4, 0xBD, 0xD4, 0xB5, 0x73, 0xB5, 0x53, +0xBD, 0xB4, 0xC5, 0xD4, 0xCE, 0x15, 0xB5, 0x73, +0x9C, 0xB0, 0x5A, 0xEB, 0x62, 0xEB, 0x7B, 0xCF, +0x73, 0xAE, 0x52, 0x6A, 0x52, 0x6A, 0x6B, 0x4D, +0x63, 0x0D, 0x84, 0x10, 0x8C, 0x31, 0x63, 0x0C, +0x42, 0x08, 0x31, 0x87, 0xAD, 0x34, 0xCE, 0x36, +0xC5, 0xF4, 0xC5, 0xF4, 0xC6, 0x14, 0xC5, 0xD4, +0xCE, 0x55, 0xC6, 0x14, 0xC5, 0xF4, 0xBD, 0xD3, +0x5B, 0xE7, 0x6C, 0x4A, 0x8D, 0x0E, 0x7C, 0x4C, +0x63, 0x89, 0x8C, 0x6C, 0x7B, 0xCB, 0x84, 0x0C, +0xAD, 0x31, 0x9C, 0xEF, 0x73, 0xE7, 0x6C, 0x06, +0x64, 0x26, 0x84, 0xA9, 0xAD, 0x2E, 0xAD, 0x10, +0xA4, 0x8E, 0x9C, 0x6D, 0x9C, 0x6D, 0xAC, 0xEF, +0xB5, 0x10, 0xAC, 0xEF, 0xB5, 0x10, 0xB5, 0x30, +0xBD, 0x31, 0xB5, 0x30, 0xB5, 0x30, 0xAC, 0xAF, +0xAC, 0xAF, 0xA4, 0x8E, 0xA4, 0x8E, 0xB4, 0xF0, +0xB4, 0xF0, 0xAC, 0xAF, 0xA4, 0x8F, 0xA4, 0x8E, +0x9C, 0x6E, 0x9C, 0x4D, 0x94, 0x0D, 0x94, 0x2D, +0x93, 0xEC, 0x8B, 0xEC, 0x9C, 0x4E, 0x9C, 0x8E, +0x9C, 0x8F, 0xA4, 0xD0, 0xAC, 0xF0, 0xA4, 0xF0, +0xAD, 0x11, 0xBD, 0x51, 0xC5, 0x71, 0xBD, 0x51, +0xBD, 0x72, 0xB5, 0x72, 0xAD, 0x31, 0xB5, 0x72, +0xB5, 0x52, 0xB5, 0x52, 0xC5, 0xD4, 0xC6, 0x15, +0xCE, 0x36, 0xCE, 0x56, 0xCE, 0x57, 0xD6, 0x77, +0xD6, 0x77, 0xCE, 0x56, 0xD6, 0x77, 0xCE, 0x36, +0xCE, 0x16, 0xCE, 0x36, 0xC5, 0xF5, 0xC5, 0xD4, +0xB5, 0x73, 0xB5, 0x10, 0xAC, 0xEF, 0x8C, 0x0D, +0xCD, 0xF4, 0xD6, 0x55, 0xCE, 0x14, 0xCD, 0xF4, +0xD6, 0x35, 0xDE, 0x56, 0xBD, 0x73, 0xA4, 0xF2, +0x9C, 0xF2, 0x9C, 0xF2, 0xAD, 0x33, 0x73, 0x8D, +0x41, 0xE7, 0x41, 0xE7, 0x41, 0xE7, 0x52, 0x69, +0x41, 0xE7, 0x4A, 0x28, 0x52, 0x69, 0x4A, 0x49, +0x52, 0x8A, 0x73, 0x6D, 0x94, 0x72, 0x9C, 0xB2, +0x94, 0x92, 0x84, 0x10, 0xAD, 0x55, 0xA4, 0xF3, +0x6B, 0x2C, 0x62, 0xEA, 0xCE, 0x36, 0xCE, 0x35, +0xC5, 0xF4, 0xC5, 0xF4, 0xCE, 0x15, 0xB5, 0x31, +0xB5, 0x30, 0x7B, 0x8B, 0x94, 0x6F, 0xA4, 0xD0, +0xA4, 0xD0, 0xBD, 0x93, 0xB5, 0x52, 0xBD, 0x93, +0xB5, 0x72, 0xA4, 0xF1, 0xBD, 0xB4, 0xB5, 0x73, +0x9C, 0xD1, 0xBD, 0xD5, 0xC5, 0xF5, 0xBD, 0x94, +0xC5, 0xF5, 0xC5, 0xF5, 0xC6, 0x15, 0xCE, 0x57, +0xA5, 0x33, 0x52, 0xA9, 0x39, 0xC7, 0x21, 0x03, +0x52, 0xAB, 0xBD, 0xF8, 0xA5, 0x14, 0x8C, 0x72, +0x63, 0x2D, 0x42, 0x08, 0x62, 0xEC, 0x6B, 0x4D, +0x6B, 0x2D, 0x5A, 0xCB, 0x63, 0x2D, 0x7B, 0xAF, +0x73, 0x6D, 0x83, 0xF0, 0x7B, 0x6E, 0x62, 0xEC, +0x94, 0x70, 0xBD, 0x94, 0xAD, 0x12, 0xC5, 0xB3, +0xC5, 0xB3, 0xC5, 0xB3, 0xC5, 0xB3, 0xA4, 0xB0, +0xB5, 0x52, 0xCD, 0xD4, 0xBD, 0x71, 0xCD, 0xD3, +0xCD, 0xD3, 0xC5, 0x72, 0xC5, 0x92, 0xC5, 0xB2, +0xDE, 0x35, 0xCD, 0xD3, 0xB5, 0x11, 0xB5, 0x31, +0xBD, 0x72, 0xBD, 0x72, 0xAC, 0xF1, 0xAD, 0x11, +0x94, 0x6F, 0x94, 0x6F, 0x73, 0x6C, 0x29, 0x25, +0x18, 0xE4, 0x21, 0x05, 0x18, 0xE4, 0x10, 0xA3, +0x10, 0xC3, 0x18, 0xE4, 0x19, 0x04, 0x18, 0xE4, +0x10, 0xA3, 0x10, 0xC3, 0x10, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, 0x40, 0xE4, +0x79, 0x46, 0x91, 0x87, 0x69, 0x46, 0x20, 0xA3, +0x18, 0xC4, 0x18, 0xA3, 0x18, 0xA3, 0x18, 0xC3, +0x18, 0xA3, 0x18, 0xA3, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xA3, 0x18, 0xC3, 0x18, 0xC4, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x21, 0x05, +0x21, 0x25, 0x21, 0x05, 0x21, 0x05, 0x21, 0x25, +0x29, 0x46, 0x29, 0x25, 0x21, 0x25, 0x29, 0x25, +0x29, 0x66, 0x29, 0x46, 0x21, 0x25, 0x21, 0x05, +0x20, 0xE4, 0x21, 0x05, 0x29, 0x46, 0x29, 0x46, +0x21, 0x25, 0x21, 0x25, 0x21, 0x05, 0x18, 0xE4, +0x21, 0x25, 0x29, 0x25, 0x29, 0x46, 0x29, 0x46, +0x29, 0x46, 0x29, 0x46, 0x31, 0x67, 0x31, 0xA7, +0x39, 0xA7, 0x39, 0xC8, 0x41, 0xE9, 0x42, 0x09, +0x4A, 0x2A, 0x4A, 0x4A, 0x4A, 0x4A, 0x52, 0x8A, +0x6B, 0x0C, 0x8C, 0x2F, 0x9C, 0xB0, 0xA4, 0xF1, +0xA4, 0xF1, 0xA4, 0xF1, 0x9C, 0xD0, 0xAD, 0x12, +0xBD, 0xD4, 0xBD, 0xD4, 0xCE, 0x35, 0xD6, 0x96, +0xD6, 0x96, 0xD6, 0x76, 0xBD, 0xB4, 0xC5, 0xF5, +0xC6, 0x16, 0xC6, 0x16, 0xBD, 0xD4, 0xBD, 0xB4, +0xB5, 0x52, 0xCE, 0x35, 0xDE, 0x96, 0xBD, 0xB3, +0xB5, 0x52, 0xBD, 0x73, 0xAD, 0x12, 0x94, 0x4F, +0x8C, 0x0D, 0xA4, 0xAF, 0xA4, 0xD0, 0xAD, 0x11, +0xA4, 0xD0, 0xAD, 0x11, 0xAD, 0x11, 0xB5, 0x31, +0xB5, 0x52, 0xB5, 0x52, 0xB5, 0x52, 0xB5, 0x73, +0xBD, 0xB4, 0xC5, 0xF4, 0xBD, 0xB3, 0xAD, 0x11, +0xAD, 0x52, 0x7B, 0xCD, 0x5A, 0xCA, 0x63, 0x0C, +0x63, 0x0C, 0x84, 0x10, 0x9C, 0xD3, 0x9C, 0xD3, +0x6B, 0x2D, 0x42, 0x29, 0x5A, 0xCB, 0x39, 0xE7, +0x39, 0xA6, 0x39, 0x87, 0xB5, 0x75, 0xDE, 0xDA, +0xAD, 0x32, 0xC5, 0xF4, 0xC6, 0x15, 0xBD, 0xD3, +0xC6, 0x14, 0xB5, 0x92, 0xC6, 0x14, 0xBD, 0xD4, +0x8D, 0x6E, 0x9D, 0xD0, 0x8D, 0x2E, 0x74, 0x4C, +0x7C, 0x2C, 0x94, 0xCF, 0x8C, 0x4E, 0x94, 0x4E, +0xAD, 0x31, 0xBD, 0xD3, 0xA5, 0x4E, 0x74, 0x47, +0x84, 0xCA, 0x9D, 0x4E, 0xBD, 0xD2, 0xC5, 0xF4, +0xC5, 0xD4, 0xD6, 0x76, 0xBD, 0x72, 0xAC, 0xCF, +0xA4, 0x8E, 0x93, 0xCC, 0x93, 0xEC, 0x83, 0x6A, +0x83, 0x8B, 0x83, 0x8A, 0x83, 0x8A, 0x83, 0xAB, +0x83, 0xAB, 0x83, 0x8A, 0x94, 0x0C, 0x94, 0x0C, +0x93, 0xEC, 0x9C, 0x2D, 0x9C, 0x4D, 0xA4, 0x8E, +0xAC, 0xAF, 0xAC, 0xAF, 0xBD, 0x30, 0xBD, 0x31, +0xB5, 0x10, 0xBD, 0x51, 0xBD, 0x30, 0xBD, 0x30, +0xB5, 0x10, 0xB4, 0xF0, 0xAC, 0xCF, 0xAC, 0xF0, +0xB5, 0x10, 0xBD, 0x30, 0xBD, 0x50, 0xB5, 0x10, +0xBD, 0x30, 0xBD, 0x51, 0xBD, 0x51, 0xBD, 0x51, +0xB5, 0x30, 0xB5, 0x30, 0xB5, 0x10, 0xB5, 0x10, +0xAD, 0x0F, 0xAC, 0xEF, 0xA4, 0xAF, 0xA4, 0xAF, +0xA4, 0xAF, 0xA4, 0xD0, 0xAC, 0xD0, 0xAD, 0x11, +0xBD, 0x72, 0xBD, 0x93, 0xBD, 0x72, 0xB5, 0x52, +0xB5, 0x10, 0xC5, 0x71, 0xBD, 0x31, 0x7B, 0x6A, +0xAD, 0x10, 0xC5, 0xB3, 0xBD, 0x72, 0xC5, 0x92, +0xCD, 0xF4, 0xD6, 0x35, 0xB5, 0x32, 0x9C, 0xB0, +0x9C, 0xD1, 0x9C, 0xD1, 0x9C, 0xF1, 0xB5, 0x73, +0x5A, 0xC9, 0x41, 0xE7, 0x39, 0xC6, 0x39, 0xC7, +0x41, 0xE7, 0x52, 0x8A, 0x5A, 0xCB, 0x62, 0xEB, +0x63, 0x0C, 0x6B, 0x6D, 0x94, 0x71, 0xA4, 0xF4, +0x9C, 0xF4, 0x9C, 0xD3, 0xC6, 0x18, 0xAD, 0x34, +0x7B, 0xAF, 0x8C, 0x50, 0xBD, 0xD5, 0xD6, 0x56, +0xCE, 0x35, 0xCE, 0x35, 0xD6, 0x56, 0xA4, 0xD0, +0xB5, 0x30, 0x83, 0xCC, 0x9C, 0xB0, 0xAD, 0x32, +0xB5, 0x52, 0xA5, 0x11, 0xA4, 0xF1, 0xA5, 0x11, +0xB5, 0x73, 0xB5, 0x93, 0xB5, 0x93, 0xB5, 0x53, +0x9C, 0xD0, 0xBD, 0xB4, 0xBD, 0xB4, 0xB5, 0x53, +0xBD, 0xB4, 0xBD, 0xB4, 0xC5, 0xF5, 0xCE, 0x36, +0xCE, 0x76, 0xBD, 0xD5, 0x5A, 0xCA, 0x29, 0x65, +0x5A, 0xEC, 0xCE, 0x59, 0xAD, 0x76, 0x8C, 0x52, +0x52, 0x8A, 0x42, 0x08, 0x52, 0xAA, 0x5A, 0xEB, +0x63, 0x2C, 0x5A, 0xEC, 0x52, 0x8A, 0x4A, 0x49, +0x52, 0x69, 0x6B, 0x2D, 0xA4, 0xF3, 0x7B, 0x8E, +0x73, 0x4D, 0x9C, 0x71, 0xCE, 0x16, 0xC5, 0xD4, +0xBD, 0x92, 0xC5, 0xB2, 0xC5, 0xD3, 0xA4, 0xD0, +0xB5, 0x31, 0xC5, 0x92, 0xB5, 0x0F, 0xC5, 0x92, +0xD6, 0x34, 0xC5, 0xB2, 0xC5, 0x92, 0xBD, 0x51, +0xC5, 0x92, 0xB5, 0x10, 0xAC, 0xD0, 0xBD, 0x72, +0xCD, 0xB3, 0xBD, 0x71, 0x9C, 0xAF, 0x9C, 0xB0, +0xA4, 0xF1, 0xA4, 0xD1, 0x6B, 0x4C, 0x29, 0x25, +0x20, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x19, 0x05, 0x19, 0x04, 0x10, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xC3, 0x10, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC3, 0x18, 0xA3, 0x59, 0x46, +0x89, 0x67, 0x89, 0x67, 0x38, 0xC3, 0x18, 0xA3, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xA3, 0x18, 0xA3, 0x18, 0xA3, 0x18, 0xC4, +0x18, 0xA3, 0x18, 0xC3, 0x18, 0xC4, 0x18, 0xE4, +0x20, 0xE4, 0x21, 0x05, 0x20, 0xE4, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x21, 0x05, +0x21, 0x25, 0x21, 0x25, 0x21, 0x05, 0x21, 0x25, +0x29, 0x25, 0x29, 0x46, 0x21, 0x25, 0x21, 0x05, +0x18, 0xE4, 0x21, 0x05, 0x21, 0x25, 0x29, 0x26, +0x29, 0x25, 0x21, 0x05, 0x21, 0x05, 0x18, 0xE4, +0x21, 0x05, 0x21, 0x05, 0x21, 0x25, 0x21, 0x25, +0x21, 0x05, 0x21, 0x25, 0x29, 0x46, 0x31, 0xA7, +0x39, 0xC8, 0x31, 0xA7, 0x39, 0xA8, 0x39, 0xC8, +0x41, 0xE9, 0x42, 0x09, 0x42, 0x2A, 0x4A, 0x2A, +0x42, 0x29, 0x4A, 0x29, 0x63, 0x0C, 0x94, 0x50, +0xAD, 0x12, 0xB5, 0x53, 0xB5, 0x53, 0xAC, 0xF1, +0xA4, 0xB0, 0x9C, 0x6F, 0x94, 0x2E, 0x8B, 0xED, +0x83, 0xED, 0x83, 0xCD, 0x83, 0xCD, 0x84, 0x0E, +0x9C, 0x70, 0x94, 0x6F, 0x83, 0xEE, 0x9C, 0xB0, +0xA4, 0xD0, 0xB5, 0x32, 0xAD, 0x11, 0x94, 0x6E, +0xA4, 0xD0, 0x9C, 0x8F, 0x9C, 0x90, 0xA4, 0xF1, +0xA4, 0xD1, 0xAD, 0x31, 0xA4, 0xD0, 0xA4, 0xD0, +0xA4, 0xD0, 0xAD, 0x11, 0xB5, 0x52, 0xB5, 0x52, +0xB5, 0x52, 0xB5, 0x52, 0xAD, 0x12, 0x9C, 0x8F, +0xBD, 0x93, 0xC5, 0xD3, 0xA4, 0xD0, 0xB5, 0x73, +0x9C, 0x8F, 0x73, 0x8C, 0x73, 0x8D, 0x62, 0xEB, +0x5A, 0xEB, 0x84, 0x10, 0xBD, 0xB6, 0x9C, 0xF3, +0x73, 0x6E, 0x4A, 0x49, 0x63, 0x2D, 0x4A, 0x49, +0x39, 0xC7, 0x39, 0xA7, 0xAD, 0x55, 0xAD, 0x34, +0x83, 0xCF, 0xAD, 0x33, 0xCE, 0x15, 0xCE, 0x35, +0xC6, 0x14, 0xBD, 0xD3, 0xC6, 0x14, 0xC6, 0x14, +0x74, 0xA9, 0x6C, 0x68, 0x6C, 0x49, 0x74, 0x4B, +0x94, 0xCF, 0xC6, 0x55, 0xBD, 0xF5, 0xB5, 0x72, +0xBD, 0xB3, 0xB5, 0x71, 0x8C, 0xAB, 0x84, 0xAA, +0xB6, 0x11, 0xAD, 0x91, 0xC5, 0xF3, 0xBD, 0x93, +0xC5, 0xD4, 0xDE, 0x96, 0xBD, 0x72, 0xB4, 0xCF, +0x93, 0xEB, 0xB4, 0x6E, 0xBC, 0xCF, 0x8B, 0x8B, +0x7B, 0x4A, 0x9C, 0x6E, 0xA4, 0xAF, 0xAC, 0xF0, +0xAC, 0xF0, 0xA4, 0xAF, 0xA4, 0xAF, 0xAC, 0xCF, +0xA4, 0x8E, 0x94, 0x2D, 0x94, 0x0C, 0x94, 0x2D, +0x94, 0x2D, 0x9C, 0x4E, 0xAC, 0xF0, 0xAC, 0xCF, +0xA4, 0x8E, 0x9C, 0x6D, 0xB4, 0xEF, 0x9C, 0x2C, +0x8B, 0xEC, 0xA4, 0x8E, 0x8B, 0xCB, 0x8B, 0xEC, +0x9C, 0x4D, 0x94, 0x2D, 0x9C, 0x4D, 0xA4, 0x8E, +0x8B, 0xCB, 0x9C, 0x4D, 0xA4, 0x8E, 0xA4, 0x6D, +0xAC, 0xCE, 0xAC, 0xAE, 0xA4, 0x8E, 0x9C, 0x4D, +0x94, 0x0C, 0x9C, 0x2D, 0x94, 0x0C, 0x9C, 0x2D, +0xA4, 0x8E, 0xBD, 0x51, 0xC5, 0x71, 0xCD, 0xB2, +0xC5, 0x51, 0xC5, 0x71, 0xC5, 0x91, 0xC5, 0x71, +0xC5, 0x71, 0xC5, 0x71, 0xC5, 0x71, 0xBD, 0x30, +0xAC, 0xCE, 0xAC, 0xAE, 0xA4, 0xAE, 0xA4, 0x8D, +0xA4, 0x8E, 0xAC, 0xAE, 0xA4, 0x8E, 0x9C, 0x6E, +0x9C, 0x8F, 0x9C, 0x6F, 0x9C, 0x6E, 0xB5, 0x10, +0x8C, 0x2E, 0x4A, 0x07, 0x39, 0xC6, 0x39, 0xA6, +0x42, 0x08, 0x52, 0x8A, 0x5A, 0xAA, 0x6B, 0x4C, +0x63, 0x2C, 0x63, 0x2C, 0x8C, 0x31, 0x9C, 0xB3, +0x9C, 0xB3, 0xAD, 0x55, 0xC6, 0x18, 0xAD, 0x35, +0x7B, 0xCF, 0x5A, 0xCB, 0x7B, 0xAE, 0xD6, 0x77, +0xD6, 0x76, 0xD6, 0x76, 0xD6, 0x56, 0xA4, 0xCF, +0xA4, 0xCF, 0x83, 0xCC, 0x9C, 0xD0, 0xA4, 0xD0, +0xA4, 0xF1, 0xB5, 0x73, 0xBD, 0xB4, 0xBD, 0xB4, +0xC5, 0xD5, 0xC6, 0x15, 0xC6, 0x15, 0xBD, 0xD4, +0xB5, 0x73, 0xB5, 0x94, 0xBD, 0xD4, 0xB5, 0x73, +0xB5, 0x93, 0xBD, 0xB4, 0xBD, 0xB4, 0xBD, 0xD4, +0xB5, 0x93, 0xBD, 0xB4, 0x83, 0xED, 0x7B, 0xCE, +0x9C, 0xB2, 0xC6, 0x18, 0xAD, 0x56, 0x8C, 0x52, +0x31, 0xA7, 0x31, 0xA6, 0x42, 0x08, 0x4A, 0x69, +0x63, 0x0B, 0x6B, 0x4D, 0x6B, 0x4D, 0x63, 0x0C, +0x63, 0x0C, 0x7B, 0xCF, 0xD6, 0x79, 0xA4, 0xF3, +0x6B, 0x0C, 0x94, 0x71, 0x9C, 0xB2, 0xCE, 0x17, +0xBD, 0x73, 0xBD, 0x92, 0xB5, 0x52, 0xA4, 0xD0, +0xB5, 0x31, 0xC5, 0x92, 0xBD, 0x51, 0xCD, 0xF3, +0xD6, 0x34, 0xD5, 0xF4, 0xC5, 0xB3, 0xC5, 0xB2, +0xC5, 0xB2, 0xC5, 0xB2, 0xB5, 0x10, 0xB5, 0x31, +0xC5, 0xB3, 0xB5, 0x31, 0x9C, 0x8F, 0xAD, 0x32, +0xBD, 0x73, 0xAD, 0x32, 0x7B, 0xCD, 0x39, 0xA7, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC4, +0x18, 0xE4, 0x10, 0xC4, 0x18, 0xE4, 0x18, 0xC4, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC4, 0x10, 0xC3, +0x10, 0xA3, 0x10, 0xC4, 0x28, 0xC4, 0x71, 0x46, +0x89, 0x67, 0x69, 0x25, 0x20, 0x62, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x18, 0xA3, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, 0x20, 0xE4, +0x20, 0xE4, 0x21, 0x05, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x18, 0xE4, +0x21, 0x05, 0x29, 0x46, 0x29, 0x46, 0x21, 0x25, +0x18, 0xC4, 0x10, 0xA3, 0x18, 0xC4, 0x18, 0xE4, +0x20, 0xE4, 0x20, 0xE4, 0x21, 0x05, 0x18, 0xE4, +0x18, 0xE4, 0x21, 0x05, 0x21, 0x05, 0x21, 0x05, +0x20, 0xE4, 0x18, 0xE4, 0x21, 0x25, 0x31, 0x67, +0x31, 0xA7, 0x31, 0x87, 0x31, 0x87, 0x31, 0xA8, +0x39, 0xC8, 0x39, 0xE9, 0x42, 0x09, 0x42, 0x09, +0x4A, 0x2A, 0x42, 0x2A, 0x4A, 0x2A, 0x52, 0x8B, +0x7B, 0x8E, 0xA4, 0xD2, 0xAC, 0xF2, 0xB5, 0x53, +0xAD, 0x12, 0xA4, 0xD1, 0xAC, 0xF1, 0xAC, 0xF1, +0xA4, 0xB0, 0xAC, 0xF2, 0xAC, 0xF1, 0xAD, 0x12, +0xAC, 0xF1, 0xAD, 0x12, 0xB5, 0x12, 0xB5, 0x12, +0xB5, 0x32, 0xB5, 0x32, 0xB5, 0x32, 0xB5, 0x53, +0xBD, 0x73, 0xB5, 0x52, 0xAD, 0x12, 0xAD, 0x12, +0xB5, 0x52, 0xB5, 0x52, 0xB5, 0x32, 0xBD, 0x73, +0xBD, 0x73, 0xB5, 0x32, 0xAC, 0xD0, 0xA4, 0xB0, +0xA4, 0xB0, 0xA4, 0xD0, 0xAC, 0xF1, 0x94, 0x4F, +0x9C, 0xB0, 0xA4, 0xD1, 0x94, 0x6F, 0xA4, 0xF1, +0x9C, 0x90, 0x8C, 0x2E, 0x94, 0x4F, 0x73, 0x6C, +0x5A, 0xCB, 0x7B, 0xAF, 0x94, 0x71, 0x73, 0x6E, +0x4A, 0x49, 0x63, 0x0C, 0x84, 0x10, 0x5A, 0xCB, +0x4A, 0x29, 0x31, 0x66, 0x7B, 0xAF, 0x83, 0xCF, +0x94, 0x31, 0x73, 0x4D, 0x83, 0xCE, 0xC5, 0xF5, +0xC6, 0x14, 0xCE, 0x55, 0xDE, 0x97, 0xBD, 0xB4, +0x5C, 0x04, 0x4B, 0xA4, 0x7C, 0xAC, 0x84, 0x8E, +0xA5, 0x91, 0xA5, 0x91, 0xD6, 0xD8, 0xBD, 0xD4, +0xBD, 0xB3, 0x84, 0x2B, 0x6B, 0xE6, 0x9D, 0x6D, +0xBE, 0x12, 0x9C, 0xEE, 0xBD, 0xB2, 0xBD, 0x92, +0xC5, 0xD3, 0xDE, 0x76, 0xB5, 0x31, 0xA4, 0x8E, +0x8B, 0x69, 0x93, 0x8A, 0x8B, 0x6A, 0x93, 0xCC, +0xA4, 0x6E, 0xB5, 0x10, 0xB5, 0x11, 0xA4, 0xAF, +0xAC, 0xF0, 0xA4, 0xAF, 0xA4, 0x8F, 0xAC, 0xCF, +0xAC, 0xF0, 0xA4, 0xD0, 0x94, 0x2D, 0xAC, 0xF0, +0xB5, 0x31, 0xB5, 0x52, 0xBD, 0x72, 0xB5, 0x31, +0xB5, 0x31, 0xA4, 0xAF, 0xB5, 0x30, 0x94, 0x0D, +0x83, 0xCC, 0x9C, 0x8F, 0x83, 0xCC, 0x83, 0xCC, +0x83, 0xED, 0x94, 0x6F, 0x8C, 0x0D, 0x8C, 0x2D, +0x7B, 0x8B, 0x94, 0x4E, 0x9C, 0x6E, 0xA4, 0xAF, +0xA4, 0x8E, 0xA4, 0xCF, 0xA4, 0xAE, 0xA4, 0xCF, +0xA4, 0xAF, 0xB5, 0x11, 0xAC, 0xF0, 0xAC, 0xF0, +0xAC, 0xF0, 0xBD, 0x31, 0xB4, 0xEF, 0xC5, 0x72, +0xBD, 0x71, 0xCD, 0xB3, 0xC5, 0x92, 0xD5, 0xF4, +0xCD, 0xD3, 0xD6, 0x14, 0xD6, 0x34, 0xD6, 0x14, +0xC5, 0x92, 0xB5, 0x30, 0xBD, 0x72, 0xBD, 0x72, +0xBD, 0x51, 0xBD, 0x51, 0xBD, 0x51, 0xAC, 0xEF, +0xA4, 0xAF, 0xBD, 0x52, 0xBD, 0x31, 0xBD, 0x31, +0xAC, 0xF0, 0x6B, 0x0A, 0x39, 0xA6, 0x39, 0xA6, +0x39, 0xC7, 0x4A, 0x28, 0x5A, 0xAA, 0x5A, 0xAA, +0x5A, 0xAA, 0x52, 0x8A, 0x6B, 0x4D, 0x7B, 0xAF, +0x7B, 0xAF, 0xAD, 0x76, 0x9C, 0xD3, 0xC5, 0xF8, +0x8C, 0x31, 0x5A, 0xCB, 0x52, 0x89, 0xA4, 0xF1, +0xA4, 0x8F, 0x8B, 0xEC, 0x8B, 0xCB, 0x83, 0x6A, +0x9C, 0x4D, 0x8C, 0x0D, 0x8B, 0xED, 0x83, 0xAC, +0x73, 0x4A, 0x7B, 0x8B, 0x83, 0xAC, 0x83, 0xCC, +0x7B, 0xAC, 0x7B, 0x8C, 0x73, 0x8B, 0x7B, 0xAC, +0x7B, 0xAC, 0x83, 0xED, 0x8C, 0x2E, 0x8C, 0x0E, +0x8C, 0x4F, 0x84, 0x0D, 0x83, 0xED, 0x7B, 0xAC, +0x83, 0xCC, 0x8C, 0x4E, 0x63, 0x0A, 0x8C, 0x2F, +0xB5, 0x75, 0xBD, 0xF7, 0xB5, 0x76, 0x8C, 0x72, +0x39, 0xC7, 0x39, 0xE7, 0x31, 0xA6, 0x39, 0xC6, +0x4A, 0x69, 0x52, 0x8A, 0x63, 0x0C, 0x63, 0x0C, +0x63, 0x0C, 0x52, 0xAB, 0x6B, 0x4D, 0x83, 0xF0, +0x42, 0x08, 0x73, 0x8E, 0x94, 0x51, 0x94, 0x51, +0xC5, 0xB6, 0xB5, 0x32, 0x9C, 0x8F, 0xA4, 0xB0, +0xAD, 0x11, 0xC5, 0x92, 0xC5, 0x71, 0xC5, 0xB2, +0xCD, 0xD3, 0xCD, 0xB2, 0xCD, 0xF3, 0xD6, 0x35, +0xD6, 0x14, 0xD5, 0xF3, 0xCD, 0xB3, 0xBD, 0x51, +0xC5, 0x92, 0xBD, 0x52, 0xAD, 0x11, 0xB5, 0x52, +0xBD, 0x92, 0xB5, 0x31, 0x8C, 0x2F, 0x52, 0x8A, +0x21, 0x05, 0x18, 0xE4, 0x18, 0xC4, 0x19, 0x04, +0x18, 0xE4, 0x19, 0x04, 0x19, 0x05, 0x18, 0xC4, +0x10, 0x83, 0x10, 0xA3, 0x18, 0xE4, 0x10, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x38, 0xE4, 0x69, 0x25, +0x71, 0x25, 0x40, 0xE4, 0x18, 0xA3, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x18, 0xA3, 0x18, 0xC3, 0x18, 0xC4, 0x21, 0x04, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x21, 0x25, 0x21, 0x05, 0x18, 0xE4, +0x18, 0xC4, 0x20, 0xE4, 0x21, 0x25, 0x21, 0x25, +0x21, 0x05, 0x18, 0xC4, 0x18, 0xC3, 0x18, 0xC3, +0x18, 0xC4, 0x18, 0xA4, 0x18, 0xC4, 0x18, 0xE4, +0x18, 0xE4, 0x21, 0x05, 0x29, 0x46, 0x29, 0x25, +0x20, 0xE4, 0x18, 0xE4, 0x21, 0x05, 0x29, 0x66, +0x31, 0x87, 0x29, 0x67, 0x31, 0x67, 0x31, 0x87, +0x31, 0x67, 0x31, 0x87, 0x39, 0xC8, 0x39, 0xC8, +0x41, 0xE9, 0x4A, 0x2A, 0x4A, 0x29, 0x42, 0x2A, +0x4A, 0x4A, 0x5A, 0xAB, 0x73, 0x6D, 0x8C, 0x2F, +0x7B, 0x6C, 0x7B, 0xAD, 0x83, 0xCD, 0x9C, 0x70, +0x94, 0x0E, 0x73, 0x4B, 0x7B, 0x6C, 0x83, 0xAC, +0x83, 0xAD, 0x73, 0x4B, 0x73, 0x2B, 0x62, 0xC9, +0x6A, 0xEA, 0x83, 0xAD, 0x6B, 0x0A, 0x73, 0x2B, +0x83, 0x8C, 0x83, 0xCD, 0xA4, 0xB0, 0x9C, 0x6F, +0x94, 0x2E, 0xA4, 0xB0, 0xAC, 0xD0, 0xB5, 0x32, +0xC5, 0xD4, 0xCD, 0xB4, 0xCD, 0xD4, 0xB5, 0x32, +0xCD, 0xB4, 0xCD, 0xF5, 0xCE, 0x15, 0xC5, 0xF5, +0xC5, 0xF5, 0xCD, 0xF5, 0xC5, 0xD5, 0xC5, 0xD4, +0xB5, 0x53, 0xBD, 0x94, 0xBD, 0x52, 0xBD, 0x73, +0x7B, 0xAD, 0x6B, 0x4D, 0x5A, 0xEB, 0x4A, 0x49, +0x39, 0xA7, 0x5A, 0xCB, 0x63, 0x0C, 0x73, 0x8E, +0x63, 0x0C, 0x21, 0x05, 0x62, 0xEC, 0x83, 0xCF, +0xCE, 0x17, 0xCE, 0x18, 0xAD, 0x14, 0xCE, 0x17, +0xC5, 0xD5, 0xCE, 0x36, 0xC5, 0xB5, 0x94, 0x4F, +0x53, 0xA6, 0x8D, 0x0F, 0x9D, 0x72, 0x84, 0x4E, +0x9D, 0x4F, 0x95, 0x2E, 0xAD, 0xD3, 0xCE, 0xB7, +0xC6, 0x34, 0x84, 0xA9, 0x8D, 0x08, 0x8D, 0x0B, +0x9D, 0x4F, 0x8C, 0x8D, 0xBD, 0xF3, 0xBD, 0xD3, +0xC5, 0xF4, 0xDE, 0x76, 0xCD, 0xB3, 0xA4, 0x4D, +0x9B, 0xCB, 0x8B, 0x6B, 0x72, 0xC9, 0x62, 0xA9, +0x73, 0x0A, 0x9C, 0x4E, 0xA4, 0x8F, 0x83, 0xCC, +0x7B, 0x8B, 0x8B, 0xED, 0x94, 0x2E, 0x83, 0xCC, +0x9C, 0x6E, 0xA4, 0xF0, 0x94, 0x4E, 0xAD, 0x31, +0xB5, 0x52, 0xBD, 0x72, 0xBD, 0x52, 0xBD, 0x72, +0xBD, 0x72, 0xAC, 0xAF, 0xBD, 0x30, 0xA4, 0xAF, +0x8C, 0x2E, 0x94, 0x4E, 0xA4, 0xD1, 0xA4, 0xD1, +0x94, 0x6F, 0x8C, 0x0D, 0x83, 0xED, 0x94, 0x6F, +0x8C, 0x2E, 0x94, 0x6F, 0x94, 0x6E, 0xA4, 0xD0, +0x94, 0x4E, 0x8C, 0x2D, 0x9C, 0xAF, 0x9C, 0xAF, +0xB5, 0x52, 0xB5, 0x52, 0xBD, 0x93, 0xBD, 0x92, +0xB5, 0x10, 0xBD, 0x30, 0xA4, 0xAE, 0x94, 0x2D, +0x8C, 0x2E, 0x8C, 0x0E, 0x7B, 0x8C, 0x7B, 0x8B, +0x7B, 0xAB, 0x7B, 0xAC, 0x83, 0xEC, 0x83, 0xCC, +0x62, 0xE9, 0x6B, 0x0A, 0x83, 0xCD, 0x8C, 0x0E, +0x83, 0xED, 0x73, 0x6B, 0x8C, 0x0D, 0x62, 0xE9, +0x6B, 0x2B, 0x7B, 0x8C, 0x7B, 0x8C, 0x73, 0x2A, +0x7B, 0xAC, 0x94, 0x90, 0x52, 0x69, 0x39, 0xC6, +0x31, 0xA6, 0x42, 0x08, 0x5A, 0x8A, 0x5A, 0xAA, +0x6B, 0x2C, 0x5A, 0xAA, 0x52, 0x8A, 0x5A, 0xCB, +0x8C, 0x51, 0x94, 0x92, 0xB5, 0x96, 0xD6, 0xBB, +0xAD, 0x35, 0x63, 0x2D, 0x42, 0x08, 0x62, 0xEA, +0x9C, 0x6F, 0xA4, 0x6E, 0x94, 0x0C, 0x9C, 0x4D, +0xA4, 0xAF, 0xA4, 0x8E, 0xA4, 0x8F, 0xA4, 0x8E, +0x9C, 0x6E, 0xA4, 0x8F, 0xAC, 0xD0, 0xAC, 0xF0, +0xB5, 0x11, 0xB5, 0x11, 0xAC, 0xF0, 0xAD, 0x10, +0xB5, 0x51, 0xB5, 0x51, 0xB5, 0x31, 0xB5, 0x31, +0xB5, 0x31, 0xB5, 0x10, 0xAC, 0xF0, 0xA4, 0xAF, +0x9C, 0x8F, 0x8C, 0x2E, 0x83, 0xED, 0x9C, 0x90, +0xC5, 0xF6, 0xB5, 0x96, 0xAD, 0x35, 0x7B, 0xF0, +0x31, 0x86, 0x31, 0xA6, 0x39, 0xE7, 0x31, 0x85, +0x31, 0xC6, 0x42, 0x08, 0x5A, 0xEB, 0x5A, 0xCB, +0x5A, 0xCB, 0x5A, 0xCB, 0x5A, 0xEB, 0x63, 0x0C, +0x52, 0x8A, 0x7B, 0xAF, 0x62, 0xCB, 0x73, 0x4E, +0x83, 0xEF, 0xAD, 0x13, 0x9C, 0x90, 0xA4, 0xB0, +0xA4, 0x8F, 0xC5, 0x92, 0xBD, 0x71, 0xC5, 0x92, +0xCD, 0xD3, 0xBD, 0x72, 0xAC, 0xF0, 0xB5, 0x10, +0xBD, 0x51, 0xD6, 0x34, 0xDE, 0x34, 0xCD, 0xB3, +0xCD, 0xB3, 0xBD, 0x51, 0xB5, 0x52, 0xAD, 0x31, +0xB5, 0x51, 0xB5, 0x52, 0x94, 0x6F, 0x83, 0xEE, +0x39, 0xC7, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x10, 0xC3, +0x10, 0xA3, 0x18, 0xE4, 0x18, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC4, 0x41, 0x05, 0x61, 0x25, +0x59, 0x04, 0x30, 0xC3, 0x20, 0xC4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xC4, 0x10, 0xA3, 0x10, 0x83, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC3, 0x18, 0xC4, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x18, 0xE4, +0x18, 0xA3, 0x18, 0xE4, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x18, 0xE4, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x21, 0x25, 0x21, 0x05, +0x20, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x21, 0x25, +0x31, 0x87, 0x31, 0x87, 0x29, 0x46, 0x29, 0x46, +0x29, 0x67, 0x31, 0x67, 0x31, 0x87, 0x39, 0xA8, +0x39, 0xC8, 0x41, 0xE9, 0x42, 0x09, 0x4A, 0x2A, +0x42, 0x09, 0x42, 0x09, 0x4A, 0x6A, 0x63, 0x0C, +0x7B, 0xAE, 0x94, 0x4F, 0x94, 0x2F, 0x9C, 0x90, +0x94, 0x70, 0x83, 0xCE, 0x94, 0x4F, 0x8C, 0x0E, +0x83, 0xCD, 0x83, 0xEE, 0x73, 0x4B, 0x6B, 0x2B, +0x6B, 0x2B, 0x6A, 0xEA, 0x5A, 0x88, 0x62, 0xCA, +0x83, 0xAD, 0x7B, 0xAD, 0x7B, 0xAC, 0x7B, 0xAC, +0x83, 0xED, 0x9C, 0x90, 0xA4, 0xB0, 0xAC, 0xD1, +0xBD, 0x93, 0xB5, 0x11, 0xBD, 0x52, 0xC5, 0x93, +0xC5, 0x72, 0xB5, 0x31, 0x9C, 0x4E, 0x94, 0x0E, +0xA4, 0xB0, 0xAC, 0xF1, 0xAD, 0x11, 0xBD, 0xB3, +0xAD, 0x11, 0xAC, 0xD0, 0x9C, 0x6E, 0xA4, 0xD1, +0x9C, 0x91, 0x73, 0x8D, 0x4A, 0x49, 0x4A, 0x29, +0x31, 0x86, 0x4A, 0x29, 0x73, 0x8E, 0x83, 0xCF, +0x6B, 0x4D, 0x29, 0x46, 0x4A, 0x29, 0x73, 0x6D, +0xB5, 0x34, 0xC5, 0x95, 0xCD, 0xD6, 0xBD, 0x74, +0x8B, 0xEF, 0xA4, 0xB2, 0x9C, 0x71, 0xA4, 0xB1, +0x9D, 0x91, 0xA5, 0xB3, 0xB6, 0x35, 0x7C, 0x4E, +0x8C, 0xCC, 0x84, 0xCA, 0x9D, 0x90, 0xA5, 0xD1, +0x9D, 0x6C, 0x95, 0x47, 0x7C, 0x85, 0x7C, 0x88, +0xB5, 0xD1, 0xB5, 0xB2, 0xC6, 0x14, 0xC6, 0x14, +0xBD, 0xB2, 0xCE, 0x34, 0xC5, 0x92, 0xA4, 0x6D, +0x93, 0xAB, 0x83, 0x4B, 0x5A, 0x68, 0x52, 0x68, +0x52, 0x48, 0x62, 0xC9, 0x62, 0xC9, 0x6B, 0x2B, +0x5A, 0xA9, 0x6B, 0x4B, 0x94, 0x4F, 0x94, 0x4F, +0x83, 0xCD, 0x9C, 0xB0, 0x73, 0x6B, 0xAD, 0x31, +0xBD, 0x72, 0xB5, 0x31, 0xB5, 0x31, 0xAC, 0xF0, +0xC5, 0x93, 0x9C, 0x6E, 0xB5, 0x10, 0x9C, 0x6E, +0x7B, 0xAC, 0x94, 0x6F, 0x9C, 0xD1, 0x9C, 0xD1, +0xBD, 0xB4, 0x9C, 0xB0, 0x8C, 0x4F, 0x94, 0x6F, +0x9C, 0xB0, 0x9C, 0xB0, 0x9C, 0xB0, 0xA4, 0xD0, +0xA4, 0xD0, 0xA4, 0xD0, 0x94, 0x4E, 0x9C, 0x8F, +0xAC, 0xF1, 0xB5, 0x52, 0xB5, 0x52, 0x7B, 0x6B, +0x73, 0x49, 0xBD, 0x30, 0xAC, 0xCF, 0xAD, 0x11, +0xBD, 0x94, 0xB5, 0x73, 0xAD, 0x53, 0xA4, 0xF1, +0xA4, 0xD1, 0x9C, 0xB0, 0x8C, 0x2E, 0x94, 0x8F, +0x94, 0x90, 0x94, 0xB0, 0x8C, 0x4F, 0x8C, 0x2E, +0x8C, 0x0E, 0x84, 0x0E, 0x83, 0xEE, 0x84, 0x0E, +0x7B, 0xEE, 0x7B, 0xEE, 0x73, 0x8D, 0x63, 0x0B, +0x7B, 0xAD, 0x8C, 0x2F, 0x83, 0xCE, 0x4A, 0x48, +0x39, 0xC7, 0x41, 0xE7, 0x5A, 0x8A, 0x5A, 0xCB, +0x52, 0x8A, 0x41, 0xE7, 0x52, 0x8A, 0x73, 0xAE, +0x94, 0xB2, 0xA5, 0x35, 0xBD, 0xD7, 0xCE, 0x59, +0xB5, 0xB7, 0x8C, 0x31, 0x73, 0x8F, 0x5A, 0xCB, +0x62, 0xEA, 0xBD, 0x93, 0xB5, 0x31, 0xBD, 0x72, +0xB5, 0x31, 0x8B, 0xCC, 0x83, 0x8A, 0x83, 0xAB, +0x7B, 0x8A, 0x7B, 0x6A, 0x8B, 0xCC, 0x7B, 0x6A, +0x83, 0xCC, 0x7B, 0x8A, 0x8B, 0xCB, 0xA4, 0xAF, +0xBD, 0x72, 0xB5, 0x10, 0xB5, 0x10, 0xB4, 0xEF, +0xA4, 0x8E, 0xAC, 0xAE, 0x9C, 0x6D, 0x83, 0xCB, +0xA4, 0xD0, 0xB5, 0x52, 0x9C, 0x6F, 0x8B, 0xED, +0xBD, 0xD6, 0xAD, 0x76, 0xA5, 0x14, 0x7B, 0xAF, +0x39, 0xC7, 0x29, 0x44, 0x31, 0xA6, 0x42, 0x08, +0x39, 0xC7, 0x39, 0xE7, 0x5A, 0xCB, 0x4A, 0x69, +0x52, 0x89, 0x52, 0xAA, 0x5A, 0xEC, 0x6B, 0x4E, +0x73, 0x6E, 0xCE, 0x39, 0xCE, 0x59, 0x6B, 0x2D, +0x62, 0xEC, 0x7B, 0x8D, 0xAD, 0x33, 0x9C, 0x6F, +0xAD, 0x12, 0x9C, 0x6F, 0x8C, 0x0D, 0x94, 0x2D, +0x94, 0x2D, 0x8B, 0xED, 0x8B, 0xED, 0x94, 0x2D, +0x94, 0x2D, 0x9C, 0x6E, 0xA4, 0xAF, 0xA4, 0xAF, +0xAC, 0xF0, 0xA4, 0xD0, 0xAC, 0xF0, 0xAC, 0xF0, +0xBD, 0x72, 0xBD, 0x72, 0xAD, 0x11, 0x9C, 0xB1, +0x52, 0x8A, 0x29, 0x25, 0x19, 0x04, 0x21, 0x04, +0x21, 0x05, 0x18, 0xE4, 0x18, 0xC3, 0x18, 0xC3, +0x18, 0xE5, 0x18, 0xE4, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC4, 0x41, 0x05, 0x58, 0xE4, +0x48, 0xE4, 0x30, 0xE4, 0x20, 0xE4, 0x21, 0x04, +0x21, 0x05, 0x18, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xA3, 0x18, 0xC4, 0x18, 0xE4, +0x20, 0xE4, 0x20, 0xE5, 0x20, 0xE4, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x20, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x21, 0x25, 0x21, 0x05, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x20, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x18, 0xE4, 0x18, 0xE4, +0x21, 0x25, 0x29, 0x66, 0x29, 0x46, 0x29, 0x46, +0x29, 0x46, 0x29, 0x46, 0x29, 0x67, 0x31, 0x87, +0x31, 0x87, 0x31, 0xA8, 0x41, 0xE9, 0x42, 0x0A, +0x42, 0x2A, 0x42, 0x09, 0x42, 0x09, 0x4A, 0x4A, +0x5A, 0xAB, 0x7B, 0x8E, 0x94, 0x2F, 0x94, 0x4F, +0x94, 0x4F, 0xA4, 0x90, 0x9C, 0x70, 0x9C, 0x70, +0x94, 0x0E, 0xA4, 0xB0, 0x94, 0x2E, 0x7B, 0x8C, +0x94, 0x0E, 0x94, 0x0F, 0x73, 0x2B, 0x73, 0x4C, +0x8B, 0xEE, 0x8C, 0x2F, 0x83, 0xCD, 0x83, 0xAD, +0x83, 0xCD, 0x8C, 0x2E, 0xAC, 0xF1, 0xB5, 0x12, +0xB5, 0x31, 0xA4, 0x8F, 0xA4, 0x8F, 0xAC, 0xF0, +0xBD, 0x51, 0xC5, 0x72, 0x9C, 0x6E, 0x94, 0x2E, +0xA4, 0xD0, 0xAC, 0xF1, 0xB5, 0x32, 0xAC, 0xF0, +0x9C, 0x4E, 0x94, 0x0D, 0x94, 0x2E, 0x94, 0x4E, +0x94, 0x2F, 0x8C, 0x0F, 0x5A, 0xCB, 0x62, 0xEC, +0x39, 0xA7, 0x39, 0xE8, 0x7B, 0xCF, 0x7B, 0xCF, +0x84, 0x10, 0x5A, 0xCB, 0x6B, 0x2D, 0x83, 0xCF, +0x73, 0x4D, 0x8B, 0xCF, 0x9C, 0x71, 0x83, 0xCE, +0xA4, 0xD2, 0xAD, 0x13, 0xA4, 0xD2, 0xBD, 0x52, +0xA5, 0xB4, 0x9D, 0x71, 0x9D, 0x70, 0xA5, 0xD2, +0x84, 0xCB, 0x74, 0x88, 0x8D, 0x6D, 0x9D, 0xAD, +0x85, 0x06, 0x8D, 0x47, 0x84, 0xC7, 0x74, 0x47, +0x84, 0x2B, 0x94, 0xCE, 0xA5, 0x2F, 0x8C, 0xAD, +0x9D, 0x2F, 0xCE, 0x34, 0xAC, 0xEF, 0xA4, 0x6D, +0xBD, 0x30, 0x9C, 0x4E, 0x62, 0xA9, 0x6B, 0x4C, +0x73, 0x8D, 0x62, 0xEB, 0x52, 0x89, 0x6B, 0x6C, +0x62, 0xCA, 0x52, 0x69, 0x6B, 0x4B, 0x6B, 0x4C, +0x5A, 0xA9, 0x5A, 0xCA, 0x5A, 0xA9, 0x94, 0x6F, +0xA4, 0xF0, 0xAD, 0x11, 0xB5, 0x31, 0xA4, 0xD0, +0xBD, 0x73, 0x8C, 0x0C, 0xB5, 0x10, 0xB5, 0x31, +0x9C, 0xB0, 0x94, 0x8F, 0x8C, 0x2F, 0x5A, 0xEA, +0x9C, 0xB0, 0xC6, 0x16, 0xB5, 0x53, 0x94, 0x6F, +0x94, 0x90, 0xA4, 0xF1, 0xA4, 0xF1, 0xAD, 0x32, +0xB5, 0x73, 0xB5, 0x73, 0xA4, 0xF1, 0x9C, 0xB0, +0xAD, 0x11, 0xAD, 0x31, 0xB5, 0x31, 0x94, 0x6F, +0x83, 0xEC, 0xBD, 0x51, 0xAC, 0xCE, 0xB5, 0x52, +0xBD, 0xB4, 0xB5, 0x73, 0xBD, 0xD5, 0xBD, 0xB4, +0xBD, 0xD4, 0xC5, 0xF5, 0xB5, 0x73, 0xAD, 0x52, +0xB5, 0x94, 0xB5, 0x93, 0xAD, 0x32, 0xA5, 0x12, +0xAD, 0x33, 0xA5, 0x12, 0xAD, 0x53, 0xB5, 0x74, +0xAD, 0x53, 0xAD, 0x53, 0xB5, 0x74, 0xAD, 0x33, +0xA4, 0xD1, 0xA4, 0xB0, 0xAC, 0xF1, 0x5A, 0xA9, +0x4A, 0x48, 0x4A, 0x28, 0x4A, 0x28, 0x39, 0xA6, +0x52, 0x69, 0x6B, 0x4D, 0x62, 0xEC, 0x6B, 0x6E, +0x8C, 0x51, 0x9C, 0xF4, 0xB5, 0x97, 0xBD, 0xD7, +0xA5, 0x35, 0xC5, 0xF8, 0x94, 0xB3, 0x6B, 0x6D, +0x6B, 0x2B, 0xB5, 0x93, 0xA4, 0xCF, 0x83, 0xCD, +0xBD, 0xB4, 0x94, 0x4E, 0x73, 0x4A, 0x6B, 0x2A, +0x83, 0xCC, 0x8C, 0x0D, 0x83, 0xEC, 0x8C, 0x0D, +0xA4, 0xF1, 0x94, 0x6F, 0x8C, 0x0D, 0xAC, 0xF0, +0x94, 0x4D, 0x9C, 0x6E, 0x94, 0x2D, 0x8B, 0xCB, +0x83, 0x89, 0x94, 0x0B, 0x94, 0x0C, 0x7B, 0x8B, +0x7B, 0xAC, 0x9C, 0x8F, 0x8C, 0x2E, 0x8C, 0x2F, +0xC6, 0x17, 0xAD, 0x55, 0xA5, 0x14, 0x7B, 0xAF, +0x4A, 0x49, 0x29, 0x45, 0x18, 0xC3, 0x29, 0x65, +0x39, 0xE7, 0x42, 0x08, 0x42, 0x08, 0x39, 0xE7, +0x42, 0x28, 0x52, 0x8A, 0x5A, 0xCB, 0x5A, 0xEC, +0x63, 0x0C, 0x7B, 0xAE, 0xBD, 0xB7, 0xB5, 0x35, +0x94, 0x51, 0x6A, 0xEC, 0x6B, 0x0B, 0x7B, 0x6C, +0xBD, 0x53, 0xB5, 0x52, 0xB5, 0x53, 0xB5, 0x32, +0xB5, 0x32, 0xB5, 0x53, 0xB5, 0x53, 0xB5, 0x33, +0xB5, 0x32, 0xB5, 0x32, 0xAD, 0x12, 0xAC, 0xF1, +0xAC, 0xF1, 0xAD, 0x32, 0xB5, 0x32, 0xB5, 0x32, +0xAC, 0xF1, 0xA4, 0xB0, 0xA4, 0xD0, 0x94, 0x2F, +0x62, 0xEB, 0x39, 0xC7, 0x29, 0x45, 0x21, 0x05, +0x18, 0xE4, 0x18, 0xC4, 0x10, 0xC3, 0x18, 0xC4, +0x18, 0xC4, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC4, 0x41, 0x05, 0x50, 0xE4, +0x40, 0xC4, 0x28, 0xE4, 0x20, 0xE4, 0x21, 0x25, +0x18, 0xE4, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC4, 0x18, 0xC4, 0x20, 0xE4, +0x21, 0x04, 0x20, 0xE4, 0x18, 0xE4, 0x18, 0xC4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xC4, 0x18, 0xC4, 0x21, 0x05, 0x21, 0x25, +0x21, 0x05, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, +0x20, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x18, 0xE4, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x25, 0x29, 0x46, +0x29, 0x46, 0x21, 0x26, 0x29, 0x26, 0x29, 0x47, +0x29, 0x67, 0x31, 0x67, 0x39, 0xA8, 0x39, 0xE9, +0x42, 0x09, 0x42, 0x09, 0x42, 0x09, 0x3A, 0x09, +0x42, 0x4A, 0x52, 0x8B, 0x6B, 0x2C, 0x9C, 0x90, +0x9C, 0xB0, 0x9C, 0x4F, 0x9C, 0x4F, 0x6B, 0x0A, +0x62, 0xC9, 0x9C, 0x6F, 0xA4, 0x90, 0x8B, 0xED, +0x94, 0x2F, 0x9C, 0x70, 0x9C, 0x70, 0x7B, 0x6C, +0x8C, 0x0E, 0xA4, 0xD1, 0x9C, 0x90, 0x9C, 0x90, +0x94, 0x4F, 0x94, 0x4F, 0xA4, 0xB0, 0xAC, 0xF1, +0xB5, 0x32, 0xAC, 0xF0, 0x9C, 0x6E, 0xA4, 0x8F, +0xAC, 0xAF, 0xB4, 0xF0, 0xA4, 0x6F, 0xA4, 0xB0, +0xA4, 0xD0, 0xAD, 0x11, 0xB5, 0x32, 0xAD, 0x11, +0xAD, 0x11, 0xA4, 0xD0, 0x94, 0x2E, 0x94, 0x2E, +0x94, 0x4F, 0x94, 0x6F, 0x63, 0x0B, 0x52, 0x6A, +0x39, 0xC7, 0x31, 0xA7, 0x63, 0x2C, 0x5A, 0xCB, +0x73, 0xAE, 0x52, 0x8A, 0x52, 0x6A, 0x83, 0xCF, +0x83, 0xAF, 0x73, 0x4D, 0xAC, 0xD2, 0xB5, 0x34, +0xC5, 0xB6, 0xBD, 0x95, 0xAC, 0xF2, 0xEE, 0xD7, +0xAD, 0xB4, 0x9D, 0x70, 0x85, 0x0B, 0x8D, 0x4C, +0x8D, 0x0B, 0x74, 0x67, 0x7C, 0xA8, 0x8D, 0x28, +0x9D, 0xC9, 0x8D, 0x08, 0x9D, 0x4A, 0x6B, 0xC7, +0x6B, 0x88, 0x63, 0xA8, 0x6B, 0xE8, 0x95, 0x0D, +0xA5, 0x70, 0x6B, 0x68, 0x9C, 0x6C, 0xB5, 0x0F, +0xAD, 0x2F, 0x7B, 0x6A, 0x7B, 0x8C, 0xB5, 0x94, +0xAD, 0x33, 0x7B, 0xAD, 0x4A, 0x07, 0x42, 0x07, +0x52, 0x68, 0x52, 0x89, 0x42, 0x07, 0x41, 0xE7, +0x42, 0x07, 0x42, 0x07, 0x42, 0x07, 0x7B, 0xAC, +0x73, 0x6B, 0x73, 0x4B, 0x83, 0xED, 0x8C, 0x0D, +0xA4, 0xD0, 0x8B, 0xEC, 0xAC, 0xEF, 0xB5, 0x51, +0xB5, 0x52, 0x94, 0x6F, 0x94, 0x90, 0x8C, 0x4F, +0x94, 0x70, 0xA5, 0x12, 0xA4, 0xD1, 0xAD, 0x32, +0xAD, 0x33, 0xA5, 0x11, 0xAD, 0x11, 0xBD, 0xB4, +0xA4, 0xD0, 0xB5, 0x52, 0xB5, 0x52, 0x9C, 0xB0, +0x9C, 0xB0, 0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x31, +0x9C, 0x6E, 0xBD, 0x51, 0xAC, 0xEF, 0xC5, 0xB3, +0xCE, 0x15, 0xB5, 0x73, 0xAD, 0x52, 0xB5, 0x93, +0xC5, 0xF5, 0xC5, 0xF5, 0xCE, 0x15, 0xC5, 0xF5, +0xCE, 0x36, 0xC5, 0xF5, 0xAD, 0x32, 0xB5, 0x73, +0xAD, 0x53, 0xAD, 0x53, 0xBD, 0xB4, 0xC5, 0xF5, +0xBD, 0xD4, 0xAD, 0x53, 0xB5, 0x94, 0xBD, 0xD4, +0xB5, 0x73, 0xBD, 0x72, 0xB5, 0x31, 0x7B, 0x6B, +0x39, 0xC6, 0x31, 0x86, 0x31, 0x65, 0x4A, 0x49, +0x52, 0x8A, 0x5A, 0xCB, 0x73, 0x6E, 0x6B, 0x4D, +0x7B, 0xCF, 0x8C, 0x72, 0x9C, 0xD3, 0xA4, 0xF4, +0xB5, 0x97, 0xCE, 0x7A, 0xAD, 0x56, 0x8C, 0x51, +0xAD, 0x13, 0x8C, 0x4F, 0x52, 0x68, 0x39, 0xC6, +0xAD, 0x33, 0xAD, 0x32, 0x8C, 0x0D, 0x94, 0x4E, +0x8C, 0x2E, 0x9C, 0x8F, 0x94, 0x6F, 0x94, 0x8F, +0xA4, 0xD1, 0x9C, 0x8F, 0x8C, 0x2E, 0x94, 0x6F, +0x94, 0x8F, 0xAD, 0x10, 0xAD, 0x10, 0x8C, 0x2D, +0x94, 0x2D, 0x9C, 0x8E, 0x9C, 0x6E, 0x94, 0x8F, +0x83, 0xED, 0x84, 0x0E, 0x9C, 0xD1, 0xAD, 0x54, +0xC6, 0x38, 0xA5, 0x35, 0xA5, 0x14, 0x6B, 0x6D, +0x31, 0x86, 0x31, 0x86, 0x21, 0x24, 0x18, 0xE3, +0x31, 0x86, 0x4A, 0x48, 0x4A, 0x49, 0x31, 0x86, +0x39, 0xE7, 0x4A, 0x48, 0x4A, 0x69, 0x52, 0x8A, +0x5A, 0xEB, 0x62, 0xEC, 0x73, 0x4D, 0x94, 0x51, +0xCE, 0x18, 0x8C, 0x10, 0x6B, 0x0C, 0x8C, 0x0F, +0x9C, 0x50, 0xAC, 0xF2, 0xAD, 0x12, 0xAC, 0xF1, +0xA4, 0xF1, 0xAC, 0xF1, 0xAC, 0xF1, 0xAC, 0xF1, +0x9C, 0x90, 0xA4, 0xD0, 0xB5, 0x32, 0xAD, 0x11, +0xAC, 0xF1, 0xAC, 0xF1, 0xA4, 0xD1, 0xA4, 0xD1, +0xAD, 0x12, 0xB5, 0x53, 0xBD, 0xB4, 0xAD, 0x12, +0x94, 0x4F, 0x52, 0x89, 0x4A, 0x69, 0x39, 0xE7, +0x21, 0x25, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA4, 0x18, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x20, 0xE4, 0x41, 0x05, 0x49, 0x05, +0x38, 0xC4, 0x28, 0xE4, 0x21, 0x05, 0x21, 0x05, +0x18, 0xC4, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xC3, 0x18, 0xA3, 0x18, 0xA3, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x10, 0xA3, 0x10, 0x83, +0x10, 0x83, 0x10, 0xA3, 0x18, 0xC4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xC4, 0x18, 0xE4, 0x21, 0x05, +0x21, 0x05, 0x18, 0xE4, 0x18, 0xE4, 0x21, 0x05, +0x21, 0x05, 0x18, 0xE4, 0x18, 0xC4, 0x20, 0xE4, +0x21, 0x25, 0x21, 0x05, 0x18, 0xC4, 0x20, 0xE4, +0x29, 0x25, 0x29, 0x46, 0x21, 0x05, 0x21, 0x05, +0x29, 0x46, 0x21, 0x26, 0x21, 0x05, 0x29, 0x46, +0x29, 0x67, 0x31, 0x67, 0x31, 0x87, 0x31, 0xA8, +0x39, 0xE9, 0x42, 0x09, 0x42, 0x09, 0x42, 0x09, +0x39, 0xE8, 0x42, 0x09, 0x52, 0xAB, 0x5A, 0xEB, +0x94, 0x70, 0x9C, 0x90, 0x9C, 0x8F, 0x73, 0x6C, +0x7B, 0xAD, 0x94, 0x2F, 0xA4, 0xD1, 0xA4, 0xF1, +0xAD, 0x12, 0xA4, 0xD1, 0xAD, 0x12, 0x9C, 0x90, +0xA4, 0xD1, 0xA4, 0xF1, 0xAC, 0xF1, 0x9C, 0x90, +0x9C, 0xB0, 0x94, 0x6F, 0xA4, 0xB0, 0xAC, 0xF1, +0xB5, 0x31, 0xAC, 0xF0, 0xB5, 0x32, 0xBD, 0x52, +0xBD, 0x72, 0xBD, 0x72, 0xB5, 0x11, 0x94, 0x4E, +0x9C, 0x8F, 0xB5, 0x32, 0xBD, 0x73, 0xBD, 0x73, +0xBD, 0x73, 0xB5, 0x32, 0x83, 0xCC, 0x8C, 0x0D, +0x94, 0x2E, 0x94, 0x4F, 0x83, 0xCE, 0x42, 0x28, +0x63, 0x0C, 0x39, 0xC7, 0x73, 0x6E, 0x52, 0x8A, +0x5A, 0xCB, 0x4A, 0x6A, 0x73, 0x8E, 0x73, 0x8E, +0x73, 0x4D, 0x7B, 0x6D, 0x8B, 0xCF, 0xA4, 0x91, +0xCE, 0x17, 0xCE, 0x17, 0xA4, 0xD1, 0xC5, 0xB3, +0x5B, 0x8A, 0x8D, 0x0E, 0x6C, 0x68, 0x85, 0x08, +0x74, 0xA7, 0x64, 0x05, 0x85, 0x08, 0x8D, 0x48, +0x84, 0xE7, 0x7C, 0xC7, 0x84, 0xC9, 0x9D, 0x0C, +0x8C, 0x8A, 0x74, 0x48, 0x95, 0x2C, 0xA5, 0x6E, +0x9D, 0x4E, 0xC6, 0x71, 0xA5, 0x2C, 0xB5, 0x4F, +0xAD, 0x4F, 0xBD, 0x92, 0xCE, 0x35, 0xBD, 0xB3, +0x9C, 0xAF, 0xAC, 0xD0, 0xB5, 0x31, 0xB5, 0x11, +0xAC, 0xF1, 0xA4, 0xAF, 0x9C, 0x4E, 0x94, 0x4E, +0x9C, 0x8F, 0x94, 0x6E, 0x94, 0x2E, 0x94, 0x2E, +0x83, 0xCC, 0x6B, 0x2B, 0x7B, 0x6B, 0x7B, 0x8B, +0x8B, 0xED, 0x9C, 0x6E, 0xAC, 0xCF, 0x8C, 0x0C, +0x9C, 0x8F, 0x94, 0x4E, 0xA4, 0xF1, 0x9C, 0xB0, +0x73, 0x4B, 0xA5, 0x12, 0x9C, 0xB0, 0x8C, 0x2E, +0xA4, 0xD0, 0xA4, 0xD1, 0xA4, 0xF1, 0xAD, 0x12, +0x9C, 0xB0, 0xB5, 0x52, 0xAD, 0x31, 0xAD, 0x11, +0x94, 0x4E, 0xA4, 0xF0, 0xAD, 0x11, 0x8B, 0xEC, +0x83, 0xCB, 0xBD, 0x51, 0xBD, 0x30, 0xD6, 0x56, +0xD6, 0x76, 0xCE, 0x35, 0xCE, 0x15, 0xCE, 0x36, +0xC6, 0x15, 0xC5, 0xF4, 0xCE, 0x35, 0xCD, 0xF4, +0xC5, 0xF4, 0xCE, 0x35, 0xC5, 0xF5, 0xC5, 0xF5, +0xC5, 0xD4, 0xC5, 0xF5, 0xCE, 0x35, 0xCE, 0x15, +0xC5, 0xF4, 0xC5, 0xF4, 0xC6, 0x15, 0xC5, 0xF4, +0xAD, 0x11, 0xBD, 0x72, 0xB5, 0x10, 0x8B, 0xCD, +0x63, 0x0B, 0x52, 0x8A, 0x5A, 0xAA, 0x62, 0xEB, +0x6B, 0x0C, 0x73, 0x8E, 0x73, 0x8E, 0x6B, 0x4D, +0x73, 0x8E, 0x73, 0x8E, 0x84, 0x10, 0xAD, 0x55, +0xBD, 0xF8, 0xC6, 0x18, 0xBD, 0xF8, 0x9C, 0xB2, +0x8C, 0x2F, 0x52, 0x8A, 0x41, 0xE8, 0x39, 0xC7, +0x7B, 0xCE, 0xCE, 0x36, 0x8C, 0x0E, 0xA5, 0x11, +0xA4, 0xF1, 0xAD, 0x12, 0xAD, 0x53, 0xB5, 0x73, +0xBD, 0xD5, 0xA4, 0xF1, 0xAD, 0x32, 0xB5, 0x93, +0xBD, 0xB4, 0xC5, 0xF4, 0xBD, 0xB3, 0xAC, 0xF0, +0xAD, 0x10, 0xAC, 0xEF, 0xAC, 0xCF, 0x8C, 0x0E, +0x84, 0x0E, 0x94, 0x4F, 0x9C, 0xB0, 0xB5, 0x74, +0xC6, 0x18, 0xA5, 0x35, 0xA5, 0x15, 0x8C, 0x50, +0x63, 0x0B, 0x29, 0x45, 0x29, 0x65, 0x21, 0x04, +0x18, 0xE3, 0x31, 0xA6, 0x4A, 0x49, 0x42, 0x08, +0x31, 0xA6, 0x39, 0xE7, 0x4A, 0x49, 0x4A, 0x69, +0x52, 0x8A, 0x4A, 0x48, 0x52, 0x69, 0x6B, 0x0C, +0x73, 0x8D, 0x52, 0x49, 0x83, 0xCF, 0xA4, 0xB2, +0x94, 0x30, 0x94, 0x2F, 0xC5, 0xD5, 0xC5, 0xD4, +0xC5, 0xD4, 0xC5, 0xD4, 0xCD, 0xF4, 0xCE, 0x15, +0xBD, 0x93, 0xC5, 0xD3, 0xD6, 0x35, 0xCE, 0x15, +0xD6, 0x15, 0xC5, 0xD4, 0xB5, 0x52, 0xAD, 0x32, +0xA4, 0xF1, 0x9C, 0xB0, 0xBD, 0xB4, 0xB5, 0x32, +0xA4, 0xD1, 0x8C, 0x2F, 0x83, 0xEE, 0x6B, 0x2C, +0x31, 0xA6, 0x21, 0x04, 0x19, 0x04, 0x18, 0xA3, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, 0x29, 0x45, +0x18, 0xC3, 0x20, 0xE4, 0x39, 0x04, 0x49, 0x25, +0x30, 0xE4, 0x20, 0xE4, 0x20, 0xE4, 0x18, 0xE4, +0x18, 0xC3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x18, 0xC4, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xA3, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xE4, 0x18, 0xC4, 0x10, 0x83, +0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, 0x18, 0xE4, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xA3, +0x18, 0xC4, 0x18, 0xC4, 0x20, 0xE4, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x18, 0xE4, 0x18, 0xE4, +0x21, 0x25, 0x21, 0x05, 0x18, 0xE4, 0x18, 0xE5, +0x21, 0x25, 0x29, 0x66, 0x29, 0x46, 0x21, 0x05, +0x21, 0x25, 0x21, 0x26, 0x21, 0x05, 0x21, 0x26, +0x29, 0x46, 0x21, 0x26, 0x21, 0x05, 0x29, 0x67, +0x31, 0x87, 0x39, 0xC8, 0x39, 0xE9, 0x41, 0xE9, +0x39, 0xC8, 0x31, 0xA8, 0x39, 0xE9, 0x4A, 0x6A, +0x5A, 0xCB, 0x83, 0xEF, 0x9C, 0x6F, 0x83, 0xCD, +0x9C, 0x4F, 0x94, 0x2F, 0x94, 0x2E, 0x8B, 0xED, +0xAC, 0xF1, 0xB5, 0x32, 0xAC, 0xF1, 0xA4, 0xD1, +0xA4, 0xF1, 0xA4, 0xB0, 0x83, 0xAC, 0x62, 0xC9, +0x9C, 0xB1, 0x9C, 0x90, 0xA4, 0xD1, 0xAD, 0x11, +0xB5, 0x11, 0xA4, 0xD0, 0xBD, 0x72, 0xC5, 0xD4, +0xB5, 0x52, 0xBD, 0x73, 0xAD, 0x11, 0x9C, 0xB0, +0xAD, 0x12, 0xB5, 0x52, 0xB5, 0x32, 0xB5, 0x32, +0xBD, 0x93, 0xAC, 0xF1, 0x7B, 0xAC, 0x94, 0x4E, +0xA4, 0xB0, 0x9C, 0x4F, 0x8C, 0x2F, 0x63, 0x0B, +0x73, 0x8E, 0x31, 0x66, 0x42, 0x08, 0x31, 0x66, +0x31, 0x66, 0x31, 0x66, 0x31, 0x86, 0x39, 0xA7, +0x5A, 0xCB, 0x94, 0x51, 0x7B, 0x4C, 0x9C, 0x71, +0xC5, 0xD6, 0xDE, 0x99, 0x94, 0x51, 0x62, 0xCA, +0x8D, 0x10, 0xA5, 0xB2, 0x64, 0x06, 0x8D, 0x68, +0x74, 0x86, 0x53, 0x64, 0x7C, 0xA7, 0x85, 0x08, +0x95, 0x8B, 0x7C, 0x88, 0x5B, 0x45, 0x6B, 0xC8, +0x63, 0xC6, 0x6C, 0x26, 0x84, 0xE9, 0x8C, 0xEB, +0x7C, 0x89, 0xA5, 0xCB, 0xA5, 0x6A, 0x94, 0xAB, +0xA5, 0x2F, 0xA5, 0x30, 0xAD, 0x30, 0xB5, 0x30, +0xB5, 0x10, 0xAC, 0xD0, 0xAC, 0xCF, 0xAC, 0xCF, +0xAC, 0xD0, 0xB5, 0x10, 0xB5, 0x10, 0xAD, 0x10, +0xAD, 0x10, 0xB5, 0x10, 0xB5, 0x10, 0xB5, 0x10, +0xBD, 0x71, 0xC5, 0x92, 0xC5, 0x72, 0xC5, 0x92, +0xC5, 0x72, 0xC5, 0x51, 0xC5, 0x71, 0xC5, 0x71, +0xB5, 0x31, 0xB5, 0x10, 0xAC, 0xF0, 0xAC, 0xF0, +0xAC, 0xF0, 0xAC, 0xCF, 0xA4, 0x8E, 0x9C, 0x4D, +0x94, 0x2D, 0x94, 0x2D, 0x94, 0x2D, 0x8B, 0xEC, +0x8B, 0xEC, 0x8B, 0xEC, 0x8B, 0xEC, 0x8B, 0xEC, +0x94, 0x0C, 0x94, 0x0D, 0x8B, 0xEC, 0x83, 0xAB, +0x94, 0x2D, 0xC5, 0x71, 0xA4, 0x8E, 0xAC, 0xF0, +0xC5, 0xB3, 0xBD, 0x93, 0xB5, 0x52, 0xB5, 0x31, +0xBD, 0x72, 0xB5, 0x52, 0xC5, 0xD4, 0xBD, 0x93, +0xAC, 0xF0, 0xBD, 0xB3, 0xBD, 0x93, 0xC5, 0xD4, +0xC5, 0xF4, 0xC5, 0xF4, 0xD6, 0x56, 0xCE, 0x15, +0xCD, 0xF5, 0xC5, 0xF4, 0xC5, 0xB4, 0xC5, 0xB4, +0x9C, 0x6E, 0xC5, 0x72, 0xBD, 0x31, 0xAD, 0x12, +0x62, 0xEB, 0x63, 0x0B, 0x5A, 0xAA, 0x52, 0x69, +0x6B, 0x4D, 0x6B, 0x4D, 0x6B, 0x2D, 0x7B, 0xAF, +0x73, 0x8E, 0x73, 0xAF, 0x9C, 0xB3, 0xA5, 0x14, +0xAD, 0x56, 0xBD, 0xD8, 0xAD, 0x15, 0x8C, 0x30, +0x8C, 0x10, 0x52, 0x8A, 0x42, 0x08, 0x31, 0xA6, +0x42, 0x28, 0xBD, 0xB5, 0xC6, 0x15, 0xBD, 0xD4, +0xC5, 0xF5, 0xCE, 0x16, 0xCE, 0x56, 0xCE, 0x56, +0xCE, 0x36, 0xBD, 0xD4, 0xC6, 0x15, 0xCE, 0x36, +0xD6, 0x76, 0xC6, 0x15, 0xC5, 0xD4, 0xAD, 0x10, +0xAD, 0x10, 0xAD, 0x0F, 0xAC, 0xF0, 0x7B, 0xAC, +0x83, 0xEE, 0x9C, 0xB0, 0x9C, 0xD1, 0xB5, 0xB5, +0xC6, 0x18, 0xA5, 0x35, 0x9C, 0xF4, 0x9C, 0xD2, +0x8C, 0x71, 0x73, 0xAE, 0x29, 0x24, 0x31, 0x86, +0x21, 0x24, 0x18, 0xE3, 0x39, 0xC7, 0x4A, 0x48, +0x31, 0xA6, 0x31, 0x86, 0x41, 0xE7, 0x52, 0x8A, +0x52, 0xAA, 0x63, 0x0C, 0x73, 0x6D, 0x4A, 0x49, +0x29, 0x45, 0x41, 0xE8, 0x5A, 0xAA, 0x8C, 0x10, +0xA4, 0xB2, 0x94, 0x0F, 0xB5, 0x53, 0xEE, 0xF8, +0xDE, 0x96, 0xD6, 0x76, 0xDE, 0x96, 0xDE, 0x96, +0xB5, 0x32, 0xBD, 0x73, 0xD6, 0x56, 0xD6, 0x35, +0xD6, 0x55, 0xCE, 0x35, 0xC5, 0xF5, 0xBD, 0xD4, +0xA4, 0xF1, 0xA4, 0xD1, 0xBD, 0x73, 0x94, 0x4F, +0x94, 0x2E, 0x94, 0x2E, 0x9C, 0x4F, 0x94, 0x2E, +0x6B, 0x0B, 0x52, 0x69, 0x4A, 0x28, 0x41, 0xE7, +0x41, 0xE7, 0x52, 0x89, 0x7B, 0xAD, 0x83, 0xCE, +0x39, 0xA6, 0x31, 0x66, 0x39, 0x25, 0x41, 0x25, +0x28, 0xE4, 0x20, 0xE4, 0x18, 0xE4, 0x18, 0xC4, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x18, 0xC4, 0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC4, 0x18, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x18, 0xC4, 0x18, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC4, 0x21, 0x05, 0x21, 0x25, +0x18, 0xC4, 0x10, 0xA3, 0x18, 0xC4, 0x18, 0xE4, +0x21, 0x05, 0x21, 0x05, 0x18, 0xE4, 0x18, 0xC4, +0x21, 0x05, 0x21, 0x25, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x29, 0x46, 0x29, 0x46, 0x21, 0x05, +0x21, 0x05, 0x21, 0x25, 0x21, 0x25, 0x21, 0x26, +0x29, 0x46, 0x29, 0x46, 0x21, 0x05, 0x21, 0x26, +0x29, 0x67, 0x31, 0xA8, 0x31, 0xA8, 0x31, 0xA8, +0x39, 0xC8, 0x31, 0xA8, 0x39, 0xC9, 0x3A, 0x09, +0x42, 0x4A, 0x52, 0x6A, 0x6A, 0xEB, 0x73, 0x4C, +0x7B, 0x6C, 0x6B, 0x0A, 0x6A, 0xEA, 0x6B, 0x0A, +0x73, 0x4B, 0x83, 0xAD, 0x8B, 0xED, 0x7B, 0x8C, +0x8C, 0x0E, 0x9C, 0x6F, 0x6B, 0x0A, 0x6B, 0x0A, +0x9C, 0xB1, 0x8C, 0x0E, 0xA4, 0xD1, 0xB5, 0x32, +0xB5, 0x31, 0xB5, 0x31, 0xBD, 0x93, 0xBD, 0x72, +0xBD, 0x72, 0xC5, 0xB3, 0xAD, 0x11, 0xAC, 0xF1, +0x9C, 0x8F, 0xA4, 0xD0, 0xAD, 0x32, 0xAC, 0xF1, +0xBD, 0xB4, 0xAD, 0x32, 0x8C, 0x2E, 0x9C, 0x90, +0xAC, 0xD1, 0xA4, 0xD1, 0x9C, 0xB0, 0x7B, 0xAD, +0x4A, 0x49, 0x29, 0x45, 0x41, 0xE8, 0x62, 0xEC, +0x39, 0xC7, 0x29, 0x45, 0x21, 0x04, 0x31, 0x66, +0x39, 0xC7, 0x6B, 0x0C, 0x73, 0x0C, 0x83, 0xAE, +0x8B, 0xEF, 0x94, 0x30, 0x83, 0x8E, 0x52, 0x49, +0xAD, 0xF4, 0x95, 0x31, 0x4B, 0x45, 0x74, 0xC7, +0x74, 0xA7, 0x74, 0x48, 0x6C, 0x25, 0x6C, 0x66, +0x8D, 0x4A, 0x84, 0xCA, 0x4A, 0xC5, 0x5B, 0x66, +0x5B, 0x86, 0x7C, 0xA8, 0x7C, 0xC7, 0x85, 0x0A, +0x7C, 0xA9, 0x7C, 0xE6, 0xAE, 0x0A, 0x94, 0xCA, +0x8C, 0x4B, 0x8C, 0x4C, 0xA4, 0xAE, 0xB5, 0x10, +0x94, 0x0C, 0x83, 0xCC, 0x83, 0xCC, 0x7B, 0x8B, +0x83, 0xED, 0x84, 0x0D, 0x8C, 0x2E, 0x94, 0x4E, +0xA4, 0xD0, 0x9C, 0x6E, 0x9C, 0x6E, 0xA4, 0xAF, +0xAC, 0xCF, 0xA4, 0x8F, 0xA4, 0x6E, 0x94, 0x0D, +0x94, 0x2D, 0x9C, 0x4D, 0xA4, 0x8E, 0x9C, 0x6E, +0xAC, 0xCF, 0xAC, 0xEF, 0xAC, 0xCF, 0xBD, 0x31, +0xAC, 0xCF, 0xAC, 0xCF, 0xA4, 0x6D, 0x9C, 0x4D, +0x9C, 0x6D, 0xA4, 0x8E, 0xA4, 0x8E, 0xB4, 0xEF, +0xB5, 0x10, 0xC5, 0x71, 0xC5, 0x71, 0xC5, 0x71, +0xCD, 0x92, 0xCD, 0xD3, 0xCD, 0xD3, 0xCD, 0xB2, +0xC5, 0x92, 0xC5, 0x51, 0xC5, 0x91, 0xBD, 0x51, +0xB4, 0xEF, 0xAC, 0xAF, 0x94, 0x2D, 0x8B, 0xCC, +0x83, 0xAB, 0x8B, 0xEC, 0x8B, 0xEC, 0x8B, 0xEC, +0x93, 0xEC, 0x94, 0x0C, 0x93, 0xEC, 0x93, 0xEC, +0x83, 0x8B, 0x83, 0xAB, 0x8B, 0xED, 0x8B, 0xEC, +0xA4, 0xAF, 0xB5, 0x52, 0xC5, 0xB3, 0xB5, 0x51, +0xC5, 0xB2, 0xCD, 0xB2, 0xBD, 0x51, 0xC5, 0xB4, +0x41, 0xE7, 0x7B, 0xCF, 0x7B, 0x8D, 0x4A, 0x28, +0x52, 0x69, 0x6B, 0x2C, 0x5A, 0xAA, 0x62, 0xEB, +0x52, 0x6A, 0x6B, 0x2D, 0x7B, 0xCF, 0x84, 0x10, +0xA5, 0x35, 0x94, 0xB2, 0x94, 0x72, 0xA4, 0xF4, +0x94, 0x51, 0x62, 0xEB, 0x41, 0xE7, 0x31, 0x86, +0x42, 0x28, 0x7B, 0xEE, 0xD6, 0x77, 0xBD, 0xD4, +0xC5, 0xF5, 0xC6, 0x15, 0xC6, 0x15, 0xC6, 0x15, +0xBD, 0xF4, 0xA5, 0x11, 0xC6, 0x15, 0xCE, 0x36, +0xCE, 0x35, 0xD6, 0x56, 0xC5, 0xF4, 0x9C, 0x6E, +0xBD, 0x50, 0xB5, 0x10, 0xB5, 0x11, 0x73, 0x6B, +0x84, 0x0E, 0x9C, 0xD1, 0xA4, 0xF1, 0xBD, 0xD6, +0xBD, 0xF8, 0xA5, 0x35, 0x84, 0x31, 0x8C, 0x50, +0x9C, 0xD1, 0x9C, 0xF2, 0x84, 0x0F, 0x63, 0x2C, +0x21, 0x24, 0x18, 0xE3, 0x29, 0x86, 0x31, 0xA6, +0x42, 0x07, 0x42, 0x08, 0x39, 0xC6, 0x42, 0x07, +0x5A, 0xEB, 0x52, 0x8A, 0x8C, 0x10, 0x83, 0xCF, +0x5A, 0x8A, 0x52, 0x49, 0x6B, 0x0C, 0x8B, 0xEF, +0x83, 0xAE, 0x8C, 0x0F, 0xA4, 0xB1, 0xBD, 0x73, +0xD6, 0x76, 0xDE, 0x96, 0xE6, 0xB7, 0xDE, 0x97, +0xB5, 0x52, 0xCE, 0x36, 0xD6, 0x56, 0xD6, 0x35, +0xCE, 0x35, 0xCE, 0x15, 0xBD, 0xD4, 0xBD, 0xB4, +0xAD, 0x32, 0xAD, 0x12, 0xB5, 0x53, 0x94, 0x4F, +0x7B, 0x8C, 0x9C, 0x6F, 0xBD, 0x52, 0xBD, 0x52, +0xAC, 0xF1, 0x9C, 0x90, 0x94, 0x2E, 0x94, 0x4F, +0xA4, 0xD1, 0xB5, 0x53, 0xC5, 0x93, 0xBD, 0x53, +0x94, 0x2F, 0x7B, 0x8D, 0x73, 0x2C, 0x49, 0xE7, +0x29, 0x05, 0x21, 0x04, 0x21, 0x04, 0x18, 0xC4, +0x18, 0xA3, 0x18, 0xC4, 0x18, 0xC3, 0x10, 0x83, +0x10, 0xA3, 0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x18, 0xC4, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, +0x10, 0xA3, 0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC4, +0x10, 0xA3, 0x10, 0xA3, 0x18, 0xC4, 0x21, 0x05, +0x21, 0x05, 0x18, 0xC4, 0x10, 0xA3, 0x18, 0xA3, +0x18, 0xE4, 0x21, 0x05, 0x21, 0x05, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xE4, 0x21, 0x25, 0x21, 0x25, +0x18, 0xE5, 0x21, 0x26, 0x29, 0x46, 0x21, 0x05, +0x18, 0xE4, 0x21, 0x05, 0x21, 0x25, 0x29, 0x46, +0x21, 0x25, 0x21, 0x25, 0x21, 0x05, 0x21, 0x05, +0x21, 0x26, 0x29, 0x67, 0x31, 0x87, 0x31, 0xA8, +0x39, 0xC8, 0x39, 0xC8, 0x31, 0xA8, 0x31, 0xA8, +0x39, 0xE9, 0x42, 0x2A, 0x4A, 0x4A, 0x63, 0x0C, +0x83, 0xCE, 0x83, 0xCE, 0x83, 0xAD, 0x83, 0xAD, +0x7B, 0x8D, 0x7B, 0x8C, 0x7B, 0x8C, 0x73, 0x2B, +0x6B, 0x2B, 0x6B, 0x0A, 0x6B, 0x2B, 0x73, 0x2B, +0x62, 0xEA, 0x73, 0x2B, 0x8C, 0x0E, 0x94, 0x4E, +0x94, 0x4E, 0x94, 0x4E, 0x94, 0x2E, 0x9C, 0x6F, +0xAC, 0xF1, 0xA4, 0xD0, 0xA4, 0x8F, 0xA4, 0xD0, +0xB5, 0x31, 0x9C, 0x6F, 0xBD, 0x73, 0xAC, 0xF1, +0xBD, 0x73, 0x94, 0x4E, 0x94, 0x4F, 0x94, 0x4F, +0x94, 0x4F, 0x8C, 0x2E, 0x8C, 0x0E, 0x7B, 0xAD, +0x4A, 0x49, 0x21, 0x25, 0x5A, 0xCB, 0x6B, 0x4D, +0x39, 0xC7, 0x39, 0xA7, 0x4A, 0x49, 0x62, 0xCB, +0x52, 0x8A, 0x52, 0x69, 0x6A, 0xEB, 0x41, 0xA6, +0x62, 0xAA, 0x8B, 0xAE, 0x8B, 0xCE, 0x5A, 0xAA, +0x8D, 0x10, 0x84, 0xCE, 0x7C, 0xAB, 0x7C, 0xC9, +0x8D, 0x4C, 0x8D, 0x0B, 0x63, 0xC4, 0x5B, 0xE3, +0x74, 0x66, 0x95, 0x2B, 0x63, 0x87, 0x53, 0x25, +0x53, 0x44, 0x74, 0x87, 0x6C, 0x65, 0x6C, 0x87, +0x6C, 0x87, 0x74, 0xC5, 0x9D, 0xA7, 0x9D, 0x2B, +0x84, 0x4D, 0xA5, 0x52, 0xBE, 0x15, 0xC6, 0x15, +0xA4, 0xD0, 0x94, 0x90, 0xA5, 0x12, 0x84, 0x2F, +0x84, 0x2E, 0x7B, 0xCD, 0x84, 0x2F, 0x9C, 0xB0, +0xA4, 0xD0, 0x7B, 0xAC, 0x7B, 0xAC, 0xAD, 0x32, +0xA4, 0xD0, 0x9C, 0xAF, 0x9C, 0x8F, 0x84, 0x0E, +0x7B, 0xAC, 0x8C, 0x2E, 0xA4, 0xF1, 0x9C, 0x90, +0x9C, 0xB0, 0x8C, 0x2E, 0x94, 0x0D, 0xB5, 0x10, +0x94, 0x0C, 0xA4, 0x8E, 0xA4, 0x8E, 0x9C, 0x6E, +0x94, 0x0C, 0x8B, 0xEC, 0x94, 0x0C, 0x94, 0x2D, +0x8B, 0xCB, 0xAC, 0x8E, 0x83, 0x6A, 0x7B, 0x49, +0x7B, 0x49, 0x7B, 0x6A, 0x83, 0x8B, 0x83, 0x8B, +0x8B, 0xAB, 0x93, 0xEB, 0x9C, 0x2C, 0xA4, 0x6E, +0xAC, 0xAF, 0xAC, 0xCF, 0xAC, 0xEF, 0xB5, 0x10, +0xBD, 0x71, 0xC5, 0x92, 0xBD, 0x51, 0xB5, 0x30, +0xB4, 0xF0, 0xAC, 0xCF, 0xB5, 0x10, 0xB5, 0x10, +0xB5, 0x10, 0xB5, 0x10, 0xB5, 0x10, 0xAC, 0xCF, +0xAC, 0xAE, 0xA4, 0x8E, 0x9C, 0x6D, 0xA4, 0x8E, +0xB5, 0x0F, 0xBD, 0x10, 0xBD, 0x30, 0xBD, 0x72, +0xA4, 0xD2, 0x9C, 0x92, 0x6B, 0x2C, 0x39, 0xA7, +0x42, 0x28, 0x52, 0x69, 0x42, 0x08, 0x42, 0x07, +0x4A, 0x28, 0x62, 0xEC, 0x4A, 0x49, 0x8C, 0x51, +0x8C, 0x71, 0xA5, 0x14, 0xBD, 0xB7, 0xBD, 0xD7, +0x9C, 0xD3, 0x73, 0x8E, 0x4A, 0x28, 0x52, 0x69, +0x4A, 0x48, 0x42, 0x28, 0xB5, 0x73, 0xBD, 0x93, +0xBD, 0x93, 0xBD, 0xD3, 0xBD, 0xB3, 0xC5, 0xD4, +0xC5, 0xF4, 0xB5, 0x72, 0xBD, 0xD4, 0xC5, 0xD3, +0xBD, 0xB3, 0xBD, 0xD3, 0xAD, 0x31, 0x8C, 0x0C, +0xB5, 0x30, 0xBD, 0x50, 0xBD, 0x31, 0x7B, 0xAC, +0x83, 0xEE, 0x84, 0x0E, 0x9C, 0xB0, 0xC6, 0x17, +0xBD, 0xB7, 0xA5, 0x15, 0x84, 0x30, 0xA5, 0x13, +0xA5, 0x33, 0xAD, 0x53, 0xA5, 0x33, 0xA4, 0xF2, +0x7B, 0xCE, 0x52, 0x89, 0x4A, 0x69, 0x4A, 0x69, +0x39, 0xC7, 0x42, 0x08, 0x31, 0xA6, 0x39, 0xC6, +0x4A, 0x48, 0x8C, 0x30, 0x94, 0x71, 0x94, 0x51, +0xAC, 0xF3, 0xC5, 0xB5, 0x73, 0x2C, 0x73, 0x4D, +0x8B, 0xEF, 0x6A, 0xEB, 0xA4, 0xB1, 0x7B, 0x8D, +0x9C, 0x50, 0xCD, 0xF5, 0xE6, 0xB7, 0xDE, 0xB7, +0xD6, 0x76, 0xDE, 0x77, 0xCE, 0x35, 0xBD, 0xB3, +0xC5, 0xD4, 0xC5, 0xF5, 0xBD, 0xD4, 0xC5, 0xF5, +0xAD, 0x53, 0xA4, 0xF1, 0xB5, 0x32, 0xAC, 0xF1, +0x83, 0xAC, 0xA4, 0xD0, 0xBD, 0x52, 0xBD, 0x52, +0xC5, 0xB3, 0xC5, 0xB3, 0xBD, 0x93, 0xC5, 0x93, +0xC5, 0x93, 0xCD, 0xB4, 0xCD, 0xB3, 0xC5, 0x93, +0xCD, 0xB4, 0xBD, 0x73, 0xB5, 0x12, 0x73, 0x6D, +0x29, 0x04, 0x21, 0x05, 0x21, 0x04, 0x18, 0xC4, +0x10, 0xA3, 0x18, 0xC4, 0x18, 0xC3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x18, 0xC4, 0x18, 0xC4, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, +0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xC4, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, +0x18, 0xE4, 0x20, 0xE4, 0x21, 0x05, 0x18, 0xE4, +0x10, 0xA3, 0x18, 0xE4, 0x21, 0x05, 0x21, 0x26, +0x21, 0x05, 0x21, 0x05, 0x21, 0x26, 0x29, 0x46, +0x18, 0xE5, 0x18, 0xC4, 0x18, 0xE5, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x18, 0xE5, 0x21, 0x05, +0x18, 0xE5, 0x21, 0x05, 0x29, 0x46, 0x31, 0x87, +0x31, 0x87, 0x31, 0x87, 0x31, 0xA8, 0x31, 0xA7, +0x31, 0xA8, 0x42, 0x09, 0x42, 0x2A, 0x4A, 0x49, +0x6B, 0x2C, 0xA4, 0xD2, 0xA4, 0xD1, 0xAD, 0x12, +0xAC, 0xF1, 0xAC, 0xF2, 0xA4, 0xD1, 0xA4, 0xB0, +0xA4, 0xB0, 0x9C, 0x70, 0x94, 0x4F, 0x94, 0x4F, +0x9C, 0x70, 0x9C, 0x90, 0xA4, 0xB0, 0xA4, 0xD0, +0xA4, 0xD1, 0xAC, 0xF1, 0xAC, 0xF1, 0xAC, 0xF1, +0xAC, 0xF1, 0xAC, 0xF1, 0xAC, 0xD0, 0xA4, 0xB0, +0x9C, 0x90, 0x94, 0x6F, 0x9C, 0x90, 0x9C, 0x6F, +0x9C, 0x8F, 0x8C, 0x0E, 0x8B, 0xED, 0x83, 0xCD, +0x8C, 0x0E, 0x8B, 0xEE, 0x83, 0xAC, 0xA4, 0xD1, +0x73, 0xAD, 0x31, 0xA6, 0x5A, 0xCB, 0x5A, 0xCB, +0x42, 0x08, 0x5A, 0xCB, 0x6B, 0x0C, 0x52, 0x49, +0x39, 0xA6, 0x41, 0xC7, 0x4A, 0x07, 0x62, 0xAA, +0x4A, 0x08, 0x7B, 0x6C, 0x94, 0x30, 0x5A, 0xAA, +0xA5, 0xF3, 0x7C, 0x8C, 0x6C, 0x28, 0x6C, 0x48, +0x8D, 0x4D, 0x9D, 0x6D, 0x5B, 0xA4, 0x85, 0x09, +0x9D, 0xAD, 0x84, 0xAA, 0x7C, 0x68, 0x7C, 0xA8, +0x74, 0x87, 0x64, 0x04, 0x5C, 0x03, 0x74, 0xA7, +0x6C, 0x86, 0x7D, 0x05, 0x9D, 0xC9, 0xBE, 0x73, +0xDF, 0x3A, 0xD7, 0x3A, 0xC6, 0x97, 0xBE, 0x14, +0x94, 0xAF, 0xAD, 0x53, 0xB5, 0xD5, 0x8C, 0x70, +0x8C, 0x4F, 0x73, 0xAD, 0x7B, 0xEE, 0x8C, 0x4F, +0x83, 0xED, 0x73, 0x8C, 0x8C, 0x70, 0xC6, 0x16, +0xBD, 0xB5, 0xA4, 0xF1, 0x94, 0x6F, 0x8C, 0x4F, +0x7B, 0xCD, 0x84, 0x0E, 0x8C, 0x70, 0x94, 0xB1, +0x9C, 0xD2, 0x9C, 0xB1, 0xA4, 0xB0, 0xBD, 0x51, +0x9C, 0x4D, 0xB5, 0x11, 0xB5, 0x32, 0xBD, 0x93, +0xB5, 0x31, 0xB5, 0x31, 0xBD, 0x72, 0xB5, 0x31, +0xAC, 0xF0, 0xA4, 0xD0, 0x94, 0x0D, 0x94, 0x0D, +0x94, 0x2E, 0x8C, 0x0D, 0x83, 0xAC, 0x83, 0xAC, +0x83, 0xAC, 0x83, 0x8B, 0x8B, 0xEC, 0x8C, 0x0D, +0x8B, 0xEC, 0x8B, 0xEC, 0xB4, 0xEF, 0xB5, 0x10, +0xBD, 0x72, 0xB5, 0x11, 0xA4, 0xCF, 0x9C, 0x8F, +0x94, 0x2D, 0x7B, 0x8B, 0x8C, 0x0C, 0x8B, 0xCB, +0x8B, 0xEC, 0x94, 0x2D, 0x94, 0x2C, 0x94, 0x0C, +0x9C, 0x4D, 0xAC, 0xF0, 0xAC, 0xF0, 0xAC, 0xF0, +0xA4, 0xAE, 0xA4, 0x6D, 0xA4, 0xAE, 0xBD, 0x73, +0xBD, 0x95, 0x7B, 0x8E, 0x4A, 0x08, 0x29, 0x24, +0x4A, 0x49, 0x42, 0x07, 0x21, 0x03, 0x31, 0x85, +0x52, 0x69, 0x5A, 0xAA, 0x73, 0x8E, 0x8C, 0x51, +0x94, 0xB3, 0xAD, 0x76, 0xB5, 0xB7, 0xBD, 0xF8, +0xB5, 0x76, 0x94, 0x72, 0x63, 0x0C, 0x52, 0x8A, +0x7B, 0x8D, 0x83, 0xCD, 0x7B, 0x8B, 0x83, 0xAB, +0x8B, 0xEC, 0x9C, 0x4D, 0xA4, 0xAE, 0xAC, 0xCF, +0xA4, 0xCF, 0xA4, 0xCF, 0xB5, 0x10, 0xAC, 0xCF, +0xA4, 0xAF, 0xA4, 0xCE, 0xA4, 0xAE, 0xAC, 0xCF, +0xAC, 0xEF, 0xBD, 0x10, 0xB5, 0x10, 0x94, 0x2D, +0x83, 0xED, 0x83, 0xED, 0x94, 0x90, 0xCE, 0x38, +0xAD, 0x55, 0x9C, 0xD3, 0x84, 0x0F, 0x8C, 0x4F, +0xA4, 0xF2, 0xAD, 0x73, 0xA5, 0x12, 0xA4, 0xF2, +0xA4, 0xF2, 0x8C, 0x2F, 0x8C, 0x2F, 0x83, 0xCE, +0x63, 0x0B, 0x52, 0xAA, 0x39, 0xE7, 0x42, 0x07, +0x52, 0x69, 0x62, 0xCA, 0x73, 0x2C, 0x6B, 0x0B, +0x9C, 0x70, 0xBD, 0x54, 0x9C, 0x91, 0x41, 0xC7, +0x5A, 0x8A, 0x7B, 0x6D, 0x83, 0xAE, 0xAC, 0xF2, +0x94, 0x4F, 0x94, 0x4F, 0xDE, 0x77, 0xDE, 0xB7, +0xDE, 0xB7, 0xE6, 0xF8, 0xDE, 0xB8, 0xD6, 0x56, +0xCE, 0x36, 0xCE, 0x15, 0xBD, 0x94, 0xBD, 0xD5, +0xAD, 0x52, 0xAD, 0x32, 0xB5, 0x53, 0xB5, 0x53, +0x83, 0xCC, 0xA4, 0x8F, 0xB5, 0x11, 0xBD, 0x72, +0xBD, 0x93, 0xC5, 0xB3, 0xCD, 0xD4, 0xD5, 0xF5, +0xD5, 0xF5, 0xD5, 0xF4, 0xD5, 0xF4, 0xC5, 0x93, +0xC5, 0x73, 0xC5, 0x73, 0xAC, 0xF1, 0x73, 0x4C, +0x29, 0x45, 0x21, 0x25, 0x18, 0xE4, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC4, 0x18, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, 0x10, 0xA3, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x10, 0xA4, 0x18, 0xE5, 0x29, 0x46, 0x21, 0x26, +0x21, 0x25, 0x21, 0x05, 0x21, 0x05, 0x21, 0x05, +0x18, 0xE5, 0x18, 0xE4, 0x18, 0xE5, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x18, 0xE5, 0x18, 0xE4, +0x18, 0xE5, 0x18, 0xE5, 0x21, 0x26, 0x29, 0x67, +0x31, 0x87, 0x31, 0xA8, 0x29, 0x87, 0x29, 0x87, +0x29, 0x67, 0x31, 0xA8, 0x42, 0x2A, 0x4A, 0x6B, +0x4A, 0x8B, 0x6B, 0x4C, 0x8C, 0x2F, 0x83, 0xED, +0x83, 0xED, 0x6B, 0x2B, 0x7B, 0x8C, 0x94, 0x4F, +0xA4, 0xB0, 0xC5, 0xB3, 0xCD, 0xD4, 0xB5, 0x11, +0xA4, 0xD0, 0xA4, 0xB0, 0xAC, 0xF1, 0xB5, 0x32, +0xBD, 0x73, 0xC5, 0x93, 0xC5, 0xB4, 0xC5, 0xB4, +0xBD, 0x52, 0xBD, 0x93, 0xB5, 0x32, 0xC5, 0xB4, +0xC5, 0xB4, 0xC5, 0xB4, 0xBD, 0x93, 0xBD, 0x73, +0xBD, 0x52, 0xBD, 0x73, 0xB5, 0x12, 0xAD, 0x12, +0xAD, 0x32, 0xA4, 0xB0, 0xA4, 0xD1, 0xAD, 0x53, +0x7B, 0x8D, 0x39, 0xC7, 0x39, 0xA6, 0x4A, 0x28, +0x42, 0x08, 0x39, 0xC7, 0x31, 0x65, 0x39, 0x86, +0x39, 0xC7, 0x41, 0xC7, 0x52, 0x28, 0x5A, 0x89, +0x49, 0xE7, 0x7B, 0x6D, 0x9C, 0x50, 0x62, 0xCB, +0x84, 0xEE, 0xB6, 0x73, 0x6C, 0x4A, 0x53, 0x85, +0x6C, 0x48, 0x85, 0x0B, 0x6C, 0x47, 0x95, 0x6C, +0x95, 0x4D, 0x8C, 0xEB, 0x74, 0x67, 0x6C, 0x65, +0x74, 0xC6, 0x64, 0x24, 0x7C, 0xE8, 0x6C, 0x67, +0x7C, 0xE8, 0x74, 0xC5, 0xB6, 0x4F, 0xBE, 0x54, +0xA5, 0x92, 0xA5, 0x92, 0x94, 0xCF, 0xA5, 0x10, +0x94, 0x6E, 0xBD, 0xD5, 0xBD, 0xF6, 0x8C, 0x70, +0x84, 0x2F, 0x7B, 0xCE, 0x84, 0x0F, 0x8C, 0x2F, +0x84, 0x0E, 0x7B, 0xEE, 0xA5, 0x33, 0xC6, 0x37, +0xCE, 0x37, 0xC6, 0x37, 0xA5, 0x33, 0x94, 0xB1, +0x8C, 0x70, 0x9C, 0xD2, 0x94, 0x90, 0x94, 0x91, +0xA5, 0x13, 0xB5, 0x95, 0xA4, 0xF1, 0xBD, 0x51, +0xA4, 0x8E, 0xC5, 0xB3, 0xBD, 0x93, 0xC5, 0xD4, +0xBD, 0x93, 0xBD, 0x93, 0xC5, 0xD4, 0xB5, 0x72, +0xBD, 0x93, 0xBD, 0xB3, 0xAD, 0x11, 0xB5, 0x32, +0xAD, 0x52, 0xAD, 0x31, 0xAD, 0x32, 0xAD, 0x32, +0xAD, 0x11, 0xA4, 0xD0, 0x9C, 0xCF, 0xAD, 0x11, +0xB5, 0x52, 0xBD, 0x72, 0xB5, 0x10, 0xAC, 0xCF, +0xCE, 0x14, 0xBD, 0x93, 0xB5, 0x52, 0xAD, 0x32, +0xAD, 0x32, 0x9C, 0xD1, 0xAD, 0x11, 0xA4, 0xB0, +0x9C, 0x8F, 0x9C, 0x8F, 0xA4, 0xD0, 0xAD, 0x11, +0xA4, 0xD0, 0xA4, 0xD0, 0xAD, 0x11, 0xAD, 0x11, +0xA4, 0xD0, 0x8B, 0xEC, 0x8B, 0xED, 0xC5, 0xD6, +0xB5, 0x34, 0x73, 0x4C, 0x4A, 0x28, 0x21, 0x04, +0x21, 0x04, 0x21, 0x24, 0x29, 0x44, 0x39, 0xC6, +0x4A, 0x69, 0x5A, 0xAB, 0x6B, 0x6D, 0x7B, 0xF0, +0x84, 0x31, 0x9C, 0xD3, 0xAD, 0x55, 0xAD, 0x76, +0xBD, 0xD8, 0xB5, 0x96, 0x83, 0xF0, 0x83, 0xEE, +0x9C, 0x90, 0xA4, 0x8F, 0x94, 0x2E, 0x9C, 0x6E, +0xA4, 0xAF, 0xAC, 0xCF, 0xB5, 0x0F, 0xB5, 0x10, +0xB5, 0x30, 0xBD, 0x50, 0xBD, 0x71, 0xB5, 0x30, +0xC5, 0x71, 0xC5, 0x71, 0xBD, 0x50, 0xBD, 0x50, +0xBD, 0x50, 0xBD, 0x50, 0xC5, 0x50, 0xC5, 0x71, +0xC5, 0x71, 0xC5, 0x71, 0xC5, 0x93, 0xCE, 0x58, +0xA5, 0x35, 0x94, 0xB2, 0x9C, 0xB1, 0x9C, 0x6F, +0xAC, 0xD0, 0xAC, 0xCF, 0xA4, 0xAF, 0xA4, 0xAF, +0xAC, 0xAF, 0xA4, 0x8E, 0xAC, 0xAF, 0xAC, 0xAF, +0xA4, 0xAF, 0x94, 0x4E, 0x39, 0xA6, 0x42, 0x28, +0x5A, 0xCA, 0x52, 0x69, 0x7B, 0x4D, 0x62, 0xCB, +0x83, 0xCE, 0x94, 0x30, 0x94, 0x50, 0x8C, 0x10, +0x39, 0x86, 0x7B, 0x6D, 0x5A, 0x69, 0x52, 0x28, +0x7B, 0x4C, 0x8B, 0xEF, 0xAC, 0xF2, 0xD6, 0x56, +0xD6, 0x56, 0xD6, 0x56, 0xD6, 0x56, 0xCE, 0x15, +0xCE, 0x15, 0xC5, 0xF5, 0xBD, 0xB4, 0xBD, 0xD4, +0xA5, 0x12, 0xBD, 0x94, 0xB5, 0x53, 0xBD, 0x73, +0x7B, 0x8B, 0x94, 0x4E, 0xA4, 0xB0, 0xCD, 0xD4, +0xCD, 0xF4, 0xCD, 0xD4, 0xCD, 0xF4, 0xD5, 0xF4, +0xD6, 0x15, 0xD6, 0x15, 0xDE, 0x35, 0xDE, 0x35, +0xCD, 0xB4, 0xD5, 0xF5, 0xBD, 0x93, 0x83, 0xAD, +0x39, 0xA6, 0x29, 0x25, 0x18, 0xE4, 0x10, 0xC3, +0x10, 0xC3, 0x18, 0xE4, 0x18, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, +0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x21, 0x05, 0x18, 0xE4, 0x21, 0x05, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x10, 0xA3, +0x18, 0xC4, 0x18, 0xC4, 0x10, 0xA3, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xC3, 0x18, 0xE4, 0x29, 0x46, 0x21, 0x25, +0x21, 0x25, 0x21, 0x25, 0x21, 0x05, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xC4, 0x18, 0xE4, 0x21, 0x05, +0x21, 0x05, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE5, 0x18, 0xE5, 0x18, 0xE5, 0x21, 0x46, +0x29, 0x67, 0x31, 0x87, 0x31, 0xA8, 0x31, 0xC8, +0x31, 0x87, 0x29, 0x67, 0x31, 0xC8, 0x42, 0x4A, +0x4A, 0x8B, 0x52, 0x8B, 0x6B, 0x6D, 0x94, 0x70, +0x94, 0x4F, 0x62, 0xEA, 0x8C, 0x4F, 0xBD, 0x53, +0xC5, 0x92, 0xD5, 0xF3, 0xE6, 0x96, 0xE6, 0x96, +0xE6, 0x96, 0xE6, 0x96, 0xE6, 0x96, 0xDE, 0x76, +0xDE, 0x55, 0xDE, 0x55, 0xDE, 0x55, 0xCD, 0xF4, +0xA4, 0xB0, 0x94, 0x4E, 0xB5, 0x52, 0xBD, 0x72, +0xCD, 0xD4, 0xDE, 0x56, 0xE6, 0x96, 0xDE, 0x56, +0xD6, 0x15, 0xDE, 0x76, 0xD6, 0x36, 0xAC, 0xF1, +0x94, 0x6F, 0xB5, 0x32, 0xA4, 0xB0, 0x9C, 0xB0, +0x83, 0xCE, 0x52, 0x69, 0x18, 0xE3, 0x31, 0x86, +0x39, 0xA7, 0x31, 0x86, 0x5A, 0xEB, 0x84, 0x10, +0x42, 0x08, 0x4A, 0x08, 0x62, 0xAA, 0x62, 0x8A, +0x49, 0xE7, 0x83, 0x8D, 0x83, 0xAD, 0x83, 0xAE, +0x8D, 0x4F, 0xBE, 0x95, 0xBE, 0x54, 0x6C, 0x09, +0x64, 0x07, 0x64, 0x07, 0x6C, 0x07, 0x64, 0x07, +0x84, 0xCB, 0x8D, 0x0B, 0x85, 0x08, 0x74, 0x85, +0x7C, 0xE6, 0x85, 0x47, 0x95, 0x89, 0x64, 0x25, +0x74, 0xA7, 0x74, 0x87, 0x95, 0x4C, 0x8C, 0xCD, +0x8C, 0xEE, 0x94, 0xEF, 0x8C, 0x6D, 0xAD, 0x30, +0x9C, 0xAF, 0xBD, 0xD5, 0xB5, 0x94, 0x8C, 0x71, +0x8C, 0x50, 0x84, 0x0F, 0x84, 0x30, 0x63, 0x2B, +0x73, 0xCD, 0x94, 0xB1, 0xA5, 0x54, 0xD6, 0x98, +0xCE, 0x37, 0xCE, 0x77, 0xAD, 0x53, 0xAD, 0x74, +0xB5, 0xB5, 0xBD, 0xD6, 0x9C, 0xF2, 0x94, 0xD2, +0xA5, 0x33, 0xAD, 0x53, 0xA4, 0xD0, 0xB5, 0x31, +0xA4, 0xAF, 0xC5, 0xD3, 0xBD, 0xB3, 0xBD, 0xB3, +0xC5, 0xB4, 0xBD, 0x93, 0xC5, 0xF4, 0xBD, 0x93, +0xBD, 0x72, 0xBD, 0xB3, 0xB5, 0x72, 0xC6, 0x15, +0xBD, 0xB3, 0xB5, 0x52, 0xB5, 0x32, 0xA4, 0xF1, +0xA4, 0xF1, 0xAD, 0x11, 0xAD, 0x52, 0xB5, 0x52, +0xAD, 0x31, 0xBD, 0x92, 0xB5, 0x10, 0xAC, 0xAF, +0xCD, 0xF4, 0xBD, 0xB4, 0xB5, 0x73, 0xBD, 0xD4, +0xB5, 0x73, 0xAD, 0x53, 0xBD, 0x94, 0xC5, 0xD4, +0xC5, 0xF5, 0xBD, 0x93, 0xBD, 0xB4, 0xC5, 0xF5, +0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x52, 0xBD, 0x93, +0xBD, 0xB4, 0xB5, 0x72, 0xB5, 0x53, 0xCE, 0x17, +0xAD, 0x13, 0xAC, 0xF2, 0x9C, 0x4F, 0x41, 0xE7, +0x31, 0x85, 0x31, 0xA5, 0x42, 0x28, 0x39, 0xE7, +0x42, 0x08, 0x52, 0x8A, 0x6B, 0x2D, 0x73, 0xAF, +0x7C, 0x10, 0x9C, 0xF4, 0x9C, 0xF4, 0x84, 0x31, +0xC6, 0x19, 0xB5, 0x76, 0x83, 0xEF, 0x83, 0xEF, +0x7B, 0x8C, 0xBD, 0x94, 0x9C, 0x90, 0x94, 0x2F, +0x73, 0x6B, 0x62, 0xE9, 0x5A, 0xA8, 0x62, 0xC8, +0x62, 0xA8, 0x6B, 0x09, 0x83, 0xAB, 0x83, 0xCB, +0xB5, 0x30, 0x9C, 0x6E, 0x9C, 0x6D, 0xAC, 0xCE, +0xA4, 0x8D, 0xAC, 0xCE, 0xBD, 0x50, 0xBD, 0x50, +0xBD, 0x50, 0xBD, 0x50, 0xC5, 0xB4, 0xC6, 0x17, +0xAD, 0x55, 0x94, 0x92, 0xA4, 0xD1, 0xD6, 0x35, +0xEE, 0xD7, 0xDE, 0x35, 0xD6, 0x14, 0xD5, 0xF3, +0xCD, 0xB2, 0xBD, 0x51, 0xC5, 0x51, 0xBD, 0x30, +0xB5, 0x10, 0xAC, 0xAF, 0x83, 0xCC, 0x4A, 0x27, +0x52, 0x69, 0x4A, 0x08, 0x62, 0xAA, 0x6B, 0x0B, +0x4A, 0x08, 0x5A, 0xAA, 0x9C, 0x51, 0xCE, 0x17, +0x73, 0x6E, 0x39, 0x86, 0x52, 0x49, 0x52, 0x28, +0x94, 0x10, 0x94, 0x0F, 0xA4, 0xD2, 0x8B, 0xEE, +0xB5, 0x53, 0xAD, 0x11, 0xA4, 0xF1, 0xA4, 0xF1, +0xAD, 0x11, 0xAD, 0x11, 0x9C, 0xB0, 0x83, 0xED, +0x83, 0xCD, 0xAD, 0x12, 0xA4, 0xB0, 0x8C, 0x0D, +0x7B, 0x8C, 0x83, 0xAC, 0x83, 0xED, 0x9C, 0x6F, +0xAD, 0x11, 0xB5, 0x32, 0xBD, 0x93, 0xBD, 0x93, +0xBD, 0x73, 0xB5, 0x32, 0xBD, 0x72, 0xC5, 0x93, +0xC5, 0xB4, 0xCD, 0xF5, 0xBD, 0x93, 0x8C, 0x0E, +0x4A, 0x07, 0x29, 0x45, 0x21, 0x04, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC3, +0x10, 0xA3, 0x18, 0xC4, 0x10, 0xA3, 0x10, 0x83, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC4, 0x18, 0xC4, 0x21, 0x25, +0x21, 0x05, 0x21, 0x05, 0x18, 0xC4, 0x10, 0xA3, +0x18, 0xC4, 0x18, 0xE4, 0x10, 0xA3, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x21, 0x25, 0x21, 0x25, +0x21, 0x05, 0x21, 0x25, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xC4, 0x10, 0xA3, 0x18, 0xC4, +0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, +0x21, 0x05, 0x21, 0x25, 0x21, 0x26, 0x21, 0x46, +0x29, 0x67, 0x21, 0x26, 0x29, 0x67, 0x31, 0xC8, +0x31, 0xC8, 0x31, 0x87, 0x29, 0x67, 0x31, 0xA8, +0x42, 0x0A, 0x4A, 0x4A, 0x4A, 0x6A, 0x73, 0xAE, +0x94, 0x90, 0x6B, 0x4C, 0xA4, 0xF1, 0xC5, 0x93, +0xDE, 0x55, 0xDE, 0x14, 0xE6, 0x96, 0xEE, 0xB6, +0xEE, 0x96, 0xEE, 0xB6, 0xEE, 0xB7, 0xEE, 0x96, +0xE6, 0x75, 0xE6, 0x75, 0xE6, 0x75, 0xE6, 0x96, +0xEE, 0xD7, 0xEE, 0xD8, 0xC5, 0xD4, 0xCD, 0xD4, +0x9C, 0xB0, 0xDE, 0x76, 0xD6, 0x14, 0xD6, 0x14, +0xCD, 0xF4, 0xCD, 0xD3, 0xDE, 0x76, 0xA4, 0xB0, +0xB5, 0x53, 0xD6, 0x77, 0xC5, 0xD5, 0xBD, 0x94, +0xA4, 0xF1, 0x7B, 0xAD, 0x39, 0xC7, 0x18, 0xC3, +0x18, 0xC3, 0x21, 0x04, 0x8C, 0x51, 0xCE, 0x39, +0x84, 0x11, 0x52, 0x49, 0x6A, 0xEB, 0x7B, 0x4C, +0x52, 0x08, 0x52, 0x28, 0x62, 0xAA, 0x94, 0x50, +0x53, 0x86, 0x84, 0xED, 0xA5, 0xD2, 0xAE, 0x12, +0x6C, 0x28, 0x64, 0x06, 0x63, 0xE6, 0x53, 0x65, +0x6C, 0x47, 0x7C, 0xA8, 0x85, 0x08, 0x7C, 0xE6, +0x95, 0x66, 0xA5, 0xE8, 0x74, 0x84, 0x6C, 0x85, +0x6C, 0x85, 0x85, 0x08, 0x84, 0xC9, 0x84, 0xAA, +0x84, 0xCB, 0x8C, 0x8D, 0x9C, 0xAE, 0xAC, 0xEF, +0x8C, 0x2D, 0xB5, 0xB4, 0xB5, 0xD5, 0xA5, 0x54, +0x9D, 0x13, 0xA5, 0x13, 0x94, 0xB1, 0x84, 0x2F, +0x94, 0x90, 0xA5, 0x13, 0xA5, 0x53, 0xBD, 0xD5, +0xB5, 0x94, 0xBD, 0xD5, 0xA5, 0x12, 0xAD, 0x54, +0xBD, 0xD5, 0xBD, 0xF6, 0xA5, 0x33, 0xAD, 0x54, +0xAD, 0x74, 0xB5, 0x74, 0xA4, 0xD0, 0xB5, 0x10, +0xA4, 0xAF, 0xC5, 0xB3, 0xC5, 0xB4, 0xC5, 0xD4, +0xC5, 0xD4, 0xC5, 0xD4, 0xC5, 0xF4, 0xBD, 0x93, +0xBD, 0x93, 0xBD, 0x93, 0xB5, 0x72, 0xC5, 0xF4, +0xC5, 0xD4, 0xC5, 0xB4, 0xBD, 0x93, 0xB5, 0x52, +0xB5, 0x72, 0xB5, 0x93, 0xBD, 0x93, 0xBD, 0x73, +0xAD, 0x11, 0xBD, 0x71, 0xBD, 0x30, 0xB5, 0x10, +0xCE, 0x14, 0xC5, 0xD4, 0xBD, 0x93, 0xBD, 0x94, +0xAD, 0x32, 0xBD, 0xD5, 0xC6, 0x15, 0xCE, 0x15, +0xD6, 0x56, 0xCE, 0x15, 0xCE, 0x15, 0xCE, 0x35, +0xC5, 0xF5, 0xCE, 0x15, 0xBD, 0xD4, 0xBD, 0xB4, +0xBD, 0xB4, 0xC5, 0xD4, 0xCE, 0x36, 0xBD, 0x95, +0xAD, 0x13, 0xAC, 0xF1, 0xAD, 0x11, 0x6A, 0xEA, +0x4A, 0x48, 0x42, 0x07, 0x39, 0xE7, 0x39, 0xA6, +0x4A, 0x48, 0x5A, 0xAA, 0x62, 0xEC, 0x63, 0x0C, +0x7B, 0xD0, 0x8C, 0x31, 0x84, 0x31, 0xAD, 0x55, +0xC6, 0x18, 0xA4, 0xF3, 0x8C, 0x51, 0xA4, 0xF3, +0x4A, 0x28, 0x8C, 0x50, 0xC5, 0xF7, 0xA4, 0xF2, +0xB5, 0x53, 0xB5, 0x73, 0xAD, 0x32, 0x9C, 0xB0, +0x84, 0x0E, 0x7B, 0xAD, 0x5A, 0xC9, 0x6B, 0x2A, +0x8C, 0x2E, 0x6B, 0x2A, 0x52, 0x48, 0x52, 0x68, +0x52, 0x68, 0x62, 0xC8, 0x8B, 0xEC, 0xB5, 0x31, +0xB5, 0x52, 0xA4, 0xB0, 0xBD, 0xB5, 0xBD, 0xD7, +0xAD, 0x35, 0x94, 0x71, 0xBD, 0x73, 0xD6, 0x35, +0xDE, 0x96, 0xD6, 0x55, 0xD6, 0x14, 0xCD, 0xF4, +0xC5, 0x92, 0xD6, 0x14, 0xC5, 0x92, 0xBD, 0x51, +0xBD, 0x72, 0xBD, 0x72, 0xC5, 0xB3, 0xAD, 0x12, +0x4A, 0x07, 0x41, 0xE7, 0x6A, 0xEB, 0x73, 0x0B, +0x5A, 0x69, 0x62, 0xCB, 0x9C, 0x71, 0xC5, 0xD6, +0xC5, 0xB6, 0x5A, 0x8A, 0x73, 0x2C, 0x7B, 0x8D, +0x73, 0x2C, 0x9C, 0x70, 0x94, 0x0F, 0x9C, 0x50, +0xBD, 0x94, 0xBD, 0x94, 0xB5, 0x53, 0xBD, 0x94, +0xBD, 0x94, 0xAD, 0x32, 0xBD, 0xB4, 0xC5, 0xB5, +0xBD, 0x94, 0xC5, 0xF5, 0xCD, 0xF5, 0xCD, 0xF5, +0xC5, 0xD5, 0xC5, 0xB5, 0xBD, 0x94, 0xB5, 0x73, +0xB5, 0x32, 0xAD, 0x11, 0xA4, 0xD1, 0xA4, 0xD1, +0xAC, 0xF2, 0xA4, 0xF2, 0xA4, 0xD1, 0x9C, 0x90, +0x94, 0x6F, 0x8C, 0x0E, 0x83, 0xCD, 0x83, 0xAD, +0x52, 0x48, 0x29, 0x45, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x18, 0xE4, 0x18, 0xC3, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x18, 0xE4, 0x21, 0x25, +0x18, 0xE4, 0x18, 0xC4, 0x10, 0xA3, 0x18, 0xC4, +0x18, 0xE4, 0x18, 0xE4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x21, 0x05, 0x21, 0x25, +0x18, 0xE5, 0x21, 0x05, 0x18, 0xE4, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC4, +0x10, 0xA3, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE5, +0x21, 0x05, 0x21, 0x26, 0x21, 0x46, 0x29, 0x46, +0x29, 0x46, 0x21, 0x26, 0x21, 0x26, 0x29, 0x67, +0x31, 0xA8, 0x31, 0xA8, 0x29, 0x87, 0x29, 0x67, +0x39, 0xC8, 0x42, 0x29, 0x42, 0x2A, 0x4A, 0x8B, +0x84, 0x0F, 0x7B, 0xCE, 0xA4, 0xF1, 0xC5, 0xD4, +0xD6, 0x14, 0xDE, 0x14, 0xE6, 0x75, 0xEE, 0xB6, +0xEE, 0xB6, 0xEE, 0x96, 0xEE, 0xB6, 0xE6, 0x96, +0xDE, 0x54, 0xD6, 0x13, 0xD5, 0xF3, 0xCD, 0xD3, +0xDE, 0x35, 0xDE, 0x76, 0xBD, 0x93, 0xE6, 0xB8, +0xDE, 0x97, 0xDE, 0x76, 0xD6, 0x35, 0xD6, 0x14, +0xD6, 0x34, 0xD5, 0xF4, 0xDE, 0x76, 0xA4, 0xD0, +0xBD, 0x94, 0xBD, 0x93, 0xBD, 0x93, 0xC5, 0xB4, +0xB5, 0x73, 0x9C, 0xD1, 0x7B, 0xCE, 0x29, 0x66, +0x10, 0xA3, 0x18, 0xE4, 0x39, 0xC7, 0xB5, 0x97, +0xBD, 0xB7, 0x73, 0x4D, 0x6A, 0xCB, 0x83, 0xAE, +0x52, 0x08, 0x7B, 0x6D, 0x6A, 0xEA, 0x8C, 0x0F, +0x4B, 0x44, 0x53, 0xA6, 0x7C, 0xCC, 0x95, 0x6F, +0x6C, 0x48, 0x64, 0x06, 0x64, 0x07, 0x53, 0x45, +0x64, 0x27, 0x74, 0xA7, 0x6C, 0x65, 0x74, 0x84, +0x8D, 0x44, 0x9D, 0xC7, 0x5B, 0xE2, 0x4B, 0x61, +0x53, 0xC2, 0x7C, 0xE7, 0x74, 0x86, 0x74, 0x66, +0x7C, 0x88, 0x7C, 0x69, 0x9C, 0xCD, 0xB5, 0x50, +0x9C, 0x8E, 0x9C, 0xB0, 0xA4, 0xF1, 0xA5, 0x12, +0xAD, 0x73, 0xBD, 0xB5, 0xBD, 0x94, 0xA4, 0xD1, +0x9C, 0xB0, 0xA5, 0x12, 0xAD, 0x53, 0xAD, 0x53, +0xAD, 0x33, 0xB5, 0xB4, 0x8C, 0x4F, 0xBD, 0xB5, +0xC6, 0x37, 0xBD, 0xF6, 0xB5, 0x94, 0xBD, 0xD5, +0xB5, 0x94, 0xAD, 0x53, 0xAC, 0xF0, 0xB5, 0x10, +0xA4, 0xAF, 0xC5, 0xD3, 0xC5, 0xD4, 0xC5, 0xF5, +0xC5, 0xD4, 0xC5, 0xF4, 0xCE, 0x15, 0xC5, 0xD4, +0xC5, 0xD4, 0xC5, 0xD4, 0xB5, 0x52, 0xCE, 0x15, +0xCE, 0x15, 0xC5, 0xF5, 0xC5, 0xD4, 0xBD, 0xB4, +0xBD, 0x93, 0xBD, 0x93, 0xC5, 0xD4, 0xC5, 0xD4, +0xBD, 0xB3, 0xB5, 0x51, 0xBD, 0x31, 0xAD, 0x10, +0xCD, 0xF4, 0xCE, 0x15, 0xCE, 0x15, 0xC5, 0xF5, +0xB5, 0x73, 0xCE, 0x36, 0xC5, 0xF5, 0xB5, 0x53, +0xC5, 0xF5, 0xCE, 0x15, 0xCE, 0x36, 0xCE, 0x35, +0xAD, 0x12, 0xB5, 0x73, 0xCE, 0x16, 0xC6, 0x15, +0xBD, 0xD4, 0xC5, 0xF5, 0xC5, 0xF5, 0xAD, 0x12, +0xAD, 0x12, 0xAC, 0xF0, 0xAD, 0x10, 0xA4, 0xB1, +0x52, 0x89, 0x52, 0x69, 0x41, 0xE7, 0x42, 0x07, +0x42, 0x28, 0x4A, 0x69, 0x52, 0x8A, 0x5A, 0xEB, +0x5A, 0xEB, 0x6B, 0x6D, 0x9C, 0xB3, 0xAD, 0x76, +0x9C, 0xF4, 0x73, 0x8E, 0xA4, 0xF3, 0xBD, 0x96, +0x5A, 0xAB, 0x39, 0xA7, 0x83, 0xEF, 0xB5, 0x54, +0xCD, 0xF5, 0xD6, 0x76, 0xCE, 0x36, 0xC5, 0xF5, +0xCE, 0x15, 0xD6, 0x56, 0x9C, 0xB0, 0xA4, 0xF1, +0xAD, 0x32, 0xA5, 0x11, 0x9C, 0xB1, 0x94, 0x6F, +0x84, 0x0E, 0x7B, 0xAD, 0x8C, 0x0E, 0x8C, 0x4F, +0x94, 0x4F, 0x8C, 0x2F, 0xC6, 0x38, 0xB5, 0x96, +0xA5, 0x35, 0x9C, 0xB2, 0xBD, 0x53, 0xBD, 0x93, +0xBD, 0x93, 0xB5, 0x52, 0xBD, 0x72, 0xCD, 0xF4, +0xB5, 0x72, 0xBD, 0x72, 0xB5, 0x31, 0xB5, 0x31, +0xB5, 0x51, 0xC5, 0xB3, 0xC5, 0xD4, 0xBD, 0x73, +0x5A, 0x89, 0x39, 0x86, 0x6B, 0x2C, 0x52, 0x48, +0x39, 0xC6, 0x4A, 0x28, 0x6A, 0xEA, 0x9C, 0x50, +0xCD, 0xF7, 0x94, 0x30, 0x62, 0x8A, 0x9C, 0x50, +0x73, 0x2C, 0x73, 0x2C, 0x94, 0x2F, 0xAD, 0x12, +0xBD, 0x74, 0x94, 0x50, 0x73, 0x4B, 0xB5, 0x53, +0xA4, 0xF1, 0xB5, 0x53, 0x9C, 0x90, 0x83, 0xCD, +0x83, 0xCD, 0x94, 0x4F, 0x94, 0x4F, 0x8C, 0x0E, +0x94, 0x4F, 0x9C, 0x6F, 0x9C, 0x4F, 0xA4, 0xD1, +0xAD, 0x12, 0xAD, 0x11, 0xBD, 0x73, 0xA4, 0xD1, +0xAD, 0x12, 0xBD, 0x73, 0xBD, 0x73, 0xB5, 0x53, +0xBD, 0x94, 0xBD, 0x74, 0xBD, 0x94, 0xA4, 0x90, +0x4A, 0x08, 0x29, 0x45, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x18, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, 0x10, 0x83, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x18, 0xC4, +0x10, 0xA3, 0x18, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xC4, 0x18, 0xE4, 0x21, 0x25, +0x18, 0xE4, 0x10, 0xA4, 0x18, 0xC4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xC4, 0x10, 0xA4, 0x10, 0xA3, +0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, 0x21, 0x05, +0x18, 0xE4, 0x18, 0xE5, 0x18, 0xE4, 0x10, 0xC4, +0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA4, 0x10, 0xC4, 0x18, 0xE4, +0x19, 0x05, 0x21, 0x25, 0x21, 0x26, 0x21, 0x26, +0x21, 0x46, 0x29, 0x46, 0x21, 0x26, 0x21, 0x26, +0x29, 0x46, 0x29, 0x87, 0x31, 0x88, 0x29, 0x67, +0x31, 0x87, 0x39, 0xE9, 0x42, 0x2A, 0x4A, 0x4A, +0x5A, 0xEC, 0x7B, 0xAE, 0xA4, 0xF2, 0xC5, 0xD4, +0xDE, 0x35, 0xD5, 0xD3, 0xE6, 0x75, 0xE6, 0x96, +0xEE, 0x96, 0xEE, 0x96, 0xEE, 0xB6, 0xE6, 0x75, +0xE6, 0x75, 0xD6, 0x14, 0xD5, 0xF4, 0xD5, 0xF4, +0xDE, 0x35, 0xCD, 0xF4, 0xC5, 0xD4, 0xDE, 0x97, +0xDE, 0x56, 0xCD, 0xD4, 0xD6, 0x35, 0xCE, 0x14, +0xCD, 0xF4, 0xDE, 0x76, 0xD6, 0x35, 0xA4, 0xF1, +0xA4, 0xD0, 0x9C, 0x8F, 0xC5, 0xF4, 0xC5, 0xF4, +0xB5, 0x73, 0xAD, 0x12, 0xC5, 0xF5, 0x73, 0x8D, +0x18, 0xE4, 0x18, 0xA3, 0x41, 0xE8, 0xAD, 0x35, +0xCE, 0x59, 0xAD, 0x35, 0x41, 0xC7, 0x52, 0x48, +0x39, 0x85, 0x6A, 0xCB, 0x8B, 0xAE, 0x94, 0x0F, +0x7C, 0xEA, 0x53, 0xE6, 0x64, 0x48, 0x74, 0xAA, +0x64, 0x26, 0x5B, 0xC5, 0x74, 0x69, 0x5B, 0x87, +0x42, 0xE4, 0x6C, 0x27, 0x6C, 0x26, 0x6C, 0x45, +0x6C, 0x63, 0x6C, 0x24, 0x7C, 0x6A, 0x74, 0x28, +0x6C, 0x26, 0x7C, 0xA8, 0x6C, 0x06, 0x5B, 0xA4, +0x63, 0xE6, 0x8C, 0xAA, 0x9C, 0xED, 0xAC, 0xCE, +0xB5, 0x10, 0xAD, 0x10, 0xB5, 0x51, 0xBD, 0x51, +0xAC, 0xF0, 0xBD, 0x51, 0xBD, 0x52, 0xC5, 0x92, +0xBD, 0x51, 0xB5, 0x31, 0xAD, 0x10, 0xAC, 0xF0, +0xAD, 0x10, 0xAC, 0xF0, 0xA4, 0xAF, 0xA4, 0xD0, +0xAD, 0x11, 0xAD, 0x31, 0xAD, 0x32, 0xAD, 0x11, +0xA4, 0xD0, 0x9C, 0x6E, 0xB5, 0x31, 0xC5, 0x71, +0xB4, 0xF0, 0xB5, 0x30, 0xB5, 0x10, 0xB5, 0x31, +0xBD, 0x72, 0xBD, 0x72, 0xB5, 0x52, 0xAC, 0xF0, +0xAC, 0xF0, 0xAC, 0xF0, 0xAC, 0xF0, 0xB5, 0x52, +0xBD, 0x72, 0xB5, 0x52, 0xB5, 0x32, 0xBD, 0x72, +0xC5, 0xB4, 0xC5, 0xD4, 0xCE, 0x15, 0xCE, 0x15, +0xC5, 0xD4, 0xB5, 0x31, 0xC5, 0x71, 0xA4, 0xAF, +0xD6, 0x76, 0xCE, 0x15, 0xCE, 0x15, 0xCE, 0x36, +0xC6, 0x15, 0xCE, 0x56, 0xCE, 0x36, 0xC6, 0x15, +0xC6, 0x15, 0xCE, 0x35, 0xCE, 0x15, 0xCE, 0x15, +0xC5, 0xD5, 0xCE, 0x56, 0xCE, 0x16, 0xCE, 0x35, +0xC6, 0x15, 0xCE, 0x15, 0xC5, 0xF5, 0xAD, 0x33, +0xB5, 0x74, 0xA4, 0xB0, 0xBD, 0x52, 0xD6, 0x57, +0x63, 0x0B, 0x62, 0xEB, 0x39, 0xC6, 0x39, 0xE7, +0x42, 0x07, 0x42, 0x28, 0x4A, 0x48, 0x52, 0x8A, +0x6B, 0x4D, 0x8C, 0x51, 0x8C, 0x72, 0x94, 0x92, +0x84, 0x10, 0x84, 0x31, 0x8C, 0x51, 0x94, 0x71, +0x73, 0x6E, 0x5A, 0xAB, 0x4A, 0x48, 0xA4, 0xF3, +0xCD, 0xF6, 0xD6, 0x56, 0xCE, 0x14, 0xCE, 0x15, +0xCE, 0x15, 0xD6, 0x56, 0xBD, 0x92, 0xCE, 0x35, +0xCE, 0x35, 0xCE, 0x15, 0xCE, 0x15, 0xCE, 0x36, +0xC5, 0xD4, 0xBD, 0x94, 0xBD, 0xB4, 0xBD, 0xB4, +0xB5, 0x94, 0xAD, 0x53, 0xCE, 0x59, 0xAD, 0x55, +0x9C, 0xF4, 0xA4, 0xF2, 0xB5, 0x52, 0xD6, 0x36, +0xC5, 0xB4, 0xB5, 0x52, 0xB5, 0x72, 0xBD, 0xB3, +0xBD, 0xB3, 0xB5, 0x72, 0xBD, 0x72, 0xB5, 0x72, +0xB5, 0x31, 0xAD, 0x11, 0xBD, 0x92, 0x83, 0xCD, +0x73, 0x4C, 0x6B, 0x0B, 0x42, 0x07, 0x41, 0xE7, +0x42, 0x07, 0x41, 0xE7, 0x5A, 0xAA, 0x7B, 0x6C, +0x83, 0xCE, 0x73, 0x4C, 0x52, 0x49, 0x49, 0xE7, +0x6B, 0x0C, 0x6A, 0xEB, 0x83, 0xAE, 0x94, 0x50, +0xB5, 0x33, 0x94, 0x2F, 0x83, 0xCE, 0x5A, 0x89, +0x6B, 0x2B, 0x83, 0xAD, 0x62, 0xEA, 0x4A, 0x48, +0x52, 0x49, 0x52, 0x68, 0x5A, 0xA9, 0x6B, 0x2B, +0x7B, 0x8C, 0x9C, 0x90, 0x9C, 0x4F, 0xAD, 0x12, +0xAD, 0x12, 0xAC, 0xF1, 0xB5, 0x53, 0xAD, 0x11, +0xBD, 0x73, 0xBD, 0x73, 0xBD, 0x93, 0xB5, 0x52, +0xBD, 0x52, 0xBD, 0x73, 0xCD, 0xD4, 0xA4, 0x90, +0x41, 0xC7, 0x29, 0x45, 0x21, 0x25, 0x21, 0x25, +0x21, 0x04, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0x83, 0x10, 0x83, +0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC4, 0x18, 0xE4, 0x21, 0x25, +0x18, 0xE4, 0x10, 0xC3, 0x18, 0xE4, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x10, 0xC4, 0x18, 0xC4, +0x18, 0xC4, 0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC3, +0x10, 0xC4, 0x10, 0xC4, 0x18, 0xC4, 0x18, 0xE4, +0x18, 0xC4, 0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC3, +0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC4, +0x10, 0xA3, 0x10, 0xA4, 0x10, 0xC4, 0x10, 0xC4, +0x19, 0x05, 0x21, 0x05, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x21, 0x46, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x21, 0x46, 0x29, 0x87, 0x31, 0x88, +0x29, 0x67, 0x31, 0xA8, 0x39, 0xE9, 0x42, 0x4A, +0x42, 0x4A, 0x63, 0x0C, 0xA4, 0xD1, 0xC5, 0xB3, +0xE6, 0x96, 0xDE, 0x14, 0xDE, 0x55, 0xE6, 0x96, +0xEE, 0x96, 0xEE, 0x96, 0xEE, 0x96, 0xE6, 0x75, +0xE6, 0x75, 0xCD, 0xF3, 0xCD, 0xB3, 0xCD, 0xD3, +0xDE, 0x55, 0xCD, 0xF4, 0xD6, 0x36, 0xE6, 0xB7, +0xDE, 0x77, 0xDE, 0x56, 0xD6, 0x35, 0xCD, 0xF4, +0xCD, 0xD4, 0xE6, 0x96, 0xC5, 0x93, 0xB5, 0x12, +0xBD, 0x73, 0xCD, 0xF5, 0xC5, 0xD4, 0xC5, 0xF4, +0xBD, 0x93, 0xAD, 0x53, 0xCE, 0x36, 0xBD, 0xD5, +0x31, 0x86, 0x18, 0xA3, 0x5A, 0xAB, 0xA4, 0xF3, +0xAD, 0x55, 0xBD, 0xD7, 0x4A, 0x69, 0x4A, 0x28, +0x31, 0x65, 0x52, 0x28, 0x8B, 0xAD, 0xB5, 0x12, +0x5B, 0xE6, 0x64, 0x47, 0x7C, 0xEA, 0x74, 0xA9, +0x5B, 0xE5, 0x6C, 0x28, 0x84, 0xCB, 0x6B, 0xEA, +0x3A, 0x64, 0x4A, 0xE5, 0x63, 0xC7, 0x7C, 0x89, +0x6C, 0x06, 0x8C, 0xED, 0xBE, 0x55, 0x95, 0x0E, +0x84, 0xAA, 0x95, 0x4C, 0x8C, 0xEB, 0x6C, 0x49, +0x64, 0x08, 0x6C, 0x08, 0x9C, 0xED, 0x9C, 0x6D, +0x7B, 0x49, 0x9C, 0x6E, 0x8C, 0x0C, 0x7B, 0x8B, +0x83, 0xCC, 0x7B, 0x8B, 0x83, 0xCB, 0x8B, 0xEC, +0x83, 0xCC, 0x8B, 0xEC, 0xAC, 0xCF, 0xAC, 0xF0, +0xA4, 0x8F, 0xA4, 0xAF, 0xAC, 0xCF, 0xB5, 0x10, +0xB5, 0x30, 0xC5, 0x92, 0xC5, 0x92, 0xCD, 0x92, +0xD5, 0xF3, 0xCD, 0xB2, 0xBD, 0x71, 0xBD, 0x50, +0xAC, 0xCF, 0xB4, 0xEF, 0xC5, 0x71, 0xC5, 0x92, +0xCD, 0x92, 0xC5, 0x72, 0xC5, 0x71, 0xC5, 0x92, +0xC5, 0x92, 0xC5, 0x92, 0xC5, 0x92, 0xC5, 0x71, +0xBD, 0x51, 0xBD, 0x31, 0xB4, 0xF0, 0xB5, 0x10, +0xB4, 0xF0, 0xA4, 0xCF, 0xAC, 0xCF, 0xB5, 0x31, +0xBD, 0x51, 0xBD, 0x50, 0xC5, 0x71, 0xB4, 0xEF, +0xB5, 0x10, 0xCE, 0x35, 0xC5, 0xB3, 0xB5, 0x52, +0xB5, 0x72, 0xC5, 0xF4, 0xCE, 0x35, 0xD6, 0x56, +0xCE, 0x36, 0xCE, 0x36, 0xD6, 0x56, 0xD6, 0x56, +0xC5, 0xD4, 0xBD, 0x93, 0xCE, 0x15, 0xCE, 0x15, +0xCE, 0x56, 0xD6, 0x97, 0xDE, 0x97, 0xC5, 0xD5, +0xB5, 0x54, 0x9C, 0x4F, 0xC5, 0x93, 0xDE, 0x98, +0x83, 0xEF, 0x73, 0x8D, 0x4A, 0x28, 0x39, 0xC6, +0x52, 0x89, 0x4A, 0x48, 0x4A, 0x48, 0x52, 0x69, +0x52, 0xAA, 0x5A, 0xEB, 0x7B, 0xCF, 0x8C, 0x72, +0xA4, 0xF4, 0xAD, 0x55, 0xBD, 0xB7, 0xB5, 0x97, +0xA4, 0xF3, 0x8C, 0x30, 0x9C, 0xD2, 0xBD, 0xB5, +0xCE, 0x15, 0xD6, 0x76, 0xD6, 0x35, 0xD6, 0x35, +0xDE, 0x56, 0xCD, 0xF4, 0xD6, 0x56, 0xD6, 0x36, +0xD6, 0x35, 0xDE, 0x76, 0xD6, 0x76, 0xD6, 0x76, +0xC5, 0xD4, 0xD6, 0x56, 0xCE, 0x16, 0xC5, 0xF5, +0xCE, 0x15, 0xC6, 0x16, 0xCE, 0x59, 0xB5, 0xB7, +0x9C, 0xB3, 0xAD, 0x12, 0xB5, 0x31, 0xB5, 0x72, +0xB5, 0x32, 0xBD, 0x73, 0xBD, 0x93, 0xCE, 0x15, +0xC5, 0xD4, 0xC5, 0xD4, 0xC5, 0xD4, 0xC5, 0xD4, +0xC5, 0xD3, 0xC5, 0xD4, 0xC5, 0xD3, 0xCD, 0xF4, +0xD6, 0x15, 0xD6, 0x15, 0x94, 0x2E, 0x39, 0x85, +0x39, 0xC7, 0x42, 0x07, 0x73, 0x4C, 0x8C, 0x0F, +0x94, 0x30, 0x9C, 0x71, 0x9C, 0x92, 0x62, 0xAA, +0x39, 0xA6, 0x7B, 0x8D, 0x73, 0x2C, 0x8B, 0xEE, +0x8B, 0xEF, 0xB5, 0x34, 0x94, 0x71, 0x62, 0xCA, +0x5A, 0xCA, 0x52, 0x89, 0x52, 0xAA, 0x73, 0x6C, +0x94, 0x70, 0xA4, 0xD1, 0xAD, 0x32, 0xA4, 0xF1, +0xA4, 0xF1, 0xB5, 0x72, 0xC5, 0xB4, 0xD6, 0x15, +0xBD, 0x93, 0xAD, 0x12, 0xB5, 0x53, 0xAD, 0x12, +0xC5, 0xB4, 0xC5, 0xD4, 0xCD, 0xF4, 0xC5, 0xD3, +0xCD, 0xD4, 0xC5, 0xB3, 0xCD, 0xD4, 0x9C, 0x4F, +0x41, 0xC7, 0x29, 0x25, 0x18, 0xE4, 0x21, 0x25, +0x18, 0xE4, 0x10, 0xA3, 0x18, 0xC3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC4, 0x18, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, +0x10, 0xA3, 0x10, 0xA3, 0x18, 0xE4, 0x21, 0x25, +0x18, 0xC3, 0x18, 0xE4, 0x21, 0x05, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x19, 0x05, 0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC4, +0x18, 0xC4, 0x10, 0xA3, 0x10, 0xC3, 0x10, 0xC3, +0x10, 0xC3, 0x10, 0xA3, 0x10, 0xC3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA4, 0x18, 0xC4, +0x21, 0x05, 0x21, 0x05, 0x21, 0x26, 0x21, 0x26, +0x21, 0x05, 0x21, 0x26, 0x29, 0x46, 0x21, 0x26, +0x29, 0x46, 0x29, 0x67, 0x29, 0x67, 0x31, 0xA8, +0x31, 0x87, 0x29, 0x87, 0x31, 0xC8, 0x39, 0xE9, +0x42, 0x2A, 0x4A, 0x4A, 0x8C, 0x0F, 0xAC, 0xF1, +0xBD, 0x52, 0xDE, 0x56, 0xEE, 0xD7, 0xF6, 0xF7, +0xF6, 0xF7, 0xF6, 0xF7, 0xEE, 0xD7, 0xEE, 0xD6, +0xEE, 0xD6, 0xE6, 0x96, 0xDE, 0x35, 0xDE, 0x75, +0xE6, 0x96, 0xCD, 0xD4, 0xDE, 0x76, 0xE6, 0xB7, +0xE6, 0x97, 0xDE, 0x56, 0xD6, 0x15, 0xCD, 0xD4, +0xC5, 0xB3, 0xDE, 0x76, 0xC5, 0x93, 0x9C, 0x8F, +0xCE, 0x36, 0xD6, 0x56, 0xCE, 0x15, 0xCE, 0x15, +0xBD, 0xB4, 0xAD, 0x32, 0xCE, 0x36, 0xD6, 0x77, +0x5A, 0xAA, 0x18, 0xE4, 0x29, 0x24, 0x6B, 0x2B, +0x94, 0x91, 0x62, 0xEA, 0x42, 0x07, 0x5A, 0xA9, +0x4A, 0x07, 0x52, 0x28, 0x6A, 0xCA, 0x8B, 0xCD, +0x63, 0xEA, 0x43, 0x44, 0x6C, 0x86, 0x64, 0x45, +0x6C, 0x47, 0x74, 0x69, 0x8D, 0x0D, 0x74, 0x2A, +0x6B, 0xEA, 0x42, 0x86, 0x42, 0x84, 0x53, 0x46, +0x64, 0x08, 0x6B, 0xEA, 0x84, 0x6D, 0x8C, 0xCD, +0x84, 0xAB, 0x9D, 0x2D, 0x94, 0xCD, 0xB5, 0xD1, +0xAD, 0xD1, 0xA5, 0x70, 0xBE, 0x13, 0xA4, 0xEF, +0x9C, 0xAF, 0x9C, 0xB0, 0x7B, 0xCC, 0xA4, 0xD1, +0xAD, 0x32, 0x8C, 0x2E, 0x9C, 0x8F, 0x9C, 0x90, +0x9C, 0x90, 0x83, 0xED, 0x94, 0x8F, 0x8C, 0x4E, +0x83, 0xED, 0x8C, 0x2E, 0x8C, 0x0E, 0xBD, 0x93, +0xBD, 0x51, 0x9C, 0x4D, 0xA4, 0x6D, 0xAC, 0xCE, +0xBD, 0x51, 0xB5, 0x31, 0xAC, 0xF0, 0x9C, 0x4D, +0x83, 0xAB, 0x73, 0x29, 0x94, 0x2D, 0x9C, 0x8E, +0xA4, 0x8F, 0xAC, 0xD0, 0xB5, 0x31, 0xA4, 0xAE, +0xB5, 0x31, 0xBD, 0x51, 0xBD, 0x51, 0xA4, 0x8E, +0x9C, 0x4D, 0xA4, 0xAF, 0xAC, 0xAF, 0xC5, 0x92, +0xC5, 0x92, 0xB4, 0xEF, 0xBD, 0x50, 0xB5, 0x10, +0xAC, 0xCF, 0xAC, 0xAF, 0xAC, 0xAE, 0xB4, 0xEF, +0xA4, 0x8E, 0xAC, 0xAF, 0xA4, 0x8E, 0x9C, 0x4E, +0xA4, 0xAF, 0xAC, 0xCF, 0xAC, 0xCF, 0xA4, 0x8E, +0xA4, 0x8E, 0xA4, 0xAF, 0xA4, 0xCF, 0xA4, 0xAF, +0xA4, 0xAF, 0xA4, 0xAF, 0xAC, 0xD0, 0xAC, 0xF0, +0xAC, 0xF1, 0xAD, 0x11, 0xA4, 0xD0, 0x9C, 0x6F, +0x73, 0x4B, 0x9C, 0x6F, 0xC5, 0xD4, 0xCE, 0x15, +0x9C, 0x90, 0x83, 0xEE, 0x52, 0x89, 0x39, 0xE7, +0x42, 0x28, 0x52, 0x69, 0x42, 0x28, 0x42, 0x28, +0x52, 0x8A, 0x63, 0x0C, 0x7B, 0xCF, 0x94, 0x92, +0x9C, 0xF4, 0xA5, 0x35, 0xAD, 0x76, 0xAD, 0x55, +0xAD, 0x34, 0x7B, 0xAE, 0x9C, 0xB1, 0xDE, 0xB8, +0xD6, 0x77, 0xD6, 0x77, 0xCE, 0x15, 0xD6, 0x56, +0xD6, 0x55, 0xCE, 0x14, 0xCE, 0x15, 0xCE, 0x15, +0xBD, 0x93, 0xCE, 0x35, 0xCE, 0x15, 0xCE, 0x35, +0xB5, 0x72, 0xD6, 0x56, 0xCE, 0x36, 0xC5, 0xD4, +0xCE, 0x36, 0xCE, 0x37, 0xD6, 0xBB, 0xCE, 0x59, +0x9C, 0xD3, 0xB5, 0x52, 0xCD, 0xF4, 0xC5, 0xB3, +0xC5, 0xB3, 0xCD, 0xF4, 0xB5, 0x31, 0xCE, 0x15, +0xD6, 0x35, 0xCE, 0x14, 0xCD, 0xF4, 0xCD, 0xF4, +0xD6, 0x14, 0xD6, 0x14, 0xD6, 0x34, 0xDE, 0x55, +0xD5, 0xF3, 0xCD, 0xF3, 0xDE, 0x55, 0xB5, 0x12, +0x4A, 0x27, 0x42, 0x07, 0x4A, 0x28, 0x83, 0xCE, +0x83, 0xEF, 0x8B, 0xEF, 0xC5, 0x95, 0x94, 0x2F, +0x49, 0xE8, 0x41, 0xA7, 0x73, 0x4D, 0x73, 0x2C, +0x83, 0xCE, 0x9C, 0x91, 0xAC, 0xF3, 0x83, 0xCE, +0x7B, 0xAD, 0x6B, 0x2C, 0x73, 0x6D, 0x94, 0x70, +0xA4, 0xD1, 0xBD, 0x93, 0xBD, 0x93, 0xAD, 0x32, +0xB5, 0x32, 0xAD, 0x31, 0xB5, 0x52, 0xC5, 0xB3, +0xC5, 0xB3, 0xAC, 0xF1, 0xBD, 0x73, 0xAD, 0x12, +0xBD, 0x93, 0xC5, 0xB3, 0xCE, 0x14, 0xC5, 0x93, +0xC5, 0x93, 0xCD, 0xD4, 0xC5, 0xD4, 0x9C, 0x6F, +0x41, 0xC7, 0x21, 0x04, 0x18, 0xE4, 0x29, 0x25, +0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, +0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, 0x10, 0x83, +0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x08, 0x83, +0x10, 0x83, 0x08, 0x83, 0x19, 0x04, 0x21, 0x05, +0x18, 0xC4, 0x21, 0x05, 0x21, 0x05, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x21, 0x05, 0x18, 0xE4, +0x21, 0x25, 0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC4, +0x18, 0xC4, 0x10, 0xC4, 0x18, 0xC4, 0x18, 0xC4, +0x10, 0xA4, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA4, 0x18, 0xE4, +0x21, 0x25, 0x21, 0x05, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x21, 0x46, 0x29, 0x46, 0x29, 0x47, +0x21, 0x46, 0x29, 0x67, 0x29, 0x67, 0x29, 0x87, +0x29, 0x87, 0x29, 0x87, 0x29, 0x87, 0x39, 0xC8, +0x42, 0x2A, 0x4A, 0x4A, 0x52, 0xAA, 0xAD, 0x32, +0xBD, 0x93, 0xAC, 0xD0, 0xAC, 0xD0, 0xAC, 0xD0, +0xAC, 0xF0, 0xB4, 0xF0, 0xB5, 0x10, 0xB5, 0x10, +0xB5, 0x10, 0xB4, 0xF0, 0xB5, 0x31, 0xB5, 0x31, +0xAD, 0x31, 0xBD, 0x73, 0xDE, 0x56, 0xDE, 0x76, +0xDE, 0x76, 0xDE, 0x76, 0xD6, 0x35, 0xD6, 0x15, +0xCD, 0xF4, 0xDE, 0x76, 0xC5, 0x93, 0x9C, 0x6F, +0xBD, 0x93, 0xBD, 0xB4, 0xBD, 0x93, 0xC5, 0xD4, +0xB5, 0x73, 0xA4, 0xD1, 0xCE, 0x16, 0xCE, 0x16, +0x63, 0x2B, 0x29, 0x65, 0x10, 0xA3, 0x31, 0x65, +0x39, 0xE6, 0x29, 0x24, 0x39, 0x86, 0x52, 0x48, +0x49, 0xE7, 0x41, 0xE7, 0x52, 0x07, 0x83, 0x6D, +0xAD, 0xF4, 0x63, 0xEB, 0x43, 0x42, 0x4B, 0xA2, +0x3A, 0xC2, 0x4B, 0x06, 0x84, 0xAC, 0x7C, 0x6C, +0xAD, 0x91, 0x6B, 0x89, 0x3A, 0x44, 0x5B, 0x87, +0x4B, 0x05, 0x8C, 0xAE, 0xAD, 0xB2, 0x94, 0xEE, +0x9D, 0x0F, 0x9C, 0xCE, 0x9C, 0xCE, 0xCE, 0x54, +0xBD, 0xF3, 0xAD, 0x50, 0x94, 0x6D, 0x84, 0x0D, +0xB5, 0x73, 0xBD, 0xD5, 0xB5, 0xB4, 0xB5, 0x94, +0xCE, 0x56, 0xB5, 0x72, 0x94, 0x8F, 0xAD, 0x53, +0xCE, 0x57, 0xBD, 0xD5, 0xCE, 0x57, 0xCE, 0x57, +0xBD, 0xF5, 0xCE, 0x36, 0xD6, 0x98, 0xD6, 0x56, +0xDE, 0x96, 0xBD, 0x72, 0xAC, 0xEF, 0xC5, 0xB3, +0xCD, 0xF5, 0xCE, 0x15, 0xC5, 0xF4, 0xBD, 0x92, +0xAD, 0x11, 0x9C, 0xAF, 0x9C, 0xAF, 0x8C, 0x2E, +0xA4, 0xF0, 0xA4, 0xF1, 0xAD, 0x11, 0xA4, 0xF0, +0xA5, 0x11, 0xA4, 0xF0, 0x9C, 0x8F, 0xA4, 0xF0, +0xAD, 0x31, 0xC5, 0xD4, 0xC5, 0xF4, 0xB5, 0x51, +0xCD, 0xF3, 0xA4, 0x8E, 0xB5, 0x10, 0x8B, 0xEC, +0x9C, 0x4E, 0x94, 0x4D, 0x9C, 0x6E, 0xB5, 0x10, +0xA4, 0x8E, 0x9C, 0x4E, 0xA4, 0x8E, 0xA4, 0x8E, +0x8B, 0xCC, 0x8B, 0xEC, 0x8B, 0xEC, 0x8B, 0xEC, +0x8B, 0xEC, 0x94, 0x0C, 0x9C, 0x6E, 0xA4, 0x8E, +0xAC, 0xCF, 0xAC, 0xAF, 0xAC, 0xCF, 0xB5, 0x10, +0xB5, 0x30, 0xAC, 0xD0, 0xB5, 0x10, 0xBD, 0x51, +0xB5, 0x10, 0xA4, 0x8E, 0xA4, 0xAE, 0xA4, 0x8F, +0x94, 0x6E, 0x94, 0x4F, 0x5A, 0x89, 0x52, 0x89, +0x42, 0x07, 0x42, 0x07, 0x39, 0xA6, 0x4A, 0x28, +0x52, 0x8A, 0x5A, 0xEC, 0x73, 0x8E, 0x84, 0x10, +0x73, 0x8E, 0x8C, 0x51, 0x84, 0x30, 0x8C, 0x51, +0x94, 0x72, 0x5A, 0xAB, 0x73, 0x4C, 0xC5, 0xB5, +0xCD, 0xF6, 0x8C, 0x2F, 0x8C, 0x2E, 0xBD, 0xB4, +0xAD, 0x31, 0xB5, 0x72, 0xAD, 0x31, 0xC5, 0xF4, +0xB5, 0x52, 0xD6, 0x56, 0xCE, 0x35, 0xBD, 0x72, +0x9C, 0x8F, 0xAD, 0x31, 0xCE, 0x35, 0xCE, 0x15, +0xDE, 0x77, 0x9C, 0x91, 0x94, 0x72, 0x94, 0xB3, +0x9C, 0xD2, 0xB5, 0x52, 0xBD, 0x52, 0xAC, 0xF0, +0xC5, 0xB3, 0xCE, 0x14, 0xC5, 0xB3, 0xCD, 0xF4, +0xD6, 0x14, 0xD6, 0x14, 0xCD, 0xF4, 0xCD, 0xD3, +0xDE, 0x35, 0xDE, 0x55, 0xDE, 0x75, 0xDE, 0x75, +0xCD, 0xB2, 0xD6, 0x13, 0xDE, 0x34, 0xDE, 0x35, +0xC5, 0xD4, 0x94, 0x6F, 0x62, 0xEA, 0x4A, 0x28, +0x7B, 0x6D, 0x7B, 0x8E, 0xB5, 0x54, 0xA4, 0xB1, +0x6A, 0xCB, 0x39, 0x65, 0x62, 0xCB, 0x5A, 0x69, +0x83, 0xAE, 0x83, 0xAE, 0xCD, 0xF7, 0x9C, 0x91, +0x94, 0x50, 0x8C, 0x0F, 0x94, 0x70, 0xAC, 0xF1, +0xBD, 0x94, 0xBD, 0x73, 0xAC, 0xD0, 0xBD, 0x52, +0xBD, 0x52, 0xB5, 0x31, 0xA4, 0xAF, 0xBD, 0x72, +0xC5, 0xD4, 0xAD, 0x11, 0xC5, 0x94, 0xB5, 0x32, +0xBD, 0x73, 0xC5, 0x93, 0xCD, 0xD3, 0xC5, 0x92, +0xCD, 0xD4, 0xC5, 0x72, 0xCD, 0xD3, 0xA4, 0x6F, +0x49, 0xC7, 0x20, 0xE4, 0x21, 0x04, 0x21, 0x25, +0x21, 0x04, 0x18, 0xC4, 0x10, 0xA3, 0x18, 0xC4, +0x18, 0xC4, 0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, +0x10, 0x83, 0x08, 0x83, 0x10, 0x83, 0x10, 0x83, +0x10, 0x83, 0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, 0x08, 0x83, +0x08, 0x83, 0x10, 0xC3, 0x21, 0x05, 0x21, 0x05, +0x18, 0xC3, 0x21, 0x05, 0x21, 0x25, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x21, 0x05, 0x18, 0xE4, +0x21, 0x05, 0x10, 0xC4, 0x10, 0xC4, 0x18, 0xE4, +0x18, 0xC4, 0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC4, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0x83, 0x10, 0x83, 0x10, 0xA4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x18, 0xE4, 0x19, 0x05, +0x21, 0x05, 0x21, 0x26, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x21, 0x46, 0x29, 0x46, 0x29, 0x46, +0x29, 0x67, 0x29, 0x46, 0x29, 0x67, 0x29, 0x67, +0x29, 0x67, 0x29, 0x46, 0x29, 0x67, 0x29, 0x87, +0x3A, 0x09, 0x42, 0x29, 0x42, 0x09, 0x63, 0x2C, +0xB5, 0x53, 0xAC, 0xF1, 0xBD, 0x94, 0xA4, 0xD0, +0xA4, 0xD0, 0xA4, 0xD0, 0xAC, 0xD1, 0xAC, 0xF1, +0xAD, 0x11, 0xAD, 0x11, 0xB5, 0x12, 0xB5, 0x53, +0xB5, 0x32, 0xAD, 0x12, 0xAC, 0xF1, 0xAD, 0x11, +0xAC, 0xF1, 0xAC, 0xF1, 0xAC, 0xF1, 0xAD, 0x32, +0xAD, 0x31, 0xB5, 0x52, 0xAD, 0x11, 0xAC, 0xF1, +0xA4, 0xB0, 0x9C, 0x90, 0x9C, 0x90, 0x9C, 0x90, +0xA4, 0xD0, 0x9C, 0x90, 0x94, 0x90, 0x9C, 0x70, +0x94, 0x6F, 0x52, 0x89, 0x20, 0xC3, 0x21, 0x04, +0x31, 0x85, 0x31, 0x45, 0x39, 0x85, 0x42, 0x07, +0x41, 0xC6, 0x39, 0xA6, 0x52, 0x48, 0x7B, 0x4C, +0x9D, 0x52, 0xAD, 0xF4, 0x6C, 0x2C, 0x43, 0x03, +0x3A, 0xA2, 0x3A, 0xA4, 0x74, 0x4A, 0x53, 0x27, +0x8C, 0xAD, 0x84, 0x4C, 0x52, 0xE6, 0x53, 0x06, +0x7C, 0x2B, 0x9D, 0x30, 0x84, 0x2C, 0x84, 0x6C, +0xAD, 0x51, 0x9C, 0xAE, 0xA4, 0xEF, 0xD6, 0x76, +0xC6, 0x14, 0xA4, 0xF0, 0x9C, 0xCF, 0xA5, 0x11, +0xCE, 0x16, 0xC5, 0xF5, 0xBD, 0xB5, 0xBD, 0xD4, +0xCE, 0x36, 0xBD, 0xD4, 0x9C, 0xD0, 0xA4, 0xF1, +0xB5, 0x94, 0xC5, 0xF6, 0x9C, 0xD1, 0xD6, 0x98, +0xC6, 0x36, 0xD6, 0x77, 0xD6, 0x56, 0xBD, 0x93, +0xBD, 0xB3, 0xC5, 0xB3, 0xB5, 0x10, 0xD6, 0x76, +0xDE, 0x97, 0xDE, 0x97, 0xDE, 0xB7, 0xDE, 0x96, +0xD6, 0x76, 0xCE, 0x15, 0xAD, 0x32, 0x94, 0x6F, +0x9C, 0x90, 0x84, 0x0E, 0xA4, 0xF1, 0xB5, 0x73, +0x9C, 0xD0, 0xAD, 0x11, 0xBD, 0xB4, 0x9C, 0xB0, +0xA4, 0xF1, 0xCE, 0x15, 0xCE, 0x56, 0xBD, 0xB3, +0xC5, 0xD3, 0xA4, 0x8E, 0xB5, 0x10, 0x83, 0xAB, +0x8C, 0x4E, 0x9C, 0xB0, 0x94, 0x4E, 0xA4, 0xD0, +0xB5, 0x31, 0xB5, 0x52, 0xAD, 0x31, 0xA4, 0xD0, +0x7B, 0x8C, 0x7B, 0x8C, 0x6B, 0x4B, 0x73, 0x6C, +0x73, 0x4B, 0x9C, 0xB0, 0xBD, 0x94, 0xBD, 0x73, +0x9C, 0x6E, 0x94, 0x2E, 0xAD, 0x11, 0x9C, 0x8E, +0x8B, 0xEC, 0xB4, 0xEF, 0xB4, 0xEF, 0xAD, 0x10, +0xC5, 0x92, 0xB5, 0x10, 0xB5, 0x30, 0xCD, 0xF4, +0xC5, 0xD3, 0xB5, 0x52, 0x62, 0xA9, 0x52, 0x69, +0x42, 0x07, 0x42, 0x07, 0x42, 0x07, 0x4A, 0x48, +0x4A, 0x49, 0x52, 0xAA, 0x63, 0x0C, 0x6B, 0x4D, +0x7B, 0xF0, 0x94, 0x92, 0xA5, 0x14, 0xA5, 0x35, +0x8C, 0x51, 0x6B, 0x4D, 0x83, 0xEF, 0xA4, 0xD2, +0xB5, 0x34, 0x7B, 0x8E, 0x41, 0xC7, 0x94, 0x6F, +0xAC, 0xCF, 0xA4, 0xAE, 0xA4, 0x6E, 0xA4, 0x8E, +0x9C, 0x6E, 0xA4, 0x8E, 0xA4, 0x8E, 0xA4, 0x8E, +0x9C, 0x6E, 0xA4, 0x8F, 0xA4, 0xAF, 0xB5, 0x10, +0xBD, 0x52, 0xB5, 0x54, 0x9C, 0xB3, 0x83, 0xF0, +0xAD, 0x12, 0xBD, 0x72, 0xB4, 0xF0, 0xA4, 0xAF, +0xAC, 0xF0, 0xA4, 0x8E, 0xB5, 0x10, 0xB4, 0xD0, +0xAC, 0xCF, 0xA4, 0x8E, 0x94, 0x2D, 0xA4, 0x6E, +0xBD, 0x51, 0xCD, 0xB2, 0xCD, 0xF3, 0xCD, 0xD2, +0xB5, 0x0F, 0xBD, 0x50, 0xDE, 0x34, 0xCD, 0xB2, +0xBD, 0x71, 0xB5, 0x10, 0x8C, 0x0E, 0x5A, 0xAA, +0x83, 0xAE, 0x94, 0x30, 0x6A, 0xEB, 0x5A, 0x8A, +0x4A, 0x08, 0x52, 0x49, 0x39, 0x86, 0x6B, 0x0B, +0x5A, 0x69, 0x73, 0x6D, 0xCE, 0x17, 0x83, 0x8D, +0x8B, 0xEF, 0xBD, 0x95, 0xA4, 0xF1, 0xBD, 0x73, +0xD5, 0xF4, 0xC5, 0x92, 0xBD, 0x51, 0xCD, 0xD3, +0xC5, 0x72, 0xAD, 0x11, 0x7B, 0x8B, 0x7B, 0x8C, +0xC5, 0xB4, 0xAD, 0x11, 0xC5, 0xB4, 0xAD, 0x12, +0xB5, 0x52, 0xBD, 0x72, 0xC5, 0xB3, 0xBD, 0x92, +0xBD, 0x72, 0xBD, 0x31, 0xC5, 0x72, 0x9C, 0x6F, +0x62, 0xA9, 0x39, 0xA7, 0x29, 0x46, 0x21, 0x05, +0x21, 0x05, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xC3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x08, 0x83, 0x08, 0x83, 0x08, 0x83, 0x08, 0x83, +0x10, 0x83, 0x08, 0x83, 0x08, 0x83, 0x08, 0x83, +0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, 0x08, 0x83, +0x10, 0xA3, 0x10, 0xC3, 0x19, 0x05, 0x18, 0xE4, +0x18, 0xC4, 0x21, 0x25, 0x19, 0x05, 0x18, 0xE4, +0x19, 0x04, 0x18, 0xE4, 0x21, 0x05, 0x18, 0xE4, +0x19, 0x05, 0x10, 0xA3, 0x10, 0xC4, 0x10, 0xC4, +0x10, 0xC4, 0x10, 0xC3, 0x18, 0xC4, 0x10, 0xC4, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC3, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xE4, 0x18, 0xE4, 0x19, 0x05, +0x19, 0x05, 0x19, 0x05, 0x21, 0x05, 0x21, 0x26, +0x21, 0x26, 0x21, 0x46, 0x21, 0x46, 0x29, 0x46, +0x29, 0x67, 0x29, 0x46, 0x29, 0x67, 0x29, 0x67, +0x29, 0x67, 0x21, 0x26, 0x29, 0x46, 0x29, 0x87, +0x39, 0xC8, 0x42, 0x09, 0x3A, 0x09, 0x39, 0xE8, +0x8C, 0x30, 0xBD, 0xB4, 0xC5, 0xF5, 0x94, 0x70, +0x8C, 0x0E, 0x9C, 0xB0, 0x8C, 0x2E, 0xAD, 0x12, +0xA4, 0xD1, 0xC5, 0xF5, 0xBD, 0xD5, 0xBD, 0xB5, +0xB5, 0x54, 0xAD, 0x33, 0xA4, 0xF2, 0xAD, 0x12, +0xB5, 0x73, 0xAD, 0x12, 0x9C, 0xB0, 0x94, 0x70, +0x94, 0x70, 0x94, 0x4F, 0x8C, 0x0E, 0x83, 0xEE, +0x94, 0x2F, 0x94, 0x6F, 0x9C, 0x90, 0x9C, 0x90, +0x9C, 0x90, 0xA4, 0xF1, 0xA4, 0xD1, 0x9C, 0x6F, +0xA4, 0xF1, 0x73, 0x8C, 0x20, 0xE4, 0x18, 0xA3, +0x31, 0x65, 0x31, 0x65, 0x39, 0x85, 0x39, 0xA6, +0x4A, 0x07, 0x39, 0xA6, 0x4A, 0x07, 0x8B, 0xCE, +0x7C, 0x8D, 0x63, 0xCA, 0x84, 0xAE, 0x5B, 0x88, +0x43, 0x04, 0x53, 0x66, 0x8D, 0x0D, 0x6B, 0xE9, +0x52, 0xC6, 0x4A, 0x65, 0x4A, 0x85, 0x94, 0xEE, +0xAD, 0xB1, 0x8C, 0xAE, 0x73, 0xEB, 0xAD, 0x71, +0xB5, 0x92, 0x9C, 0xCE, 0xA4, 0xEF, 0xCE, 0x55, +0xCE, 0x14, 0xAD, 0x31, 0xA4, 0xF0, 0xBD, 0xB4, +0xC5, 0xF5, 0xB5, 0x94, 0xB5, 0x73, 0xC6, 0x15, +0xD6, 0xB7, 0xD6, 0x77, 0xC6, 0x15, 0xBD, 0xD4, +0xB5, 0x94, 0xAD, 0x53, 0x6B, 0x4C, 0x9C, 0xD1, +0xBD, 0xB4, 0xC5, 0xF5, 0xCE, 0x15, 0xD6, 0x76, +0xD6, 0x76, 0xBD, 0x72, 0xB5, 0x51, 0xD6, 0x56, +0xCE, 0x14, 0xCE, 0x14, 0xD6, 0x55, 0xCE, 0x14, +0xCE, 0x35, 0xD6, 0x76, 0xCE, 0x35, 0xBD, 0xB4, +0xBD, 0xB4, 0xAD, 0x53, 0xB5, 0x94, 0xCE, 0x36, +0xAD, 0x52, 0xAD, 0x11, 0x94, 0x6F, 0xA4, 0xD0, +0xB5, 0x72, 0xCE, 0x35, 0xCE, 0x35, 0xCE, 0x14, +0xCD, 0xF4, 0xAC, 0xEF, 0xB4, 0xEF, 0x8C, 0x0D, +0x9C, 0xB0, 0xAD, 0x12, 0x8C, 0x0D, 0x9C, 0x6F, +0xB5, 0x52, 0xC5, 0xD4, 0xC5, 0xD4, 0xB5, 0x93, +0x9C, 0xB1, 0x84, 0x0F, 0x6B, 0x6C, 0x5A, 0xEA, +0x6B, 0x6C, 0xB5, 0x94, 0x8C, 0x0E, 0xAC, 0xF1, +0x9C, 0x8F, 0xBD, 0xB3, 0xCE, 0x15, 0x9C, 0x8F, +0x83, 0xAB, 0xB5, 0x10, 0xB5, 0x0F, 0xC5, 0xB2, +0xCE, 0x15, 0xD6, 0x35, 0xB5, 0x51, 0xCE, 0x14, +0xC5, 0xD4, 0xBD, 0xB3, 0xBD, 0x73, 0x83, 0xCD, +0x4A, 0x68, 0x4A, 0x48, 0x42, 0x07, 0x4A, 0x48, +0x4A, 0x48, 0x4A, 0x69, 0x5A, 0xCA, 0x63, 0x2D, +0x7B, 0xCF, 0x84, 0x10, 0x94, 0x92, 0x8C, 0x71, +0x8C, 0x51, 0xAD, 0x55, 0x9C, 0xB2, 0x83, 0xCE, +0x9C, 0x91, 0x9C, 0x91, 0x42, 0x08, 0x7B, 0x8D, +0xB5, 0x52, 0x94, 0x2D, 0x8B, 0xEC, 0x83, 0xAB, +0x8B, 0xCC, 0x94, 0x2C, 0x93, 0xEC, 0x94, 0x0C, +0x9C, 0x4E, 0xA4, 0x8E, 0xAC, 0xAE, 0xBD, 0x30, +0xC5, 0x73, 0xC5, 0xF7, 0xA5, 0x14, 0x8C, 0x51, +0xAC, 0xF2, 0xB5, 0x10, 0xBD, 0x31, 0xBD, 0x31, +0xB5, 0x31, 0xBD, 0x31, 0xBD, 0x50, 0xBD, 0x51, +0xBD, 0x31, 0xBD, 0x50, 0xC5, 0x51, 0xBD, 0x30, +0xB5, 0x10, 0xB4, 0xEF, 0xB4, 0xCE, 0xAC, 0x8E, +0x9C, 0x2C, 0x9C, 0x4D, 0xB5, 0x0F, 0xBD, 0x10, +0xAC, 0xAE, 0xB5, 0x10, 0x9C, 0x6F, 0x5A, 0xA9, +0x7B, 0xAE, 0x8B, 0xEF, 0x41, 0xE7, 0x29, 0x45, +0x4A, 0x08, 0x5A, 0x69, 0x4A, 0x08, 0x83, 0xCF, +0x7B, 0x8D, 0x4A, 0x08, 0x9C, 0x91, 0x7B, 0x8D, +0x73, 0x2C, 0x9C, 0x90, 0xA4, 0xD0, 0xCD, 0xD4, +0xDE, 0x15, 0xD6, 0x14, 0xCD, 0x92, 0xC5, 0x92, +0xBD, 0x72, 0xBD, 0x72, 0x9C, 0x6F, 0xA4, 0xB1, +0xC5, 0xD4, 0x9C, 0x8F, 0xC5, 0xB4, 0xAC, 0xF1, +0xAD, 0x11, 0xAC, 0xF0, 0xAC, 0xF0, 0xB5, 0x11, +0xB5, 0x31, 0xB5, 0x10, 0xB5, 0x31, 0xAC, 0xAF, +0x9C, 0x4E, 0x6B, 0x0B, 0x31, 0x66, 0x21, 0x25, +0x21, 0x25, 0x18, 0xE4, 0x18, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0x83, 0x10, 0x83, 0x08, 0x83, 0x08, 0x83, +0x08, 0x83, 0x08, 0x83, 0x08, 0x83, 0x08, 0x83, +0x08, 0x83, 0x08, 0x83, 0x08, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, +0x10, 0xA3, 0x10, 0xA3, 0x19, 0x05, 0x18, 0xE4, +0x18, 0xC4, 0x21, 0x25, 0x18, 0xE4, 0x18, 0xE4, +0x10, 0xC3, 0x18, 0xE4, 0x18, 0xE4, 0x10, 0xC4, +0x18, 0xE4, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC3, +0x10, 0xA3, 0x10, 0xC3, 0x10, 0xC3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC4, 0x18, 0xE4, 0x10, 0xC4, +0x18, 0xE4, 0x19, 0x05, 0x19, 0x05, 0x18, 0xE4, +0x19, 0x05, 0x18, 0xE5, 0x21, 0x05, 0x21, 0x46, +0x21, 0x46, 0x29, 0x46, 0x21, 0x46, 0x21, 0x46, +0x29, 0x46, 0x29, 0x67, 0x29, 0x67, 0x29, 0x67, +0x29, 0x67, 0x29, 0x46, 0x29, 0x46, 0x29, 0x67, +0x31, 0xC8, 0x3A, 0x09, 0x39, 0xE9, 0x31, 0xC8, +0x39, 0xC8, 0x94, 0x71, 0xCE, 0x16, 0x94, 0x90, +0x94, 0x4F, 0xA4, 0xD1, 0xA4, 0xD0, 0xB5, 0x53, +0xAD, 0x53, 0xCE, 0x77, 0xC6, 0x37, 0xC5, 0xF6, +0xC6, 0x17, 0xBD, 0xF6, 0xAD, 0x53, 0x9C, 0xB1, +0xAD, 0x33, 0xA5, 0x12, 0x8C, 0x50, 0x8C, 0x50, +0x9C, 0x91, 0xA4, 0xD1, 0x9C, 0xB1, 0x94, 0x70, +0x9C, 0xD2, 0xA4, 0xD2, 0xA5, 0x12, 0xB5, 0x74, +0xAD, 0x53, 0xA4, 0xF1, 0xA4, 0xD1, 0x8C, 0x2E, +0xA4, 0xF1, 0xAD, 0x12, 0x29, 0x44, 0x21, 0x04, +0x18, 0xC3, 0x29, 0x44, 0x39, 0x85, 0x41, 0xE7, +0x52, 0x48, 0x5A, 0x69, 0x4A, 0x07, 0x8B, 0xCE, +0x63, 0xCA, 0x6C, 0x0A, 0x5B, 0x89, 0x4B, 0x26, +0x5B, 0xC7, 0x5B, 0xC8, 0x6B, 0xE8, 0x5B, 0x67, +0x73, 0xEA, 0x4A, 0xA6, 0x6B, 0x68, 0x84, 0x4B, +0x7C, 0x0A, 0x7C, 0x0B, 0x84, 0x6D, 0x8C, 0xAE, +0x8C, 0x6D, 0xAD, 0x72, 0xB5, 0xB3, 0xC6, 0x34, +0xCE, 0x55, 0xCE, 0x35, 0xB5, 0x72, 0xBD, 0xB3, +0xBD, 0xD4, 0xA5, 0x12, 0xB5, 0x73, 0xC6, 0x35, +0xDE, 0xB7, 0xD6, 0x97, 0xCE, 0x56, 0xCE, 0x36, +0xC5, 0xF5, 0xB5, 0x74, 0x9C, 0xB1, 0xAD, 0x74, +0xB5, 0x94, 0xC5, 0xF5, 0xC5, 0xF4, 0xCE, 0x55, +0xD6, 0x55, 0xB5, 0x10, 0xB5, 0x51, 0xC5, 0xD3, +0xCD, 0xF4, 0xA4, 0xAF, 0xB5, 0x72, 0xCE, 0x35, +0xD6, 0x76, 0xB5, 0x52, 0x83, 0xEE, 0x9C, 0xD1, +0xBD, 0xD5, 0xD6, 0x57, 0xAD, 0x53, 0xB5, 0x53, +0xCE, 0x36, 0xBD, 0xD4, 0xAD, 0x53, 0xB5, 0x93, +0xCE, 0x36, 0xD6, 0x76, 0xCE, 0x56, 0xCD, 0xF4, +0xC5, 0xB3, 0xB4, 0xEF, 0xB4, 0xEF, 0x8C, 0x0D, +0x94, 0x6F, 0xA4, 0xF1, 0x8C, 0x0D, 0x9C, 0x8F, +0xB5, 0x52, 0xC5, 0xD4, 0xBD, 0xB4, 0xBD, 0xB4, +0xA4, 0xF2, 0x8C, 0x2F, 0x83, 0xEF, 0x73, 0xCD, +0x84, 0x2F, 0xBD, 0xB5, 0x9C, 0x90, 0x73, 0x4B, +0x7B, 0x8C, 0xB5, 0x73, 0xBD, 0x94, 0x9C, 0x90, +0x94, 0x2D, 0xBD, 0x31, 0xB5, 0x10, 0xCD, 0xF4, +0xB5, 0x72, 0xCE, 0x14, 0xBD, 0x92, 0xBD, 0x93, +0xBD, 0x93, 0xB5, 0x73, 0xB5, 0x73, 0x94, 0x6F, +0x4A, 0x68, 0x4A, 0x69, 0x39, 0xC6, 0x31, 0xA5, +0x39, 0xE7, 0x4A, 0x48, 0x5A, 0xCB, 0x63, 0x2C, +0x6B, 0x4D, 0x73, 0x8E, 0x83, 0xF0, 0x8C, 0x51, +0xAD, 0x75, 0xAD, 0x75, 0x94, 0x71, 0xA4, 0xB2, +0x9C, 0x91, 0x9C, 0x91, 0x5A, 0x8A, 0x62, 0xEB, +0xB5, 0x73, 0xAD, 0x11, 0x9C, 0xAF, 0x94, 0x6F, +0x7B, 0xAC, 0x83, 0xCC, 0x9C, 0x8F, 0x94, 0x0D, +0x94, 0x2D, 0xA4, 0xCF, 0x9C, 0x6D, 0xB4, 0xF0, +0xBD, 0x93, 0xBD, 0xD6, 0xAD, 0x35, 0x94, 0x71, +0x8B, 0xEE, 0x8B, 0xEC, 0x83, 0xAB, 0x7B, 0x6B, +0x83, 0xAC, 0x94, 0x2D, 0xA4, 0x6E, 0xAC, 0xCF, +0xAC, 0xCF, 0xAC, 0xAE, 0xAC, 0xAE, 0xAC, 0xCF, +0xAC, 0xCF, 0xB4, 0xEF, 0xB5, 0x10, 0xB4, 0xEF, +0xB5, 0x0F, 0xC5, 0x71, 0xBD, 0x51, 0xB4, 0xEF, +0xBD, 0x31, 0xBD, 0x52, 0x6B, 0x0A, 0x62, 0xEA, +0x4A, 0x28, 0x41, 0xE7, 0x29, 0x44, 0x31, 0x86, +0x41, 0xC7, 0x4A, 0x08, 0x52, 0x49, 0x5A, 0x89, +0x94, 0x30, 0x62, 0xCB, 0x5A, 0x69, 0x7B, 0x8E, +0x7B, 0x8E, 0x83, 0x8E, 0xB5, 0x13, 0xCE, 0x16, +0xAD, 0x12, 0x9C, 0x90, 0x9C, 0x6F, 0x94, 0x2E, +0xA4, 0xAF, 0xAD, 0x11, 0xBD, 0x53, 0xB5, 0x32, +0xAC, 0xF0, 0x94, 0x2E, 0xBD, 0x74, 0xA4, 0xB0, +0x9C, 0x6F, 0x9C, 0x4E, 0x9C, 0x4E, 0x9C, 0x6E, +0xA4, 0xAF, 0xAC, 0xD0, 0xAC, 0xD0, 0xA4, 0xB0, +0xAC, 0xF1, 0x94, 0x0E, 0x5A, 0x69, 0x31, 0x66, +0x21, 0x25, 0x21, 0x25, 0x18, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0x83, 0x08, 0x83, 0x08, 0x83, 0x10, 0x83, +0x10, 0x83, 0x10, 0x83, 0x10, 0x83, 0x08, 0x83, +0x08, 0x83, 0x08, 0x82, 0x08, 0x83, 0x08, 0x83, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x19, 0x04, 0x18, 0xC4, +0x18, 0xE4, 0x21, 0x25, 0x18, 0xE4, 0x18, 0xC4, +0x10, 0xC3, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC4, +0x18, 0xE4, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xC3, 0x10, 0xC3, 0x10, 0xA3, +0x10, 0x83, 0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xE4, 0x18, 0xE4, 0x19, 0x05, +0x19, 0x05, 0x21, 0x05, 0x21, 0x05, 0x19, 0x05, +0x18, 0xE5, 0x18, 0xE5, 0x21, 0x26, 0x21, 0x46, +0x21, 0x46, 0x29, 0x46, 0x21, 0x46, 0x21, 0x46, +0x29, 0x46, 0x29, 0x46, 0x21, 0x46, 0x29, 0x46, +0x21, 0x46, 0x21, 0x46, 0x29, 0x46, 0x29, 0x46, +0x29, 0x87, 0x39, 0xE9, 0x39, 0xE9, 0x39, 0xE9, +0x31, 0x87, 0x39, 0xE8, 0x8C, 0x50, 0x9C, 0xF1, +0x94, 0x6F, 0x9C, 0x90, 0x9C, 0xB0, 0xB5, 0x53, +0xB5, 0x53, 0xCE, 0x57, 0xC6, 0x37, 0xBD, 0xB5, +0xB5, 0xB5, 0xBD, 0xB5, 0xA5, 0x12, 0x84, 0x2F, +0x8C, 0x91, 0x8C, 0x50, 0x7B, 0xEE, 0x8C, 0x50, +0x94, 0x91, 0x9C, 0xF2, 0xA5, 0x13, 0xA5, 0x33, +0xBD, 0xB5, 0xA5, 0x12, 0x9C, 0x91, 0xA4, 0xF2, +0x9C, 0xB0, 0x94, 0x90, 0xA4, 0xF1, 0xA4, 0xF1, +0xC5, 0xB4, 0xD6, 0x56, 0x52, 0x89, 0x18, 0xE4, +0x10, 0x82, 0x29, 0x44, 0x39, 0x85, 0x39, 0xA6, +0x52, 0x48, 0x6A, 0xEA, 0x5A, 0x89, 0x7B, 0x8D, +0x95, 0x70, 0x9D, 0x91, 0x74, 0x6D, 0x5B, 0xC9, +0x6C, 0x49, 0x53, 0x66, 0x53, 0x46, 0x6C, 0x08, +0x6B, 0xE9, 0x5B, 0x27, 0x8C, 0x6C, 0x8C, 0x4C, +0x84, 0x0B, 0x73, 0xCB, 0x74, 0x0B, 0x6B, 0xEB, +0x7C, 0x4D, 0xBE, 0x34, 0xA5, 0x10, 0xA5, 0x10, +0xB5, 0x71, 0xBD, 0xB3, 0xB5, 0x52, 0xB5, 0x52, +0xBD, 0xD4, 0x9C, 0xD0, 0xAD, 0x32, 0xBD, 0xD4, +0xCE, 0x35, 0xBD, 0xB3, 0xAD, 0x31, 0xCE, 0x36, +0xC5, 0xD5, 0xAD, 0x33, 0x8C, 0x2F, 0xB5, 0xB5, +0xB5, 0x94, 0xCE, 0x36, 0xCE, 0x56, 0xCE, 0x55, +0xD6, 0x55, 0xAD, 0x10, 0xBD, 0x92, 0xBD, 0x92, +0xD6, 0x35, 0x94, 0x6F, 0x39, 0xA5, 0x73, 0x4B, +0xB5, 0x73, 0xD6, 0x57, 0xBD, 0xB5, 0x5A, 0xCA, +0x4A, 0x68, 0x73, 0xAD, 0x83, 0xEE, 0x9C, 0xB1, +0xB5, 0x95, 0xCE, 0x57, 0xD6, 0x78, 0xCE, 0x57, +0xCE, 0x36, 0xD6, 0x97, 0xDE, 0x97, 0xD6, 0x76, +0xCE, 0x14, 0xB4, 0xEF, 0xB5, 0x10, 0xA4, 0xB0, +0xAD, 0x32, 0xAD, 0x52, 0xA4, 0xF0, 0xA4, 0xF1, +0xBD, 0xB4, 0xBD, 0xB4, 0xBD, 0x94, 0xB5, 0x93, +0xAD, 0x32, 0x94, 0xD1, 0xA4, 0xF2, 0xA5, 0x13, +0x7B, 0xEE, 0xB5, 0x95, 0xB5, 0x53, 0x6B, 0x2A, +0x83, 0xCD, 0xBD, 0xB4, 0xCD, 0xF5, 0x9C, 0x8F, +0x94, 0x4E, 0xBD, 0x31, 0xBD, 0x30, 0xCE, 0x35, +0xBD, 0xB3, 0xC5, 0xF4, 0xC5, 0xF4, 0xBD, 0xB3, +0xC5, 0xD3, 0xBD, 0xB4, 0xB5, 0x52, 0xA4, 0xF1, +0x41, 0xE7, 0x62, 0xEB, 0x4A, 0x48, 0x29, 0x44, +0x39, 0xA6, 0x42, 0x28, 0x4A, 0x49, 0x52, 0x8A, +0x6B, 0x4D, 0x73, 0x6E, 0x84, 0x10, 0x94, 0x92, +0xA5, 0x14, 0xA5, 0x14, 0xAD, 0x55, 0xC5, 0xD7, +0x9C, 0x92, 0x6B, 0x2C, 0x62, 0xEB, 0x73, 0x8D, +0x94, 0x6F, 0x9C, 0xD0, 0xAD, 0x52, 0xB5, 0x73, +0xA5, 0x11, 0xA4, 0xF1, 0x8C, 0x0D, 0x73, 0x4A, +0x84, 0x0D, 0xB5, 0x31, 0xAC, 0xF0, 0xAC, 0xCF, +0xC5, 0xB4, 0xBD, 0xD6, 0xA5, 0x35, 0x84, 0x10, +0x6A, 0xEA, 0x8C, 0x0D, 0x83, 0x8B, 0x7B, 0x6C, +0x5A, 0x89, 0x5A, 0x89, 0x4A, 0x07, 0x41, 0xE6, +0x52, 0x47, 0x62, 0xC9, 0x5A, 0xA8, 0x62, 0xC9, +0x62, 0xC9, 0x62, 0xA8, 0x6A, 0xE9, 0x94, 0x2D, +0xB5, 0x10, 0x8B, 0xEC, 0x73, 0x29, 0x8B, 0xEC, +0xB5, 0x32, 0x9C, 0x4F, 0x62, 0xCA, 0x62, 0xCA, +0x31, 0x85, 0x21, 0x04, 0x29, 0x45, 0x31, 0x85, +0x31, 0x65, 0x39, 0xA6, 0x6B, 0x2C, 0x4A, 0x08, +0x41, 0xA7, 0x73, 0x4D, 0x83, 0xCE, 0x62, 0xEB, +0xC6, 0x18, 0xDE, 0x9A, 0xBD, 0x95, 0xC5, 0xD6, +0xD6, 0x37, 0xB5, 0x33, 0xBD, 0x94, 0xBD, 0x94, +0xC5, 0xD4, 0xB5, 0x32, 0xB5, 0x52, 0xBD, 0x53, +0xB5, 0x32, 0xB5, 0x53, 0xC5, 0xD5, 0xC5, 0xD5, +0xC5, 0xD4, 0xC5, 0xD4, 0xC5, 0xD5, 0xC5, 0xB4, +0xC5, 0xB4, 0xCD, 0xD4, 0xCD, 0xB4, 0xC5, 0x94, +0xCD, 0xD4, 0xAC, 0xF1, 0x8B, 0xCE, 0x52, 0x28, +0x29, 0x25, 0x21, 0x25, 0x18, 0xE4, 0x19, 0x04, +0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, 0x10, 0x83, +0x10, 0x83, 0x10, 0x83, 0x08, 0x83, 0x08, 0x83, +0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, 0x10, 0x83, +0x10, 0x83, 0x10, 0xC4, 0x18, 0xE4, 0x10, 0xA3, +0x18, 0xE4, 0x19, 0x05, 0x18, 0xE4, 0x18, 0xE4, +0x10, 0xC4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xC4, 0x10, 0xC3, 0x10, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xC3, 0x10, 0xC4, 0x10, 0xA3, +0x10, 0x83, 0x08, 0x83, 0x08, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC4, 0x18, 0xE4, 0x19, 0x05, +0x19, 0x05, 0x19, 0x05, 0x21, 0x05, 0x19, 0x05, +0x19, 0x05, 0x19, 0x05, 0x21, 0x46, 0x21, 0x26, +0x21, 0x46, 0x21, 0x46, 0x21, 0x46, 0x21, 0x46, +0x29, 0x46, 0x21, 0x46, 0x21, 0x26, 0x21, 0x46, +0x21, 0x46, 0x21, 0x46, 0x21, 0x46, 0x29, 0x46, +0x29, 0x67, 0x31, 0xA8, 0x39, 0xE9, 0x39, 0xE9, +0x39, 0xC8, 0x29, 0x87, 0x42, 0x28, 0x83, 0xEF, +0x94, 0x4F, 0x9C, 0xB0, 0x8C, 0x2F, 0xB5, 0x53, +0xB5, 0x53, 0xD6, 0x98, 0xCE, 0x57, 0xBD, 0xB5, +0xAD, 0x74, 0xB5, 0x74, 0x9C, 0xF2, 0x84, 0x30, +0x8C, 0x91, 0x84, 0x2F, 0x7B, 0xEE, 0x7B, 0xEF, +0x94, 0x71, 0xA5, 0x13, 0xA4, 0xF2, 0x94, 0x90, +0xB5, 0x94, 0xA5, 0x13, 0x8C, 0x50, 0xA5, 0x33, +0x94, 0xB0, 0x94, 0x90, 0xA4, 0xD1, 0xAD, 0x12, +0xC5, 0xB4, 0xD6, 0x55, 0x9C, 0x90, 0x18, 0xE4, +0x10, 0xA3, 0x18, 0xE3, 0x39, 0xC6, 0x39, 0xA5, +0x4A, 0x27, 0x62, 0xEA, 0x6B, 0x0B, 0x7B, 0x6C, +0x63, 0xEB, 0x8D, 0x10, 0x74, 0x4D, 0x74, 0x4C, +0x64, 0x29, 0x5B, 0xC8, 0x43, 0x04, 0x64, 0x07, +0x53, 0x26, 0x52, 0xE6, 0x6B, 0x89, 0x94, 0xAE, +0x84, 0x2C, 0x74, 0x0B, 0x74, 0x4A, 0x6C, 0x09, +0x84, 0x6D, 0x94, 0x6D, 0xA4, 0xAF, 0xA4, 0xAE, +0x9C, 0x6D, 0xA4, 0xAF, 0xAC, 0xF0, 0xB5, 0x31, +0xAC, 0xF0, 0xAC, 0xF0, 0xB5, 0x11, 0xAC, 0xF0, +0xAC, 0xCF, 0xB5, 0x10, 0xB5, 0x10, 0xB5, 0x31, +0xB5, 0x11, 0xAC, 0xF1, 0xA4, 0xB0, 0x94, 0x6F, +0x9C, 0x8F, 0xA4, 0xD0, 0xB5, 0x31, 0xC5, 0xB3, +0xBD, 0x92, 0xBD, 0x51, 0xBD, 0x31, 0x9C, 0x6D, +0xAC, 0xF0, 0xA4, 0x8F, 0x73, 0x2A, 0x39, 0xC6, +0x52, 0xA9, 0x5A, 0xC9, 0x6B, 0x6C, 0x73, 0x6D, +0x31, 0x65, 0x42, 0x49, 0x52, 0x8A, 0x42, 0x29, +0x42, 0x4A, 0x5A, 0xEC, 0x7B, 0xF0, 0xA5, 0x34, +0xC6, 0x37, 0xD6, 0x97, 0xDE, 0x97, 0xD6, 0x76, +0xC5, 0xB3, 0xB5, 0x10, 0xB5, 0x10, 0xB5, 0x52, +0xB5, 0x93, 0xBD, 0xB4, 0xBD, 0x94, 0xAD, 0x11, +0xC5, 0xD5, 0xC5, 0xF5, 0xC5, 0xD4, 0xC5, 0xD4, +0xB5, 0x73, 0xA5, 0x33, 0xA5, 0x33, 0xAD, 0x54, +0x7B, 0xAE, 0x84, 0x0E, 0x8C, 0x2E, 0x5A, 0xC9, +0x8C, 0x0E, 0xA4, 0xD0, 0xAD, 0x32, 0x8C, 0x2E, +0x9C, 0x6E, 0xBD, 0x51, 0xB5, 0x10, 0xC5, 0xF4, +0xC5, 0xD3, 0xC5, 0xF4, 0xC5, 0xF4, 0xC5, 0xD4, +0xC5, 0xD4, 0xC5, 0xD4, 0xBD, 0x93, 0xBD, 0x93, +0x73, 0x6C, 0x42, 0x07, 0x5A, 0xEA, 0x31, 0xA6, +0x39, 0xA6, 0x42, 0x07, 0x42, 0x28, 0x52, 0x8A, +0x63, 0x0C, 0x6B, 0x4D, 0x73, 0x8E, 0x84, 0x10, +0x9C, 0xD3, 0xA5, 0x15, 0xB5, 0x96, 0xCE, 0x38, +0xBD, 0x96, 0x94, 0x51, 0x73, 0x6D, 0xA5, 0x13, +0xAD, 0x53, 0x9C, 0xD1, 0xB5, 0x73, 0xC5, 0xF5, +0xCE, 0x36, 0xB5, 0x93, 0x8C, 0x2E, 0x9C, 0xD1, +0xAD, 0x32, 0xAD, 0x11, 0xB5, 0x31, 0xAC, 0xD0, +0xD6, 0x57, 0x9C, 0xD3, 0x7B, 0xCF, 0x94, 0x71, +0x83, 0xED, 0x8B, 0xED, 0x8B, 0xED, 0xB5, 0x52, +0x83, 0xCD, 0x94, 0x4F, 0x6B, 0x4C, 0x52, 0x8A, +0x52, 0x89, 0x52, 0x89, 0x84, 0x0F, 0xA4, 0xD1, +0xA4, 0xD1, 0x94, 0x4F, 0x5A, 0x89, 0x94, 0x4F, +0xA4, 0x8F, 0x94, 0x4E, 0x83, 0xCD, 0x94, 0x4F, +0xBD, 0x73, 0x94, 0x2F, 0x41, 0xE7, 0x62, 0xCA, +0x4A, 0x07, 0x20, 0xE3, 0x21, 0x24, 0x29, 0x44, +0x29, 0x44, 0x29, 0x45, 0x5A, 0x89, 0x52, 0x69, +0x41, 0xC7, 0x5A, 0xAA, 0x39, 0xA6, 0x39, 0xA7, +0x6B, 0x2D, 0xAD, 0x14, 0xCD, 0xF7, 0xAD, 0x13, +0xC5, 0xD6, 0x83, 0xCD, 0x94, 0x4F, 0x94, 0x6F, +0xBD, 0x73, 0xB5, 0x52, 0xB5, 0x53, 0xBD, 0xB4, +0xBD, 0x94, 0xA4, 0xD0, 0xA4, 0xF1, 0xA4, 0xB0, +0x8C, 0x0D, 0xAD, 0x32, 0xA4, 0xD1, 0xA4, 0xD0, +0xAC, 0xF1, 0xA4, 0xB0, 0xA4, 0xD1, 0xA4, 0xB0, +0xC5, 0xD4, 0xC5, 0xB4, 0x9C, 0x6F, 0x73, 0x2B, +0x41, 0xE7, 0x29, 0x45, 0x21, 0x04, 0x21, 0x25, +0x18, 0xC4, 0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xC4, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0x83, 0x08, 0x83, +0x08, 0x83, 0x08, 0x83, 0x08, 0x83, 0x08, 0x83, +0x10, 0xA3, 0x10, 0xC3, 0x10, 0xA3, 0x10, 0xC4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC4, +0x10, 0xC3, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x10, 0xC4, 0x10, 0xC3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC4, 0x10, 0xC4, +0x10, 0xA3, 0x08, 0x83, 0x08, 0x83, 0x10, 0xA3, +0x10, 0xC3, 0x10, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x19, 0x05, 0x18, 0xE5, 0x21, 0x05, 0x21, 0x05, +0x19, 0x05, 0x21, 0x26, 0x29, 0x46, 0x21, 0x26, +0x21, 0x46, 0x21, 0x46, 0x21, 0x26, 0x21, 0x46, +0x21, 0x46, 0x21, 0x46, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x21, 0x46, 0x29, 0x46, 0x29, 0x46, +0x29, 0x46, 0x29, 0x87, 0x39, 0xE9, 0x39, 0xC8, +0x39, 0xC8, 0x29, 0x87, 0x29, 0x67, 0x52, 0x6A, +0xA4, 0xF2, 0xBD, 0xB4, 0x8C, 0x0E, 0xB5, 0x53, +0xAD, 0x53, 0xCE, 0x57, 0xC6, 0x37, 0xC6, 0x37, +0xC6, 0x16, 0xC5, 0xF6, 0xAD, 0x54, 0x94, 0xB2, +0x94, 0xD2, 0x94, 0x91, 0x84, 0x30, 0x8C, 0x50, +0xA5, 0x13, 0xB5, 0x94, 0x8C, 0x4F, 0x7B, 0xCE, +0xAD, 0x54, 0x94, 0x91, 0x8C, 0x70, 0xB5, 0x94, +0x9C, 0xD1, 0x94, 0xB1, 0x9C, 0xB1, 0xA4, 0xF2, +0xCE, 0x15, 0xD6, 0x54, 0xD6, 0x56, 0x39, 0xA6, +0x18, 0xE3, 0x10, 0x82, 0x31, 0x65, 0x41, 0xE7, +0x4A, 0x28, 0x5A, 0xA9, 0x6A, 0xEB, 0x5A, 0x89, +0x7C, 0x6D, 0x74, 0x4D, 0x74, 0x4D, 0x63, 0xEA, +0x64, 0x0A, 0x5B, 0xA7, 0x4B, 0x44, 0x64, 0x07, +0x4B, 0x24, 0x84, 0xCC, 0x74, 0x4B, 0x53, 0x08, +0x84, 0xAD, 0x6C, 0x28, 0x74, 0x67, 0x95, 0x4D, +0x8C, 0x8D, 0x7B, 0xCC, 0x7B, 0x8B, 0x73, 0x2A, +0x83, 0xCC, 0x8C, 0x0D, 0xAD, 0x31, 0xCD, 0xD4, +0xA4, 0xAF, 0xA4, 0xAF, 0x9C, 0x4E, 0xB5, 0x31, +0xAC, 0xF0, 0xAC, 0xCF, 0x9C, 0x6E, 0x9C, 0x8E, +0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0xAF, 0xAC, 0xF0, +0xB5, 0x10, 0xAD, 0x10, 0xA4, 0xAF, 0xAC, 0xCF, +0xB5, 0x31, 0xBD, 0x31, 0xD5, 0xF4, 0xCD, 0xD2, +0xD5, 0xF3, 0xC5, 0x92, 0xCD, 0xB3, 0x7B, 0x8B, +0x5A, 0xCA, 0x63, 0x0B, 0x29, 0x65, 0x18, 0xC3, +0x19, 0x04, 0x18, 0xC3, 0x29, 0x45, 0x31, 0x86, +0x29, 0x66, 0x29, 0x87, 0x31, 0xA8, 0x31, 0xC9, +0x4A, 0x8B, 0x7B, 0xCF, 0x9C, 0xB1, 0x9C, 0xB0, +0xA4, 0x8E, 0xBD, 0x51, 0xB5, 0x30, 0xBD, 0x72, +0xBD, 0x93, 0xBD, 0x93, 0xB5, 0x73, 0xC5, 0xD4, +0xCE, 0x15, 0xBD, 0x93, 0xCE, 0x35, 0xCE, 0x15, +0xB5, 0x93, 0xAD, 0x74, 0x9C, 0xD2, 0x9C, 0xD2, +0x7B, 0xAE, 0x7B, 0xCD, 0x9C, 0xB0, 0x83, 0xED, +0xAD, 0x12, 0xB5, 0x73, 0xA4, 0xD0, 0x83, 0xED, +0x8B, 0xED, 0xBD, 0x71, 0xAC, 0xEF, 0xB5, 0x31, +0xB5, 0x72, 0xB5, 0x72, 0xC5, 0xF4, 0xC5, 0xF4, +0xD6, 0x55, 0xC5, 0xF5, 0xC5, 0xD4, 0xCE, 0x15, +0xAD, 0x12, 0x31, 0x65, 0x63, 0x0B, 0x42, 0x07, +0x29, 0x65, 0x4A, 0x48, 0x4A, 0x69, 0x4A, 0x69, +0x5A, 0xAA, 0x63, 0x0B, 0x73, 0x6E, 0x8C, 0x31, +0x94, 0xB3, 0x9C, 0xD4, 0xB5, 0x96, 0xBD, 0xD7, +0xAD, 0x34, 0xAD, 0x14, 0xAD, 0x34, 0xAD, 0x33, +0xB5, 0x94, 0xB5, 0x53, 0xAD, 0x52, 0xCE, 0x15, +0xCE, 0x56, 0xCE, 0x36, 0xB5, 0x73, 0xAD, 0x32, +0xAD, 0x11, 0xA4, 0xF1, 0xC5, 0xD4, 0xB5, 0x53, +0xD6, 0x58, 0x83, 0xEF, 0x63, 0x2D, 0x8C, 0x51, +0xAD, 0x11, 0xAC, 0xF1, 0x94, 0x0D, 0xC5, 0xD4, +0x9C, 0x6F, 0x9C, 0x90, 0x7B, 0x8D, 0x73, 0x6D, +0x6B, 0x4C, 0x5A, 0xAA, 0x84, 0x0E, 0xA4, 0xF1, +0xAD, 0x12, 0xB5, 0x52, 0x7B, 0x8C, 0xA4, 0xB0, +0xC5, 0x93, 0xD6, 0x15, 0xA4, 0xD0, 0xAC, 0xF1, +0xBD, 0x73, 0x9C, 0xB0, 0x83, 0xEE, 0x5A, 0x69, +0x62, 0xAA, 0x4A, 0x69, 0x6B, 0x4C, 0x5A, 0xCB, +0x31, 0x85, 0x31, 0x85, 0x31, 0x85, 0x39, 0xC6, +0x4A, 0x49, 0x39, 0xA6, 0x29, 0x44, 0x29, 0x44, +0x42, 0x08, 0x52, 0x49, 0x6B, 0x0C, 0x6B, 0x0C, +0x94, 0x50, 0xB5, 0x53, 0x9C, 0x70, 0x94, 0x6F, +0xBD, 0x94, 0xB5, 0x32, 0xBD, 0x73, 0xC5, 0xF5, +0xCE, 0x36, 0xA4, 0xF1, 0x9C, 0xB0, 0x8C, 0x0D, +0x8C, 0x2E, 0xA4, 0xD0, 0xAD, 0x11, 0xC5, 0xD5, +0xCD, 0xF5, 0xAC, 0xF1, 0x9C, 0x90, 0x8C, 0x0D, +0xAD, 0x11, 0xC5, 0xB3, 0xC5, 0x93, 0xAC, 0xF1, +0x9C, 0x91, 0x73, 0x4C, 0x52, 0x49, 0x6B, 0x2C, +0x31, 0xA6, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, +0x18, 0xC4, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xC3, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, 0x08, 0x83, +0x08, 0x83, 0x08, 0x83, 0x08, 0x83, 0x10, 0x83, +0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC4, +0x10, 0xA3, 0x18, 0xE4, 0x19, 0x04, 0x18, 0xE4, +0x19, 0x04, 0x10, 0xC4, 0x10, 0xC4, 0x10, 0xA3, +0x10, 0xC3, 0x10, 0xA3, 0x18, 0xE4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xC3, 0x10, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x19, 0x05, 0x21, 0x05, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x21, 0x26, 0x21, 0x46, 0x21, 0x26, +0x21, 0x26, 0x29, 0x46, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x21, 0x26, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x21, 0x26, 0x29, 0x46, 0x29, 0x67, +0x21, 0x46, 0x29, 0x67, 0x31, 0xC8, 0x31, 0xC8, +0x31, 0xA8, 0x31, 0xA8, 0x31, 0x87, 0x31, 0x87, +0x6B, 0x4C, 0xBD, 0xB4, 0x94, 0x4E, 0xB5, 0x53, +0xB5, 0x94, 0xD6, 0x98, 0xD6, 0x98, 0xCE, 0x78, +0xCE, 0x57, 0xC6, 0x36, 0xBD, 0xB5, 0xA5, 0x33, +0xAD, 0x74, 0xA5, 0x34, 0xA5, 0x34, 0xB5, 0x95, +0xC6, 0x16, 0xAD, 0x74, 0x73, 0xAD, 0x9C, 0xF2, +0xAD, 0x74, 0xA5, 0x13, 0x9C, 0xD2, 0xBD, 0xB5, +0xAD, 0x53, 0x9C, 0xB1, 0x9C, 0xB1, 0xA4, 0xF2, +0xD6, 0x56, 0xDE, 0x75, 0xDE, 0x96, 0x52, 0x89, +0x18, 0xE4, 0x10, 0xA3, 0x18, 0xA3, 0x41, 0xE7, +0x4A, 0x07, 0x4A, 0x27, 0x62, 0xEA, 0x52, 0x48, +0xBE, 0x75, 0x6C, 0x0B, 0x5B, 0xAA, 0x7C, 0xCE, +0x6C, 0x0A, 0x53, 0x86, 0x4B, 0x64, 0x53, 0x85, +0x63, 0xE7, 0x85, 0x0C, 0x6C, 0x49, 0x5B, 0xA7, +0x5B, 0xA6, 0x64, 0x05, 0x7C, 0xC8, 0x9D, 0x8E, +0x8C, 0xAF, 0x63, 0x09, 0x9C, 0xD1, 0x9C, 0xD1, +0x8C, 0x4F, 0x8C, 0x2E, 0x9C, 0xD1, 0xA4, 0xF1, +0xA4, 0xD1, 0xA4, 0xF1, 0x9C, 0xAF, 0xB5, 0x10, +0xAC, 0xF0, 0xB5, 0x52, 0xA4, 0xB0, 0xA4, 0xD1, +0xAD, 0x33, 0xA4, 0xF2, 0xA4, 0xD1, 0xA4, 0xF0, +0x94, 0x6E, 0x8C, 0x4E, 0x8C, 0x2E, 0x8C, 0x0D, +0x83, 0x8B, 0x7B, 0x8B, 0xA4, 0xAF, 0x9C, 0x4D, +0xAC, 0xF0, 0xAC, 0xF0, 0xA4, 0x8F, 0x94, 0x2D, +0x6B, 0x0A, 0x5A, 0xCA, 0x5A, 0xCA, 0x31, 0x86, +0x21, 0x04, 0x21, 0x25, 0x19, 0x04, 0x10, 0xA3, +0x10, 0xC3, 0x21, 0x25, 0x21, 0x25, 0x21, 0x47, +0x29, 0xA8, 0x31, 0xC9, 0x42, 0x2A, 0x6B, 0x6E, +0x94, 0x70, 0xAC, 0xF1, 0xBD, 0x72, 0xC5, 0x92, +0xBD, 0x51, 0xBD, 0x31, 0xB5, 0x30, 0xB5, 0x10, +0xB5, 0x10, 0xAC, 0xCF, 0x9C, 0x6E, 0x94, 0x2D, +0x83, 0xCB, 0x8C, 0x2E, 0x94, 0x4E, 0x94, 0x2E, +0x8B, 0xEC, 0x9C, 0x6F, 0xA4, 0xD0, 0x8B, 0xED, +0xA4, 0xB0, 0xB5, 0x31, 0xB5, 0x32, 0xB5, 0x31, +0xAC, 0xF0, 0xAC, 0xCE, 0x83, 0xAA, 0x7B, 0x6A, +0x94, 0x4D, 0xA4, 0xCF, 0xB5, 0x72, 0xCE, 0x14, +0xD6, 0x35, 0xCE, 0x35, 0xCD, 0xF4, 0xBD, 0x72, +0xC5, 0xD4, 0x52, 0x68, 0x42, 0x28, 0x5A, 0xEB, +0x39, 0xC6, 0x31, 0xA6, 0x42, 0x28, 0x39, 0xC6, +0x4A, 0x69, 0x62, 0xEB, 0x6B, 0x6D, 0x7B, 0xAF, +0x8C, 0x72, 0x94, 0x93, 0xA5, 0x35, 0xB5, 0x96, +0xB5, 0x75, 0xAD, 0x14, 0xCE, 0x38, 0xAD, 0x13, +0xBD, 0xB5, 0xBD, 0xB4, 0xC5, 0xF5, 0xD6, 0x97, +0xD6, 0x56, 0xCE, 0x56, 0xBD, 0xB4, 0xB5, 0x73, +0xB5, 0x72, 0xAD, 0x52, 0xBD, 0xB3, 0xB5, 0x32, +0xBD, 0x95, 0x94, 0x92, 0x7B, 0xEF, 0x9C, 0xB1, +0xBD, 0x73, 0xAC, 0xD0, 0x8B, 0xCC, 0xC5, 0xB4, +0xA4, 0xD0, 0xB5, 0x53, 0x8C, 0x2F, 0x8C, 0x2F, +0x73, 0x8D, 0x6B, 0x4C, 0x94, 0x90, 0xBD, 0xB4, +0xCD, 0xF5, 0xC5, 0xD4, 0x83, 0xCD, 0xA5, 0x11, +0xB5, 0x31, 0xCD, 0xF4, 0x9C, 0x8F, 0xA4, 0xD0, +0xC5, 0xB4, 0xA4, 0xB0, 0xA4, 0xD1, 0x6B, 0x2B, +0x39, 0xA6, 0x39, 0xC6, 0x41, 0xE7, 0xA5, 0x13, +0x7B, 0xCD, 0x39, 0xA6, 0x29, 0x65, 0x39, 0xC7, +0x39, 0xC6, 0x31, 0xA6, 0x31, 0x85, 0x29, 0x44, +0x29, 0x64, 0x42, 0x07, 0x83, 0xEF, 0x9C, 0x92, +0x7B, 0x6D, 0xA4, 0xD2, 0xCE, 0x16, 0xA4, 0xD1, +0xBD, 0x73, 0xC5, 0xD4, 0xCE, 0x15, 0xCE, 0x36, +0xC5, 0xD4, 0xB5, 0x53, 0x94, 0x6F, 0x8C, 0x2E, +0x9C, 0x90, 0xC5, 0xB4, 0xB5, 0x73, 0xC5, 0xF5, +0xBD, 0x93, 0xA4, 0xB0, 0xAD, 0x32, 0x8C, 0x2E, +0xA4, 0xD1, 0xB5, 0x52, 0xC5, 0xD4, 0xBD, 0x73, +0xC5, 0xD4, 0xB5, 0x32, 0xAC, 0xD1, 0xBD, 0x73, +0x7B, 0x8C, 0x52, 0x69, 0x29, 0x25, 0x18, 0xE4, +0x10, 0xC3, 0x10, 0xA3, 0x10, 0xC3, 0x10, 0xC3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, +0x10, 0x83, 0x08, 0x83, 0x08, 0x83, 0x08, 0x83, +0x08, 0x83, 0x10, 0x83, 0x10, 0xA3, 0x10, 0xC4, +0x10, 0xC4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC4, +0x10, 0x83, 0x18, 0xE4, 0x19, 0x05, 0x18, 0xE4, +0x19, 0x04, 0x18, 0xC4, 0x10, 0xC3, 0x10, 0xA3, +0x10, 0xC3, 0x10, 0xA3, 0x10, 0xC4, 0x10, 0xC3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xC4, 0x18, 0xE4, 0x18, 0xE4, 0x21, 0x25, +0x21, 0x05, 0x21, 0x05, 0x19, 0x05, 0x19, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x26, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x21, 0x26, +0x21, 0x26, 0x21, 0x46, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x21, 0x26, 0x21, 0x46, 0x29, 0x46, +0x29, 0x46, 0x21, 0x46, 0x31, 0x87, 0x39, 0xE9, +0x31, 0xA8, 0x31, 0xA7, 0x39, 0xC8, 0x31, 0x87, +0x39, 0xA7, 0x7B, 0xAE, 0x9C, 0x90, 0xB5, 0x53, +0xB5, 0x73, 0xC6, 0x16, 0xAD, 0x53, 0xBD, 0xB5, +0xBD, 0xB4, 0xBD, 0xB4, 0xB5, 0x94, 0xB5, 0x94, +0xB5, 0x74, 0xA5, 0x13, 0xAD, 0x33, 0xA5, 0x13, +0xAD, 0x33, 0x9C, 0xD1, 0x84, 0x0E, 0xA4, 0xF2, +0xB5, 0x74, 0xAD, 0x53, 0xA5, 0x13, 0xBD, 0xB5, +0xCE, 0x37, 0xB5, 0x74, 0xA4, 0xF1, 0xAD, 0x12, +0xCE, 0x15, 0xE6, 0xB6, 0xD6, 0x35, 0x7B, 0xAD, +0x39, 0xC7, 0x18, 0xC3, 0x10, 0x82, 0x31, 0x66, +0x42, 0x07, 0x4A, 0x07, 0x6B, 0x2B, 0x4A, 0x27, +0x64, 0x29, 0x5B, 0xE8, 0x2A, 0x43, 0x42, 0xE8, +0x74, 0x6C, 0x63, 0xE8, 0x4B, 0x44, 0x4B, 0x64, +0x6C, 0x28, 0x6C, 0x29, 0x4B, 0x65, 0x64, 0x27, +0x6C, 0x68, 0x7C, 0xCB, 0x9D, 0xAF, 0xA5, 0x70, +0xA5, 0x11, 0x9C, 0xF1, 0xA5, 0x33, 0xB5, 0x94, +0x9C, 0xD1, 0x94, 0x90, 0x8C, 0x4F, 0x8C, 0x6F, +0x94, 0x90, 0x9C, 0xD1, 0x9C, 0xAF, 0xB5, 0x10, +0xB5, 0x10, 0xC5, 0xD4, 0xAD, 0x53, 0xB5, 0x94, +0xAD, 0x53, 0xA5, 0x12, 0xA5, 0x12, 0xA4, 0xF1, +0x9C, 0xD0, 0x9C, 0xB0, 0xA4, 0xF1, 0x9C, 0xB0, +0x9C, 0x90, 0x9C, 0xB0, 0xA4, 0xD1, 0xAD, 0x11, +0xC5, 0xD4, 0xCD, 0xF4, 0x94, 0x6F, 0x94, 0x6F, +0xA4, 0xF2, 0x62, 0xEB, 0x52, 0xAA, 0x52, 0xAA, +0x31, 0x86, 0x19, 0x04, 0x18, 0xE4, 0x10, 0xC3, +0x08, 0x82, 0x08, 0x82, 0x10, 0xE3, 0x19, 0x25, +0x21, 0x46, 0x21, 0x67, 0x31, 0xA9, 0x31, 0xC9, +0x39, 0xEA, 0x4A, 0x69, 0x5A, 0xA9, 0x73, 0x4B, +0x8B, 0xEC, 0x9C, 0x4E, 0xA4, 0xAF, 0x9C, 0x6D, +0xA4, 0x8E, 0xB4, 0xEF, 0xC5, 0x71, 0xBD, 0x51, +0xB5, 0x10, 0xB5, 0x31, 0xBD, 0x51, 0xB5, 0x10, +0xBD, 0x30, 0xBD, 0x51, 0xC5, 0x72, 0xBD, 0x30, +0xBD, 0x51, 0xC5, 0x72, 0xC5, 0x92, 0xC5, 0xB2, +0xCD, 0xB2, 0xC5, 0x92, 0xBD, 0x30, 0xB5, 0x31, +0xBD, 0x71, 0xBD, 0x51, 0xAC, 0xCF, 0xA4, 0xAF, +0x9C, 0x6E, 0x9C, 0x4D, 0x9C, 0x4D, 0x94, 0x2D, +0x94, 0x2E, 0x52, 0x68, 0x18, 0xE3, 0x52, 0x89, +0x5A, 0xCA, 0x39, 0xC6, 0x42, 0x07, 0x31, 0x86, +0x42, 0x08, 0x52, 0x8A, 0x63, 0x0C, 0x63, 0x0C, +0x73, 0x8E, 0x73, 0xAF, 0x94, 0xB3, 0xAD, 0x55, +0x8C, 0x71, 0xAD, 0x55, 0xD6, 0x58, 0xD6, 0x58, +0xBD, 0x94, 0xC5, 0xF5, 0xD6, 0x77, 0xD6, 0x56, +0xCE, 0x56, 0xBD, 0xD4, 0xBD, 0xB4, 0xB5, 0x73, +0xAD, 0x32, 0xBD, 0xB4, 0xAD, 0x11, 0xC5, 0xB5, +0xB5, 0x95, 0x9C, 0xF3, 0x84, 0x30, 0xBD, 0x94, +0xC5, 0x94, 0x8B, 0xCD, 0xAC, 0xF1, 0xC5, 0xB3, +0xB5, 0x52, 0xC5, 0xB4, 0x9C, 0x6F, 0xB5, 0x73, +0x94, 0x4F, 0x94, 0x2F, 0xBD, 0x94, 0xCE, 0x36, +0xCE, 0x15, 0xC5, 0xD4, 0x7B, 0x8C, 0xAD, 0x11, +0x83, 0xCC, 0xB5, 0x32, 0x9C, 0x8F, 0x9C, 0x8F, +0xC5, 0xB4, 0x94, 0x6F, 0xAD, 0x32, 0x9C, 0xB1, +0x31, 0x64, 0x21, 0x24, 0x52, 0x89, 0xB5, 0x53, +0xB5, 0x73, 0x7B, 0xCD, 0x31, 0x85, 0x31, 0x85, +0x31, 0x85, 0x39, 0xC6, 0x39, 0xC6, 0x31, 0x85, +0x39, 0xC6, 0x42, 0x07, 0x4A, 0x08, 0x7B, 0x8E, +0x62, 0xCA, 0x73, 0x6C, 0xBD, 0xB5, 0xBD, 0xB5, +0xC5, 0xB5, 0xCE, 0x16, 0xD6, 0x77, 0xCE, 0x35, +0xBD, 0xB4, 0xA4, 0xF1, 0xA4, 0xF1, 0x9C, 0x8F, +0x94, 0x4E, 0xA4, 0xD0, 0xBD, 0x93, 0xC5, 0xD4, +0xB5, 0x52, 0xAD, 0x52, 0xB5, 0x73, 0xAD, 0x12, +0xB5, 0x53, 0xC5, 0xF4, 0xC5, 0xF4, 0xD6, 0x15, +0xD6, 0x15, 0xCD, 0xD4, 0xCD, 0xD4, 0xC5, 0xF4, +0xB5, 0x32, 0x9C, 0x6F, 0x62, 0xEB, 0x39, 0xA6, +0x29, 0x25, 0x18, 0xC4, 0x18, 0xC4, 0x10, 0xA3, +0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x08, 0x83, 0x08, 0x82, 0x08, 0x83, 0x08, 0x83, +0x10, 0x83, 0x08, 0x83, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xC4, 0x10, 0xC4, 0x18, 0xE4, 0x10, 0xC3, +0x08, 0x83, 0x10, 0xC3, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x10, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xC4, 0x10, 0xA3, 0x10, 0xC3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x18, 0xE4, 0x18, 0xE4, 0x19, 0x05, 0x21, 0x26, +0x21, 0x05, 0x19, 0x05, 0x19, 0x05, 0x19, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x21, 0x26, +0x19, 0x05, 0x19, 0x05, 0x19, 0x05, 0x19, 0x05, +0x21, 0x05, 0x21, 0x26, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x21, 0x26, 0x21, 0x26, 0x21, 0x46, +0x21, 0x46, 0x21, 0x46, 0x29, 0x46, 0x39, 0xC8, +0x31, 0xA8, 0x29, 0x67, 0x39, 0xC8, 0x39, 0xE9, +0x31, 0x87, 0x4A, 0x4A, 0x73, 0x6D, 0x94, 0x70, +0x9C, 0xB0, 0x9C, 0xB0, 0x9C, 0xB0, 0x94, 0x6F, +0x8C, 0x2E, 0x8C, 0x0E, 0x84, 0x0E, 0x84, 0x0E, +0x8C, 0x2F, 0x8C, 0x0E, 0x83, 0xEE, 0x83, 0xCD, +0x73, 0x6C, 0x73, 0x6C, 0x7B, 0x8C, 0x7B, 0xAD, +0x94, 0x4F, 0x83, 0xEE, 0x84, 0x0E, 0x84, 0x0E, +0x94, 0x70, 0x84, 0x0E, 0x8C, 0x2F, 0x9C, 0xB0, +0xA4, 0x90, 0xCD, 0xD4, 0xD6, 0x55, 0x9C, 0xB0, +0x4A, 0x48, 0x21, 0x04, 0x18, 0xA3, 0x18, 0xC3, +0x41, 0xC7, 0x4A, 0x28, 0x73, 0x4C, 0x62, 0xCA, +0x64, 0x07, 0x64, 0x48, 0x53, 0x87, 0x3A, 0xA5, +0x5B, 0xA9, 0x53, 0x87, 0x6C, 0x28, 0x53, 0x85, +0x6C, 0x28, 0x42, 0xE4, 0x43, 0x44, 0x74, 0xAA, +0xA5, 0xF1, 0xC6, 0xF7, 0xA5, 0x71, 0x8C, 0xCF, +0x8C, 0xAF, 0x9C, 0xF0, 0xA5, 0x53, 0xB5, 0xD4, +0xB5, 0xB4, 0xA5, 0x53, 0x94, 0x90, 0x9C, 0xF2, +0xA5, 0x12, 0xB5, 0x94, 0xA4, 0xAF, 0xAC, 0xF0, +0xBD, 0x72, 0xD6, 0x56, 0xCE, 0x15, 0xE6, 0xF9, +0xD6, 0x97, 0xCE, 0x36, 0xB5, 0x74, 0xAD, 0x73, +0xAD, 0x53, 0xAD, 0x32, 0xAD, 0x32, 0xB5, 0x53, +0xAD, 0x53, 0xB5, 0x94, 0xB5, 0x94, 0xC5, 0xF5, +0xDE, 0xB7, 0xE6, 0xD8, 0xD6, 0x77, 0xCE, 0x58, +0xF7, 0x9D, 0xCE, 0x38, 0x4A, 0x48, 0x42, 0x07, +0x18, 0xC3, 0x08, 0x82, 0x08, 0x62, 0x08, 0x82, +0x08, 0x82, 0x08, 0x82, 0x08, 0x82, 0x10, 0xA3, +0x21, 0x25, 0x21, 0x66, 0x21, 0x47, 0x21, 0x67, +0x29, 0x88, 0x29, 0x88, 0x29, 0x87, 0x63, 0x2D, +0x52, 0x8A, 0x63, 0x0A, 0x8C, 0x4E, 0xA4, 0xB0, +0x94, 0x2D, 0x8C, 0x0C, 0xB5, 0x10, 0xC5, 0x71, +0xAC, 0xAE, 0x7B, 0x6A, 0x94, 0x4D, 0x94, 0x0C, +0x9C, 0x6E, 0x9C, 0x4E, 0x8B, 0xEC, 0x94, 0x2D, +0xAC, 0xCF, 0xB5, 0x10, 0xAC, 0xCF, 0xAC, 0xEF, +0xAC, 0xCF, 0xA4, 0x8E, 0xB4, 0xEF, 0xAC, 0xAF, +0xB4, 0xEF, 0xAC, 0xEF, 0xAC, 0xCF, 0xA4, 0x8F, +0xB4, 0xF0, 0xB5, 0x10, 0xB4, 0xEF, 0xB5, 0x10, +0xB4, 0xF0, 0x83, 0xAC, 0x29, 0x45, 0x39, 0xE7, +0x5A, 0xEB, 0x4A, 0x48, 0x42, 0x28, 0x39, 0xC6, +0x39, 0xE7, 0x4A, 0x69, 0x52, 0xAA, 0x52, 0x8A, +0x6B, 0x6D, 0x7B, 0xF0, 0x8C, 0x71, 0x84, 0x30, +0x9C, 0xB3, 0xBD, 0x96, 0xCE, 0x17, 0xB5, 0x74, +0xBD, 0xB5, 0xB5, 0x31, 0xAD, 0x10, 0xB5, 0x10, +0xB5, 0x31, 0xAC, 0xF0, 0x9C, 0xAF, 0x9C, 0x8F, +0x9C, 0x8F, 0xAD, 0x11, 0xAC, 0xF0, 0xD6, 0x37, +0xAD, 0x34, 0x9C, 0xD3, 0xA4, 0xD2, 0xDE, 0x97, +0xDE, 0x55, 0xBD, 0x52, 0xC5, 0x73, 0xC5, 0x93, +0xC5, 0x93, 0xBD, 0x72, 0xB5, 0x11, 0xE6, 0xB7, +0xDE, 0x35, 0xDE, 0x56, 0xDE, 0x56, 0xB5, 0x72, +0xB5, 0x72, 0xAD, 0x11, 0x8C, 0x0E, 0xC5, 0xB4, +0x94, 0x2E, 0xAD, 0x11, 0xA4, 0xF1, 0x9C, 0x6F, +0xC5, 0xD5, 0x94, 0x4F, 0xAD, 0x52, 0xA4, 0xD1, +0x6B, 0x4B, 0x63, 0x0B, 0xAD, 0x53, 0xB5, 0x93, +0xB5, 0x73, 0xB5, 0x74, 0x73, 0x8D, 0x39, 0xC6, +0x41, 0xE7, 0x39, 0xE7, 0x39, 0xC6, 0x39, 0xE7, +0x42, 0x07, 0x29, 0x44, 0x21, 0x24, 0x4A, 0x28, +0x6B, 0x2C, 0x4A, 0x28, 0x39, 0xA6, 0x4A, 0x48, +0x73, 0x6C, 0xA4, 0xD1, 0xCE, 0x15, 0xCE, 0x16, +0xAD, 0x32, 0x9C, 0xB0, 0x94, 0x2E, 0x9C, 0x8F, +0x83, 0xEC, 0x73, 0x6A, 0xA4, 0xD0, 0xCE, 0x15, +0xC5, 0xF5, 0xBD, 0x93, 0xB5, 0x93, 0x9C, 0xB0, +0xB5, 0x52, 0xC5, 0xF4, 0xD6, 0x36, 0xCD, 0xF4, +0xD6, 0x15, 0xCD, 0xF4, 0xCD, 0xD3, 0xC5, 0x93, +0xB5, 0x52, 0xB5, 0x32, 0xAC, 0xF1, 0x8C, 0x0E, +0x73, 0x2C, 0x62, 0xEB, 0x52, 0x69, 0x31, 0x66, +0x20, 0xE4, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xC4, 0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0x83, 0x08, 0x83, 0x08, 0x83, 0x08, 0x83, +0x08, 0x83, 0x08, 0x83, 0x08, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xC3, 0x10, 0xC4, 0x10, 0xA3, +0x10, 0x83, 0x10, 0xA3, 0x10, 0xC4, 0x18, 0xC4, +0x18, 0xE4, 0x10, 0xC4, 0x10, 0xC3, 0x10, 0xC3, +0x10, 0xC4, 0x10, 0xA3, 0x10, 0xC4, 0x10, 0xC3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x18, 0xC4, 0x19, 0x04, 0x19, 0x05, 0x19, 0x05, +0x18, 0xE4, 0x18, 0xE5, 0x21, 0x05, 0x21, 0x05, +0x19, 0x05, 0x21, 0x05, 0x21, 0x05, 0x21, 0x05, +0x19, 0x05, 0x19, 0x05, 0x21, 0x05, 0x21, 0x05, +0x19, 0x05, 0x21, 0x05, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x21, 0x26, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x21, 0x26, 0x21, 0x26, 0x29, 0x87, +0x31, 0xA8, 0x21, 0x46, 0x31, 0xC8, 0x39, 0xE9, +0x31, 0x87, 0x39, 0xC8, 0x52, 0x8B, 0x63, 0x0C, +0x9C, 0xD1, 0xBD, 0x94, 0xB5, 0x73, 0xAD, 0x53, +0xAD, 0x32, 0xB5, 0x73, 0xB5, 0x73, 0xAD, 0x12, +0xB5, 0x73, 0xAD, 0x32, 0xAD, 0x32, 0xAD, 0x12, +0xB5, 0x74, 0xAD, 0x32, 0xAD, 0x32, 0xBD, 0xB4, +0xAD, 0x33, 0xA4, 0xF2, 0xAD, 0x12, 0xAD, 0x32, +0xA4, 0xF2, 0xA4, 0xD1, 0xA4, 0xF2, 0xAD, 0x12, +0xAC, 0xF2, 0x9C, 0x90, 0x8C, 0x2F, 0x94, 0x70, +0x52, 0x89, 0x21, 0x04, 0x18, 0xC3, 0x10, 0x82, +0x31, 0x65, 0x42, 0x07, 0x73, 0x4C, 0x73, 0x6C, +0x74, 0xAA, 0x5C, 0x07, 0x53, 0xC7, 0x42, 0xE5, +0x4B, 0x47, 0x43, 0x05, 0x8D, 0x2D, 0x6C, 0x49, +0x4B, 0x25, 0x4B, 0x65, 0x5C, 0x07, 0x5B, 0xE7, +0x7C, 0xAC, 0xB6, 0x54, 0x8C, 0xEF, 0x7C, 0x4C, +0x84, 0x8D, 0x9D, 0x11, 0x9D, 0x11, 0x9C, 0xD1, +0xB5, 0x73, 0xAD, 0x53, 0x9C, 0xD1, 0xAD, 0x94, +0xAD, 0x74, 0xB5, 0x94, 0xA4, 0xD0, 0xAC, 0xEF, +0xC5, 0xF4, 0xCE, 0x55, 0xD6, 0x56, 0xE7, 0x19, +0xEF, 0x3A, 0xE7, 0x1A, 0xD6, 0x57, 0xC5, 0xF5, +0xC5, 0xF5, 0xC6, 0x16, 0xBD, 0xD5, 0xBD, 0xB5, +0xB5, 0x95, 0xAD, 0x54, 0xA5, 0x34, 0xAD, 0x54, +0xAD, 0x33, 0x9C, 0xD1, 0x7B, 0xCE, 0x6B, 0x2D, +0x7B, 0xCF, 0x73, 0x8E, 0x29, 0x45, 0x10, 0xA3, +0x10, 0x82, 0x10, 0xA2, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x08, 0xA3, 0x08, 0x83, 0x08, 0x82, +0x08, 0xA3, 0x21, 0x46, 0x31, 0x87, 0x29, 0x87, +0x21, 0x67, 0x21, 0x46, 0x21, 0x46, 0x42, 0x29, +0x94, 0xB3, 0x8C, 0x91, 0x6B, 0x4C, 0xA4, 0xF2, +0x9C, 0x90, 0xAD, 0x11, 0xBD, 0x51, 0xC5, 0x92, +0xB4, 0xF0, 0x94, 0x6F, 0xA4, 0xD0, 0xA4, 0xD1, +0x94, 0x6F, 0xA4, 0xD1, 0xAD, 0x32, 0xB5, 0x93, +0xA4, 0xF1, 0xA4, 0xF1, 0x9C, 0x8F, 0xA4, 0xF0, +0xAD, 0x31, 0xB5, 0x52, 0xAC, 0xF0, 0xA4, 0xD0, +0xA4, 0xAF, 0x94, 0x4E, 0xA4, 0xF0, 0x8C, 0x2D, +0x9C, 0x6E, 0x9C, 0x8F, 0xB5, 0x10, 0xBD, 0x31, +0xA4, 0x6E, 0x94, 0x4E, 0x6B, 0x0B, 0x31, 0x85, +0x39, 0xE7, 0x5A, 0xAA, 0x4A, 0x28, 0x39, 0xC6, +0x4A, 0x48, 0x52, 0x89, 0x42, 0x08, 0x4A, 0x69, +0x73, 0x8E, 0x73, 0xAE, 0x73, 0x8E, 0x83, 0xEF, +0x9C, 0xB3, 0xB5, 0x96, 0xC5, 0xF7, 0xCE, 0x17, +0xDE, 0x98, 0xAD, 0x12, 0xA4, 0xAF, 0xAD, 0x10, +0xAC, 0xF0, 0xB5, 0x11, 0xBD, 0x51, 0xBD, 0x31, +0xB5, 0x30, 0xB5, 0x31, 0xB5, 0x52, 0xB5, 0x74, +0x9C, 0xD3, 0x8C, 0x51, 0x9C, 0x90, 0xAC, 0xAF, +0xA4, 0x8E, 0xA4, 0x8E, 0xA4, 0x8E, 0xAC, 0xCF, +0xAC, 0xCF, 0xC5, 0x71, 0xBD, 0x31, 0xC5, 0x71, +0xCD, 0x92, 0xC5, 0x71, 0xBD, 0x51, 0xB5, 0x31, +0xAC, 0xD0, 0xA4, 0xAF, 0xB5, 0x11, 0xD6, 0x15, +0xBD, 0x72, 0xAC, 0xB0, 0x83, 0x8B, 0x8B, 0xED, +0xC5, 0xB4, 0x8C, 0x2E, 0x9C, 0xB0, 0x8C, 0x2E, +0x8C, 0x2F, 0x8C, 0x4F, 0xAD, 0x52, 0xA5, 0x12, +0xA5, 0x12, 0xAD, 0x32, 0xAD, 0x53, 0x6B, 0x4C, +0x41, 0xE7, 0x42, 0x07, 0x42, 0x07, 0x42, 0x07, +0x42, 0x28, 0x29, 0x65, 0x31, 0x85, 0x31, 0x85, +0x39, 0xC6, 0x41, 0xE7, 0x42, 0x28, 0x29, 0x45, +0x31, 0x65, 0x62, 0xCA, 0x8B, 0xEE, 0xB5, 0x74, +0xC5, 0xD5, 0xBD, 0xB4, 0x9C, 0xB0, 0x94, 0x4E, +0x9C, 0x8F, 0x9C, 0xB0, 0xB5, 0x53, 0xD6, 0x57, +0xCE, 0x56, 0xC5, 0xD4, 0xC5, 0xF5, 0xAD, 0x32, +0xAD, 0x52, 0xC5, 0xB4, 0xD6, 0x36, 0xD6, 0x35, +0xD6, 0x15, 0xD6, 0x15, 0xCD, 0xD4, 0xB5, 0x11, +0xB5, 0x52, 0xB5, 0x52, 0xBD, 0xB4, 0xBD, 0x93, +0xAC, 0xF1, 0xAC, 0xF1, 0xAC, 0xF1, 0x7B, 0xAD, +0x52, 0x69, 0x21, 0x04, 0x18, 0xC4, 0x10, 0xC3, +0x18, 0xC4, 0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0x83, 0x08, 0x83, 0x08, 0x83, 0x08, 0x83, +0x08, 0x83, 0x08, 0x83, 0x08, 0x83, 0x08, 0x83, +0x08, 0x83, 0x10, 0xA3, 0x10, 0xC4, 0x10, 0xC3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC3, 0x10, 0xC4, +0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC3, 0x10, 0xC4, +0x10, 0xC3, 0x10, 0xA3, 0x10, 0xC4, 0x10, 0xC3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC4, 0x10, 0xC4, +0x10, 0xC4, 0x18, 0xE4, 0x18, 0xE5, 0x19, 0x05, +0x18, 0xE5, 0x19, 0x05, 0x19, 0x05, 0x19, 0x05, +0x18, 0xE5, 0x19, 0x05, 0x18, 0xE5, 0x18, 0xE5, +0x18, 0xE5, 0x18, 0xE5, 0x18, 0xE5, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x21, 0x26, +0x21, 0x26, 0x21, 0x46, 0x29, 0x46, 0x29, 0x46, +0x21, 0x46, 0x21, 0x46, 0x21, 0x46, 0x29, 0x67, +0x29, 0x67, 0x21, 0x26, 0x29, 0x67, 0x31, 0x87, +0x29, 0x66, 0x21, 0x46, 0x39, 0xC9, 0x52, 0x8B, +0x63, 0x0C, 0xAD, 0x53, 0xD6, 0x77, 0xB5, 0x94, +0xB5, 0x73, 0xCE, 0x36, 0xCE, 0x36, 0xCE, 0x36, +0xC5, 0xF5, 0xBD, 0xD4, 0xBD, 0x94, 0xBD, 0xB4, +0xD6, 0x56, 0xB5, 0x53, 0xB5, 0x73, 0xBD, 0x94, +0xBD, 0xB4, 0xA4, 0xD1, 0xB5, 0x73, 0xB5, 0x32, +0xB5, 0x73, 0xAD, 0x12, 0xAD, 0x12, 0xAD, 0x11, +0xAD, 0x12, 0xB5, 0x53, 0xAD, 0x12, 0xB5, 0x73, +0x6B, 0x2C, 0x29, 0x46, 0x18, 0xC3, 0x10, 0xA2, +0x21, 0x04, 0x4A, 0x08, 0x5A, 0xA9, 0x62, 0xEA, +0x74, 0x8A, 0x53, 0xA6, 0x5B, 0xE7, 0x53, 0xA8, +0x3A, 0xC5, 0x43, 0x05, 0x43, 0x04, 0x53, 0x65, +0x43, 0x24, 0x7C, 0xEB, 0x53, 0xC6, 0x4B, 0x44, +0x6C, 0x29, 0x8D, 0x0E, 0x6B, 0xEA, 0x5B, 0x67, +0xAD, 0xF2, 0xBE, 0x76, 0xA5, 0x53, 0x84, 0x0F, +0x94, 0xB1, 0x94, 0xB1, 0x8C, 0x71, 0x9C, 0xD2, +0x9C, 0xF2, 0xA5, 0x13, 0x94, 0x90, 0x9C, 0xB0, +0xA4, 0xF1, 0xA4, 0xF2, 0x94, 0xB1, 0x94, 0x91, +0x8C, 0x50, 0x84, 0x0F, 0x7B, 0xEF, 0x7B, 0xCF, +0x73, 0x8E, 0x6B, 0x4D, 0x63, 0x2E, 0x63, 0x2E, +0x63, 0x2E, 0x63, 0x2E, 0x6B, 0x4E, 0x63, 0x0E, +0x52, 0xAC, 0x4A, 0x6B, 0x42, 0x2A, 0x41, 0xE9, +0x39, 0xC8, 0x29, 0x67, 0x29, 0x46, 0x21, 0x04, +0x18, 0xE4, 0x18, 0xE4, 0x10, 0xC3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x08, 0x83, +0x08, 0x83, 0x21, 0x25, 0x29, 0x46, 0x31, 0xC8, +0x31, 0xA8, 0x29, 0x67, 0x21, 0x46, 0x21, 0x46, +0x4A, 0x6B, 0xBE, 0x18, 0xDE, 0xFC, 0x94, 0xB2, +0x94, 0x50, 0xBD, 0xB4, 0xBD, 0x71, 0xC5, 0x92, +0xB5, 0x31, 0xC5, 0xD4, 0xC6, 0x16, 0xC5, 0xF5, +0xB5, 0x73, 0xBD, 0xB4, 0xC6, 0x16, 0xCE, 0x36, +0xC5, 0xF5, 0xB5, 0x94, 0xBD, 0x94, 0xC6, 0x16, +0xB5, 0x73, 0xBD, 0xB4, 0xBD, 0xB4, 0xBD, 0xD4, +0xB5, 0x73, 0xAD, 0x52, 0xB5, 0x94, 0xAD, 0x32, +0xAD, 0x32, 0xB5, 0x93, 0xBD, 0x92, 0xB5, 0x10, +0xA4, 0xAF, 0xBD, 0x93, 0xBD, 0xD4, 0x9C, 0xD1, +0x6B, 0x2B, 0x52, 0x89, 0x4A, 0x48, 0x31, 0x85, +0x39, 0xC6, 0x39, 0xE7, 0x4A, 0x48, 0x5A, 0xCB, +0x5A, 0xAA, 0x6B, 0x2D, 0x8C, 0x30, 0x94, 0x92, +0xA4, 0xF3, 0x94, 0x71, 0xB5, 0x75, 0xCE, 0x17, +0xCE, 0x17, 0xE6, 0xDA, 0x94, 0x50, 0xCE, 0x15, +0xCD, 0xF4, 0xA4, 0xB0, 0x94, 0x2D, 0x9C, 0x8E, +0x94, 0x2C, 0x8B, 0xEC, 0xA4, 0xB0, 0xB5, 0x75, +0x9C, 0xD3, 0x83, 0xF0, 0x9C, 0xB1, 0xBD, 0x51, +0xCD, 0x92, 0xCD, 0xB2, 0xC5, 0x51, 0x9C, 0x4D, +0x9C, 0x6D, 0xA4, 0x8E, 0xAC, 0xEF, 0xAC, 0xAE, +0xB4, 0xEF, 0xBD, 0x31, 0xC5, 0x72, 0xCD, 0x92, +0xC5, 0x92, 0xC5, 0xB2, 0xC5, 0x51, 0xBD, 0x30, +0xC5, 0x51, 0xC5, 0x71, 0xC5, 0x72, 0xC5, 0x93, +0xC5, 0x94, 0xC5, 0xD5, 0xBD, 0x94, 0xB5, 0x73, +0xBD, 0x94, 0xB5, 0x53, 0xB5, 0x73, 0xB5, 0x53, +0xAD, 0x32, 0xAD, 0x12, 0xAD, 0x12, 0x7B, 0xAD, +0x41, 0xE7, 0x4A, 0x28, 0x42, 0x28, 0x42, 0x28, +0x42, 0x07, 0x4A, 0x48, 0x42, 0x28, 0x39, 0xA6, +0x39, 0xE7, 0x42, 0x07, 0x29, 0x65, 0x29, 0x44, +0x42, 0x07, 0x83, 0xEF, 0x73, 0x6D, 0x8C, 0x0F, +0xAD, 0x32, 0xAD, 0x32, 0x9C, 0xB0, 0xA4, 0xF0, +0xB5, 0x73, 0xD6, 0x56, 0xD6, 0x56, 0xCE, 0x56, +0xCE, 0x35, 0xCE, 0x15, 0xBD, 0xB4, 0xAD, 0x32, +0xC5, 0xD4, 0xCE, 0x15, 0xD6, 0x56, 0xD6, 0x76, +0xD6, 0x35, 0xD6, 0x15, 0xC5, 0xB3, 0x94, 0x0D, +0xBD, 0x73, 0xBD, 0x72, 0xA4, 0xD0, 0xC5, 0xD4, +0xC5, 0xB4, 0xC5, 0xB4, 0xC5, 0xB3, 0xCD, 0xD4, +0x94, 0x2F, 0x6B, 0x0B, 0x52, 0x89, 0x18, 0xE4, +0x18, 0xC4, 0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x08, 0x83, 0x08, 0x83, 0x08, 0x83, +0x08, 0x83, 0x08, 0x83, 0x08, 0x83, 0x08, 0x83, +0x08, 0x83, 0x10, 0x83, 0x10, 0xA3, 0x10, 0xC4, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC3, 0x10, 0xC4, +0x10, 0xC4, 0x18, 0xC4, 0x10, 0xC4, 0x10, 0xC3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xC3, 0x10, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, 0x19, 0x05, +0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE5, 0x18, 0xE5, +0x18, 0xE5, 0x18, 0xE5, 0x18, 0xE5, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE5, 0x21, 0x05, +0x19, 0x05, 0x19, 0x05, 0x19, 0x05, 0x19, 0x05, +0x21, 0x25, 0x21, 0x26, 0x21, 0x46, 0x29, 0x66, +0x21, 0x46, 0x29, 0x67, 0x29, 0x46, 0x29, 0x46, +0x21, 0x46, 0x19, 0x05, 0x21, 0x05, 0x21, 0x26, +0x21, 0x46, 0x19, 0x05, 0x29, 0x66, 0x39, 0xE8, +0x4A, 0x6A, 0x6B, 0x4D, 0x94, 0x90, 0x94, 0x70, +0xD6, 0x77, 0xDE, 0xB8, 0xCE, 0x56, 0xD6, 0x97, +0xD6, 0x77, 0xD6, 0x57, 0xCE, 0x36, 0xD6, 0x56, +0xD6, 0x77, 0xD6, 0x56, 0xD6, 0x76, 0xD6, 0x97, +0xD6, 0x77, 0x9C, 0x90, 0x8C, 0x0E, 0xAD, 0x32, +0xC5, 0xF5, 0xBD, 0x93, 0xB5, 0x73, 0xBD, 0xB4, +0xB5, 0x73, 0xAD, 0x32, 0xB5, 0x73, 0xBD, 0x93, +0x9C, 0xB1, 0x31, 0xA6, 0x18, 0xC4, 0x10, 0xA3, +0x18, 0xC3, 0x4A, 0x49, 0x4A, 0x28, 0x4A, 0x28, +0x64, 0x28, 0x5B, 0xE8, 0x4B, 0x45, 0x4B, 0x46, +0x3A, 0xE5, 0x43, 0x25, 0x3A, 0xE3, 0x3A, 0xE3, +0x3A, 0xE4, 0x5B, 0xC7, 0x3A, 0xC3, 0x43, 0x24, +0x53, 0x85, 0x5B, 0x86, 0x5B, 0x87, 0x84, 0x8C, +0xA5, 0x71, 0xA5, 0x52, 0x94, 0xB0, 0x31, 0x86, +0x39, 0xC8, 0x39, 0xE8, 0x3A, 0x09, 0x42, 0x09, +0x42, 0x29, 0x42, 0x4A, 0x4A, 0x4A, 0x4A, 0x6B, +0x52, 0x8B, 0x4A, 0x8B, 0x4A, 0x8B, 0x52, 0xAB, +0x52, 0xAC, 0x5B, 0x0D, 0x63, 0x2E, 0x63, 0x2D, +0x63, 0x4E, 0x73, 0xB0, 0x73, 0x90, 0x73, 0x90, +0x73, 0x8F, 0x6B, 0x4E, 0x6B, 0x4E, 0x6B, 0x4E, +0x73, 0x8E, 0x6B, 0x4D, 0x4A, 0x6B, 0x52, 0xAB, +0x42, 0x09, 0x21, 0x26, 0x18, 0xE4, 0x19, 0x04, +0x18, 0xC4, 0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x08, 0xA3, 0x08, 0xA3, +0x21, 0x46, 0x73, 0xAF, 0x94, 0xD4, 0x8C, 0x94, +0x73, 0xB0, 0x4A, 0x4B, 0x29, 0x67, 0x31, 0xA8, +0x29, 0x87, 0x42, 0x4A, 0xAD, 0xB7, 0xEF, 0x9E, +0xC6, 0x38, 0xA4, 0xD1, 0xBD, 0x51, 0xC5, 0x71, +0xB5, 0x31, 0xC5, 0xF4, 0xC6, 0x16, 0xC5, 0xF5, +0xC5, 0xF5, 0xCE, 0x56, 0xC5, 0xF5, 0xBD, 0xD4, +0xC5, 0xF5, 0xBD, 0xD5, 0xC5, 0xF5, 0x84, 0x0E, +0x9C, 0xD1, 0xC5, 0xF5, 0xC6, 0x15, 0xC6, 0x36, +0xC5, 0xF5, 0xBD, 0xD5, 0xBD, 0xB4, 0xBD, 0xD4, +0xBD, 0xF5, 0xD6, 0x97, 0xC5, 0xB3, 0xB4, 0xF0, +0xAC, 0xF0, 0xC6, 0x15, 0xBD, 0xD5, 0x84, 0x0E, +0x5A, 0xCA, 0x39, 0xC6, 0x52, 0x69, 0x52, 0x69, +0x42, 0x07, 0x42, 0x08, 0x52, 0x69, 0x5A, 0xAA, +0x63, 0x0C, 0x73, 0x8E, 0x8C, 0x30, 0x94, 0x72, +0xAD, 0x14, 0xA4, 0xF3, 0xB5, 0x96, 0xBD, 0xD7, +0xB5, 0x55, 0xBD, 0xB6, 0x9C, 0x91, 0xB5, 0x53, +0xAD, 0x11, 0x7B, 0x8C, 0x7B, 0x8B, 0xA4, 0xF0, +0xAD, 0x10, 0x94, 0x4E, 0x9C, 0xD1, 0xB5, 0x75, +0x9C, 0xB3, 0x7B, 0xCF, 0x7B, 0xAD, 0xA4, 0xAF, +0xC5, 0x51, 0xBD, 0x30, 0x93, 0xEC, 0x8C, 0x0D, +0xAC, 0xF0, 0x9C, 0x8E, 0x94, 0x2D, 0x8B, 0xED, +0x7B, 0x8B, 0x7B, 0x6B, 0x8B, 0xCC, 0x83, 0xAC, +0x8B, 0xCC, 0x8B, 0xCC, 0x8B, 0xED, 0x7B, 0x6A, +0x73, 0x2A, 0x7B, 0x6A, 0x8C, 0x0C, 0x9C, 0x6E, +0xA4, 0xF0, 0x9C, 0x6F, 0x94, 0x4F, 0xAD, 0x12, +0xB5, 0x53, 0xA4, 0xD1, 0xB5, 0x53, 0xAD, 0x12, +0xA4, 0xD1, 0xA4, 0xD1, 0x9C, 0xF1, 0x7B, 0xAD, +0x29, 0x45, 0x4A, 0x48, 0x4A, 0x48, 0x42, 0x07, +0x39, 0xC6, 0x4A, 0x69, 0x39, 0xC6, 0x4A, 0x28, +0x52, 0xAA, 0x5A, 0xCB, 0x5A, 0xCA, 0x39, 0xE7, +0x7B, 0xAE, 0x5A, 0xAA, 0x83, 0xAE, 0x94, 0x30, +0x8B, 0xEE, 0xAD, 0x12, 0xBD, 0x73, 0xB5, 0x53, +0xAD, 0x32, 0xAD, 0x12, 0xAC, 0xF1, 0xA4, 0xD1, +0xA4, 0xB0, 0xAD, 0x11, 0xA4, 0xD0, 0x94, 0x70, +0x9C, 0xB0, 0xB5, 0x32, 0xBD, 0x93, 0xBD, 0xB4, +0xC5, 0xB4, 0xBD, 0x52, 0xB5, 0x11, 0xA4, 0xD0, +0xC5, 0xB4, 0xCD, 0xF4, 0xC5, 0x93, 0xD6, 0x56, +0xDE, 0x76, 0xDE, 0x76, 0xE6, 0x97, 0xDE, 0x97, +0xC5, 0xB4, 0xCD, 0xD5, 0x62, 0xCA, 0x18, 0xC3, +0x10, 0xC4, 0x18, 0xE4, 0x18, 0xC3, 0x10, 0xC3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0x83, 0x08, 0x83, +0x08, 0x83, 0x08, 0x83, 0x08, 0x83, 0x08, 0x83, +0x08, 0x83, 0x08, 0x83, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xC4, 0x10, 0xA3, 0x18, 0xE4, 0x10, 0xA3, +0x18, 0xC4, 0x18, 0xC4, 0x10, 0xC4, 0x10, 0xA3, +0x10, 0xC3, 0x10, 0xC3, 0x10, 0xC4, 0x18, 0xC4, +0x18, 0xC4, 0x10, 0xC3, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x19, 0x05, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x19, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x19, 0x05, +0x19, 0x05, 0x21, 0x05, 0x21, 0x26, 0x29, 0x67, +0x21, 0x46, 0x29, 0x67, 0x29, 0x67, 0x21, 0x46, +0x21, 0x05, 0x19, 0x05, 0x18, 0xE5, 0x18, 0xE5, +0x21, 0x26, 0x19, 0x05, 0x21, 0x26, 0x31, 0x87, +0x39, 0xC8, 0x52, 0x8A, 0x7B, 0xAE, 0x94, 0x91, +0xD6, 0x78, 0xDE, 0xD8, 0xD6, 0x97, 0xD6, 0x77, +0xD6, 0x97, 0xD6, 0x97, 0xDE, 0xB8, 0xDE, 0xB7, +0xD6, 0x56, 0xCE, 0x56, 0xD6, 0x76, 0xDE, 0xB7, +0xCE, 0x35, 0x9C, 0xB0, 0xAD, 0x32, 0xBD, 0xD4, +0xCE, 0x15, 0xBD, 0x93, 0xBD, 0x93, 0xBD, 0x93, +0xBD, 0x93, 0xB5, 0x73, 0xB5, 0x52, 0xBD, 0x93, +0xBD, 0xD4, 0x5A, 0xA9, 0x21, 0x04, 0x18, 0xA3, +0x10, 0x82, 0x41, 0xE7, 0x4A, 0x28, 0x41, 0xE7, +0x53, 0x86, 0x53, 0x86, 0x43, 0x05, 0x42, 0xE5, +0x4B, 0x67, 0x43, 0x05, 0x5B, 0xC7, 0x53, 0x86, +0x4B, 0x86, 0x4B, 0x86, 0x53, 0x85, 0x5B, 0xC7, +0x63, 0xC7, 0x7C, 0x4A, 0x94, 0xCD, 0xA5, 0x0F, +0xA5, 0x0F, 0xA4, 0xF0, 0x62, 0xEA, 0x18, 0xC3, +0x21, 0x25, 0x29, 0x46, 0x29, 0x66, 0x29, 0x66, +0x31, 0xA7, 0x4A, 0x49, 0x63, 0x0B, 0x6B, 0x2C, +0x73, 0x6D, 0x73, 0x8D, 0x73, 0x6D, 0x73, 0x6D, +0x7B, 0xAE, 0x83, 0xAE, 0x73, 0x6D, 0x6B, 0x4C, +0x6B, 0x2C, 0x6B, 0x6D, 0x6B, 0x4D, 0x7B, 0x8E, +0x8C, 0x0F, 0xAD, 0x33, 0xD6, 0x57, 0xDE, 0x77, +0xE6, 0x97, 0xD6, 0x36, 0x62, 0xA9, 0x41, 0xE8, +0x4A, 0x49, 0x21, 0x25, 0x10, 0xA3, 0x10, 0xA3, +0x08, 0x82, 0x08, 0x82, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC4, +0x5B, 0x2D, 0xD6, 0xDC, 0xE7, 0x7E, 0xEF, 0x7E, +0xEF, 0x5E, 0xD6, 0x7B, 0x7B, 0xD1, 0x29, 0x67, +0x29, 0xA8, 0x29, 0xA8, 0x3A, 0x4B, 0x94, 0xF4, +0xEF, 0x7E, 0xE6, 0xFB, 0xBD, 0x32, 0xB5, 0x10, +0xBD, 0x72, 0xCE, 0x36, 0xCE, 0x77, 0xCE, 0x56, +0xC5, 0xF5, 0xC6, 0x15, 0xA4, 0xF1, 0x94, 0x90, +0xC6, 0x15, 0xC6, 0x16, 0xC5, 0xF6, 0xA5, 0x33, +0xB5, 0xB5, 0xCE, 0x36, 0xC6, 0x15, 0xC6, 0x15, +0xC5, 0xF5, 0xBD, 0xD5, 0xC6, 0x15, 0xC6, 0x36, +0xC6, 0x15, 0xD6, 0x97, 0xC5, 0xB3, 0xAC, 0xEF, +0xB5, 0x31, 0xC6, 0x15, 0xB5, 0x73, 0xB5, 0x74, +0x94, 0x70, 0x29, 0x45, 0x39, 0xC6, 0x52, 0x89, +0x31, 0x86, 0x39, 0xC6, 0x4A, 0x48, 0x52, 0x8A, +0x63, 0x0B, 0x7B, 0xAE, 0x7B, 0xAE, 0x7B, 0xCF, +0x8C, 0x31, 0xA4, 0xF4, 0xAD, 0x55, 0xA5, 0x14, +0x8C, 0x51, 0x73, 0x8E, 0x8C, 0x50, 0x94, 0x70, +0x94, 0x70, 0x83, 0xEE, 0x8C, 0x2E, 0xAD, 0x11, +0xA4, 0xF0, 0x94, 0x8F, 0xBD, 0x95, 0xAD, 0x35, +0x8C, 0x72, 0x7B, 0xCF, 0x6B, 0x4C, 0xA4, 0xAF, +0xBD, 0x51, 0xAC, 0xAF, 0x83, 0x8B, 0xA4, 0xF0, +0xB5, 0x73, 0xA4, 0xD0, 0x94, 0x8F, 0x83, 0xCD, +0x73, 0x4B, 0x62, 0xEA, 0x5A, 0xA9, 0x62, 0xEA, +0x6B, 0x2B, 0x62, 0xEA, 0x83, 0xED, 0x62, 0xCA, +0x5A, 0xCA, 0x62, 0xCA, 0x73, 0x4B, 0x94, 0x4E, +0x94, 0x8F, 0x83, 0xCD, 0x83, 0xCC, 0xA4, 0xF1, +0xAD, 0x32, 0xB5, 0x33, 0xBD, 0x93, 0xC5, 0xB4, +0xC5, 0xB5, 0xAD, 0x33, 0xAD, 0x12, 0xAD, 0x33, +0x83, 0xEE, 0x39, 0xC6, 0x39, 0xE7, 0x42, 0x07, +0x41, 0xE7, 0x39, 0xE7, 0x42, 0x07, 0x5A, 0xCA, +0x5A, 0xCA, 0x5A, 0xAA, 0x4A, 0x69, 0x5A, 0xCB, +0xB5, 0x96, 0xAD, 0x34, 0x6A, 0xEB, 0x94, 0x0F, +0x8B, 0xCE, 0xAC, 0xF2, 0xB5, 0x53, 0xB5, 0x53, +0xAD, 0x12, 0xB5, 0x53, 0xBD, 0x73, 0xB5, 0x73, +0xBD, 0x94, 0xBD, 0xB4, 0xC5, 0xD5, 0xCD, 0xF5, +0xCD, 0xF5, 0xC5, 0xB4, 0xBD, 0xB4, 0xBD, 0xB3, +0xC5, 0xB4, 0xC5, 0xB4, 0xCD, 0xD4, 0xCD, 0xD5, +0xCD, 0xF5, 0xCD, 0xD4, 0xC5, 0xB4, 0xC5, 0xB3, +0xB5, 0x32, 0xB5, 0x32, 0xBD, 0x32, 0xB5, 0x11, +0xAC, 0xF0, 0xAC, 0xF1, 0x41, 0xC6, 0x10, 0xC3, +0x10, 0xA3, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC4, +0x10, 0xA3, 0x10, 0x83, 0x08, 0x83, 0x08, 0x83, +0x08, 0x83, 0x08, 0x83, 0x08, 0x83, 0x08, 0x82, +0x08, 0x82, 0x08, 0x82, 0x08, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x18, 0xC4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x10, 0xC4, 0x10, 0xA3, +0x10, 0xC4, 0x10, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xC4, 0x10, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x19, 0x04, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x19, 0x04, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x19, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x21, 0x26, +0x19, 0x05, 0x21, 0x05, 0x21, 0x46, 0x29, 0x67, +0x21, 0x26, 0x29, 0x46, 0x29, 0x67, 0x21, 0x26, +0x18, 0xE5, 0x18, 0xE4, 0x10, 0xC3, 0x18, 0xC4, +0x21, 0x25, 0x21, 0x26, 0x21, 0x26, 0x29, 0x67, +0x31, 0xA8, 0x52, 0x8B, 0x94, 0xB2, 0xBD, 0xB5, +0x8C, 0x2F, 0xC5, 0xF6, 0xD6, 0x97, 0xD6, 0x77, +0xD6, 0x97, 0xDE, 0xB8, 0xCE, 0x35, 0xD6, 0x97, +0xD6, 0x97, 0xD6, 0x77, 0xD6, 0x97, 0xDE, 0xB7, +0xDE, 0xD7, 0xBD, 0xB3, 0xAD, 0x32, 0xB5, 0x73, +0xC6, 0x15, 0xB5, 0x73, 0xBD, 0x93, 0xBD, 0x93, +0xBD, 0xD4, 0xAD, 0x11, 0xCE, 0x35, 0xC5, 0xF4, +0xCE, 0x56, 0x8C, 0x2F, 0x29, 0x45, 0x18, 0xC3, +0x10, 0xA2, 0x29, 0x65, 0x42, 0x07, 0x41, 0xC6, +0x5B, 0xC8, 0x5B, 0xC7, 0x5B, 0xC7, 0x42, 0xE5, +0x43, 0x45, 0x32, 0x82, 0x4B, 0x45, 0x5B, 0xE7, +0x43, 0x25, 0x53, 0x86, 0x74, 0x8A, 0x7C, 0x6B, +0x74, 0x0A, 0x63, 0x89, 0x73, 0xA9, 0x84, 0x0B, +0x8C, 0x4D, 0xA4, 0xCF, 0xA4, 0xD0, 0x8C, 0x4E, +0x8C, 0x4F, 0x94, 0x4F, 0x9C, 0xB1, 0x94, 0x70, +0x8C, 0x2F, 0x9C, 0x90, 0xA4, 0xF0, 0xB5, 0x11, +0xB5, 0x10, 0xB5, 0x11, 0xB5, 0x11, 0xB4, 0xF0, +0xAC, 0xF0, 0xB5, 0x31, 0xBD, 0x51, 0xB5, 0x11, +0xB5, 0x10, 0xAC, 0xF0, 0xAC, 0xF0, 0xAC, 0xCF, +0xAC, 0xAF, 0xA4, 0x8E, 0xA4, 0x8E, 0xA4, 0x6D, +0x9C, 0x6D, 0xB5, 0x10, 0xAC, 0xF0, 0x9C, 0x6F, +0x73, 0x2B, 0x41, 0xE6, 0x4A, 0x6A, 0x8C, 0x72, +0x29, 0x66, 0x08, 0x82, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x21, 0x25, +0x94, 0xF4, 0xD7, 0x1C, 0xDF, 0x5D, 0xE7, 0x5D, +0xE7, 0x5E, 0xEF, 0x7F, 0xE7, 0x3E, 0x94, 0xB4, +0x19, 0x05, 0x21, 0x46, 0x21, 0x88, 0x31, 0xC9, +0x73, 0xB0, 0xDE, 0xFC, 0xF7, 0x5C, 0xB5, 0x31, +0xCD, 0xD4, 0xD6, 0x76, 0xCE, 0x36, 0xC6, 0x15, +0xCE, 0x36, 0xCE, 0x77, 0xC6, 0x15, 0xBD, 0xD5, +0xB5, 0x94, 0xC5, 0xF5, 0xAD, 0x53, 0xBD, 0xD5, +0xC6, 0x16, 0xCE, 0x56, 0xC5, 0xF5, 0xC6, 0x15, +0xBD, 0xF5, 0xBD, 0xF5, 0xC6, 0x16, 0xAD, 0x53, +0xBD, 0xB4, 0xC5, 0xF5, 0xBD, 0x92, 0xB5, 0x10, +0xB5, 0x31, 0xB5, 0x73, 0xBD, 0x94, 0xBD, 0xD5, +0xCE, 0x36, 0x6B, 0x4C, 0x29, 0x45, 0x42, 0x08, +0x42, 0x07, 0x39, 0xA6, 0x39, 0xA6, 0x4A, 0x49, +0x52, 0x8A, 0x5A, 0xAA, 0x5A, 0xCB, 0x6B, 0x2D, +0x73, 0x6E, 0x94, 0x92, 0x9C, 0xB2, 0x7B, 0xAE, +0x73, 0x6D, 0x84, 0x10, 0xB5, 0x95, 0xB5, 0x95, +0x84, 0x0F, 0x94, 0x90, 0x94, 0x6F, 0x94, 0x8F, +0xA4, 0xD0, 0xA4, 0xD1, 0xBD, 0xB5, 0x94, 0xB3, +0x84, 0x31, 0x83, 0xEF, 0x7B, 0xAD, 0xA4, 0xCF, +0xC5, 0x51, 0x9C, 0x4E, 0x73, 0x6B, 0x83, 0xED, +0x9C, 0xD0, 0x94, 0x6F, 0xB5, 0x73, 0xAD, 0x52, +0x73, 0x4B, 0x62, 0xEA, 0x63, 0x0B, 0x62, 0xEB, +0x62, 0xEB, 0x5A, 0xCA, 0x8C, 0x4F, 0x7B, 0xAD, +0x7B, 0xCD, 0x6B, 0x4B, 0x7B, 0xAD, 0x8C, 0x2E, +0x8C, 0x2E, 0x73, 0x4B, 0x73, 0x8C, 0xAD, 0x32, +0xAD, 0x32, 0xBD, 0x94, 0xCE, 0x15, 0xCD, 0xF5, +0xC5, 0xF5, 0xB5, 0x74, 0xAD, 0x12, 0xAD, 0x32, +0xC5, 0xD5, 0x94, 0x4F, 0x31, 0x65, 0x4A, 0x68, +0x39, 0xC6, 0x39, 0xC6, 0x52, 0x89, 0x5A, 0xEB, +0x42, 0x28, 0x52, 0x89, 0x39, 0xE7, 0x52, 0xAA, +0x84, 0x30, 0xCE, 0x79, 0x9C, 0xB3, 0x73, 0x0C, +0x8B, 0xCE, 0x94, 0x2F, 0x9C, 0x50, 0x9C, 0x90, +0x8C, 0x2E, 0x9C, 0x8F, 0x9C, 0x90, 0x9C, 0x90, +0xAD, 0x12, 0xA4, 0xF1, 0xA4, 0xD0, 0x8B, 0xED, +0xAD, 0x32, 0xB5, 0x33, 0xB5, 0x32, 0x9C, 0xAF, +0x94, 0x4E, 0x8C, 0x2E, 0x94, 0x6F, 0x94, 0x6F, +0x9C, 0x4F, 0x9C, 0x6F, 0xAC, 0xF0, 0xB5, 0x31, +0xAC, 0xF1, 0xBD, 0x73, 0xBD, 0x73, 0xD6, 0x15, +0xCD, 0xD4, 0x9C, 0x90, 0x39, 0x85, 0x18, 0xC3, +0x10, 0xC3, 0x10, 0xC3, 0x18, 0xC4, 0x19, 0x05, +0x18, 0xE4, 0x10, 0x83, 0x10, 0x83, 0x08, 0x83, +0x08, 0x83, 0x08, 0x83, 0x08, 0x83, 0x08, 0x83, +0x10, 0x83, 0x10, 0x83, 0x08, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x18, 0xE4, +0x19, 0x04, 0x18, 0xE4, 0x10, 0xC4, 0x10, 0xC3, +0x10, 0xC4, 0x10, 0xC4, 0x18, 0xE4, 0x10, 0xC4, +0x18, 0xE4, 0x18, 0xC4, 0x10, 0xA3, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x19, 0x05, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x19, 0x04, 0x19, 0x05, +0x18, 0xE4, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x19, 0x05, 0x21, 0x26, 0x21, 0x25, 0x21, 0x26, +0x19, 0x05, 0x21, 0x25, 0x21, 0x26, 0x21, 0x46, +0x21, 0x26, 0x21, 0x46, 0x21, 0x26, 0x21, 0x05, +0x18, 0xE4, 0x18, 0xC4, 0x10, 0xA4, 0x18, 0xE4, +0x21, 0x05, 0x21, 0x26, 0x21, 0x26, 0x21, 0x46, +0x31, 0x87, 0x4A, 0x4A, 0xA5, 0x34, 0xB5, 0x95, +0x8C, 0x2F, 0xDE, 0xB9, 0xDE, 0xB8, 0xDE, 0x97, +0xE6, 0xF9, 0xBD, 0xB4, 0xC6, 0x15, 0xD6, 0x97, +0xD6, 0x77, 0xD6, 0x77, 0xD6, 0x76, 0xD6, 0x76, +0xD6, 0x96, 0xBD, 0xB4, 0xAD, 0x32, 0xB5, 0x52, +0xCE, 0x36, 0xC5, 0xF4, 0xC5, 0xF4, 0xCE, 0x15, +0xCE, 0x15, 0xBD, 0x93, 0xCE, 0x35, 0xCE, 0x14, +0xC5, 0xF4, 0xA4, 0xF1, 0x5A, 0xCB, 0x20, 0xE4, +0x18, 0xC3, 0x21, 0x04, 0x4A, 0x28, 0x41, 0xC6, +0x74, 0x8B, 0x74, 0x69, 0x74, 0x6A, 0x64, 0x08, +0x53, 0xA6, 0x64, 0x28, 0x4B, 0x45, 0x4B, 0x45, +0x32, 0x62, 0x63, 0xC9, 0x74, 0x2B, 0x53, 0x28, +0x52, 0xE8, 0x6B, 0xAB, 0x53, 0x07, 0x4A, 0xE6, +0x6B, 0xAA, 0x73, 0x89, 0x9C, 0xAE, 0xB5, 0x70, +0xBD, 0xB2, 0xA5, 0x11, 0xA5, 0x11, 0x9C, 0xD0, +0x9C, 0x90, 0x94, 0x4E, 0xA4, 0xF0, 0xCD, 0xF3, +0xA4, 0xAE, 0xC5, 0xB3, 0xC5, 0xD3, 0xBD, 0x52, +0xBD, 0x92, 0xCD, 0xD3, 0xC5, 0x93, 0x9C, 0x6E, +0xAD, 0x10, 0xD6, 0x14, 0xCD, 0xF4, 0xB5, 0x31, +0x9C, 0x4D, 0xB4, 0xEF, 0xC5, 0xB2, 0xC5, 0xB2, +0xBD, 0x51, 0xA4, 0x6E, 0xBD, 0x31, 0xB5, 0x30, +0xAC, 0xF0, 0xB5, 0x53, 0xE7, 0x3B, 0xF7, 0x7D, +0x5A, 0xEB, 0x08, 0x82, 0x08, 0x82, 0x10, 0x83, +0x08, 0x82, 0x08, 0x83, 0x10, 0xC3, 0x3A, 0x09, +0xB5, 0xD8, 0xD6, 0xDB, 0xD7, 0x1C, 0xDF, 0x3D, +0xE7, 0x3E, 0xE7, 0x5E, 0xEF, 0x7E, 0xEF, 0x7F, +0xAD, 0x76, 0x31, 0xA8, 0x19, 0x05, 0x19, 0x26, +0x21, 0x66, 0x63, 0x4D, 0xE7, 0x3B, 0xE6, 0xB9, +0xB5, 0x31, 0xC5, 0xD3, 0xBD, 0xB3, 0xB5, 0x51, +0xB5, 0x52, 0xBD, 0xB4, 0xBD, 0xD4, 0xBD, 0xD5, +0xBD, 0x93, 0xC5, 0xD5, 0xC5, 0xF5, 0xC6, 0x16, +0xCE, 0x36, 0xCE, 0x56, 0xC6, 0x15, 0xC6, 0x16, +0xC5, 0xF5, 0xC6, 0x16, 0xD6, 0x77, 0xC6, 0x36, +0xBD, 0xD4, 0xC5, 0xF5, 0x9C, 0x8F, 0xBD, 0x30, +0xB5, 0x31, 0xC6, 0x15, 0xCE, 0x36, 0xC6, 0x36, +0xD6, 0x77, 0xBD, 0xB4, 0x41, 0xE7, 0x52, 0xAA, +0x63, 0x0B, 0x42, 0x07, 0x39, 0xC6, 0x39, 0xA6, +0x4A, 0x49, 0x52, 0x89, 0x5A, 0xAA, 0x6B, 0x2C, +0x73, 0x6E, 0x94, 0x92, 0x94, 0x71, 0x8C, 0x30, +0x83, 0xEF, 0x9C, 0xD2, 0x94, 0x71, 0xC5, 0xD7, +0xA5, 0x13, 0x9C, 0xB1, 0x94, 0x90, 0x94, 0x6F, +0xA5, 0x11, 0xAD, 0x33, 0xB5, 0x95, 0xA5, 0x14, +0x94, 0x72, 0x7B, 0xAE, 0x83, 0xCE, 0xAC, 0xD0, +0xBD, 0x50, 0x83, 0xAC, 0x7B, 0xCD, 0xA5, 0x12, +0xB5, 0x53, 0x9C, 0x90, 0x94, 0x6F, 0x94, 0x6F, +0x6B, 0x2B, 0x5A, 0xEA, 0x62, 0xEB, 0x5A, 0xCB, +0x62, 0xEB, 0x5A, 0xEA, 0xA5, 0x12, 0xA4, 0xF1, +0xA4, 0xD1, 0x84, 0x0E, 0x94, 0x6F, 0x9C, 0x90, +0xA4, 0xD0, 0x73, 0x4B, 0x7B, 0x8C, 0xBD, 0x94, +0xA4, 0xF1, 0xBD, 0x94, 0xC5, 0xF5, 0xC5, 0xD5, +0xC5, 0xF5, 0xB5, 0x94, 0xB5, 0x53, 0xA4, 0xF1, +0xAD, 0x32, 0xA4, 0xF2, 0x73, 0x8C, 0x8C, 0x50, +0x63, 0x0B, 0x39, 0xE7, 0x4A, 0x28, 0x5A, 0xCA, +0x42, 0x07, 0x4A, 0x49, 0x52, 0xAA, 0x52, 0xAA, +0x62, 0xEC, 0x9C, 0xF3, 0xAD, 0x34, 0x6B, 0x0B, +0x94, 0x0F, 0x8B, 0xCE, 0x94, 0x50, 0x83, 0xCE, +0x7B, 0xAD, 0x7B, 0xAD, 0xA4, 0xF1, 0xA4, 0xF1, +0xB5, 0x52, 0xAD, 0x32, 0xBD, 0xB4, 0xAD, 0x32, +0xAD, 0x32, 0xB5, 0x53, 0x9C, 0xB0, 0x94, 0x6F, +0x9C, 0x8F, 0x9C, 0x8F, 0xAD, 0x32, 0xA4, 0xF1, +0xA4, 0xF1, 0xA4, 0xD0, 0xA4, 0xD0, 0xA5, 0x10, +0x9C, 0xAF, 0xC5, 0xB4, 0xB5, 0x32, 0xC5, 0x93, +0xBD, 0x93, 0x9C, 0x6F, 0x39, 0x86, 0x18, 0xC3, +0x10, 0xA3, 0x10, 0xA3, 0x18, 0xC3, 0x21, 0x25, +0x18, 0xE4, 0x10, 0xA3, 0x10, 0xA3, 0x08, 0x83, +0x10, 0x83, 0x10, 0x83, 0x10, 0x83, 0x08, 0x83, +0x10, 0x83, 0x08, 0x83, 0x10, 0xA3, 0x10, 0xC4, +0x18, 0xC4, 0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, +0x18, 0xE4, 0x18, 0xC4, 0x10, 0xC4, 0x10, 0xC4, +0x10, 0xC4, 0x10, 0xC4, 0x18, 0xE4, 0x10, 0xC4, +0x18, 0xE4, 0x18, 0xE4, 0x10, 0xA3, 0x18, 0xC4, +0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x19, 0x04, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x19, 0x05, +0x18, 0xE4, 0x18, 0xC4, 0x10, 0xC4, 0x18, 0xC4, +0x18, 0xE4, 0x21, 0x05, 0x21, 0x25, 0x19, 0x05, +0x19, 0x05, 0x21, 0x05, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x21, 0x46, 0x21, 0x26, 0x18, 0xE5, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE5, 0x19, 0x05, +0x21, 0x25, 0x21, 0x26, 0x21, 0x26, 0x21, 0x26, +0x29, 0x87, 0x31, 0xA8, 0x94, 0xB2, 0xA5, 0x12, +0x8C, 0x2F, 0xE6, 0xFA, 0xD6, 0x97, 0xDE, 0xD8, +0xDE, 0xB8, 0x83, 0xCE, 0xDE, 0xB8, 0xDE, 0xB7, +0xD6, 0x97, 0xDE, 0x97, 0xDE, 0xB7, 0xD6, 0x96, +0xDE, 0xB7, 0xB5, 0x52, 0xAD, 0x12, 0xCE, 0x35, +0xD6, 0x35, 0xCE, 0x35, 0xCE, 0x14, 0xCE, 0x14, +0xCE, 0x35, 0xBD, 0xB3, 0xCE, 0x14, 0xC6, 0x14, +0xC5, 0xF4, 0xCE, 0x35, 0xC5, 0xF6, 0x39, 0xA7, +0x18, 0xE4, 0x18, 0xA3, 0x4A, 0x08, 0x39, 0xC6, +0x4B, 0x27, 0x3A, 0xC4, 0x5B, 0xC8, 0x42, 0xE4, +0x53, 0x86, 0x53, 0x86, 0x32, 0x42, 0x43, 0x05, +0x53, 0x48, 0x74, 0x0B, 0x74, 0x2C, 0x63, 0x8A, +0x95, 0x10, 0x9D, 0x31, 0x5B, 0xA9, 0x63, 0xE8, +0xA5, 0xAF, 0x9D, 0x4D, 0x7C, 0x69, 0xA5, 0x8E, +0xAD, 0x70, 0xAD, 0x11, 0xA4, 0xF1, 0x94, 0x4F, +0x94, 0x6F, 0x83, 0xED, 0xAD, 0x11, 0xCE, 0x34, +0xCE, 0x14, 0xD6, 0x55, 0xC5, 0xD3, 0xC5, 0xD3, +0xC5, 0xD4, 0xCE, 0x15, 0xC5, 0xD3, 0xCD, 0xD3, +0xB5, 0x31, 0xCD, 0xF4, 0xD6, 0x55, 0xBD, 0x51, +0x8B, 0xAB, 0xB5, 0x10, 0xAC, 0xCF, 0xAC, 0xAE, +0xDE, 0x34, 0x9C, 0x4D, 0xCD, 0xF4, 0xD6, 0x35, +0xBD, 0x92, 0xCE, 0x56, 0xEF, 0x7C, 0xEF, 0x7D, +0x8C, 0x31, 0x08, 0x63, 0x08, 0x82, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC3, 0x63, 0x6E, +0xC6, 0x79, 0xD6, 0xFC, 0xD6, 0xFC, 0xDE, 0xFC, +0xDF, 0x1C, 0xDF, 0x1C, 0xE7, 0x1D, 0xEF, 0x5E, +0xF7, 0xBE, 0xCE, 0x39, 0x41, 0xE8, 0x21, 0x46, +0x29, 0x87, 0x21, 0x45, 0x6B, 0x8E, 0xE7, 0x1A, +0xB5, 0x11, 0xB5, 0x10, 0xBD, 0x50, 0xBD, 0x51, +0xC5, 0x72, 0xBD, 0x31, 0xB5, 0x10, 0xAC, 0xEF, +0xA4, 0xAF, 0x9C, 0x8E, 0x9C, 0x6E, 0x9C, 0x4D, +0x94, 0x4D, 0x94, 0x4D, 0x94, 0x4E, 0x94, 0x2D, +0x9C, 0x8F, 0xAD, 0x11, 0xAD, 0x31, 0xAC, 0xF1, +0xA4, 0xAF, 0xAC, 0xF0, 0x9C, 0x8E, 0xB5, 0x10, +0xBD, 0x51, 0xD6, 0x56, 0xD6, 0x56, 0xCE, 0x15, +0xCE, 0x36, 0xD6, 0x77, 0xC5, 0xF5, 0xC5, 0xF5, +0xB5, 0x73, 0x5A, 0x88, 0x42, 0x07, 0x39, 0xC6, +0x41, 0xE7, 0x4A, 0x28, 0x52, 0x8A, 0x63, 0x0C, +0x73, 0x8E, 0x7B, 0xCF, 0x73, 0x6D, 0x7B, 0xCF, +0x8C, 0x51, 0x9C, 0xB2, 0xAD, 0x55, 0xBD, 0xD6, +0xBD, 0xD6, 0xA5, 0x13, 0xAD, 0x53, 0xA4, 0xF1, +0xA5, 0x11, 0xB5, 0x74, 0xAD, 0x54, 0x9C, 0xD3, +0xAD, 0x15, 0x73, 0x6D, 0x83, 0xEE, 0xA4, 0xCF, +0xB4, 0xEF, 0x7B, 0x8B, 0x94, 0x4F, 0xAD, 0x32, +0xB5, 0x52, 0xAD, 0x32, 0x9C, 0x90, 0x8C, 0x2F, +0x8C, 0x2F, 0x6B, 0x4C, 0x84, 0x0F, 0x73, 0x8D, +0x73, 0x6D, 0x63, 0x2B, 0xB5, 0x74, 0xAD, 0x11, +0xA4, 0xD1, 0x9C, 0xB0, 0xA4, 0xF1, 0x9C, 0xB0, +0x94, 0x8F, 0x73, 0x6B, 0x7B, 0xCD, 0xBD, 0xD5, +0xA4, 0xF2, 0xA5, 0x12, 0xB5, 0x94, 0xAD, 0x53, +0x9C, 0xB1, 0x9C, 0xB0, 0xA4, 0xD1, 0x94, 0x4F, +0x94, 0x4F, 0x8C, 0x4F, 0x73, 0x6C, 0x8C, 0x30, +0x83, 0xEE, 0x52, 0x89, 0x39, 0xC6, 0x5A, 0xAA, +0x52, 0x89, 0x5A, 0xCA, 0x5A, 0xCA, 0x5A, 0xCB, +0x6B, 0x2D, 0x62, 0xEC, 0x52, 0x8A, 0x41, 0xE7, +0x73, 0x4C, 0x7B, 0x4C, 0x7B, 0x8D, 0x6B, 0x0C, +0x62, 0xCB, 0x4A, 0x28, 0xA4, 0xD1, 0xBD, 0xD4, +0xB5, 0x53, 0xAD, 0x52, 0xB5, 0x73, 0xAD, 0x12, +0x9C, 0xD0, 0xB5, 0x73, 0x9C, 0xB0, 0xA4, 0xD1, +0x94, 0x6F, 0x8C, 0x2E, 0x9C, 0xD0, 0x94, 0x6F, +0x94, 0x4E, 0x8C, 0x2E, 0x8C, 0x4E, 0x94, 0x6F, +0x9C, 0x8F, 0xBD, 0x94, 0xBD, 0x73, 0xC5, 0xD4, +0xBD, 0x93, 0xA4, 0xB0, 0x39, 0x86, 0x18, 0xC3, +0x10, 0xA3, 0x10, 0xA3, 0x18, 0xC3, 0x21, 0x25, +0x19, 0x04, 0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, 0x10, 0x82, +0x10, 0x83, 0x21, 0x05, 0x42, 0x08, 0x5A, 0xCA, +0x4A, 0x69, 0x29, 0x65, 0x18, 0xE4, 0x21, 0x05, +0x10, 0xC3, 0x10, 0xA3, 0x10, 0xC3, 0x18, 0xC4, +0x10, 0xC4, 0x10, 0xC4, 0x18, 0xC4, 0x10, 0xA3, +0x18, 0xE4, 0x19, 0x04, 0x10, 0xC4, 0x10, 0xC4, +0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x19, 0x05, 0x21, 0x05, +0x19, 0x05, 0x18, 0xE4, 0x19, 0x05, 0x19, 0x05, +0x19, 0x05, 0x18, 0xE4, 0x10, 0xC4, 0x10, 0xC4, +0x10, 0xC4, 0x19, 0x05, 0x21, 0x05, 0x18, 0xE5, +0x18, 0xC4, 0x19, 0x05, 0x21, 0x05, 0x18, 0xE5, +0x19, 0x05, 0x21, 0x26, 0x21, 0x25, 0x18, 0xE4, +0x18, 0xE5, 0x18, 0xE5, 0x19, 0x05, 0x19, 0x05, +0x21, 0x05, 0x21, 0x26, 0x21, 0x26, 0x21, 0x46, +0x31, 0x87, 0x31, 0x87, 0x5A, 0xCB, 0x9C, 0xD2, +0xBD, 0x94, 0xD6, 0x77, 0xD6, 0x77, 0xD6, 0x98, +0xD6, 0x78, 0x8C, 0x30, 0xE7, 0x1A, 0xDE, 0xD8, +0xD6, 0x77, 0xCE, 0x15, 0xC5, 0xF4, 0xDE, 0x96, +0xE6, 0xF8, 0xAD, 0x11, 0xA4, 0xB0, 0xDE, 0x96, +0xE6, 0xB6, 0xDE, 0x96, 0xD6, 0x55, 0xDE, 0x76, +0xD6, 0x75, 0xC5, 0xD3, 0xD6, 0x35, 0xD6, 0x55, +0xCE, 0x14, 0xD6, 0x35, 0xDE, 0xB7, 0x83, 0xEE, +0x20, 0xE4, 0x10, 0xA3, 0x29, 0x24, 0x41, 0xE7, +0x53, 0x69, 0x5B, 0x89, 0x74, 0x2B, 0x63, 0xA9, +0x42, 0xC4, 0x42, 0xA3, 0x3A, 0x64, 0x3A, 0x85, +0x5B, 0x69, 0x5B, 0x29, 0x3A, 0x66, 0x42, 0xA7, +0x9D, 0x52, 0x74, 0x0C, 0x3A, 0xA3, 0x4B, 0x64, +0x53, 0xA4, 0x6C, 0x26, 0x9D, 0x8C, 0xBE, 0x30, +0xBD, 0xD2, 0xC6, 0x15, 0xB5, 0x73, 0x94, 0x8F, +0x94, 0x70, 0xA4, 0xD1, 0xC6, 0x15, 0xDE, 0x96, +0xD6, 0x75, 0xD6, 0x76, 0xC5, 0xF4, 0xAD, 0x11, +0xB5, 0x73, 0xB5, 0x73, 0xA4, 0xF0, 0xC5, 0xB3, +0xBD, 0x92, 0xB5, 0x31, 0xCE, 0x34, 0xC5, 0xB2, +0x8B, 0xCC, 0xA4, 0x8E, 0xB5, 0x30, 0xDE, 0x55, +0xD5, 0xF4, 0xCD, 0xD3, 0xD6, 0x55, 0xCE, 0x14, +0xC5, 0xD4, 0xC6, 0x15, 0xDE, 0xFA, 0xE7, 0x1B, +0xAD, 0x55, 0x18, 0xA3, 0x08, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x18, 0xE4, 0x7C, 0x31, +0xC6, 0x59, 0xD6, 0xFB, 0xD6, 0xDB, 0xD6, 0xDB, +0xD6, 0xDB, 0xDE, 0xDB, 0xDE, 0xDB, 0xDE, 0xFC, +0xE7, 0x1C, 0xEF, 0x5D, 0xB5, 0x75, 0x29, 0x66, +0x31, 0xA7, 0x29, 0x86, 0x21, 0x45, 0x7B, 0xEF, +0xAD, 0x32, 0x8B, 0xEC, 0x9C, 0x4D, 0xA4, 0xAF, +0x8B, 0xEC, 0xA4, 0xAE, 0x9C, 0x4D, 0x94, 0x0C, +0x9C, 0x4D, 0x9C, 0x6E, 0xA4, 0x8E, 0x9C, 0x6D, +0xAC, 0xEF, 0xB5, 0x0F, 0xAC, 0xEF, 0xA4, 0xAE, +0x9C, 0x6E, 0x9C, 0x4D, 0xA4, 0x8E, 0xA4, 0x8E, +0xAC, 0xCF, 0xB5, 0x0F, 0xB5, 0x10, 0xB5, 0x10, +0xA4, 0x8E, 0x9C, 0x6E, 0x9C, 0x8E, 0x9C, 0x6E, +0x9C, 0x6E, 0xA4, 0x8E, 0x9C, 0x6E, 0x9C, 0x6D, +0x94, 0x2D, 0x7B, 0x6B, 0x52, 0x48, 0x39, 0xA6, +0x39, 0xC6, 0x39, 0xA6, 0x52, 0x69, 0x63, 0x0C, +0x73, 0x6D, 0x52, 0x8A, 0x63, 0x0C, 0x7B, 0xAF, +0xA4, 0xF3, 0xA4, 0xF3, 0xBD, 0xB6, 0xAD, 0x54, +0xB5, 0x75, 0xCE, 0x17, 0xA5, 0x12, 0x9C, 0xB0, +0x94, 0x8F, 0xAD, 0x54, 0xA5, 0x14, 0x9C, 0xD3, +0xB5, 0xB7, 0x7B, 0xCE, 0x73, 0x6B, 0xA4, 0xD0, +0xB5, 0x10, 0x7B, 0x8B, 0x73, 0x4B, 0x94, 0x6F, +0xA4, 0xF1, 0xAD, 0x12, 0x9C, 0x90, 0x94, 0x70, +0x6B, 0x2B, 0x63, 0x0B, 0x94, 0x91, 0x8C, 0x2F, +0x73, 0x8D, 0x6B, 0x8D, 0xB5, 0x94, 0xC5, 0xF5, +0xC5, 0xF5, 0xAD, 0x32, 0xAD, 0x52, 0x9C, 0xD0, +0x8C, 0x4E, 0x73, 0x4B, 0x84, 0x0E, 0xC5, 0xF6, +0xA4, 0xF2, 0x83, 0xEE, 0x7B, 0xAD, 0x73, 0x8C, +0x6B, 0x4C, 0x62, 0xEA, 0x6B, 0x4C, 0x6B, 0x2B, +0x6B, 0x2B, 0x6B, 0x4B, 0x62, 0xEB, 0x63, 0x0B, +0x63, 0x0B, 0x63, 0x0B, 0x4A, 0x28, 0x4A, 0x48, +0x42, 0x07, 0x4A, 0x48, 0x52, 0x89, 0x4A, 0x69, +0x63, 0x0C, 0x6B, 0x2C, 0x6B, 0x4D, 0x41, 0xC7, +0x5A, 0x69, 0x62, 0xAA, 0x62, 0x8A, 0x73, 0x0C, +0x83, 0xCF, 0x7B, 0x6D, 0x83, 0xCD, 0xAD, 0x32, +0xCE, 0x57, 0xB5, 0x93, 0xAD, 0x31, 0xA4, 0xF0, +0x9C, 0xB0, 0xBD, 0x74, 0xBD, 0x93, 0xA5, 0x11, +0x9C, 0xB0, 0x8C, 0x2E, 0x94, 0x90, 0x8C, 0x4E, +0x94, 0x6F, 0x94, 0x6F, 0x9C, 0xB0, 0x9C, 0xB0, +0x9C, 0xB0, 0xBD, 0x73, 0xB5, 0x52, 0xCD, 0xF5, +0xC5, 0xD4, 0xB5, 0x33, 0x4A, 0x08, 0x18, 0xA3, +0x10, 0x83, 0x10, 0x83, 0x18, 0xC4, 0x21, 0x45, +0x19, 0x04, 0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x08, 0x83, 0x08, 0x83, +0x21, 0x05, 0x73, 0xAE, 0x94, 0x91, 0x9C, 0xB1, +0x9C, 0xD1, 0x8C, 0x2F, 0x63, 0x0B, 0x6B, 0x4C, +0x4A, 0x48, 0x19, 0x04, 0x10, 0xC3, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x10, 0xC4, 0x10, 0xC4, +0x10, 0xC4, 0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE5, 0x19, 0x05, +0x19, 0x05, 0x18, 0xE5, 0x18, 0xE5, 0x19, 0x05, +0x19, 0x05, 0x19, 0x05, 0x19, 0x05, 0x19, 0x05, +0x18, 0xE5, 0x18, 0xE5, 0x21, 0x05, 0x18, 0xE5, +0x18, 0xC4, 0x18, 0xE5, 0x18, 0xE5, 0x18, 0xC4, +0x10, 0xC4, 0x19, 0x05, 0x19, 0x05, 0x18, 0xE4, +0x19, 0x05, 0x19, 0x05, 0x18, 0xE5, 0x21, 0x05, +0x19, 0x05, 0x21, 0x05, 0x21, 0x05, 0x29, 0x46, +0x31, 0xA8, 0x29, 0x87, 0x39, 0xE8, 0x73, 0x6D, +0x94, 0x70, 0x9C, 0x90, 0x9C, 0x90, 0x9C, 0xB1, +0x9C, 0x90, 0x8C, 0x2F, 0x9C, 0x90, 0x9C, 0x6F, +0x94, 0x2F, 0x8C, 0x0E, 0x94, 0x2E, 0xA4, 0xB0, +0xB5, 0x31, 0xAC, 0xF0, 0x9C, 0x8F, 0xA4, 0x8F, +0xB5, 0x11, 0xC5, 0xB3, 0xC5, 0xD3, 0xC5, 0xD3, +0xB5, 0x52, 0xBD, 0x92, 0xD6, 0x35, 0xD6, 0x35, +0xCE, 0x15, 0xD6, 0x76, 0xD6, 0x76, 0xCE, 0x36, +0x73, 0x8D, 0x6B, 0x4C, 0x31, 0x86, 0x41, 0xE7, +0x74, 0x4D, 0x53, 0x28, 0x42, 0xA6, 0x5B, 0x48, +0x6B, 0xE9, 0x74, 0x4A, 0x6C, 0x0A, 0x4B, 0x06, +0x42, 0xE6, 0x4A, 0xE7, 0x5B, 0x8A, 0x95, 0x31, +0xBE, 0x15, 0x6B, 0xCB, 0x43, 0x24, 0x5B, 0xC5, +0x5B, 0xE4, 0x8D, 0x0A, 0xA5, 0x6D, 0xAD, 0x90, +0xAD, 0x51, 0x9C, 0xF0, 0x8C, 0x4E, 0x8C, 0x2E, +0x8C, 0x2E, 0x9C, 0xD1, 0xCE, 0x14, 0xDE, 0xB6, +0xD6, 0x54, 0xCE, 0x35, 0xC5, 0xF4, 0xAD, 0x31, +0xBD, 0xB4, 0xAD, 0x32, 0xA4, 0xF1, 0xBD, 0x92, +0xCD, 0xF4, 0xAD, 0x31, 0xCE, 0x14, 0xB5, 0x31, +0xB5, 0x31, 0xA4, 0x8E, 0xB5, 0x10, 0xD5, 0xF3, +0xCD, 0xD3, 0xCD, 0xD3, 0xCE, 0x14, 0xCD, 0xF4, +0xCE, 0x15, 0xC6, 0x35, 0xD6, 0xB9, 0xCE, 0x78, +0xC5, 0xF7, 0x62, 0xEB, 0x08, 0x82, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xC3, 0x19, 0x25, 0x84, 0x72, +0xBE, 0x38, 0xCE, 0xBA, 0xCE, 0x9A, 0xCE, 0x9A, +0xD6, 0xBA, 0xD6, 0x99, 0xCE, 0x99, 0xCE, 0x9A, +0xD6, 0x9A, 0xD6, 0x99, 0xC6, 0x37, 0x7B, 0xAE, +0x29, 0x45, 0x21, 0x25, 0x21, 0x45, 0x39, 0xC7, +0x94, 0x90, 0x94, 0x6F, 0x8C, 0x2E, 0x8C, 0x2E, +0x94, 0x6F, 0x94, 0x6F, 0x7B, 0xCC, 0x83, 0xED, +0x94, 0x4E, 0x94, 0x6E, 0x83, 0xCB, 0x83, 0xCB, +0xA4, 0x8E, 0xAC, 0xEF, 0xAC, 0xCF, 0xAC, 0xCF, +0xB5, 0x51, 0xAC, 0xEF, 0x94, 0x2C, 0x8B, 0xEB, +0x9C, 0x4D, 0xB5, 0x30, 0xAC, 0xCF, 0x9C, 0x4D, +0xA4, 0x6D, 0xA4, 0xAE, 0xAC, 0xEF, 0xB5, 0x10, +0xBD, 0x31, 0xC5, 0x71, 0xB5, 0x30, 0xAC, 0xCF, +0x9C, 0x6E, 0x94, 0x4E, 0x8B, 0xED, 0x52, 0x68, +0x42, 0x08, 0x4A, 0x28, 0x52, 0x89, 0x5A, 0xCB, +0x73, 0x6D, 0x62, 0xEB, 0x73, 0x8E, 0x94, 0x71, +0x9C, 0xD3, 0x9C, 0xD3, 0xBD, 0xD7, 0xBD, 0xB6, +0xA5, 0x13, 0xCE, 0x38, 0xD6, 0x58, 0xAC, 0xF2, +0xA4, 0xD1, 0xAD, 0x33, 0x94, 0x91, 0x84, 0x10, +0x6B, 0x4D, 0x83, 0xCD, 0x94, 0x2D, 0xBD, 0x52, +0xC5, 0x72, 0xAC, 0xF0, 0x8B, 0xED, 0x8B, 0xCD, +0x9C, 0x6E, 0x94, 0x4E, 0x8C, 0x0D, 0x83, 0xAC, +0x83, 0xAC, 0x73, 0x6C, 0x84, 0x0E, 0x83, 0xED, +0x7B, 0xCD, 0x83, 0xEE, 0xBD, 0xB4, 0xC5, 0xF5, +0xB5, 0x73, 0x94, 0x6F, 0xAD, 0x11, 0xA4, 0xD0, +0x8C, 0x2E, 0x62, 0xEA, 0x7B, 0xAD, 0xC5, 0xF5, +0xA4, 0xF1, 0x8C, 0x2F, 0x8C, 0x2F, 0x8C, 0x2F, +0x84, 0x2F, 0x73, 0x8D, 0x84, 0x0F, 0x7B, 0xCE, +0x73, 0x8D, 0x6B, 0x6D, 0x6B, 0x4C, 0x5A, 0xCA, +0x6B, 0x4C, 0x62, 0xEB, 0x5A, 0xEB, 0x5A, 0xCA, +0x39, 0xA6, 0x42, 0x08, 0x4A, 0x48, 0x4A, 0x49, +0x52, 0x8A, 0x6B, 0x4C, 0x63, 0x0C, 0x41, 0xE7, +0x5A, 0x69, 0x62, 0xAA, 0x73, 0x2C, 0x7B, 0x6D, +0x73, 0x4C, 0x7B, 0x6D, 0x83, 0xAD, 0x83, 0xCE, +0xAD, 0x13, 0xB5, 0x93, 0xB5, 0x73, 0xAD, 0x31, +0x9C, 0xB0, 0xB5, 0x73, 0xAD, 0x12, 0xAD, 0x12, +0xA4, 0xF1, 0x94, 0x90, 0xAD, 0x32, 0x9C, 0xD0, +0xA4, 0xF1, 0x9C, 0xD1, 0xAD, 0x12, 0xAD, 0x52, +0x9C, 0xB0, 0xBD, 0x94, 0xB5, 0x52, 0xD6, 0x56, +0xCE, 0x15, 0xC5, 0xB4, 0x62, 0xCA, 0x18, 0xC3, +0x10, 0x83, 0x10, 0x83, 0x18, 0xC3, 0x21, 0x46, +0x21, 0x05, 0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x08, 0x82, 0x10, 0xA3, +0x63, 0x0C, 0x9C, 0xF1, 0xB5, 0x94, 0xB5, 0x73, +0xC5, 0xD5, 0xAD, 0x12, 0xA4, 0xD1, 0xA5, 0x12, +0xA4, 0xD1, 0x52, 0x89, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x10, 0xC4, 0x10, 0xC4, +0x10, 0xC4, 0x10, 0xC4, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE5, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x19, 0x04, +0x19, 0x05, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE5, +0x18, 0xE5, 0x19, 0x05, 0x19, 0x05, 0x19, 0x05, +0x21, 0x25, 0x21, 0x05, 0x19, 0x05, 0x19, 0x05, +0x18, 0xE5, 0x18, 0xE5, 0x18, 0xE5, 0x18, 0xE4, +0x10, 0xA4, 0x10, 0xC4, 0x18, 0xE4, 0x18, 0xC4, +0x18, 0xE5, 0x19, 0x05, 0x19, 0x05, 0x21, 0x25, +0x19, 0x05, 0x19, 0x05, 0x19, 0x05, 0x29, 0x46, +0x31, 0xA8, 0x29, 0x66, 0x31, 0x87, 0x5A, 0xCC, +0x94, 0x50, 0xCE, 0x16, 0xCD, 0xF5, 0xD6, 0x15, +0xCD, 0xF5, 0xC5, 0xB4, 0xBD, 0x73, 0xB5, 0x53, +0xC5, 0xB4, 0x94, 0x4F, 0xA4, 0xB0, 0xA4, 0xB0, +0x94, 0x4E, 0x9C, 0x8F, 0xB5, 0x32, 0x9C, 0x8F, +0xAC, 0xF1, 0xC5, 0x92, 0xC5, 0x93, 0xA4, 0xB0, +0xA4, 0xB0, 0xA4, 0xD0, 0x9C, 0x8F, 0x9C, 0x8F, +0x94, 0x2E, 0x9C, 0x8F, 0xA4, 0xD0, 0xA5, 0x11, +0x9C, 0xB0, 0x63, 0x2B, 0x18, 0xA2, 0x39, 0xA6, +0x8D, 0x10, 0x8C, 0xEF, 0x63, 0xCA, 0x53, 0x48, +0x53, 0x27, 0x5B, 0x67, 0x53, 0x06, 0x42, 0xC6, +0x63, 0xC9, 0x7C, 0x8D, 0xAD, 0xD3, 0x8C, 0xD0, +0xB5, 0xB4, 0x84, 0x6C, 0x43, 0x03, 0x4B, 0x63, +0x6C, 0x27, 0x84, 0x89, 0x94, 0xAC, 0xA5, 0x0F, +0x94, 0x8E, 0xA5, 0x10, 0x94, 0x8F, 0x94, 0x6F, +0x8C, 0x2E, 0x7B, 0xAC, 0xAD, 0x31, 0xD6, 0x55, +0xC5, 0xF3, 0xCE, 0x34, 0xBD, 0x93, 0xA5, 0x11, +0xBD, 0xB4, 0x9C, 0x90, 0x8C, 0x2F, 0xB5, 0x52, +0xC5, 0xF4, 0xC5, 0xD3, 0xCE, 0x34, 0xB5, 0x30, +0xD6, 0x35, 0xAC, 0xCF, 0xAC, 0xEF, 0xC5, 0x91, +0xCD, 0xD3, 0xD6, 0x35, 0xD6, 0x55, 0xCE, 0x15, +0xCE, 0x35, 0xCE, 0x56, 0xD6, 0x97, 0xC6, 0x37, +0xBD, 0xB6, 0x94, 0x71, 0x31, 0x86, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x19, 0x04, 0x7C, 0x30, +0xB5, 0xF7, 0xBE, 0x38, 0xC6, 0x38, 0xC6, 0x38, +0xC6, 0x58, 0xCE, 0x58, 0xC6, 0x58, 0xC6, 0x38, +0xC6, 0x58, 0xC6, 0x37, 0xC5, 0xF6, 0xB5, 0x94, +0x7B, 0xAE, 0x31, 0xA6, 0x19, 0x04, 0x21, 0x24, +0x73, 0xAD, 0x84, 0x2F, 0x7B, 0xCD, 0x6B, 0x6B, +0x63, 0x4B, 0x73, 0x8C, 0x7B, 0xAC, 0x73, 0x8C, +0x73, 0x8C, 0x7B, 0xAC, 0x7B, 0xAB, 0x8C, 0x0D, +0x8B, 0xEC, 0xB4, 0xF0, 0xAC, 0xEF, 0xC5, 0xB2, +0xB5, 0x51, 0x9C, 0x6D, 0x94, 0x4D, 0xA4, 0xF0, +0xAD, 0x10, 0xA4, 0xCF, 0x9C, 0x8E, 0x9C, 0x8E, +0xAC, 0xF0, 0xA4, 0xCF, 0xB5, 0x30, 0xBD, 0x71, +0xBD, 0x30, 0xC5, 0x91, 0xC5, 0x91, 0xAC, 0xEF, +0xBD, 0xB2, 0xC5, 0xF4, 0xCE, 0x35, 0x9C, 0xB0, +0x52, 0x68, 0x52, 0x8A, 0x52, 0x8A, 0x52, 0x69, +0x6B, 0x4D, 0x7B, 0xAE, 0x83, 0xEF, 0x73, 0x8E, +0x8C, 0x71, 0xA4, 0xF3, 0xB5, 0x76, 0xBD, 0xB6, +0x9C, 0x92, 0xC5, 0xF7, 0xE6, 0xBA, 0xC5, 0xB5, +0x9C, 0xB1, 0x94, 0x50, 0x83, 0xEF, 0x8C, 0x51, +0x94, 0x51, 0xB5, 0x53, 0xAC, 0xF0, 0xA4, 0x8E, +0x9C, 0x4D, 0x9C, 0x6E, 0xA4, 0x8F, 0xB4, 0xF0, +0xB5, 0x30, 0xB5, 0x30, 0xBD, 0x51, 0xB4, 0xF0, +0xAC, 0xF0, 0xA4, 0xD0, 0xA4, 0x8F, 0xA4, 0x8F, +0x9C, 0x4E, 0x94, 0x0D, 0xA4, 0xCF, 0xA4, 0xCF, +0x9C, 0x6E, 0x8C, 0x0D, 0x8C, 0x0D, 0x8C, 0x0D, +0x7B, 0xAD, 0x7B, 0x8D, 0x94, 0x90, 0xBD, 0xB4, +0xA4, 0xF1, 0x8C, 0x2F, 0x83, 0xEE, 0x83, 0xEE, +0x83, 0xEE, 0x7B, 0xCE, 0x83, 0xEE, 0x83, 0xEE, +0x83, 0xEE, 0x83, 0xEE, 0x83, 0xEE, 0x83, 0xEE, +0x8C, 0x2F, 0x73, 0x8D, 0x6B, 0x4C, 0x6B, 0x6C, +0x5A, 0xAA, 0x39, 0xC7, 0x42, 0x28, 0x42, 0x07, +0x52, 0x89, 0x63, 0x0B, 0x52, 0x8A, 0x52, 0x8A, +0x5A, 0xAA, 0x5A, 0x89, 0x62, 0xAA, 0x7B, 0x6D, +0x6B, 0x0C, 0x7B, 0x8E, 0x94, 0x50, 0x8B, 0xEF, +0x7B, 0x8D, 0xA4, 0xF2, 0x94, 0x70, 0x84, 0x0E, +0x9C, 0xB0, 0xBD, 0x93, 0xBD, 0xB4, 0xB5, 0x94, +0xAD, 0x52, 0xAD, 0x73, 0xBD, 0xD5, 0xB5, 0x94, +0xB5, 0x73, 0xAD, 0x32, 0xB5, 0x73, 0xBD, 0xB4, +0xA4, 0xF1, 0xBD, 0x94, 0xB5, 0x53, 0xDE, 0x97, +0xCE, 0x36, 0xC5, 0xF5, 0x62, 0xEA, 0x18, 0xC3, +0x10, 0x83, 0x10, 0x83, 0x10, 0xC3, 0x29, 0x66, +0x21, 0x25, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, 0x5A, 0xAA, +0xBD, 0xB4, 0xC5, 0xF5, 0xC5, 0xD5, 0xC5, 0xD4, +0xBD, 0xB4, 0xA4, 0xF1, 0xAD, 0x32, 0xC6, 0x15, +0xC5, 0xF5, 0xA4, 0xF2, 0x29, 0x65, 0x18, 0xC4, +0x18, 0xE4, 0x18, 0xC4, 0x10, 0xC4, 0x10, 0xC4, +0x10, 0xC4, 0x10, 0xC3, 0x10, 0xC4, 0x18, 0xC4, +0x18, 0xE4, 0x18, 0xE4, 0x19, 0x05, 0x19, 0x05, +0x19, 0x05, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC4, +0x18, 0xE4, 0x19, 0x05, 0x19, 0x05, 0x18, 0xE5, +0x18, 0xE5, 0x19, 0x05, 0x19, 0x05, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x19, 0x05, 0x18, 0xE4, +0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC4, 0x18, 0xC4, +0x18, 0xE5, 0x21, 0x05, 0x19, 0x05, 0x21, 0x26, +0x19, 0x05, 0x19, 0x05, 0x21, 0x26, 0x29, 0x46, +0x31, 0xA8, 0x29, 0x46, 0x21, 0x25, 0x42, 0x29, +0x7B, 0xAE, 0xCD, 0xF5, 0xD6, 0x35, 0xD5, 0xF5, +0xD5, 0xF4, 0xD6, 0x14, 0xC5, 0xB3, 0xC5, 0xB3, +0xD5, 0xF5, 0xA4, 0x90, 0x8B, 0xED, 0x8B, 0xED, +0xA4, 0xAF, 0xBD, 0x51, 0xBD, 0x52, 0x9C, 0x6F, +0xBD, 0x52, 0xD5, 0xF4, 0xDE, 0x55, 0xA4, 0x8F, +0xAD, 0x11, 0xB5, 0x53, 0xB5, 0x73, 0xB5, 0x73, +0xA5, 0x11, 0xA4, 0xD1, 0xA5, 0x11, 0xA4, 0xF1, +0x9C, 0xD0, 0x5A, 0xCA, 0x18, 0xC3, 0x20, 0xE3, +0x3A, 0xC5, 0x42, 0xE6, 0x5B, 0xA9, 0x4B, 0x07, +0x5B, 0x69, 0x4A, 0xA6, 0x42, 0x86, 0x5B, 0x89, +0x6C, 0x0B, 0x8D, 0x0F, 0xA5, 0x93, 0xA5, 0x72, +0x6B, 0x8A, 0x8C, 0xED, 0x4B, 0x24, 0x63, 0xE9, +0xA5, 0xB2, 0x9D, 0x10, 0x94, 0xAD, 0x9C, 0xEE, +0xA5, 0x30, 0xAD, 0x52, 0x9C, 0xF1, 0xA4, 0xF1, +0x9C, 0xD1, 0x8C, 0x4E, 0xB5, 0x73, 0xDE, 0xB7, +0xCE, 0x14, 0xCE, 0x14, 0xB5, 0x72, 0x9C, 0xB0, +0xA5, 0x12, 0x94, 0x90, 0x8C, 0x0F, 0xAD, 0x11, +0xA5, 0x11, 0x94, 0x6E, 0xBD, 0xB2, 0xB5, 0x30, +0xCE, 0x14, 0xAC, 0xCF, 0xA4, 0x6D, 0x8B, 0xEB, +0x94, 0x4D, 0xA4, 0xAE, 0xA4, 0xCF, 0xB5, 0x51, +0xBD, 0x93, 0xBD, 0xD4, 0xCE, 0x36, 0xCE, 0x36, +0xB5, 0x95, 0x9C, 0xB1, 0x6B, 0x0C, 0x18, 0xE3, +0x10, 0xC3, 0x10, 0xA3, 0x18, 0xE4, 0x6B, 0xAE, +0xAD, 0x95, 0xB5, 0xF6, 0xBD, 0xF6, 0xBD, 0xF6, +0xBD, 0xF6, 0xBD, 0xF6, 0xBD, 0xF6, 0xBD, 0xD6, +0xBD, 0xD6, 0xBD, 0xF6, 0xBD, 0xD5, 0xBD, 0xF6, +0xBD, 0xD6, 0xAD, 0x33, 0x5A, 0xCA, 0x10, 0xA2, +0x52, 0xAA, 0x84, 0x2F, 0x7B, 0xEE, 0x73, 0xAC, +0x73, 0xAD, 0x84, 0x0E, 0x83, 0xEE, 0x8C, 0x2F, +0x8C, 0x4F, 0x7B, 0xCD, 0x8C, 0x2E, 0x94, 0x6E, +0xA4, 0xAF, 0xB4, 0xEF, 0xAC, 0xCF, 0xB5, 0x51, +0xBD, 0x92, 0x9C, 0xAF, 0x9C, 0xAF, 0xB5, 0x72, +0xC5, 0xF4, 0xCE, 0x14, 0xBD, 0x92, 0xBD, 0xB3, +0xBD, 0x93, 0xAD, 0x10, 0xAD, 0x31, 0xB5, 0x51, +0xB5, 0x31, 0xD6, 0x35, 0xB5, 0x30, 0xB5, 0x30, +0xCE, 0x14, 0xCE, 0x55, 0xD6, 0x76, 0xBD, 0xB3, +0x83, 0xEE, 0x4A, 0x48, 0x42, 0x07, 0x39, 0xC7, +0x4A, 0x49, 0x52, 0x69, 0x52, 0x69, 0x63, 0x0C, +0x7C, 0x10, 0x9C, 0xF3, 0xB5, 0x96, 0xA4, 0xF4, +0xBD, 0x96, 0xBD, 0xD7, 0xB5, 0x95, 0xCE, 0x17, +0xBD, 0xB6, 0xBD, 0xD7, 0x84, 0x10, 0x84, 0x30, +0x94, 0x91, 0x94, 0x70, 0x83, 0xAC, 0x7B, 0xAC, +0x6B, 0x0A, 0x6B, 0x2A, 0x5A, 0x88, 0x73, 0x6B, +0x7B, 0x8B, 0x8C, 0x2D, 0x94, 0x2D, 0x9C, 0x8E, +0xAC, 0xCF, 0x94, 0x2D, 0x8C, 0x0C, 0x94, 0x2D, +0x9C, 0x6E, 0xAC, 0xF0, 0x9C, 0x8E, 0xA4, 0xCF, +0xAC, 0xCF, 0xAC, 0xF0, 0xAC, 0xF0, 0xB5, 0x52, +0xBD, 0x93, 0xBD, 0x74, 0xBD, 0x94, 0xBD, 0xB4, +0xBD, 0x94, 0xBD, 0x94, 0xBD, 0xB4, 0xBD, 0x94, +0xBD, 0x74, 0xC5, 0xD5, 0xC5, 0xF5, 0xC5, 0xD5, +0xBD, 0xB4, 0xBD, 0xB4, 0xBD, 0x74, 0xC5, 0xD5, +0xC5, 0xB4, 0xB5, 0x33, 0xB5, 0x74, 0xB5, 0x74, +0xAD, 0x12, 0x83, 0xCE, 0x42, 0x27, 0x42, 0x28, +0x4A, 0x48, 0x52, 0x89, 0x5A, 0x89, 0x83, 0xCE, +0x7B, 0x6D, 0x52, 0x28, 0x7B, 0x8D, 0x9C, 0x71, +0x8B, 0xEF, 0xA4, 0xB2, 0x7B, 0x6D, 0x73, 0x0C, +0x7B, 0x8E, 0x7B, 0x8E, 0xA4, 0xF2, 0xA4, 0xF2, +0xA4, 0xF2, 0xBD, 0x93, 0xC5, 0xD4, 0xD6, 0x97, +0xCE, 0x16, 0xC6, 0x15, 0xD6, 0x77, 0xAD, 0x32, +0xC5, 0xF5, 0xC5, 0xF5, 0xC5, 0xF5, 0xC5, 0xF4, +0x94, 0x6F, 0xBD, 0xB4, 0xB5, 0x32, 0xDE, 0xB7, +0xDE, 0xB7, 0xCE, 0x15, 0x73, 0x6C, 0x18, 0xC3, +0x10, 0x83, 0x10, 0x82, 0x10, 0xC3, 0x29, 0x86, +0x21, 0x05, 0x19, 0x04, 0x19, 0x04, 0x18, 0xE4, +0x18, 0xC3, 0x10, 0xA3, 0x10, 0xC3, 0x84, 0x0F, +0xCE, 0x56, 0xCE, 0x35, 0xCE, 0x15, 0xCE, 0x35, +0xCE, 0x15, 0xAD, 0x11, 0xB5, 0x52, 0xD6, 0x76, +0xDE, 0x97, 0xD6, 0x77, 0x83, 0xCE, 0x20, 0xE4, +0x10, 0xC3, 0x10, 0xC3, 0x18, 0xC4, 0x10, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x10, 0xC4, 0x10, 0xC4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE5, 0x19, 0x05, +0x19, 0x05, 0x19, 0x05, 0x19, 0x05, 0x18, 0xE5, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xE4, 0x19, 0x05, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x19, 0x05, +0x19, 0x05, 0x18, 0xE5, 0x19, 0x05, 0x18, 0xE4, +0x18, 0xC4, 0x10, 0xA4, 0x10, 0xA3, 0x18, 0xE4, +0x19, 0x05, 0x21, 0x26, 0x18, 0xE5, 0x21, 0x05, +0x19, 0x05, 0x19, 0x05, 0x29, 0x46, 0x29, 0x46, +0x31, 0x87, 0x29, 0x67, 0x21, 0x46, 0x31, 0x87, +0x5A, 0xCC, 0xB5, 0x32, 0xE6, 0x76, 0xDE, 0x35, +0xDE, 0x35, 0xDE, 0x35, 0xD6, 0x14, 0xDE, 0x35, +0xDE, 0x35, 0xBD, 0x52, 0xC5, 0xB3, 0xCD, 0xD4, +0xCD, 0xB3, 0xD5, 0xF3, 0xCD, 0xB3, 0xD5, 0xD3, +0xDE, 0x14, 0xDE, 0x34, 0xDE, 0x34, 0xA4, 0x8F, +0xAC, 0xF1, 0xB5, 0x73, 0xBD, 0xB4, 0xBD, 0xD5, +0xBD, 0xB4, 0xB5, 0x73, 0xB5, 0x53, 0xAD, 0x32, +0xAD, 0x32, 0x8C, 0x4F, 0x21, 0x04, 0x10, 0xA2, +0x3A, 0x85, 0x53, 0x88, 0x4B, 0x07, 0x4A, 0xE7, +0x4A, 0xE7, 0x4A, 0x86, 0x5B, 0x08, 0x5B, 0x28, +0x74, 0x0B, 0x7C, 0x6D, 0x8C, 0xAE, 0xA5, 0x30, +0x5B, 0x28, 0x8C, 0xCD, 0x8C, 0xED, 0xC6, 0xD6, +0xD7, 0x39, 0xAD, 0x93, 0x94, 0x8D, 0xAD, 0x2F, +0xAD, 0x0F, 0x9C, 0xAE, 0x94, 0x4E, 0x94, 0x4E, +0x9C, 0x8F, 0x9C, 0xAF, 0x9C, 0xAF, 0xB5, 0x31, +0x9C, 0x8E, 0xAD, 0x10, 0x9C, 0x8E, 0x94, 0x4E, +0x9C, 0xAF, 0x94, 0x4E, 0x8C, 0x2E, 0x9C, 0x8F, +0xBD, 0x73, 0xAD, 0x10, 0xAC, 0xCF, 0x94, 0x4D, +0xA4, 0xAF, 0x9C, 0x6D, 0xBD, 0x51, 0xB5, 0x30, +0x94, 0x4D, 0xA4, 0xF0, 0xB5, 0x72, 0xB5, 0x72, +0xBD, 0xB3, 0xB5, 0x52, 0xCE, 0x35, 0xD6, 0x77, +0xCE, 0x57, 0xA5, 0x12, 0x73, 0x6C, 0x10, 0xA2, +0x19, 0x04, 0x21, 0x25, 0x18, 0xE4, 0x3A, 0x28, +0x8C, 0x91, 0xA5, 0x54, 0xA5, 0x54, 0xAD, 0x74, +0xAD, 0x74, 0xAD, 0x74, 0xB5, 0x94, 0xB5, 0xB5, +0xAD, 0x74, 0xB5, 0x94, 0xAD, 0x94, 0xB5, 0xB4, +0xBD, 0xD5, 0xA4, 0xF2, 0x31, 0x85, 0x10, 0x82, +0x31, 0xA6, 0x8C, 0x50, 0x8C, 0x4F, 0x73, 0xCD, +0x73, 0xAD, 0x84, 0x2F, 0x94, 0x6F, 0x8C, 0x90, +0xAD, 0x53, 0x94, 0x90, 0x9C, 0xB0, 0x9C, 0xAF, +0xA4, 0xEF, 0xAC, 0xCF, 0xAC, 0xCF, 0x9C, 0x8E, +0xAD, 0x10, 0x94, 0x6E, 0xAD, 0x11, 0xC5, 0xD4, +0xBD, 0x93, 0xBD, 0xB3, 0xBD, 0x93, 0xB5, 0x52, +0xAD, 0x31, 0x94, 0x6E, 0xAD, 0x51, 0xB5, 0x52, +0xB5, 0x72, 0xCE, 0x35, 0xA4, 0xCE, 0xB5, 0x30, +0xCE, 0x14, 0xCE, 0x34, 0xC5, 0xF4, 0xAD, 0x32, +0xB5, 0x53, 0x5A, 0xA9, 0x4A, 0x08, 0x42, 0x08, +0x4A, 0x49, 0x52, 0x69, 0x52, 0x8A, 0x52, 0xAA, +0x6B, 0x6D, 0x73, 0x8E, 0x7B, 0xCF, 0xAD, 0x55, +0xCE, 0x18, 0x84, 0x10, 0xAD, 0x34, 0xCE, 0x39, +0xCE, 0x38, 0xCE, 0x59, 0xA4, 0xF3, 0x94, 0x71, +0x9C, 0xD2, 0x8C, 0x2F, 0x8C, 0x2F, 0x9C, 0xB1, +0x8C, 0x0E, 0x84, 0x0E, 0x7B, 0xAD, 0x94, 0x90, +0x7B, 0xAC, 0x52, 0x68, 0x73, 0x6B, 0x94, 0x4F, +0x8C, 0x4E, 0x83, 0xED, 0x84, 0x0D, 0x83, 0xED, +0x7B, 0xAC, 0x83, 0xED, 0x83, 0xEC, 0x94, 0x4E, +0x94, 0x4E, 0xA4, 0xD0, 0xAD, 0x11, 0xC5, 0xF5, +0xCE, 0x15, 0xC5, 0xF4, 0xC5, 0xF5, 0xCE, 0x36, +0xCE, 0x15, 0xBD, 0x93, 0xB5, 0x53, 0xAD, 0x32, +0xB5, 0x52, 0xB5, 0x53, 0xAD, 0x12, 0xAD, 0x32, +0xAD, 0x32, 0xB5, 0x52, 0xBD, 0x73, 0xB5, 0x53, +0xC5, 0xB4, 0xC5, 0xD5, 0xC5, 0xB4, 0xC5, 0xB4, +0xC5, 0xD5, 0xAD, 0x12, 0x8B, 0xEE, 0x4A, 0x48, +0x42, 0x27, 0x4A, 0x28, 0x7B, 0x8D, 0x8C, 0x2F, +0x94, 0x0F, 0x5A, 0x69, 0x83, 0xCE, 0xAD, 0x13, +0x94, 0x50, 0xA4, 0xD2, 0x8C, 0x0F, 0x6B, 0x0B, +0x8B, 0xEF, 0x8C, 0x10, 0x8C, 0x0F, 0xA4, 0xB2, +0xB5, 0x33, 0xBD, 0x94, 0xA4, 0xD1, 0xA4, 0xD0, +0x9C, 0xB0, 0xA4, 0xB0, 0xA4, 0xD0, 0x94, 0x6F, +0xA4, 0xB0, 0x9C, 0xB0, 0x9C, 0x90, 0x9C, 0xD0, +0xAD, 0x32, 0xB5, 0x73, 0xAD, 0x11, 0xC5, 0xF5, +0xCE, 0x36, 0xCE, 0x15, 0x6B, 0x2B, 0x18, 0xA3, +0x10, 0x83, 0x10, 0x83, 0x18, 0xC3, 0x29, 0x86, +0x19, 0x04, 0x19, 0x05, 0x18, 0xE4, 0x18, 0xE4, +0x10, 0xC3, 0x18, 0xC3, 0x41, 0xE7, 0xAD, 0x53, +0xCE, 0x35, 0xD6, 0x76, 0xD6, 0x56, 0xCE, 0x36, +0xBD, 0xB3, 0xB5, 0x52, 0xAD, 0x11, 0xCE, 0x35, +0xB5, 0x73, 0xD6, 0x56, 0xBD, 0x94, 0x5A, 0xCA, +0x18, 0xE4, 0x10, 0xC4, 0x18, 0xE4, 0x18, 0xC4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x19, 0x05, 0x18, 0xE4, 0x18, 0xE5, 0x18, 0xE4, +0x19, 0x05, 0x19, 0x05, 0x19, 0x05, 0x19, 0x05, +0x19, 0x05, 0x19, 0x05, 0x19, 0x05, 0x18, 0xE4, +0x10, 0xC4, 0x18, 0xE4, 0x18, 0xE5, 0x18, 0xE5, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x19, 0x04, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC4, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x18, 0xE4, +0x19, 0x05, 0x21, 0x05, 0x18, 0xE5, 0x19, 0x05, +0x19, 0x05, 0x21, 0x05, 0x29, 0x46, 0x29, 0x46, +0x31, 0x87, 0x29, 0x87, 0x29, 0x87, 0x21, 0x46, +0x4A, 0x4A, 0x7B, 0xAE, 0xE6, 0x97, 0xEE, 0xD7, +0xE6, 0x96, 0xE6, 0x75, 0xE6, 0x75, 0xE6, 0x75, +0xDE, 0x55, 0xDE, 0x35, 0xD5, 0xF4, 0xDE, 0x55, +0xE6, 0x75, 0xE6, 0x75, 0xE6, 0x55, 0xEE, 0x96, +0xE6, 0x75, 0xE6, 0x55, 0xDE, 0x14, 0xAC, 0xD0, +0xAD, 0x11, 0xB5, 0x93, 0xBD, 0xD5, 0xBD, 0xB4, +0xC6, 0x16, 0xAD, 0x53, 0xAD, 0x53, 0xAD, 0x53, +0xAD, 0x53, 0xAD, 0x12, 0x6B, 0x2B, 0x18, 0xA2, +0x7C, 0x8E, 0x63, 0xAA, 0x3A, 0x65, 0x32, 0x05, +0x4A, 0xA7, 0x63, 0x4A, 0x6B, 0xAB, 0x63, 0x8A, +0x52, 0xC8, 0x5B, 0x09, 0x63, 0x4A, 0x84, 0x0C, +0x63, 0x68, 0x5B, 0x88, 0x63, 0xC9, 0x84, 0xAF, +0x73, 0xEC, 0x8C, 0x4D, 0x94, 0x6D, 0x9C, 0x6E, +0xA4, 0xAE, 0xA4, 0xAF, 0xB5, 0x10, 0xAC, 0xEF, +0xB5, 0x10, 0xB5, 0x10, 0xB5, 0x31, 0xB5, 0x10, +0xA4, 0xAE, 0xB5, 0x10, 0xAC, 0xF0, 0xB5, 0x10, +0xB5, 0x30, 0xAC, 0xCF, 0xAC, 0xEF, 0xAC, 0xF0, +0xB5, 0x31, 0xB5, 0x30, 0xB5, 0x10, 0xAC, 0xEF, +0xAC, 0xEF, 0xB4, 0xEF, 0xB5, 0x0F, 0xB4, 0xEF, +0xAC, 0xCF, 0xA4, 0xAF, 0x94, 0x4D, 0x8C, 0x0C, +0x9C, 0x6E, 0xA4, 0xCF, 0xAD, 0x10, 0xB5, 0x51, +0xBD, 0x72, 0xB5, 0x31, 0x9C, 0x6F, 0x29, 0x45, +0x10, 0xA3, 0x42, 0x49, 0x42, 0x28, 0x18, 0xE3, +0x52, 0xCB, 0x8C, 0x91, 0x94, 0xD1, 0x9C, 0xD1, +0x9C, 0xD1, 0xA4, 0xF2, 0xA5, 0x12, 0xAD, 0x33, +0xA5, 0x33, 0xA5, 0x32, 0xA5, 0x12, 0x94, 0xB1, +0x63, 0x2B, 0x18, 0xE3, 0x10, 0x82, 0x10, 0xA3, +0x21, 0x04, 0xAD, 0x54, 0xA5, 0x33, 0x8C, 0x4F, +0x8C, 0x4F, 0xA5, 0x33, 0xAD, 0x53, 0x9D, 0x12, +0xB5, 0x94, 0xAD, 0x53, 0xA4, 0xF1, 0xA4, 0xD0, +0xAC, 0xF0, 0xAC, 0xCE, 0xAC, 0xCE, 0x9C, 0x8E, +0x9C, 0xCF, 0x83, 0xED, 0xB5, 0x72, 0xB5, 0x93, +0xBD, 0x92, 0xBD, 0xB3, 0xBD, 0xD3, 0xA5, 0x10, +0xB5, 0x52, 0x7B, 0xAC, 0x94, 0x8F, 0x94, 0x8F, +0x8C, 0x4E, 0xC5, 0xB3, 0xA4, 0x8E, 0xBD, 0x50, +0xCD, 0xF3, 0xCE, 0x14, 0xAD, 0x31, 0xC5, 0xD4, +0xC5, 0xB4, 0x8C, 0x2F, 0x52, 0x69, 0x52, 0x69, +0x4A, 0x49, 0x52, 0x69, 0x52, 0x8A, 0x63, 0x0C, +0x6B, 0x4D, 0x6B, 0x6D, 0x73, 0x8E, 0x8C, 0x72, +0x9C, 0xF3, 0xA4, 0xF3, 0xC5, 0xF8, 0xD6, 0x7A, +0xD6, 0x79, 0xAD, 0x14, 0xA4, 0xD3, 0xC5, 0xF7, +0x8C, 0x30, 0x9C, 0xB1, 0xA4, 0xF2, 0xA4, 0xF2, +0xAD, 0x12, 0xAD, 0x53, 0xA5, 0x12, 0x9C, 0xB1, +0x6B, 0x2B, 0x63, 0x0B, 0x73, 0xAD, 0x73, 0x8C, +0x6B, 0x4B, 0x7B, 0xAC, 0x84, 0x0D, 0x8C, 0x4F, +0x94, 0x6F, 0x8C, 0x2E, 0x8C, 0x4F, 0x84, 0x0E, +0x83, 0xED, 0x94, 0x6F, 0xB5, 0x32, 0xB5, 0x72, +0xBD, 0x93, 0xBD, 0x93, 0xB5, 0x52, 0xB5, 0x73, +0xBD, 0xB4, 0xA4, 0xF1, 0x94, 0x4F, 0x8C, 0x2F, +0x83, 0xED, 0x8C, 0x2E, 0x83, 0xEE, 0x7B, 0xAD, +0x7B, 0x8D, 0x7B, 0xAD, 0x7B, 0x8C, 0x83, 0xEE, +0x84, 0x0E, 0x9C, 0x90, 0xB5, 0x73, 0xC5, 0xD5, +0xCE, 0x15, 0xAC, 0xF2, 0xB5, 0x33, 0x7B, 0xAD, +0x42, 0x07, 0x41, 0xE7, 0x6B, 0x2B, 0x83, 0xCD, +0xAC, 0xF2, 0x8B, 0xEE, 0x7B, 0x8D, 0x6B, 0x0B, +0x7B, 0x8D, 0x83, 0xCF, 0x62, 0xAA, 0x6B, 0x2C, +0x8B, 0xEF, 0x94, 0x30, 0x94, 0x30, 0x6A, 0xEB, +0x7B, 0x6D, 0x83, 0xAE, 0xA4, 0xB1, 0xAD, 0x12, +0xB5, 0x53, 0xBD, 0x73, 0xBD, 0x73, 0xBD, 0x73, +0xAD, 0x12, 0xB5, 0x52, 0xAD, 0x32, 0xB5, 0x32, +0xBD, 0x73, 0xBD, 0x94, 0xB5, 0x52, 0xAC, 0xF1, +0xA4, 0xD0, 0xAC, 0xF1, 0x52, 0x48, 0x18, 0xA3, +0x10, 0x83, 0x10, 0x83, 0x18, 0xE4, 0x31, 0x87, +0x19, 0x04, 0x19, 0x04, 0x18, 0xE4, 0x18, 0xC4, +0x18, 0xC3, 0x18, 0xE4, 0x6B, 0x6D, 0xC5, 0xF5, +0xC5, 0xB3, 0xB5, 0x52, 0xAC, 0xF1, 0xCE, 0x15, +0xC5, 0xF4, 0xB5, 0x72, 0xAC, 0xF1, 0xC5, 0xD4, +0xCD, 0xF5, 0xD6, 0x76, 0xD6, 0x56, 0xB5, 0x33, +0x39, 0xA6, 0x10, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x19, 0x04, +0x19, 0x05, 0x19, 0x05, 0x19, 0x05, 0x18, 0xE5, +0x18, 0xE4, 0x18, 0xE5, 0x19, 0x05, 0x19, 0x05, +0x19, 0x05, 0x19, 0x05, 0x19, 0x05, 0x18, 0xE4, +0x10, 0xC4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x19, 0x05, 0x18, 0xE5, 0x18, 0xE5, 0x19, 0x05, +0x18, 0xE5, 0x10, 0xA3, 0x10, 0xC4, 0x10, 0xA4, +0x10, 0x83, 0x08, 0x83, 0x10, 0xA4, 0x18, 0xE4, +0x18, 0xE5, 0x19, 0x05, 0x19, 0x05, 0x21, 0x05, +0x19, 0x05, 0x19, 0x05, 0x21, 0x26, 0x29, 0x46, +0x31, 0x87, 0x31, 0x87, 0x31, 0xA8, 0x31, 0xC8, +0x39, 0xE8, 0x4A, 0x4A, 0x8C, 0x30, 0xD6, 0x56, +0xEE, 0xD7, 0xEE, 0xD6, 0xE6, 0x95, 0xEE, 0x96, +0xE6, 0x55, 0xDE, 0x55, 0xCD, 0xF3, 0xDE, 0x54, +0xEE, 0x95, 0xEE, 0x95, 0xEE, 0xB6, 0xEE, 0x96, +0xE6, 0x75, 0xE6, 0x55, 0xDE, 0x14, 0xAC, 0xD0, +0xA4, 0xF1, 0xB5, 0x73, 0xC5, 0xD4, 0xBD, 0xB4, +0xCE, 0x16, 0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x73, +0xB5, 0x74, 0xC5, 0xD4, 0xCE, 0x57, 0x5A, 0xAA, +0x95, 0x31, 0x5B, 0x2A, 0x29, 0x83, 0x52, 0xE9, +0x5B, 0x2A, 0x5B, 0x2A, 0x63, 0x4A, 0x6B, 0xCC, +0x6B, 0xAC, 0x6B, 0xAB, 0x42, 0x67, 0x7B, 0xED, +0x63, 0x49, 0x4B, 0x07, 0x53, 0x08, 0x4A, 0xA8, +0x52, 0xE9, 0x7B, 0xED, 0x84, 0x0D, 0x8C, 0x2E, +0x9C, 0x8F, 0x9C, 0xB0, 0x7B, 0xAB, 0x94, 0x6E, +0xAC, 0xCF, 0xA4, 0xAF, 0xAC, 0xF0, 0xA4, 0xAF, +0x9C, 0x8E, 0xAC, 0xEF, 0x9C, 0x4D, 0x8B, 0xEB, +0x9C, 0x4D, 0x94, 0x0C, 0xA4, 0xCE, 0x94, 0x2D, +0x9C, 0x4D, 0xA4, 0x8E, 0xAC, 0xCF, 0xAC, 0xCF, +0xA4, 0xAE, 0xAC, 0xCE, 0xBD, 0x50, 0xB5, 0x30, +0xB5, 0x30, 0xB5, 0x30, 0xBD, 0x30, 0xBD, 0x30, +0xBD, 0x30, 0xB5, 0x30, 0xBD, 0x50, 0xBD, 0x30, +0xB5, 0x30, 0xBD, 0x50, 0xC5, 0x72, 0x8B, 0xEE, +0x42, 0x07, 0x18, 0xC3, 0x39, 0xE7, 0x21, 0x04, +0x18, 0xE3, 0x4A, 0x89, 0x6B, 0xAD, 0x73, 0xCD, +0x7B, 0xED, 0x84, 0x0E, 0x8C, 0x4F, 0x8C, 0x4F, +0x8C, 0x6F, 0x8C, 0x4F, 0x7B, 0xAD, 0x39, 0xC6, +0x10, 0x82, 0x10, 0xA2, 0x10, 0xA2, 0x10, 0xA3, +0x18, 0xC3, 0xA5, 0x33, 0xD6, 0xB8, 0xB5, 0xB4, +0xAD, 0x73, 0xC6, 0x36, 0xCE, 0x56, 0xBD, 0xF5, +0xBD, 0xF5, 0xB5, 0x94, 0xA4, 0xF1, 0xAD, 0x11, +0xA4, 0xCF, 0xAC, 0xEF, 0xAC, 0xEF, 0x9C, 0x6E, +0x83, 0xEC, 0x6B, 0x6A, 0x9C, 0xD0, 0xC5, 0xD4, +0xC5, 0xF4, 0xBD, 0xB3, 0xBD, 0xB3, 0xA4, 0xF0, +0xAD, 0x52, 0x83, 0xCD, 0x8C, 0x2E, 0x84, 0x0D, +0x7B, 0xAC, 0xAC, 0xF0, 0xA4, 0x6D, 0xBD, 0x30, +0xC5, 0xF3, 0xCD, 0xF4, 0xB5, 0x92, 0xC5, 0xD4, +0xCE, 0x36, 0x9C, 0x70, 0x41, 0xE7, 0x52, 0x69, +0x52, 0x69, 0x52, 0x89, 0x63, 0x0C, 0x73, 0xAE, +0x73, 0x8E, 0x4A, 0x49, 0x6B, 0x4D, 0x8C, 0x72, +0x9C, 0xF3, 0xBD, 0xB7, 0xC6, 0x18, 0xCE, 0x59, +0xAD, 0x14, 0x83, 0xF0, 0xC5, 0xB6, 0xCD, 0xF7, +0x73, 0x4D, 0x9C, 0xB1, 0x6B, 0x0B, 0x62, 0xCA, +0x8C, 0x2F, 0xB5, 0x94, 0xB5, 0x74, 0x6B, 0x6C, +0x5A, 0xEA, 0x7B, 0xEE, 0x8C, 0x50, 0x84, 0x0E, +0x7B, 0xCD, 0x83, 0xEE, 0x94, 0x70, 0xA4, 0xF1, +0xAD, 0x33, 0xA4, 0xF2, 0x9C, 0xD1, 0x94, 0x6F, +0x83, 0xCD, 0x94, 0x4E, 0xB5, 0x52, 0xB5, 0x72, +0xBD, 0x93, 0xB5, 0x72, 0xAD, 0x12, 0x8C, 0x2F, +0x84, 0x0E, 0x84, 0x0E, 0x8C, 0x4F, 0x9C, 0xB0, +0xA4, 0xD1, 0x9C, 0xB1, 0xB5, 0x74, 0xAD, 0x33, +0xAD, 0x33, 0xAD, 0x53, 0xB5, 0x94, 0xA4, 0xF1, +0xA4, 0xD1, 0xB5, 0x53, 0xBD, 0xB4, 0xAD, 0x32, +0xAD, 0x11, 0xAC, 0xF2, 0xB5, 0x33, 0x94, 0x4F, +0x7B, 0xCD, 0x4A, 0x47, 0x41, 0xE6, 0x52, 0x68, +0x83, 0xCD, 0xB5, 0x33, 0xAC, 0xF2, 0x7B, 0x8D, +0x7B, 0x6D, 0x8C, 0x10, 0x73, 0x2C, 0x83, 0xCE, +0x9C, 0x71, 0xA4, 0xB2, 0x8B, 0xEF, 0x83, 0xAE, +0x94, 0x30, 0x94, 0x30, 0x8C, 0x0F, 0x9C, 0x90, +0xC5, 0xF5, 0xBD, 0x94, 0xB5, 0x32, 0xC5, 0xB4, +0xCD, 0xF5, 0xDE, 0x97, 0xCD, 0xF5, 0xCE, 0x15, +0xC5, 0xD4, 0xBD, 0x53, 0xB5, 0x32, 0xAD, 0x32, +0xAD, 0x11, 0xAC, 0xF1, 0x41, 0xA6, 0x18, 0xA3, +0x10, 0x83, 0x10, 0x82, 0x19, 0x04, 0x31, 0xA7, +0x21, 0x04, 0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC3, +0x18, 0xE4, 0x39, 0xA7, 0xA4, 0xF2, 0xAD, 0x32, +0xB5, 0x11, 0xAD, 0x11, 0xAC, 0xF0, 0xAC, 0xF0, +0xAC, 0xF0, 0xAD, 0x10, 0xAD, 0x11, 0xAC, 0xF1, +0xA4, 0xD0, 0xA4, 0xD0, 0xAC, 0xF0, 0xB5, 0x11, +0x62, 0xCA, 0x21, 0x05, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x19, 0x04, 0x19, 0x05, 0x19, 0x05, +0x19, 0x04, 0x19, 0x05, 0x19, 0x05, 0x19, 0x05, +0x19, 0x05, 0x19, 0x04, 0x19, 0x05, 0x19, 0x05, +0x19, 0x04, 0x18, 0xE4, 0x19, 0x04, 0x18, 0xE4, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x19, 0x05, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x10, 0xC4, 0x10, 0xC4, 0x10, 0xA4, +0x10, 0x83, 0x08, 0x83, 0x10, 0xC4, 0x18, 0xE4, +0x19, 0x05, 0x21, 0x25, 0x21, 0x05, 0x21, 0x26, +0x18, 0xE5, 0x19, 0x05, 0x21, 0x46, 0x29, 0x66, +0x31, 0xA7, 0x31, 0xA8, 0x31, 0xC8, 0x39, 0xE9, +0x31, 0xA8, 0x31, 0xC8, 0x4A, 0x2A, 0x7B, 0x8D, +0xB5, 0x32, 0xDE, 0x35, 0xE6, 0x75, 0xE6, 0x75, +0xE6, 0x75, 0xE6, 0x95, 0xD6, 0x14, 0xE6, 0x55, +0xEE, 0xB6, 0xEE, 0xB6, 0xEE, 0xD6, 0xEE, 0xB6, +0xE6, 0x95, 0xE6, 0x75, 0xD5, 0xF3, 0xAC, 0xF0, +0xAD, 0x32, 0xAD, 0x52, 0xBD, 0x94, 0xB5, 0x53, +0xC5, 0xF5, 0xAD, 0x32, 0xB5, 0x73, 0xB5, 0x94, +0xBD, 0x94, 0xC5, 0xF5, 0xCE, 0x36, 0x9C, 0xB1, +0x31, 0xE5, 0x42, 0x87, 0x52, 0xE8, 0x6B, 0xCC, +0x6B, 0xAC, 0x63, 0x8C, 0x6B, 0xAC, 0x6B, 0x8C, +0x73, 0xED, 0x6B, 0x8B, 0x3A, 0x46, 0x7C, 0x4E, +0x5B, 0x08, 0x4A, 0xE7, 0x5B, 0x4B, 0x4A, 0xA9, +0x52, 0xC9, 0x84, 0x2E, 0x8C, 0x4F, 0x94, 0x90, +0xA5, 0x12, 0xA5, 0x32, 0x9C, 0xD1, 0xAD, 0x31, +0xA4, 0xCF, 0xAD, 0x31, 0xC5, 0xD4, 0xAD, 0x31, +0xAD, 0x31, 0xBD, 0x93, 0xBD, 0x93, 0xA4, 0xD0, +0xA4, 0xF0, 0xA4, 0xF0, 0xAC, 0xF0, 0xA4, 0xAF, +0xA4, 0xCF, 0xB5, 0x51, 0xBD, 0x72, 0xBD, 0x92, +0xAC, 0xCF, 0xB5, 0x10, 0x7B, 0x6A, 0x8B, 0xEC, +0x94, 0x2D, 0x9C, 0x8E, 0xC5, 0x92, 0xAC, 0xCF, +0xBD, 0x30, 0xCD, 0xD3, 0xB5, 0x10, 0xBD, 0x30, +0x94, 0x2C, 0x94, 0x2C, 0x9C, 0x2D, 0xA4, 0x6E, +0x9C, 0x6F, 0x7B, 0x8C, 0x42, 0x07, 0x18, 0xE3, +0x18, 0xE4, 0x19, 0x04, 0x29, 0x65, 0x42, 0x27, +0x52, 0xA9, 0x62, 0xEA, 0x63, 0x2A, 0x6B, 0x6B, +0x6B, 0x4B, 0x4A, 0x27, 0x18, 0xC2, 0x10, 0x82, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA2, 0x10, 0xA3, +0x10, 0xA3, 0x73, 0x8D, 0xAD, 0x32, 0xAC, 0xF0, +0xA4, 0xCF, 0xAD, 0x10, 0xAC, 0xF0, 0xA4, 0xAF, +0x94, 0x4E, 0x9C, 0x6E, 0x9C, 0x8E, 0xAD, 0x31, +0x9C, 0x8E, 0xB4, 0xEF, 0xC5, 0x91, 0xBD, 0x51, +0x94, 0x2D, 0x83, 0xCC, 0x73, 0x6B, 0xAD, 0x11, +0xBD, 0x93, 0xBD, 0x92, 0xB5, 0x72, 0x8C, 0x2D, +0x94, 0x6E, 0x83, 0xED, 0x8C, 0x2E, 0x9C, 0xD0, +0xAD, 0x52, 0xA4, 0xAF, 0xA4, 0x8E, 0xAC, 0xEF, +0xC5, 0xB2, 0xC5, 0xF3, 0xBD, 0xD3, 0xC5, 0xF4, +0xD6, 0x56, 0xC5, 0xD5, 0x4A, 0x27, 0x52, 0x89, +0x5A, 0xCA, 0x73, 0x8E, 0x8C, 0x10, 0x62, 0xCB, +0x52, 0x8A, 0x6B, 0x4D, 0x7B, 0xCF, 0x8C, 0x31, +0xA4, 0xF4, 0xBD, 0xD7, 0xB5, 0x55, 0x7B, 0xAF, +0x7B, 0x8E, 0xB5, 0x34, 0xBD, 0x95, 0x8C, 0x0F, +0x62, 0xAA, 0x62, 0xAA, 0x29, 0x24, 0x20, 0xE4, +0x5A, 0xEB, 0xB5, 0x95, 0xB5, 0x74, 0x94, 0xB1, +0x94, 0x91, 0x8C, 0x2F, 0x7B, 0xCE, 0x84, 0x0E, +0x84, 0x0F, 0x8C, 0x4F, 0xAD, 0x33, 0xB5, 0x73, +0xAD, 0x53, 0xA5, 0x32, 0xA5, 0x12, 0x94, 0x90, +0x84, 0x0E, 0x94, 0x4F, 0xB5, 0x53, 0xB5, 0x73, +0xA4, 0xD1, 0x94, 0x4F, 0x8C, 0x2E, 0x6B, 0x6C, +0x84, 0x2E, 0xAD, 0x33, 0x9C, 0xD1, 0x9C, 0x90, +0xAD, 0x12, 0x9C, 0xB1, 0xAD, 0x53, 0xAD, 0x32, +0xAD, 0x12, 0xA5, 0x12, 0xBD, 0xB4, 0xA4, 0xF1, +0x94, 0x90, 0xA4, 0xF1, 0xA4, 0xD1, 0x9C, 0xB0, +0x94, 0x6F, 0xAD, 0x12, 0xAD, 0x32, 0x8C, 0x2E, +0x9C, 0x90, 0x94, 0x6F, 0x5A, 0x88, 0x31, 0x65, +0x41, 0xC6, 0x73, 0x2B, 0xA4, 0xD1, 0x83, 0xCE, +0x62, 0xA9, 0x83, 0xCE, 0x8B, 0xEF, 0x7B, 0x4C, +0x8C, 0x0F, 0x8C, 0x0F, 0x73, 0x2C, 0x8C, 0x0F, +0x9C, 0x71, 0x8B, 0xEF, 0x73, 0x2C, 0x7B, 0x8D, +0x94, 0x2F, 0x9C, 0x91, 0xB5, 0x33, 0xBD, 0x74, +0xB5, 0x53, 0xC5, 0xF5, 0xC5, 0xD4, 0xC5, 0xD4, +0xBD, 0x73, 0xBD, 0x73, 0xBD, 0x93, 0xC5, 0x93, +0xC5, 0xD4, 0x8B, 0xEE, 0x29, 0x25, 0x10, 0x82, +0x10, 0x82, 0x18, 0xC4, 0x21, 0x25, 0x31, 0x86, +0x19, 0x04, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC3, +0x18, 0xC3, 0x4A, 0x49, 0xB5, 0x74, 0xAC, 0xD0, +0xC5, 0xB3, 0xBD, 0x72, 0xB5, 0x31, 0xB5, 0x31, +0xB5, 0x31, 0xAD, 0x11, 0xA4, 0xD0, 0xBD, 0x52, +0xBD, 0x72, 0xCD, 0xF4, 0xD6, 0x15, 0xD6, 0x35, +0x9C, 0x6F, 0x41, 0xE7, 0x18, 0xC4, 0x18, 0xE5, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x19, 0x05, +0x18, 0xE4, 0x19, 0x04, 0x18, 0xE4, 0x19, 0x05, +0x19, 0x04, 0x18, 0xE4, 0x19, 0x04, 0x19, 0x05, +0x19, 0x05, 0x19, 0x05, 0x19, 0x04, 0x10, 0xC4, +0x10, 0xC4, 0x10, 0xA3, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC4, 0x10, 0xC4, +0x10, 0xC4, 0x10, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x08, 0x83, 0x08, 0x83, 0x10, 0xC4, 0x18, 0xE4, +0x19, 0x05, 0x21, 0x05, 0x18, 0xE5, 0x21, 0x26, +0x18, 0xE5, 0x21, 0x06, 0x29, 0x46, 0x31, 0x87, +0x31, 0xA8, 0x31, 0xA8, 0x31, 0xC8, 0x39, 0xC8, +0x29, 0x67, 0x31, 0xC8, 0x42, 0x0A, 0x4A, 0x6A, +0x63, 0x0C, 0xAC, 0xF1, 0xDE, 0x54, 0xEE, 0x95, +0xE6, 0x95, 0xE6, 0x75, 0xE6, 0x75, 0xE6, 0x75, +0xE6, 0x75, 0xE6, 0x54, 0xEE, 0x95, 0xEE, 0xB6, +0xEE, 0x95, 0xEE, 0x95, 0xCD, 0x93, 0xB5, 0x11, +0xA4, 0xF1, 0xAD, 0x12, 0xBD, 0x94, 0xAD, 0x32, +0xBD, 0xB4, 0xAD, 0x53, 0xB5, 0x53, 0xB5, 0x73, +0xBD, 0xB4, 0xB5, 0x93, 0xC5, 0xF5, 0xBD, 0xB4, +0x32, 0x06, 0x21, 0x62, 0x29, 0xC4, 0x42, 0x67, +0x4A, 0xC9, 0x73, 0xED, 0x7C, 0x0E, 0x7C, 0x0E, +0x7C, 0x2E, 0x73, 0xAC, 0x3A, 0x25, 0x6B, 0xCC, +0x7C, 0x4E, 0x95, 0x11, 0x94, 0xF2, 0x73, 0xCE, +0x5B, 0x0B, 0x84, 0x2F, 0x8C, 0x90, 0xA5, 0x33, +0xC6, 0x16, 0xAD, 0x53, 0xAD, 0x54, 0xB5, 0x53, +0xAC, 0xD0, 0xBD, 0x93, 0xDE, 0x97, 0xC5, 0xF4, +0xB5, 0x52, 0xAD, 0x11, 0xA4, 0xD0, 0xAD, 0x31, +0xC5, 0xD4, 0xC5, 0xB3, 0xCD, 0xD4, 0xCD, 0xD4, +0xC5, 0xB3, 0xCD, 0xF4, 0xC5, 0xD3, 0xC5, 0xB3, +0xC5, 0xB3, 0xC5, 0xB3, 0x9C, 0x8E, 0xA4, 0xF1, +0xA4, 0xAF, 0x9C, 0xAF, 0xC5, 0xD3, 0x9C, 0x4D, +0xBD, 0x30, 0xD6, 0x15, 0xDE, 0x76, 0xDE, 0x55, +0xA4, 0xD0, 0xB5, 0x31, 0xB5, 0x52, 0xB5, 0x52, +0xB5, 0x11, 0x9C, 0x8F, 0x94, 0x4F, 0x7B, 0x8D, +0x18, 0xE3, 0x10, 0xC3, 0x19, 0x04, 0x29, 0x65, +0x39, 0xC7, 0x39, 0xE6, 0x31, 0xC6, 0x31, 0x85, +0x18, 0xC2, 0x10, 0x82, 0x10, 0x82, 0x10, 0xA2, +0x10, 0x82, 0x08, 0x82, 0x10, 0xA2, 0x10, 0xA3, +0x10, 0xA3, 0x52, 0x69, 0xA4, 0xB0, 0xA4, 0x8E, +0xA4, 0x8E, 0xA4, 0xAE, 0xA4, 0xAE, 0xAC, 0xCF, +0xAC, 0xEF, 0xAC, 0xEF, 0xAC, 0xCF, 0xAC, 0xCF, +0xBD, 0x30, 0xBD, 0x51, 0xBD, 0x51, 0xBD, 0x51, +0xBD, 0x51, 0xBD, 0x51, 0xBD, 0x31, 0xB5, 0x10, +0xB5, 0x10, 0xB5, 0x10, 0xAC, 0xCF, 0xA4, 0xAF, +0xB5, 0x10, 0xB5, 0x10, 0xBD, 0x31, 0xB5, 0x30, +0xBD, 0x71, 0xBD, 0x30, 0xB5, 0x10, 0xA4, 0x8D, +0xAC, 0xCE, 0xBD, 0x72, 0xAD, 0x31, 0xC5, 0xD4, +0xB5, 0x52, 0xA4, 0xD1, 0x94, 0x4F, 0x7B, 0x8D, +0x6B, 0x2C, 0x73, 0x4D, 0x63, 0x0C, 0x52, 0x6A, +0x7B, 0x8E, 0x83, 0xF0, 0x94, 0x72, 0xAD, 0x76, +0xCE, 0x39, 0x9C, 0xD3, 0x5A, 0x8B, 0x62, 0xCB, +0x94, 0x51, 0xAD, 0x14, 0x9C, 0xB2, 0x6A, 0xEB, +0x5A, 0x69, 0x49, 0xE7, 0x29, 0x24, 0x41, 0xE7, +0x9C, 0xD2, 0xAD, 0x33, 0xB5, 0x74, 0x94, 0xB1, +0x94, 0xB1, 0x9C, 0xD2, 0x84, 0x0E, 0x83, 0xEE, +0x94, 0x70, 0x94, 0x90, 0xB5, 0x53, 0xA5, 0x12, +0xAD, 0x32, 0xB5, 0x94, 0xAD, 0x53, 0x9C, 0xD1, +0x8C, 0x2E, 0x94, 0x6F, 0xBD, 0x94, 0xA4, 0xB0, +0x63, 0x0A, 0x6B, 0x4B, 0x73, 0x6C, 0x7B, 0xCD, +0x83, 0xED, 0x9C, 0xF1, 0xC5, 0xF5, 0xA4, 0xF1, +0x94, 0x6F, 0x9C, 0x90, 0x9C, 0xB0, 0xA4, 0xF1, +0xA4, 0xF2, 0x9C, 0xD1, 0x9C, 0x90, 0x94, 0x90, +0x9C, 0xD1, 0xA4, 0xD1, 0x8C, 0x2F, 0x73, 0x6C, +0x8C, 0x0E, 0xAD, 0x12, 0xB5, 0x53, 0xA4, 0xD0, +0x9C, 0x8F, 0x9C, 0xD0, 0x94, 0x6F, 0x5A, 0xC9, +0x39, 0xA6, 0x39, 0xA5, 0x62, 0xC9, 0x8B, 0xEE, +0x73, 0x2C, 0x52, 0x48, 0x52, 0x48, 0x73, 0x4C, +0x6A, 0xEB, 0x7B, 0x4D, 0x73, 0x0C, 0x94, 0x10, +0x7B, 0x4C, 0x7B, 0x6D, 0x8B, 0xEF, 0x73, 0x0C, +0x6A, 0xEB, 0x6A, 0xEB, 0x8C, 0x0F, 0xB5, 0x54, +0xAD, 0x13, 0xAD, 0x13, 0xB5, 0x53, 0xAD, 0x32, +0xAD, 0x32, 0xA4, 0xB0, 0x8C, 0x0D, 0x94, 0x4E, +0x8C, 0x0E, 0x4A, 0x07, 0x31, 0x65, 0x21, 0x04, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x21, 0x25, +0x18, 0xE4, 0x18, 0xC3, 0x18, 0xE4, 0x18, 0xC3, +0x31, 0xA6, 0x8C, 0x2F, 0xB5, 0x32, 0xB5, 0x31, +0xCD, 0xF4, 0xC5, 0xB3, 0xB5, 0x32, 0xB5, 0x52, +0xAC, 0xF1, 0xA4, 0x8F, 0x83, 0xAC, 0x9C, 0x6E, +0xA4, 0xAF, 0xB5, 0x31, 0xBD, 0x52, 0xBD, 0x51, +0xAD, 0x11, 0x7B, 0x8D, 0x29, 0x45, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x19, 0x04, 0x19, 0x05, +0x21, 0x25, 0x21, 0x25, 0x18, 0xE4, 0x18, 0xE4, +0x19, 0x04, 0x18, 0xE4, 0x18, 0xC4, 0x18, 0xE4, +0x19, 0x05, 0x19, 0x05, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x10, 0xA3, 0x10, 0xA3, 0x18, 0xE4, +0x10, 0xC4, 0x10, 0xC4, 0x18, 0xC4, 0x10, 0xC4, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, +0x08, 0x83, 0x10, 0x83, 0x10, 0xC4, 0x18, 0xE4, +0x18, 0xE5, 0x19, 0x05, 0x18, 0xE5, 0x21, 0x26, +0x18, 0xE5, 0x21, 0x46, 0x29, 0x47, 0x31, 0xA8, +0x31, 0x88, 0x31, 0x87, 0x31, 0xA8, 0x31, 0xA8, +0x31, 0xA8, 0x42, 0x2A, 0x42, 0x09, 0x42, 0x09, +0x4A, 0x4A, 0x73, 0x6D, 0xA4, 0x90, 0xA4, 0x8F, +0xB5, 0x10, 0xBD, 0x51, 0xC5, 0x92, 0xCD, 0xD3, +0xD5, 0xD3, 0xD5, 0xD3, 0xD5, 0xD3, 0xD5, 0xD3, +0xDE, 0x34, 0xB4, 0xF0, 0x83, 0x8B, 0xA4, 0xF1, +0x8C, 0x2E, 0x94, 0x4E, 0x9C, 0xB0, 0x9C, 0xD0, +0x9C, 0xD0, 0xA4, 0xF1, 0xA4, 0xF1, 0xAD, 0x32, +0xAD, 0x32, 0xA4, 0xF1, 0x9C, 0xAF, 0xAD, 0x11, +0x4A, 0x88, 0x73, 0xCD, 0x5B, 0x2A, 0x84, 0x4F, +0x84, 0x4F, 0x7C, 0x0E, 0x8C, 0x90, 0x8C, 0x91, +0x8C, 0x90, 0x8C, 0x6E, 0x3A, 0x25, 0x53, 0x09, +0x63, 0x8B, 0x84, 0x6F, 0x84, 0x4F, 0x73, 0xAD, +0x6B, 0x8D, 0x8C, 0x91, 0xA5, 0x33, 0xB5, 0x94, +0xC6, 0x37, 0xAD, 0x74, 0xAD, 0x94, 0xAD, 0x52, +0xA4, 0xD0, 0xAD, 0x31, 0xCE, 0x36, 0xBD, 0xB3, +0xB5, 0x73, 0x8C, 0x2E, 0x6B, 0x2B, 0xCE, 0x15, +0xD6, 0x56, 0xCD, 0xF4, 0xCD, 0xF3, 0xCD, 0xD4, +0xD6, 0x14, 0xD6, 0x14, 0xCD, 0xF4, 0xCD, 0xF4, +0xCD, 0xF4, 0xCD, 0xF4, 0xBD, 0x92, 0xBD, 0x93, +0xBD, 0x93, 0xAD, 0x31, 0xB5, 0x51, 0x9C, 0x6E, +0xBD, 0x51, 0xCD, 0xD3, 0xDE, 0x55, 0xD6, 0x15, +0xC5, 0xB3, 0xC5, 0xF5, 0xCE, 0x15, 0xC5, 0xF4, +0xA4, 0xD1, 0x8B, 0xED, 0x62, 0xCA, 0x5A, 0xCA, +0x21, 0x24, 0x10, 0xA3, 0x08, 0x82, 0x10, 0xA3, +0x31, 0x86, 0x3A, 0x08, 0x39, 0xC7, 0x18, 0xC3, +0x08, 0x62, 0x10, 0x82, 0x10, 0x82, 0x10, 0x82, +0x10, 0x82, 0x08, 0x82, 0x10, 0xA2, 0x10, 0xA2, +0x10, 0xA3, 0x31, 0x86, 0x84, 0x0E, 0x7B, 0xAC, +0x7B, 0x6B, 0x73, 0x6A, 0x73, 0x4A, 0x7B, 0x8A, +0x7B, 0x6A, 0x73, 0x29, 0x73, 0x29, 0x7B, 0x8A, +0x83, 0xCB, 0x9C, 0x4D, 0x8B, 0xEB, 0xA4, 0x8E, +0xA4, 0xAE, 0xAC, 0xCF, 0xAC, 0xCF, 0xC5, 0x91, +0xB5, 0x0F, 0xAC, 0xCE, 0xB5, 0x0F, 0xB4, 0xEF, +0xB5, 0x30, 0xB5, 0x10, 0xB5, 0x0F, 0xB4, 0xEF, +0xB5, 0x0F, 0xBD, 0x10, 0xAC, 0xCE, 0xB4, 0xEF, +0xA4, 0xAE, 0xBD, 0x93, 0xAD, 0x32, 0x8C, 0x0E, +0x83, 0x8B, 0x83, 0xCC, 0xA4, 0x90, 0x8C, 0x0F, +0x7B, 0x8D, 0x5A, 0xAA, 0x62, 0xCB, 0x62, 0xCB, +0x8C, 0x51, 0xA5, 0x14, 0xB5, 0x96, 0xAD, 0x76, +0x7B, 0xCF, 0x42, 0x29, 0x6B, 0x2D, 0x6B, 0x2D, +0x73, 0x8E, 0xAD, 0x14, 0x8C, 0x30, 0x52, 0x28, +0x52, 0x28, 0x4A, 0x28, 0x52, 0x28, 0x6A, 0xEA, +0x62, 0xEB, 0x8C, 0x4F, 0x9C, 0xB1, 0x94, 0x70, +0x73, 0x8C, 0x9C, 0xD1, 0x9C, 0xB1, 0x9C, 0xD1, +0xAD, 0x12, 0xA4, 0xD2, 0xAD, 0x53, 0xB5, 0x73, +0xBD, 0xB4, 0xBD, 0xB4, 0xB5, 0x73, 0xAD, 0x32, +0x9C, 0xD0, 0x8C, 0x4F, 0xBD, 0xB4, 0xBD, 0x73, +0x94, 0x4F, 0x8C, 0x2F, 0x84, 0x0E, 0x8C, 0x2F, +0x73, 0xAC, 0x84, 0x0E, 0x9C, 0xD1, 0x84, 0x0E, +0x73, 0x6B, 0x94, 0x6F, 0x7B, 0xCD, 0x94, 0x90, +0x9C, 0xD1, 0xA5, 0x12, 0x8C, 0x2F, 0x94, 0x4F, +0x8C, 0x2F, 0x8C, 0x4F, 0x8C, 0x4F, 0x73, 0x8D, +0x8C, 0x2F, 0xB5, 0x52, 0xB5, 0x53, 0xAD, 0x32, +0xAD, 0x31, 0x94, 0x6F, 0x9C, 0x90, 0x94, 0x6F, +0x63, 0x0A, 0x4A, 0x28, 0x42, 0x07, 0x6B, 0x2B, +0x5A, 0xAA, 0x4A, 0x28, 0x41, 0xE7, 0x62, 0xCA, +0x83, 0xAE, 0x8B, 0xCF, 0x73, 0x0C, 0x6A, 0xEB, +0x83, 0xCF, 0x83, 0xCE, 0x9C, 0x92, 0x7B, 0x6D, +0x94, 0x50, 0x83, 0xCE, 0x94, 0x30, 0x9C, 0x71, +0x94, 0x30, 0x8B, 0xEE, 0x94, 0x30, 0x83, 0xCE, +0x94, 0x2F, 0x39, 0xA6, 0x18, 0xC3, 0x18, 0xA2, +0x18, 0xE3, 0x41, 0xE7, 0x31, 0x66, 0x20, 0xE4, +0x10, 0xC3, 0x10, 0x83, 0x10, 0xA3, 0x18, 0xE4, +0x18, 0xC4, 0x18, 0xC3, 0x18, 0xE4, 0x21, 0x04, +0x94, 0x70, 0xB5, 0x73, 0xAD, 0x11, 0xB5, 0x32, +0xBD, 0x93, 0xBD, 0x93, 0xBD, 0xB3, 0xBD, 0xB3, +0xC5, 0xB3, 0xC5, 0xD4, 0xAC, 0xD0, 0xBD, 0x73, +0xC5, 0xD4, 0xC5, 0x93, 0xBD, 0x52, 0xBD, 0x93, +0xB5, 0x72, 0x94, 0x4F, 0x5A, 0x8A, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x19, 0x04, 0x19, 0x05, +0x21, 0x05, 0x21, 0x25, 0x18, 0xE4, 0x18, 0xE4, +0x19, 0x04, 0x19, 0x04, 0x18, 0xC4, 0x18, 0xE4, +0x18, 0xE4, 0x21, 0x05, 0x19, 0x05, 0x19, 0x05, +0x18, 0xE4, 0x10, 0xC3, 0x10, 0xA3, 0x10, 0xC4, +0x10, 0xC4, 0x10, 0xC3, 0x10, 0xC4, 0x10, 0xC3, +0x10, 0x83, 0x08, 0x83, 0x08, 0x83, 0x08, 0x83, +0x08, 0x83, 0x10, 0xA3, 0x18, 0xC4, 0x18, 0xE4, +0x18, 0xE4, 0x19, 0x05, 0x19, 0x05, 0x21, 0x26, +0x21, 0x26, 0x21, 0x46, 0x29, 0x46, 0x29, 0x87, +0x21, 0x46, 0x29, 0x67, 0x29, 0x87, 0x31, 0x87, +0x39, 0xE9, 0x3A, 0x09, 0x39, 0xC8, 0x31, 0xC8, +0x42, 0x09, 0x52, 0xCC, 0x84, 0x0F, 0xB5, 0x32, +0xB5, 0x52, 0xB5, 0x52, 0xB5, 0x32, 0xB5, 0x32, +0xB5, 0x12, 0xAC, 0xF1, 0xAC, 0xF1, 0xB5, 0x11, +0xAD, 0x11, 0xA4, 0xB0, 0xAD, 0x32, 0xBD, 0x93, +0xB5, 0x32, 0xA4, 0xF1, 0xA4, 0xD1, 0x9C, 0x90, +0x9C, 0x90, 0x94, 0x6F, 0x8C, 0x2E, 0x94, 0x4F, +0x8C, 0x2E, 0x8C, 0x0E, 0x83, 0xED, 0x83, 0xED, +0x8C, 0xB0, 0x94, 0xB1, 0x6B, 0x6C, 0x8C, 0xB0, +0x7C, 0x2F, 0x94, 0xB1, 0xB5, 0xF6, 0xAD, 0x94, +0x9C, 0xD1, 0x52, 0x87, 0x42, 0x26, 0x63, 0x8B, +0x74, 0x2E, 0x84, 0x90, 0x8C, 0xB0, 0x84, 0x50, +0x84, 0x2F, 0x9C, 0xF2, 0xAD, 0x74, 0xAD, 0x74, +0xC6, 0x57, 0xB5, 0xB5, 0xAD, 0x74, 0x9C, 0xD0, +0xAC, 0xF0, 0xB5, 0x52, 0xC5, 0xD4, 0xBD, 0x93, +0xB5, 0x52, 0xB5, 0x73, 0xB5, 0x52, 0xCE, 0x15, +0xDE, 0x76, 0xD6, 0x15, 0xCE, 0x14, 0xCE, 0x14, +0xDE, 0x76, 0xD6, 0x35, 0xCE, 0x14, 0xCD, 0xF4, +0xCD, 0xF4, 0xD6, 0x55, 0xD6, 0x15, 0xCD, 0xF4, +0xCE, 0x14, 0xBD, 0xB3, 0xAD, 0x11, 0x9C, 0x8E, +0xBD, 0x51, 0xA4, 0xAE, 0xBD, 0x92, 0xC5, 0xB3, +0xC5, 0xD4, 0xD6, 0x56, 0xD6, 0x76, 0xD6, 0x36, +0xA4, 0xB1, 0x8C, 0x2F, 0x73, 0x6C, 0x4A, 0x08, +0x18, 0xE4, 0x10, 0xC3, 0x19, 0x04, 0x29, 0x86, +0x31, 0xC8, 0x31, 0xC8, 0x39, 0xE8, 0x4A, 0x6A, +0x29, 0x46, 0x08, 0x62, 0x08, 0x62, 0x08, 0x82, +0x08, 0x82, 0x08, 0x82, 0x08, 0x82, 0x08, 0x82, +0x10, 0xA3, 0x21, 0x25, 0xAD, 0x53, 0xB5, 0x53, +0xB5, 0x53, 0xAD, 0x32, 0x9C, 0xB0, 0x9C, 0xB0, +0xA4, 0xF1, 0xA4, 0xD1, 0x94, 0x6F, 0x8C, 0x2E, +0x94, 0x6E, 0x94, 0x4E, 0x8B, 0xED, 0x9C, 0xAF, +0xAD, 0x11, 0xA4, 0xAF, 0x8C, 0x0D, 0xAC, 0xEF, +0x9C, 0x4D, 0xA4, 0x6D, 0xA4, 0x6D, 0xA4, 0x8E, +0xBD, 0x51, 0xAD, 0x11, 0xAC, 0xD0, 0x7B, 0x8B, +0x73, 0x2A, 0x7B, 0x8B, 0x8C, 0x0C, 0x9C, 0x6E, +0x83, 0xCD, 0xAD, 0x13, 0xA4, 0xF2, 0x73, 0x4C, +0x73, 0x4B, 0xA4, 0x90, 0x9C, 0x4F, 0x6A, 0xCA, +0x6B, 0x2C, 0x7B, 0xAE, 0xA4, 0xF3, 0x94, 0x72, +0x7B, 0xAE, 0x52, 0x8A, 0x39, 0xA7, 0x4A, 0x6A, +0x62, 0xEC, 0x73, 0x6E, 0x63, 0x0C, 0x6B, 0x0C, +0x7B, 0x8E, 0x83, 0xEF, 0x73, 0x2C, 0x6B, 0x2C, +0x5A, 0x89, 0x31, 0x44, 0x29, 0x44, 0x39, 0x85, +0x62, 0xEB, 0x9C, 0x91, 0x94, 0x50, 0x94, 0x50, +0x8C, 0x2E, 0x94, 0x0D, 0x94, 0x0D, 0x94, 0x4E, +0x9C, 0x8E, 0x9C, 0x8F, 0xA4, 0x8F, 0xA4, 0xD0, +0xB5, 0x11, 0xAD, 0x11, 0xAD, 0x11, 0xAC, 0xF1, +0xAD, 0x11, 0x94, 0x4E, 0xA4, 0xD0, 0xAD, 0x12, +0xAD, 0x32, 0x9C, 0x90, 0x7B, 0xAD, 0x7B, 0x8C, +0x7B, 0xCD, 0x83, 0xEE, 0x83, 0xEE, 0x8C, 0x4F, +0x94, 0x6F, 0xA4, 0xF1, 0x9C, 0xB0, 0x8C, 0x2E, +0x83, 0xED, 0x83, 0xEE, 0x73, 0x8C, 0x83, 0xEE, +0x8C, 0x0E, 0x94, 0x70, 0x94, 0x70, 0x9C, 0xB1, +0x9C, 0x90, 0xAC, 0xF1, 0xB5, 0x52, 0xB5, 0x32, +0xC5, 0xD4, 0xB5, 0x52, 0xBD, 0x93, 0xC5, 0xF4, +0xBD, 0x93, 0x8C, 0x2E, 0x41, 0xE6, 0x41, 0xE6, +0x41, 0xE7, 0x41, 0xE7, 0x42, 0x07, 0x41, 0xE7, +0xA5, 0x14, 0xBD, 0x96, 0x94, 0x71, 0x62, 0xCB, +0x62, 0xEB, 0x6A, 0xEB, 0x83, 0xCF, 0x73, 0x2C, +0x94, 0x30, 0x6A, 0xEB, 0x8B, 0xEF, 0xAC, 0xD2, +0x94, 0x30, 0x83, 0x8D, 0x52, 0x49, 0x4A, 0x07, +0x6B, 0x0B, 0x73, 0x4D, 0x83, 0xEF, 0x62, 0xEB, +0x29, 0x24, 0x31, 0x86, 0x21, 0x04, 0x18, 0xC3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, +0x18, 0xE4, 0x18, 0xC3, 0x18, 0xE4, 0x29, 0x65, +0xAD, 0x53, 0xC5, 0xD4, 0xAC, 0xF1, 0xBD, 0x73, +0xC5, 0xD4, 0xC5, 0xB3, 0xC5, 0xD4, 0xCD, 0xF4, +0xCD, 0xF4, 0xCD, 0xD4, 0xBD, 0x73, 0xCD, 0xF4, +0xD6, 0x36, 0xCE, 0x15, 0xCD, 0xF5, 0xCD, 0xF5, +0xCE, 0x15, 0xB5, 0x32, 0x83, 0xEE, 0x29, 0x65, +0x18, 0xE4, 0x18, 0xE4, 0x19, 0x04, 0x18, 0xE4, +0x18, 0xE4, 0x21, 0x05, 0x18, 0xE4, 0x18, 0xE4, +0x19, 0x04, 0x19, 0x05, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x19, 0x04, 0x18, 0xE5, +0x18, 0xE4, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA4, 0x10, 0xA3, 0x10, 0xA3, +0x08, 0x83, 0x08, 0x83, 0x08, 0x83, 0x08, 0x83, +0x10, 0x83, 0x10, 0xA3, 0x10, 0xC4, 0x10, 0xC4, +0x18, 0xE4, 0x19, 0x05, 0x19, 0x05, 0x21, 0x26, +0x21, 0x26, 0x21, 0x26, 0x21, 0x46, 0x21, 0x26, +0x18, 0xE5, 0x29, 0x46, 0x29, 0x67, 0x29, 0x87, +0x31, 0xC8, 0x39, 0xC9, 0x39, 0xC8, 0x39, 0xE9, +0x42, 0x2A, 0x3A, 0x09, 0x42, 0x49, 0xA4, 0xF2, +0xCE, 0x16, 0xBD, 0x73, 0xBD, 0x93, 0xA4, 0xB0, +0xAC, 0xF1, 0xCD, 0xD4, 0xBD, 0x52, 0x9C, 0x8F, +0x83, 0xCD, 0x7B, 0xAC, 0x94, 0x2E, 0xAD, 0x11, +0xB5, 0x52, 0x9C, 0x6F, 0xA4, 0xF1, 0xAD, 0x12, +0xA4, 0xD1, 0x9C, 0x6F, 0x9C, 0xAF, 0xAD, 0x11, +0xAD, 0x11, 0xAD, 0x32, 0xB5, 0x52, 0xB5, 0x52, +0x9D, 0x53, 0x8C, 0xB0, 0x5A, 0xC9, 0x73, 0xAD, +0x7C, 0x2E, 0xC6, 0x37, 0xB5, 0xD6, 0x7C, 0x2F, +0x5A, 0xEA, 0x63, 0x0A, 0x52, 0x87, 0x31, 0xE4, +0x3A, 0x46, 0x63, 0x8C, 0x94, 0xF1, 0x9C, 0xF2, +0x9D, 0x13, 0xA5, 0x54, 0xBD, 0xF6, 0xBD, 0xD5, +0xC6, 0x16, 0xBD, 0xD5, 0xA5, 0x33, 0xA4, 0xF1, +0xAD, 0x10, 0xB5, 0x52, 0xAD, 0x11, 0xBD, 0x93, +0xBD, 0xB3, 0xBD, 0xD4, 0xC5, 0xD4, 0xCE, 0x35, +0xD6, 0x56, 0xC5, 0xF4, 0xD6, 0x35, 0xD6, 0x15, +0xD6, 0x56, 0xCD, 0xD4, 0xC5, 0xD4, 0xD6, 0x35, +0xDE, 0x56, 0xDE, 0x56, 0xBD, 0x52, 0xCE, 0x15, +0xBD, 0xB3, 0xBD, 0xB3, 0xAD, 0x32, 0x9C, 0x4E, +0xBD, 0x30, 0xAC, 0xCF, 0xC5, 0x93, 0xCD, 0xF4, +0xCE, 0x35, 0xD6, 0x77, 0xD6, 0x77, 0x8C, 0x0E, +0x8B, 0xEF, 0x8C, 0x10, 0x62, 0xCB, 0x39, 0xA7, +0x42, 0x08, 0x39, 0xE8, 0x29, 0x86, 0x31, 0xA7, +0x29, 0x66, 0x29, 0x86, 0x21, 0x45, 0x42, 0x29, +0x63, 0x0D, 0x29, 0x45, 0x10, 0xA3, 0x08, 0x62, +0x08, 0x82, 0x08, 0x82, 0x08, 0x82, 0x10, 0xA2, +0x18, 0xC3, 0x21, 0x24, 0xBD, 0xF6, 0xCE, 0x36, +0xCE, 0x16, 0xAD, 0x53, 0xAD, 0x32, 0xCE, 0x36, +0xCE, 0x57, 0xCE, 0x36, 0xC5, 0xF5, 0xBD, 0x94, +0xAD, 0x52, 0xAD, 0x11, 0xAD, 0x32, 0xB5, 0x93, +0xB5, 0x73, 0xA4, 0xF1, 0x8C, 0x0D, 0xA4, 0xCF, +0xAC, 0xAE, 0xAC, 0xCF, 0xC5, 0xB2, 0xC5, 0xB2, +0xBD, 0xB3, 0xBD, 0xD4, 0xB5, 0x93, 0x9C, 0xF1, +0x94, 0x6F, 0x8C, 0x4F, 0x94, 0x90, 0x83, 0xEE, +0x41, 0xE7, 0x5A, 0x8A, 0x5A, 0xAA, 0x5A, 0xCB, +0x5A, 0xAA, 0x8B, 0xEE, 0x83, 0xAD, 0x5A, 0x89, +0x62, 0xAA, 0x5A, 0x69, 0x62, 0xEB, 0xA4, 0xF4, +0x7B, 0xCF, 0x5A, 0xAB, 0x42, 0x08, 0x39, 0xC7, +0x62, 0xEC, 0x8C, 0x10, 0x5A, 0xAA, 0x83, 0xAF, +0x73, 0x6D, 0x7B, 0xAE, 0x63, 0x0B, 0x52, 0x69, +0x4A, 0x48, 0x39, 0x85, 0x29, 0x24, 0x39, 0x85, +0x62, 0xEB, 0x83, 0xEF, 0x8C, 0x30, 0x7B, 0x8D, +0xAC, 0xF1, 0xBD, 0x31, 0xBD, 0x31, 0xBD, 0x51, +0xBD, 0x51, 0xB5, 0x31, 0xB5, 0x10, 0xBD, 0x10, +0xBD, 0x31, 0xBD, 0x31, 0xBD, 0x31, 0xBD, 0x10, +0xBD, 0x31, 0xB5, 0x10, 0xB5, 0x11, 0xB5, 0x32, +0xAD, 0x12, 0xAD, 0x11, 0xB5, 0x53, 0xB5, 0x73, +0xB5, 0x33, 0xAC, 0xF1, 0xA4, 0xD1, 0xA4, 0xD1, +0x9C, 0x8F, 0x9C, 0x90, 0x9C, 0x90, 0x9C, 0x70, +0x94, 0x4F, 0x94, 0x4F, 0x8C, 0x2E, 0x8C, 0x2F, +0x8C, 0x2F, 0x8C, 0x2E, 0x8C, 0x2F, 0x94, 0x4F, +0x94, 0x4F, 0xAD, 0x11, 0xB5, 0x32, 0xB5, 0x31, +0xB5, 0x52, 0xCD, 0xF4, 0xC5, 0xF4, 0xBD, 0xB3, +0xC5, 0xD4, 0xBD, 0x93, 0x83, 0xAC, 0x31, 0x85, +0x31, 0x65, 0x39, 0xA6, 0x31, 0x85, 0x42, 0x08, +0x94, 0x92, 0x7B, 0xCF, 0x7B, 0xCF, 0x7B, 0xCF, +0xB5, 0x96, 0x83, 0xF0, 0x62, 0xEB, 0x5A, 0x8A, +0x7B, 0x6D, 0x5A, 0x69, 0x7B, 0x4D, 0x93, 0xEF, +0x7B, 0x2C, 0x8B, 0xCE, 0x62, 0xCB, 0x62, 0xCB, +0x73, 0x2C, 0x6B, 0x0C, 0x83, 0xCF, 0x9C, 0x71, +0x8C, 0x30, 0x4A, 0x08, 0x20, 0xE4, 0x18, 0xC4, +0x10, 0xC4, 0x18, 0xC4, 0x10, 0xA3, 0x10, 0x83, +0x10, 0x83, 0x10, 0xA3, 0x10, 0xC3, 0x42, 0x08, +0xC5, 0xD5, 0xCD, 0xF5, 0xAC, 0xD0, 0xC5, 0x93, +0xDE, 0x35, 0xD6, 0x14, 0xD5, 0xF4, 0xD5, 0xF4, +0xD6, 0x14, 0xD6, 0x35, 0xCD, 0xB3, 0xD5, 0xF5, +0xCD, 0xF4, 0xCD, 0xD4, 0xC5, 0x93, 0xBD, 0x92, +0xAC, 0xF0, 0xC5, 0xB4, 0xAD, 0x12, 0x5A, 0xCA, +0x29, 0x45, 0x18, 0xE4, 0x19, 0x05, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xE4, 0x19, 0x05, 0x18, 0xE4, 0x18, 0xE4, +0x19, 0x04, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x08, 0x83, 0x08, 0x83, +0x08, 0x83, 0x10, 0x83, 0x08, 0x83, 0x08, 0x83, +0x08, 0x83, 0x10, 0xA3, 0x10, 0xC4, 0x10, 0xC4, +0x18, 0xE4, 0x19, 0x05, 0x21, 0x05, 0x21, 0x26, +0x21, 0x26, 0x21, 0x26, 0x21, 0x26, 0x19, 0x05, +0x21, 0x26, 0x21, 0x26, 0x21, 0x46, 0x29, 0x67, +0x31, 0x87, 0x39, 0xC8, 0x39, 0xE9, 0x39, 0xE9, +0x31, 0xA8, 0x31, 0x88, 0x31, 0x87, 0x6B, 0x4C, +0xC5, 0xD5, 0xC5, 0xB4, 0xBD, 0x94, 0xA4, 0xF1, +0xA4, 0xB0, 0xB5, 0x32, 0xBD, 0x72, 0xBD, 0x93, +0xD6, 0x36, 0xD6, 0x56, 0xAD, 0x32, 0x9C, 0x8F, +0xA4, 0xB0, 0xBD, 0x93, 0xCD, 0xF4, 0xBD, 0x93, +0x94, 0x6F, 0x8C, 0x0E, 0x8B, 0xED, 0xBD, 0x93, +0xBD, 0x92, 0xB5, 0x11, 0xB5, 0x31, 0xAD, 0x11, +0xBD, 0xF5, 0xBD, 0xD5, 0x73, 0x8C, 0x6B, 0x4B, +0x52, 0xC8, 0x7C, 0x4E, 0x5B, 0x29, 0x7B, 0xEC, +0x9C, 0xD1, 0xAD, 0x73, 0xA5, 0x52, 0x84, 0x2D, +0x84, 0x2C, 0x7B, 0xEB, 0x84, 0x0D, 0x94, 0xB0, +0x8C, 0x6F, 0x94, 0x90, 0x9C, 0xB0, 0xAD, 0x32, +0xB5, 0x93, 0xB5, 0x94, 0xA4, 0xF2, 0x9C, 0x8F, +0xAC, 0xCF, 0x9C, 0x8F, 0x94, 0x6F, 0xA4, 0xF0, +0xAD, 0x11, 0x94, 0x6F, 0x83, 0xED, 0xBD, 0x93, +0xC5, 0xD4, 0xBD, 0xB4, 0xBD, 0x93, 0x9C, 0xB0, +0xB5, 0x52, 0xBD, 0x93, 0xBD, 0x93, 0xCD, 0xF4, +0xCE, 0x15, 0xDE, 0x76, 0xCE, 0x15, 0xCE, 0x15, +0xD6, 0x56, 0xCE, 0x36, 0xCE, 0x36, 0xAC, 0xCF, +0xB4, 0xEF, 0xC5, 0x71, 0xB5, 0x31, 0xB5, 0x52, +0xD6, 0x56, 0xDE, 0x97, 0xC5, 0xF5, 0x8C, 0x0F, +0xAC, 0xF3, 0x83, 0xAF, 0x73, 0x4D, 0x83, 0xEF, +0x6B, 0x2D, 0x5A, 0xEC, 0x3A, 0x08, 0x31, 0xA7, +0x31, 0xC7, 0x42, 0x29, 0x29, 0x86, 0x18, 0xE4, +0x52, 0x8B, 0x5A, 0xCC, 0x4A, 0x6A, 0x21, 0x25, +0x18, 0xE4, 0x08, 0x82, 0x08, 0x82, 0x10, 0xA2, +0x18, 0xC3, 0x21, 0x25, 0xBD, 0xF6, 0xCE, 0x36, +0xCE, 0x15, 0xD6, 0x57, 0xD6, 0x77, 0xD6, 0x56, +0xD6, 0x76, 0xCE, 0x35, 0xBD, 0xD4, 0xBD, 0xB4, +0xBD, 0x94, 0xAD, 0x52, 0xB5, 0x94, 0xBD, 0xB4, +0xC5, 0xF5, 0xAD, 0x52, 0x9C, 0xB0, 0x9C, 0x8E, +0xAC, 0xCF, 0x8C, 0x0C, 0xC5, 0x92, 0xAC, 0xAE, +0x9C, 0x6F, 0x9C, 0xB0, 0x7B, 0xAC, 0x8C, 0x2E, +0x94, 0x70, 0x8C, 0x4F, 0x9C, 0xD2, 0xBD, 0xD6, +0x9C, 0xD3, 0x94, 0x92, 0x9C, 0x92, 0xAD, 0x14, +0x94, 0x30, 0x8C, 0x2F, 0x4A, 0x28, 0x5A, 0x8A, +0x62, 0xEB, 0x5A, 0xAA, 0x5A, 0xAA, 0x6B, 0x2C, +0x7B, 0xCF, 0x8C, 0x10, 0x83, 0xAF, 0x52, 0x69, +0x4A, 0x28, 0x5A, 0x8A, 0x63, 0x0B, 0x73, 0x8D, +0x7B, 0xAE, 0x8C, 0x30, 0x52, 0x69, 0x52, 0x69, +0x41, 0xE7, 0x29, 0x03, 0x31, 0x85, 0x4A, 0x28, +0x39, 0xA6, 0x5A, 0xAA, 0x7B, 0x8E, 0x52, 0x69, +0x52, 0x89, 0x62, 0xC9, 0x73, 0x4B, 0x8C, 0x0D, +0xAD, 0x11, 0xB5, 0x32, 0xBD, 0x52, 0xBD, 0x72, +0xCD, 0xD4, 0xC5, 0xD3, 0xC5, 0x92, 0xDE, 0x55, +0xD6, 0x35, 0xD6, 0x35, 0xD6, 0x35, 0x9C, 0x8F, +0xB5, 0x53, 0xB5, 0x53, 0xB5, 0x33, 0xB5, 0x33, +0xAD, 0x12, 0xB5, 0x52, 0xBD, 0x73, 0xC5, 0x93, +0xBD, 0x53, 0xB5, 0x32, 0xB5, 0x53, 0xB5, 0x53, +0xBD, 0x53, 0xBD, 0x73, 0xBD, 0x73, 0xBD, 0x73, +0xBD, 0x93, 0xBD, 0x53, 0xB5, 0x32, 0xBD, 0x73, +0xBD, 0x94, 0xC5, 0xB4, 0xCD, 0xD5, 0xBD, 0x73, +0xB5, 0x31, 0xAC, 0xF1, 0xAC, 0xF0, 0xB5, 0x31, +0xB5, 0x52, 0xA4, 0x90, 0x7B, 0x6C, 0x31, 0x65, +0x42, 0x07, 0x31, 0x85, 0x29, 0x44, 0x29, 0x45, +0x4A, 0x49, 0x4A, 0x8A, 0x3A, 0x08, 0x52, 0xAA, +0x94, 0x72, 0x9C, 0x92, 0x94, 0x92, 0x8C, 0x51, +0x52, 0x49, 0x52, 0x49, 0x5A, 0x8A, 0x52, 0x28, +0x52, 0x28, 0x8B, 0xEF, 0x62, 0xCB, 0x83, 0xCE, +0x7B, 0x8E, 0x62, 0xAB, 0x7B, 0x6D, 0x94, 0x30, +0x8C, 0x30, 0x83, 0xAE, 0x39, 0x87, 0x18, 0xC4, +0x18, 0xE4, 0x19, 0x04, 0x18, 0xC3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xC3, 0x21, 0x24, 0x94, 0x70, +0xD6, 0x56, 0xCD, 0xF4, 0xAC, 0xD0, 0xC5, 0x93, +0xD6, 0x14, 0xD6, 0x14, 0xE6, 0x76, 0xDE, 0x76, +0xDE, 0x75, 0xDE, 0x35, 0xCD, 0xD3, 0xCD, 0xB4, +0xC5, 0x93, 0xBD, 0x72, 0xC5, 0x93, 0xC5, 0xD3, +0xA4, 0xAF, 0xD6, 0x35, 0xCD, 0xF5, 0xAD, 0x12, +0x7B, 0xAD, 0x31, 0x86, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x10, 0xC4, 0x18, 0xC4, +0x18, 0xE4, 0x19, 0x04, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x10, 0xC4, 0x10, 0xC4, 0x18, 0xE4, +0x18, 0xE4, 0x10, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x08, 0x83, 0x10, 0x83, +0x10, 0x83, 0x10, 0x83, 0x10, 0x83, 0x10, 0x83, +0x08, 0x83, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA4, +0x18, 0xE4, 0x19, 0x05, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x21, 0x26, 0x21, 0x05, 0x19, 0x05, +0x21, 0x05, 0x21, 0x26, 0x21, 0x26, 0x21, 0x26, +0x29, 0x67, 0x39, 0xC8, 0x31, 0xC8, 0x39, 0xE9, +0x31, 0xA8, 0x4A, 0x6B, 0x4A, 0x4A, 0x4A, 0x29, +0x7B, 0xAD, 0xB5, 0x32, 0xBD, 0x73, 0xAD, 0x32, +0xA4, 0xF1, 0xAD, 0x11, 0xB5, 0x12, 0xD6, 0x35, +0xDE, 0x76, 0xE6, 0x96, 0xDE, 0x96, 0xBD, 0x72, +0xBD, 0x72, 0xE6, 0xB7, 0xDE, 0x76, 0xD6, 0x56, +0xBD, 0x93, 0xB5, 0x52, 0xBD, 0x52, 0xD6, 0x35, +0xD6, 0x34, 0xDE, 0x54, 0xDE, 0x55, 0xDE, 0x76, +0x7B, 0xAD, 0xAD, 0x32, 0x9C, 0xB1, 0x8C, 0x2E, +0x7B, 0xCC, 0x7C, 0x0D, 0x7B, 0xEC, 0x73, 0xAB, +0x6B, 0x6B, 0x7B, 0xCD, 0x8C, 0x4E, 0x8C, 0x2D, +0x9C, 0xAF, 0xA4, 0xEF, 0xA4, 0xEF, 0x9C, 0xAF, +0xA4, 0xAF, 0xA4, 0xCF, 0xA4, 0xCF, 0xAC, 0xF0, +0xA4, 0xCF, 0xA4, 0xAF, 0xAC, 0xF0, 0xB5, 0x31, +0xBD, 0x31, 0xB5, 0x10, 0xB5, 0x10, 0xAC, 0xCF, +0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0xAF, 0xAC, 0xF0, +0xAC, 0xF0, 0xAD, 0x10, 0xB5, 0x31, 0xAC, 0xF0, +0xAC, 0xCF, 0xA4, 0xCF, 0x9C, 0x8E, 0xAC, 0xF0, +0xAD, 0x11, 0xA4, 0xAF, 0x9C, 0xAF, 0x9C, 0xAF, +0xBD, 0x93, 0xBD, 0x72, 0xCE, 0x15, 0xB5, 0x10, +0xB5, 0x10, 0xB4, 0xEF, 0x73, 0x29, 0x7B, 0x6B, +0xC5, 0xD4, 0xCE, 0x16, 0x94, 0x4F, 0x8B, 0xEF, +0x8B, 0xEF, 0x73, 0x6D, 0x8C, 0x10, 0xAD, 0x14, +0x94, 0x72, 0x73, 0x8E, 0x39, 0xE7, 0x31, 0xA6, +0x4A, 0x49, 0x5A, 0xEC, 0x63, 0x0C, 0x52, 0x8A, +0x39, 0xE8, 0x52, 0x8A, 0x5A, 0xCB, 0x5A, 0xCB, +0x29, 0x66, 0x08, 0x62, 0x08, 0x82, 0x10, 0xA3, +0x10, 0xA3, 0x39, 0xE7, 0xC6, 0x37, 0xBD, 0xB4, +0xB5, 0x73, 0xCE, 0x56, 0xD6, 0x56, 0xD6, 0x56, +0xD6, 0x56, 0xCE, 0x36, 0xAD, 0x32, 0xBD, 0xB5, +0xBD, 0x94, 0xAD, 0x52, 0xA5, 0x11, 0xBD, 0xB4, +0xCE, 0x36, 0xB5, 0xB4, 0xAD, 0x52, 0x9C, 0x8E, +0xBD, 0x71, 0x7B, 0x8A, 0xCD, 0xF3, 0x9C, 0x6E, +0x84, 0x0D, 0x8C, 0x4F, 0x83, 0xEE, 0x9C, 0xD1, +0x9C, 0xB0, 0xA5, 0x12, 0xB5, 0x95, 0xAD, 0x34, +0xA5, 0x14, 0xBD, 0x96, 0xB5, 0x76, 0x9C, 0x92, +0xA4, 0xF3, 0x73, 0x6D, 0x31, 0x65, 0x4A, 0x28, +0x5A, 0x8A, 0x62, 0xCB, 0x5A, 0x8A, 0x42, 0x08, +0x5A, 0xCB, 0x73, 0x6E, 0x5A, 0x8A, 0x4A, 0x49, +0x5A, 0xAA, 0x73, 0x6D, 0x94, 0x71, 0x73, 0x6D, +0x73, 0x6D, 0x7B, 0xAE, 0x42, 0x07, 0x5A, 0xAA, +0x41, 0xE7, 0x21, 0x03, 0x29, 0x44, 0x41, 0xE7, +0x21, 0x24, 0x73, 0x6D, 0x73, 0x4D, 0x4A, 0x49, +0x63, 0x0C, 0x5A, 0xCB, 0x63, 0x0B, 0x7B, 0xAD, +0x83, 0xEE, 0x7B, 0xCD, 0x73, 0x6B, 0x63, 0x0A, +0x6B, 0x4B, 0x7B, 0xCD, 0x8C, 0x2E, 0xBD, 0xD4, +0xC5, 0xF5, 0xAD, 0x12, 0xCE, 0x36, 0xB5, 0x73, +0xD6, 0x36, 0xB5, 0x53, 0x9C, 0x6F, 0xAD, 0x12, +0xD6, 0x36, 0xE6, 0xB6, 0xE6, 0xB7, 0xDE, 0x76, +0xDE, 0x56, 0xD6, 0x55, 0xD6, 0x56, 0xDE, 0x76, +0xD6, 0x35, 0xCD, 0xF4, 0xBD, 0x73, 0xB5, 0x32, +0xB5, 0x32, 0xB5, 0x32, 0xAC, 0xF0, 0x9C, 0x6F, +0x8C, 0x0D, 0xAD, 0x11, 0xB5, 0x11, 0xAD, 0x11, +0xBD, 0x73, 0xBD, 0x73, 0xAD, 0x11, 0xB5, 0x32, +0xB5, 0x32, 0x52, 0x48, 0x39, 0x86, 0x52, 0x68, +0xAD, 0x32, 0x73, 0x6C, 0x31, 0x85, 0x29, 0x44, +0x29, 0x45, 0x31, 0xA6, 0x31, 0x85, 0x31, 0xA6, +0x42, 0x07, 0x4A, 0x29, 0x7B, 0xAF, 0xB5, 0x96, +0x9C, 0xB2, 0x7B, 0xAE, 0x6B, 0x0C, 0x62, 0xAB, +0x49, 0xE7, 0x7B, 0x6E, 0x7B, 0xAE, 0x8C, 0x30, +0x6B, 0x0C, 0x7B, 0xAE, 0x9C, 0x71, 0x9C, 0x70, +0x8B, 0xEF, 0x94, 0x10, 0x73, 0x4D, 0x31, 0x66, +0x18, 0xA3, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x4A, 0x49, 0x8C, 0x0F, +0xBD, 0x93, 0xB5, 0x11, 0xB5, 0x11, 0xCD, 0xF4, +0xE6, 0x96, 0xE6, 0x76, 0xDE, 0x76, 0xE6, 0x96, +0xE6, 0x96, 0xB5, 0x11, 0xA4, 0x6F, 0x8B, 0xED, +0x8B, 0xCD, 0x94, 0x2E, 0x9C, 0x90, 0x94, 0x2E, +0x73, 0x6B, 0xBD, 0xB4, 0xE6, 0xB8, 0xDE, 0x76, +0xBD, 0x93, 0x73, 0x4C, 0x31, 0xA7, 0x18, 0xC4, +0x18, 0xE4, 0x10, 0xE4, 0x10, 0xC4, 0x10, 0xC4, +0x10, 0xC4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xC4, 0x10, 0xA3, 0x18, 0xE4, +0x18, 0xC4, 0x10, 0xC4, 0x10, 0xA4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0x83, 0x08, 0x83, +0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC3, +0x18, 0xE4, 0x21, 0x25, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x19, 0x05, 0x19, 0x05, 0x19, 0x05, +0x21, 0x05, 0x21, 0x46, 0x21, 0x26, 0x19, 0x05, +0x29, 0x46, 0x31, 0xA8, 0x31, 0xA8, 0x31, 0xA8, +0x39, 0xE9, 0x3A, 0x09, 0x39, 0xE9, 0x39, 0xA8, +0x41, 0xE8, 0x73, 0x6C, 0x9C, 0x90, 0xAD, 0x32, +0x9C, 0x90, 0xA4, 0xD1, 0xAC, 0xF1, 0xC5, 0xD4, +0xCD, 0xD4, 0xD6, 0x14, 0xD6, 0x35, 0xCD, 0xD4, +0xCD, 0xD4, 0xD6, 0x35, 0xCE, 0x14, 0xCD, 0xF4, +0xCD, 0xF5, 0xD6, 0x36, 0xC5, 0x93, 0xE6, 0xB7, +0xE6, 0x95, 0xE6, 0x95, 0xE6, 0x95, 0xE6, 0xB6, +0x73, 0x8D, 0x8C, 0x0F, 0x84, 0x0E, 0x94, 0x4E, +0x94, 0x6E, 0x83, 0xED, 0x8C, 0x6E, 0x94, 0x8F, +0x8C, 0x4F, 0x84, 0x0D, 0x8C, 0x2E, 0x9C, 0xD0, +0xA4, 0xF0, 0xA4, 0xCF, 0xA4, 0xEF, 0xA4, 0xCF, +0xAC, 0xCF, 0xAC, 0xCF, 0xAC, 0xCF, 0x94, 0x4D, +0xA4, 0x8E, 0x94, 0x0C, 0x8B, 0xCB, 0x94, 0x2C, +0xA4, 0x6E, 0xA4, 0x8E, 0xAC, 0xAE, 0xA4, 0x8E, +0xB4, 0xF0, 0xBD, 0x71, 0xB5, 0x30, 0xAC, 0xEF, +0xB4, 0xEF, 0xB4, 0xEF, 0xB5, 0x10, 0xB5, 0x10, +0xB5, 0x10, 0xB5, 0x10, 0xBD, 0x30, 0xBD, 0x51, +0xB5, 0x30, 0xAC, 0xF0, 0xB5, 0x10, 0xB5, 0x10, +0xB4, 0xF0, 0xA4, 0xAF, 0xA4, 0x8E, 0xAC, 0xEF, +0xB5, 0x10, 0xBD, 0x10, 0xB5, 0x10, 0xB4, 0xF0, +0xA4, 0x8E, 0x5A, 0xA8, 0x39, 0xC6, 0x42, 0x07, +0x4A, 0x28, 0x62, 0xCB, 0x94, 0x72, 0xB5, 0x96, +0xBD, 0xF8, 0x6B, 0x4D, 0x4A, 0x69, 0x73, 0x8E, +0x73, 0x8E, 0x7B, 0xCF, 0x8C, 0x51, 0x8C, 0x71, +0x84, 0x31, 0x84, 0x10, 0x6B, 0x2D, 0x31, 0xA7, +0x08, 0x62, 0x08, 0x62, 0x08, 0x62, 0x10, 0xC3, +0x39, 0xE8, 0x6B, 0x6D, 0xD6, 0x57, 0xAD, 0x32, +0x8C, 0x0E, 0xB5, 0x73, 0xD6, 0x76, 0xCE, 0x56, +0xCE, 0x56, 0xCE, 0x36, 0xBD, 0xD4, 0xC5, 0xF5, +0xC5, 0xD5, 0xBD, 0xB4, 0xBD, 0x94, 0xBD, 0xB4, +0xC6, 0x15, 0xC5, 0xD5, 0xB5, 0x52, 0x9C, 0x6E, +0xCD, 0xD3, 0x8C, 0x0C, 0xD6, 0x35, 0xAC, 0xF0, +0x94, 0x8F, 0xA5, 0x12, 0x94, 0xB0, 0xB5, 0xB4, +0xAD, 0x52, 0xBD, 0xB4, 0xBD, 0x95, 0x8C, 0x30, +0x8C, 0x30, 0x9C, 0xB2, 0xA4, 0xF3, 0x73, 0x6D, +0x5A, 0xCB, 0x29, 0x24, 0x41, 0xE7, 0x42, 0x07, +0x4A, 0x48, 0x5A, 0xAA, 0x6B, 0x2C, 0x6B, 0x0C, +0x6B, 0x2C, 0x6B, 0x2C, 0x52, 0x69, 0x4A, 0x08, +0x5A, 0xAA, 0x52, 0x69, 0x63, 0x0B, 0x52, 0x89, +0x5A, 0xAA, 0x5A, 0xCA, 0x52, 0x89, 0x5A, 0xAA, +0x4A, 0x28, 0x39, 0xA6, 0x39, 0xC6, 0x21, 0x24, +0x21, 0x04, 0x6B, 0x4D, 0x63, 0x0B, 0x6B, 0x4C, +0x83, 0xEF, 0x84, 0x0F, 0x94, 0x70, 0x9C, 0xD1, +0xA5, 0x13, 0xAD, 0x53, 0xA5, 0x32, 0x94, 0x90, +0x94, 0x70, 0x94, 0x90, 0x8C, 0x4F, 0x94, 0x70, +0xA4, 0xF2, 0x94, 0x90, 0xA4, 0xF2, 0xB5, 0x53, +0xC5, 0xF5, 0xCE, 0x16, 0xA4, 0xD1, 0xB5, 0x32, +0xDE, 0x76, 0xDE, 0x96, 0xE6, 0x96, 0xE6, 0x96, +0xD6, 0x35, 0xDE, 0x75, 0xE6, 0xB7, 0xC5, 0xB3, +0xBD, 0x72, 0xD6, 0x35, 0xDE, 0x55, 0xD6, 0x35, +0xD6, 0x35, 0xCD, 0xF5, 0xC5, 0xD4, 0xBD, 0x93, +0xAC, 0xF1, 0xB5, 0x52, 0xAC, 0xF0, 0xA4, 0x6F, +0xCD, 0xF4, 0xDE, 0x55, 0xCD, 0xF4, 0xAC, 0xD0, +0xC5, 0xD5, 0xA4, 0xD1, 0x9C, 0xB1, 0x8C, 0x4F, +0xA5, 0x11, 0xA4, 0xD1, 0x8C, 0x2E, 0x52, 0xA9, +0x31, 0xA6, 0x31, 0x85, 0x29, 0x44, 0x29, 0x44, +0x29, 0x65, 0x39, 0xC7, 0x52, 0x8A, 0x63, 0x2C, +0x9D, 0x14, 0xCE, 0x59, 0xB5, 0x96, 0x7B, 0x8E, +0x52, 0x49, 0x83, 0xCE, 0x62, 0xCA, 0x52, 0x29, +0x41, 0xE7, 0x73, 0x6D, 0xA4, 0x91, 0x94, 0x0F, +0x83, 0x8D, 0x8C, 0x0F, 0x83, 0xCE, 0x6B, 0x0C, +0x39, 0x86, 0x21, 0x25, 0x18, 0xE4, 0x18, 0xE4, +0x21, 0x04, 0x5A, 0xAA, 0x9C, 0x91, 0x9C, 0x90, +0xA4, 0xB0, 0xAC, 0xF1, 0xB5, 0x11, 0xAC, 0xF0, +0xAC, 0xD0, 0xA4, 0xAF, 0x9C, 0x4E, 0x9C, 0x4E, +0xA4, 0x8F, 0x94, 0x0D, 0x83, 0xAD, 0x83, 0x8C, +0x7B, 0x4C, 0x6A, 0xEA, 0x5A, 0xA9, 0x5A, 0x89, +0x73, 0x2C, 0xB5, 0x32, 0xA4, 0xD0, 0x94, 0x2E, +0x83, 0xED, 0x83, 0xCD, 0x73, 0x4C, 0x39, 0xC7, +0x18, 0xE4, 0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC4, +0x10, 0xC3, 0x10, 0xC3, 0x10, 0xC3, 0x10, 0xC4, +0x18, 0xC4, 0x18, 0xE4, 0x10, 0xC4, 0x10, 0xC4, +0x10, 0xC4, 0x10, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0x83, 0x10, 0x83, 0x10, 0x83, 0x10, 0x83, +0x08, 0x83, 0x10, 0x83, 0x10, 0xA3, 0x10, 0xC4, +0x21, 0x05, 0x29, 0x46, 0x29, 0x66, 0x21, 0x26, +0x19, 0x05, 0x19, 0x05, 0x19, 0x05, 0x18, 0xE5, +0x21, 0x26, 0x29, 0x46, 0x21, 0x26, 0x21, 0x26, +0x29, 0x67, 0x29, 0x87, 0x29, 0x87, 0x29, 0x67, +0x29, 0x67, 0x29, 0x67, 0x29, 0x67, 0x31, 0xA7, +0x42, 0x09, 0x5A, 0xCB, 0x73, 0x6D, 0xA4, 0xD1, +0x94, 0x6F, 0xA4, 0xB0, 0x9C, 0xB0, 0xB5, 0x73, +0xBD, 0x93, 0xC5, 0xB3, 0xC5, 0xB3, 0xCD, 0xD3, +0xD6, 0x14, 0xD6, 0x55, 0xD6, 0x14, 0xCD, 0xB4, +0xBD, 0x93, 0xC5, 0xD4, 0xD6, 0x15, 0xE6, 0xB7, +0xE6, 0x96, 0xE6, 0x75, 0xDE, 0x75, 0xDE, 0x75, +0x83, 0xEE, 0x83, 0xCE, 0x73, 0x6D, 0xC6, 0x17, +0xC6, 0x16, 0x84, 0x0D, 0x6B, 0x6A, 0x94, 0x8F, +0x9C, 0xD1, 0xA4, 0xF2, 0x8C, 0x4E, 0x94, 0x6F, +0x8C, 0x4E, 0x94, 0x6F, 0xA4, 0xF0, 0x94, 0x4D, +0x9C, 0x4D, 0xA4, 0xAE, 0xAC, 0xEF, 0x9C, 0x8F, +0x9C, 0x8F, 0x9C, 0x8F, 0x94, 0x4E, 0x94, 0x4E, +0x9C, 0x4E, 0x9C, 0x4E, 0x94, 0x4E, 0x94, 0x0D, +0x8B, 0xEC, 0x94, 0x0D, 0x83, 0xAB, 0x8B, 0xEC, +0x83, 0xCB, 0x83, 0xCB, 0x83, 0xAB, 0x7B, 0x4A, +0x73, 0x4A, 0x83, 0x8B, 0xA4, 0x6E, 0xA4, 0xAE, +0xB4, 0xEF, 0xAC, 0xAE, 0xA4, 0x8E, 0xC5, 0xB3, +0xB5, 0x31, 0x9C, 0x6E, 0xB5, 0x10, 0xB5, 0x10, +0xAC, 0xCF, 0xAC, 0xAE, 0xA4, 0x6E, 0x9C, 0x2C, +0xA4, 0xAE, 0x83, 0xCC, 0x39, 0xA5, 0x52, 0x89, +0x39, 0xC6, 0x6B, 0x4D, 0x8C, 0x71, 0x9C, 0xF4, +0xB5, 0x76, 0x5A, 0xCB, 0x73, 0x8E, 0x84, 0x30, +0x84, 0x10, 0x8C, 0x51, 0x94, 0xB2, 0x94, 0xB2, +0x94, 0xB3, 0xB5, 0x76, 0xA5, 0x14, 0x6B, 0x6E, +0x52, 0x8A, 0x42, 0x08, 0x3A, 0x08, 0x4A, 0x8A, +0x41, 0xE8, 0x8C, 0x70, 0xB5, 0x73, 0xB5, 0x52, +0xA4, 0xD1, 0xA4, 0xF1, 0xAD, 0x32, 0xA5, 0x11, +0xAD, 0x32, 0xB5, 0x52, 0xB5, 0x52, 0xBD, 0xB4, +0xBD, 0xD4, 0xBD, 0xB4, 0xBD, 0xD4, 0xBD, 0xB4, +0xBD, 0xD4, 0xBD, 0xD5, 0xB5, 0x52, 0xA4, 0xAF, +0xCD, 0xF3, 0xB5, 0x10, 0xCD, 0xF3, 0xB5, 0x11, +0xB5, 0x32, 0xB5, 0x93, 0xB5, 0x94, 0xBD, 0xB4, +0x9C, 0xB0, 0x9C, 0xD1, 0xA4, 0xF2, 0x6B, 0x4C, +0x73, 0x8E, 0x8C, 0x30, 0x8C, 0x10, 0x6B, 0x0C, +0x52, 0x49, 0x52, 0x69, 0x31, 0x65, 0x41, 0xE7, +0x4A, 0x28, 0x52, 0x69, 0x5A, 0xAA, 0x6B, 0x0C, +0x6B, 0x0C, 0x6B, 0x0C, 0x52, 0x69, 0x41, 0xC7, +0x62, 0xCB, 0x39, 0xA6, 0x39, 0xC6, 0x4A, 0x28, +0x42, 0x28, 0x4A, 0x28, 0x4A, 0x48, 0x52, 0x89, +0x41, 0xE7, 0x29, 0x24, 0x39, 0xA6, 0x4A, 0x28, +0x5A, 0xAA, 0x7B, 0xCE, 0x84, 0x0F, 0x7B, 0xCE, +0x83, 0xEF, 0x7B, 0xEE, 0x84, 0x0F, 0x8C, 0x4F, +0x8C, 0x4F, 0x94, 0x90, 0x9C, 0xD1, 0xB5, 0x73, +0xA5, 0x12, 0x8C, 0x4F, 0x9C, 0xD1, 0x8C, 0x4F, +0xA5, 0x12, 0xBD, 0xD5, 0xBD, 0xB5, 0xB5, 0x53, +0xC5, 0xF5, 0xCE, 0x15, 0xAD, 0x11, 0xB5, 0x32, +0xDE, 0x96, 0xD6, 0x34, 0xD6, 0x34, 0xDE, 0x75, +0xDE, 0x75, 0xE6, 0x96, 0xDE, 0x55, 0xC5, 0x92, +0xD6, 0x14, 0xCD, 0xF4, 0xE6, 0x96, 0xE6, 0x96, +0xE6, 0xB6, 0xE6, 0x96, 0xE6, 0xB6, 0xE6, 0x96, +0xE6, 0x96, 0xCD, 0xD3, 0xBD, 0x51, 0xCD, 0xF4, +0xE6, 0xD7, 0xE6, 0x96, 0xB5, 0x31, 0xAD, 0x11, +0xAD, 0x32, 0xAD, 0x52, 0xBD, 0xB4, 0xB5, 0x52, +0x94, 0x8F, 0xBD, 0x94, 0xBD, 0xB4, 0xAD, 0x12, +0x8C, 0x4F, 0x42, 0x07, 0x31, 0x85, 0x29, 0x65, +0x29, 0x44, 0x29, 0x44, 0x31, 0x65, 0x39, 0xC6, +0x52, 0xCA, 0x7B, 0xCE, 0x9C, 0xD3, 0x6B, 0x4C, +0x5A, 0xAA, 0x73, 0x6D, 0x42, 0x28, 0x4A, 0x28, +0x62, 0xCA, 0x62, 0xAA, 0x73, 0x0B, 0x7B, 0x2C, +0x8B, 0xEF, 0x83, 0xAE, 0x6A, 0xAA, 0x7B, 0x6C, +0x73, 0x0C, 0x6B, 0x0C, 0x6B, 0x0B, 0x7B, 0x6D, +0x7B, 0xAE, 0x7B, 0x8D, 0x8C, 0x0E, 0xAD, 0x32, +0xBD, 0x73, 0xBD, 0x52, 0xBD, 0x72, 0xB5, 0x31, +0xAC, 0xD0, 0xA4, 0x8F, 0xA4, 0xB0, 0xAC, 0xF1, +0xB5, 0x11, 0xB5, 0x11, 0xAC, 0xF1, 0xA4, 0x90, +0xA4, 0xB0, 0xA4, 0xB0, 0x9C, 0x6F, 0x94, 0x4F, +0x94, 0x4F, 0x9C, 0x70, 0x9C, 0x6F, 0x94, 0x2E, +0x94, 0x4F, 0x94, 0x4F, 0x8C, 0x0E, 0x6B, 0x4C, +0x31, 0x86, 0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC4, +0x10, 0xC4, 0x10, 0xC4, 0x18, 0xE4, 0x10, 0xC4, +0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, 0x08, 0x83, +0x08, 0x83, 0x10, 0x83, 0x10, 0xA3, 0x10, 0xC4, +0x21, 0x05, 0x29, 0x66, 0x31, 0xA7, 0x29, 0x67, +0x21, 0x26, 0x18, 0xE5, 0x18, 0xE5, 0x18, 0xE5, +0x21, 0x26, 0x21, 0x26, 0x21, 0x26, 0x21, 0x46, +0x29, 0x46, 0x29, 0x67, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x21, 0x26, 0x29, 0x67, 0x31, 0xA8, +0x42, 0x4A, 0x5A, 0xEC, 0x5A, 0xCB, 0x73, 0xAD, +0x9C, 0x90, 0x9C, 0xB0, 0x94, 0x6F, 0xB5, 0x53, +0xB5, 0x72, 0xB5, 0x52, 0xB5, 0x52, 0xB5, 0x52, +0xBD, 0x92, 0xD6, 0x55, 0xCD, 0xF4, 0xBD, 0x52, +0xB5, 0x32, 0xB5, 0x73, 0xCE, 0x15, 0xE6, 0xD7, +0xD6, 0x14, 0xD6, 0x14, 0xD6, 0x14, 0xD6, 0x34, +0x6B, 0x6C, 0x7B, 0xCE, 0x7B, 0xEF, 0xDE, 0xFB, +0xDE, 0x99, 0xAD, 0x2F, 0x94, 0x6C, 0xAD, 0x31, +0xC5, 0xF5, 0xCE, 0x37, 0xAD, 0x12, 0xAD, 0x32, +0xA4, 0xF1, 0x9C, 0xB0, 0xA4, 0xD0, 0xB5, 0x30, +0xAC, 0xEF, 0xAC, 0xCE, 0xBD, 0x92, 0xE6, 0x97, +0xC5, 0xD4, 0xBD, 0x93, 0xBD, 0x93, 0xBD, 0x93, +0xBD, 0x93, 0xBD, 0x93, 0xB5, 0x52, 0xB5, 0x32, +0xB5, 0x52, 0xB5, 0x32, 0xAD, 0x11, 0xAD, 0x11, +0x9C, 0xB0, 0x9C, 0x8F, 0xAD, 0x11, 0xB5, 0x52, +0xAD, 0x11, 0xAD, 0x32, 0xC5, 0xB3, 0xBD, 0x93, +0xBD, 0x72, 0xAC, 0xCF, 0xB5, 0x51, 0xC5, 0xF4, +0xBD, 0xB3, 0xAD, 0x32, 0xA4, 0xD0, 0x8C, 0x0D, +0x9C, 0x8E, 0x94, 0x4D, 0x94, 0x4D, 0x8C, 0x2C, +0x9C, 0xAF, 0x8C, 0x2D, 0x52, 0x68, 0x6B, 0x4C, +0x52, 0x69, 0x52, 0x8A, 0x6B, 0x4D, 0x7C, 0x10, +0x9C, 0xD3, 0x5A, 0xEB, 0x94, 0x92, 0x73, 0x8E, +0x94, 0x92, 0x9C, 0xD3, 0x94, 0xB3, 0xA5, 0x14, +0xA5, 0x35, 0x9C, 0xD3, 0x39, 0xC7, 0xA5, 0x14, +0x9C, 0xB3, 0x4A, 0x49, 0x63, 0x2C, 0x5A, 0xCB, +0x8C, 0x2F, 0xB5, 0x72, 0xB5, 0x51, 0xBD, 0x71, +0xB5, 0x30, 0xB5, 0x10, 0xB5, 0x31, 0xB5, 0x30, +0xB5, 0x30, 0xAC, 0xEF, 0xAC, 0xCF, 0x9C, 0x8E, +0x9C, 0x6E, 0x9C, 0x8E, 0xAD, 0x11, 0xAD, 0x31, +0xB5, 0x52, 0xAC, 0xF0, 0x94, 0x4D, 0xB5, 0x10, +0xBD, 0x71, 0xBD, 0x51, 0xC5, 0x71, 0xC5, 0x92, +0xBD, 0x72, 0x94, 0x6F, 0xA5, 0x11, 0xAD, 0x11, +0x8C, 0x2D, 0x8C, 0x2E, 0x9C, 0xB1, 0x6B, 0x0B, +0x4A, 0x28, 0x5A, 0x8A, 0x52, 0x49, 0x52, 0x49, +0x4A, 0x48, 0x4A, 0x28, 0x29, 0x44, 0x41, 0xE7, +0x4A, 0x28, 0x42, 0x07, 0x4A, 0x08, 0x52, 0x8A, +0x5A, 0xAA, 0x52, 0x69, 0x4A, 0x08, 0x39, 0xC6, +0x39, 0xC6, 0x31, 0x86, 0x41, 0xE7, 0x41, 0xE7, +0x5A, 0xAA, 0x62, 0xEB, 0x5A, 0xCA, 0x63, 0x0B, +0x52, 0x8A, 0x4A, 0x48, 0x62, 0xEB, 0x84, 0x0F, +0x83, 0xEF, 0x9C, 0xB2, 0xBD, 0xD6, 0x9C, 0xB2, +0x8C, 0x50, 0x7B, 0xEE, 0x8C, 0x2F, 0x9C, 0xB1, +0x94, 0x4F, 0x9C, 0xB1, 0xA5, 0x12, 0x9C, 0xD1, +0x94, 0x70, 0x7B, 0xAD, 0x8C, 0x4F, 0x6B, 0x6C, +0x8C, 0x50, 0x8C, 0x4F, 0x94, 0x90, 0x9C, 0xB1, +0x94, 0x6F, 0xB5, 0x32, 0xAD, 0x11, 0xAD, 0x11, +0xC5, 0xD4, 0xE6, 0xB6, 0xE6, 0xB6, 0xE6, 0xB6, +0xDE, 0x95, 0xDE, 0x95, 0xD6, 0x14, 0xB5, 0x30, +0xB5, 0x31, 0xC5, 0x92, 0xDE, 0x76, 0xE6, 0x96, +0xE6, 0xB6, 0xE6, 0x95, 0xE6, 0xB6, 0xE6, 0xB6, +0xE6, 0x75, 0xCD, 0xB2, 0xE6, 0x75, 0xE6, 0x96, +0xE6, 0xB6, 0xDE, 0x55, 0xCD, 0xF4, 0xB5, 0x32, +0xAD, 0x11, 0xB5, 0x93, 0xC5, 0xD4, 0xBD, 0x93, +0xBD, 0xD5, 0x9C, 0xB1, 0xBD, 0xD5, 0xBD, 0xD5, +0xC5, 0xF5, 0xAD, 0x32, 0x63, 0x2B, 0x31, 0x85, +0x21, 0x24, 0x29, 0x44, 0x31, 0xA5, 0x29, 0x44, +0x21, 0x24, 0x29, 0x65, 0x31, 0xA6, 0x31, 0x85, +0x29, 0x44, 0x31, 0x85, 0x29, 0x65, 0x4A, 0x48, +0x5A, 0xAA, 0x73, 0x2B, 0x83, 0x8D, 0x73, 0x0C, +0x8B, 0xEF, 0x8B, 0xAE, 0x83, 0x8D, 0x93, 0xEF, +0x72, 0xEB, 0x73, 0x2C, 0x9C, 0x30, 0x83, 0x8E, +0x83, 0xCE, 0xA4, 0xD2, 0x6B, 0x0B, 0x73, 0x6C, +0x9C, 0x90, 0xB5, 0x52, 0xB5, 0x72, 0xAD, 0x11, +0x8B, 0xEC, 0x94, 0x2E, 0x9C, 0x6E, 0x9C, 0x8F, +0xA4, 0xD0, 0xAC, 0xD0, 0xBD, 0x73, 0xD6, 0x15, +0xB5, 0x11, 0xC5, 0xB3, 0xC5, 0xB3, 0xBD, 0x72, +0xAC, 0xF0, 0xAD, 0x11, 0xB5, 0x11, 0xAC, 0xF1, +0xC5, 0xB4, 0xB5, 0x32, 0xAD, 0x11, 0x7B, 0xAC, +0x29, 0x86, 0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC3, +0x10, 0xC4, 0x18, 0xC4, 0x18, 0xE4, 0x10, 0xC4, +0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0x83, 0x08, 0x83, 0x08, 0x83, 0x10, 0x83, +0x08, 0x83, 0x10, 0x83, 0x10, 0xA3, 0x10, 0xC4, +0x21, 0x05, 0x29, 0x66, 0x39, 0xE8, 0x39, 0xC7, +0x29, 0x67, 0x21, 0x05, 0x18, 0xE5, 0x19, 0x05, +0x21, 0x26, 0x21, 0x26, 0x21, 0x46, 0x21, 0x26, +0x21, 0x46, 0x21, 0x46, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x29, 0x46, 0x29, 0x87, 0x31, 0xC8, +0x42, 0x2A, 0x42, 0x29, 0x39, 0xA8, 0x4A, 0x29, +0x94, 0x70, 0xA4, 0xD1, 0x9C, 0xB0, 0xAD, 0x32, +0xB5, 0x32, 0xB5, 0x52, 0xAD, 0x12, 0xAD, 0x12, +0xAC, 0xF1, 0xC5, 0x93, 0xBD, 0x93, 0xAD, 0x32, +0xAD, 0x32, 0xA4, 0xF1, 0xBD, 0x93, 0xCE, 0x15, +0xC5, 0x93, 0xC5, 0xB3, 0xC5, 0xB3, 0xC5, 0xD3, +0x63, 0x2B, 0x7B, 0xCE, 0x9C, 0xB2, 0xD6, 0x9A, +0xB5, 0x74, 0xB5, 0x31, 0xBD, 0xB2, 0xBD, 0xD3, +0xCE, 0x36, 0xB5, 0x74, 0xB5, 0x74, 0xC5, 0xF5, +0xAD, 0x52, 0xA5, 0x11, 0xA4, 0xF1, 0xAC, 0xF0, +0xC5, 0x71, 0xAC, 0xAE, 0xB5, 0x31, 0xDE, 0x76, +0xCE, 0x15, 0xCE, 0x15, 0xCE, 0x15, 0xCE, 0x15, +0xCD, 0xF5, 0xCD, 0xF5, 0xCD, 0xF5, 0xCE, 0x15, +0xCE, 0x15, 0xBD, 0xB3, 0xBD, 0x93, 0xBD, 0x93, +0xB5, 0x52, 0xB5, 0x52, 0xBD, 0xB4, 0xC5, 0xF4, +0xCE, 0x35, 0xC5, 0xF4, 0xC5, 0xD4, 0xDE, 0x97, +0xDE, 0x55, 0xAC, 0xAE, 0xAC, 0xF0, 0xBD, 0xD3, +0xC6, 0x14, 0xB5, 0x52, 0x9C, 0xAF, 0x8C, 0x2E, +0xA4, 0xD0, 0xAD, 0x31, 0xAD, 0x31, 0xAD, 0x31, +0xAD, 0x31, 0xA5, 0x11, 0x73, 0x6C, 0x5A, 0xAA, +0x52, 0x69, 0x4A, 0x69, 0x5A, 0xCB, 0x6B, 0x4D, +0x7B, 0xCF, 0x7B, 0xF0, 0x84, 0x10, 0x6B, 0x6E, +0xA5, 0x35, 0xA5, 0x35, 0x8C, 0x51, 0x9C, 0xD4, +0xA4, 0xF4, 0x5A, 0xAB, 0x73, 0xAF, 0xAD, 0x75, +0x83, 0xEF, 0x29, 0x45, 0x4A, 0x6A, 0x6B, 0x4C, +0x83, 0xCE, 0x94, 0x2E, 0x83, 0xCB, 0xB5, 0x51, +0xAD, 0x10, 0x83, 0xAB, 0x83, 0xAB, 0x8B, 0xEB, +0x8B, 0xEC, 0x94, 0x0C, 0xAC, 0xF0, 0xD6, 0x14, +0xBD, 0x51, 0xB5, 0x30, 0xAC, 0xAE, 0xA4, 0x8E, +0xA4, 0x8E, 0x9C, 0x6E, 0xB4, 0xF0, 0xCD, 0xD2, +0xCD, 0xB2, 0xC5, 0x91, 0xC5, 0x91, 0xC5, 0x71, +0xBD, 0x71, 0xBD, 0x30, 0xBD, 0x51, 0xBD, 0x51, +0xBD, 0x51, 0xBD, 0x51, 0xBD, 0x52, 0x6A, 0xEB, +0x29, 0x04, 0x31, 0x65, 0x31, 0x85, 0x31, 0x85, +0x39, 0xA6, 0x29, 0x44, 0x29, 0x24, 0x41, 0xE7, +0x4A, 0x28, 0x52, 0x69, 0x31, 0x65, 0x4A, 0x48, +0x5A, 0xAA, 0x41, 0xE7, 0x52, 0x69, 0x4A, 0x28, +0x41, 0xE7, 0x39, 0xC7, 0x31, 0x65, 0x31, 0x65, +0x4A, 0x48, 0x62, 0xCA, 0x39, 0xA6, 0x63, 0x0B, +0x6B, 0x4C, 0x73, 0x8D, 0x83, 0xCE, 0x7B, 0xCE, +0x8C, 0x10, 0xA5, 0x34, 0xC6, 0x38, 0xBD, 0xB6, +0xAD, 0x33, 0x84, 0x2F, 0x8C, 0x2F, 0x9C, 0xB1, +0xB5, 0x33, 0xB5, 0x53, 0xB5, 0x73, 0xB5, 0x52, +0xA4, 0xD1, 0x8C, 0x2F, 0x73, 0xAD, 0x6B, 0x4C, +0x84, 0x0F, 0x7B, 0xEE, 0x84, 0x2F, 0x94, 0x90, +0x94, 0x90, 0x9C, 0xB0, 0xAD, 0x12, 0xB5, 0x12, +0xD6, 0x15, 0xDE, 0x55, 0xDE, 0x54, 0xDE, 0x75, +0xCD, 0xD3, 0xCD, 0xB2, 0xC5, 0x92, 0xAC, 0xF0, +0xA4, 0xCF, 0xC5, 0xB3, 0xDE, 0x95, 0xE6, 0x96, +0xE6, 0x96, 0xDE, 0x95, 0xDE, 0x34, 0xD6, 0x14, +0xE6, 0x96, 0xC5, 0x71, 0xC5, 0x91, 0xDE, 0x34, +0xDE, 0x54, 0xD6, 0x34, 0xBD, 0x72, 0xB5, 0x53, +0xB5, 0x73, 0xC6, 0x15, 0xBD, 0xD4, 0xBD, 0xD4, +0xC5, 0xF5, 0xB5, 0x53, 0xBD, 0xD5, 0xAD, 0x53, +0xBD, 0xB4, 0xBD, 0xD4, 0xAD, 0x32, 0x94, 0x90, +0x6B, 0x2C, 0x31, 0x85, 0x29, 0x44, 0x21, 0x44, +0x21, 0x03, 0x21, 0x03, 0x21, 0x24, 0x29, 0x44, +0x21, 0x44, 0x29, 0x65, 0x31, 0x65, 0x52, 0x49, +0x62, 0xAA, 0x7B, 0x8D, 0x7B, 0x8D, 0x73, 0x2C, +0x73, 0x2C, 0x7B, 0x6D, 0x83, 0x8D, 0x94, 0x0F, +0x83, 0x8D, 0x83, 0x8D, 0x94, 0x0F, 0x83, 0xAE, +0x94, 0x50, 0xA4, 0xB2, 0x9C, 0x71, 0x94, 0x0F, +0x6B, 0x2B, 0x73, 0x4B, 0x9C, 0x90, 0xBD, 0x93, +0xB5, 0x52, 0xAD, 0x31, 0xAD, 0x31, 0xB5, 0x31, +0xB5, 0x31, 0xB5, 0x52, 0xCD, 0xD4, 0xD6, 0x56, +0xB5, 0x11, 0xAC, 0xF0, 0xA4, 0xD0, 0x8C, 0x0D, +0xAC, 0xF1, 0xC5, 0x93, 0xB5, 0x12, 0x83, 0xED, +0x9C, 0x70, 0x8C, 0x0E, 0x7B, 0xAC, 0x42, 0x07, +0x18, 0xE3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC3, +0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC4, +0x10, 0xC4, 0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, 0x18, 0xE4, +0x19, 0x05, 0x29, 0x66, 0x42, 0x29, 0x52, 0x8A, +0x41, 0xE8, 0x29, 0x46, 0x21, 0x25, 0x19, 0x05, +0x21, 0x26, 0x21, 0x26, 0x21, 0x46, 0x21, 0x26, +0x21, 0x46, 0x21, 0x46, 0x21, 0x26, 0x21, 0x26, +0x21, 0x46, 0x29, 0x67, 0x29, 0x87, 0x31, 0xA8, +0x31, 0xA7, 0x29, 0x66, 0x29, 0x46, 0x39, 0xC8, +0x73, 0x4D, 0x94, 0x4F, 0x83, 0xEE, 0x7B, 0xAD, +0x83, 0xCD, 0x83, 0xED, 0x7B, 0xAD, 0x7B, 0xAD, +0x8B, 0xEE, 0x94, 0x4F, 0x94, 0x2F, 0x94, 0x4F, +0x94, 0x6F, 0x9C, 0x90, 0xB5, 0x32, 0xAD, 0x12, +0xAC, 0xF1, 0xAD, 0x11, 0xB5, 0x52, 0xB5, 0x73, +0x52, 0xAA, 0x6B, 0x4C, 0x8C, 0x50, 0xAD, 0x35, +0x73, 0x8E, 0x9C, 0x91, 0xC5, 0xF6, 0xBD, 0x94, +0xC5, 0xD5, 0xB5, 0x54, 0x62, 0xEB, 0x73, 0x8C, +0xA5, 0x32, 0xA4, 0xF1, 0x9C, 0xB0, 0xA4, 0xAF, +0xBD, 0x51, 0xAC, 0xAE, 0xA4, 0x8E, 0xD6, 0x36, +0xD6, 0x15, 0xD6, 0x35, 0xCE, 0x15, 0xCE, 0x15, +0xD6, 0x35, 0xD6, 0x35, 0xCE, 0x15, 0xCE, 0x15, +0xD6, 0x56, 0xD6, 0x56, 0xCE, 0x36, 0xD6, 0x77, +0xCE, 0x15, 0xC5, 0xF4, 0xC5, 0xD4, 0xC5, 0xF4, +0xCE, 0x15, 0xCE, 0x15, 0xC5, 0xB3, 0xD6, 0x35, +0xD6, 0x35, 0xAC, 0xAE, 0x94, 0x2D, 0xA4, 0xF0, +0xA4, 0xF0, 0xAD, 0x11, 0x9C, 0xB0, 0xA5, 0x11, +0xBD, 0xB3, 0xBD, 0xB3, 0xBD, 0xB3, 0xBD, 0xB3, +0xC5, 0xD4, 0xBD, 0xB3, 0xAD, 0x11, 0x52, 0x89, +0x52, 0x69, 0x4A, 0x28, 0x52, 0xCA, 0x5B, 0x0B, +0x4A, 0x49, 0x7B, 0xEF, 0x63, 0x0C, 0x73, 0xAF, +0xAD, 0x75, 0xA5, 0x14, 0x94, 0xB3, 0x8C, 0x72, +0x84, 0x10, 0x8C, 0x72, 0xA5, 0x35, 0x84, 0x10, +0x52, 0x8A, 0x31, 0xA7, 0x6B, 0x4D, 0xAD, 0x33, +0xAD, 0x33, 0x94, 0x6F, 0x7B, 0xAD, 0x62, 0xEA, +0x83, 0xCD, 0x8C, 0x2E, 0x6B, 0x4A, 0x83, 0xED, +0x8C, 0x0E, 0x84, 0x0D, 0x83, 0xCD, 0xB5, 0x31, +0xBD, 0x50, 0xAC, 0xEF, 0xCD, 0xD2, 0xD5, 0xF3, +0xD6, 0x13, 0xCD, 0xB2, 0xC5, 0x92, 0xCD, 0xB2, +0xCD, 0xB2, 0xD5, 0xB2, 0xCD, 0xB2, 0xC5, 0x70, +0xC5, 0x70, 0xC5, 0x71, 0xCD, 0xB2, 0xD5, 0xD2, +0xCD, 0xB2, 0xC5, 0x71, 0xCD, 0xF4, 0x83, 0xCD, +0x31, 0x65, 0x31, 0x44, 0x29, 0x44, 0x29, 0x24, +0x29, 0x24, 0x29, 0x23, 0x21, 0x03, 0x29, 0x44, +0x39, 0xA6, 0x42, 0x07, 0x29, 0x44, 0x31, 0x85, +0x4A, 0x48, 0x4A, 0x48, 0x52, 0x69, 0x41, 0xE7, +0x39, 0xE6, 0x31, 0x65, 0x29, 0x44, 0x39, 0xC6, +0x42, 0x27, 0x62, 0xEA, 0x5A, 0xAA, 0x63, 0x0B, +0x62, 0xEB, 0x6B, 0x2C, 0x6B, 0x4C, 0x73, 0x4C, +0x84, 0x30, 0xC6, 0x18, 0xCE, 0x79, 0xCE, 0x79, +0x9C, 0xB1, 0x8C, 0x0E, 0x94, 0x4F, 0x83, 0xED, +0x8C, 0x2E, 0x83, 0xED, 0x94, 0x2E, 0x9C, 0x8F, +0x8C, 0x2E, 0x94, 0x6F, 0x7B, 0x8D, 0x73, 0xAD, +0x7B, 0xCE, 0x8C, 0x4F, 0x7B, 0xCE, 0x7B, 0xCD, +0x8C, 0x0E, 0x94, 0x6F, 0xB5, 0x52, 0xBD, 0x72, +0xEE, 0xD7, 0xE6, 0x75, 0xDE, 0x55, 0xE6, 0xB6, +0xE6, 0x96, 0xD6, 0x14, 0xC5, 0x92, 0xB5, 0x10, +0xC5, 0xB3, 0xDE, 0x55, 0xE6, 0xB6, 0xEE, 0xB6, +0xEE, 0xD6, 0xE6, 0x95, 0xD6, 0x13, 0xD5, 0xF3, +0xBD, 0x50, 0xCD, 0xD2, 0xCD, 0xB2, 0xD6, 0x13, +0xD6, 0x13, 0xD5, 0xD3, 0xAC, 0xF0, 0xB5, 0x72, +0xBD, 0xB4, 0xC5, 0xD4, 0xCE, 0x36, 0xBD, 0xB4, +0xB5, 0x73, 0xB5, 0x73, 0xAD, 0x53, 0xAD, 0x32, +0xB5, 0x73, 0xC5, 0xD4, 0xC5, 0xF5, 0xAD, 0x12, +0xB5, 0x32, 0x9C, 0x70, 0x52, 0x68, 0x29, 0x44, +0x21, 0x03, 0x21, 0x24, 0x29, 0x65, 0x31, 0x85, +0x29, 0x64, 0x29, 0x65, 0x62, 0xEB, 0x62, 0xEA, +0x5A, 0x89, 0x73, 0x2C, 0x73, 0x2C, 0x62, 0xCA, +0x62, 0xCA, 0x5A, 0x8A, 0x6A, 0xCA, 0x83, 0x8D, +0x8B, 0xCE, 0x8B, 0xCE, 0x9C, 0x50, 0x8B, 0xEF, +0x7B, 0x6D, 0x83, 0xAE, 0xB4, 0xF3, 0xB5, 0x13, +0xAC, 0xF2, 0x62, 0xAA, 0x62, 0xCA, 0x7B, 0x6D, +0xAC, 0xF1, 0xB5, 0x32, 0xBD, 0x93, 0xB5, 0x52, +0xB5, 0x31, 0xCE, 0x15, 0xDE, 0x56, 0xD6, 0x56, +0xCD, 0xF5, 0xCE, 0x15, 0xCD, 0xF5, 0xBD, 0x93, +0xC5, 0xD4, 0xC5, 0xB4, 0xC5, 0x94, 0xBD, 0xB4, +0x9C, 0x90, 0x62, 0xA9, 0x31, 0x65, 0x18, 0xC3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0x83, 0x08, 0x83, 0x08, 0x83, 0x10, 0x83, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC3, 0x10, 0xC3, +0x10, 0xC3, 0x10, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x18, 0xE4, +0x21, 0x05, 0x31, 0x87, 0x73, 0x4D, 0x8C, 0x30, +0x62, 0xEB, 0x42, 0x08, 0x31, 0xA7, 0x21, 0x26, +0x21, 0x26, 0x21, 0x26, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x21, 0x26, 0x21, 0x26, 0x21, 0x26, +0x29, 0x67, 0x29, 0x46, 0x29, 0x67, 0x29, 0x67, +0x21, 0x26, 0x21, 0x26, 0x29, 0x67, 0x39, 0xC8, +0x52, 0x49, 0x83, 0xEF, 0xBD, 0xB4, 0xC5, 0xF5, +0xBD, 0x74, 0xB5, 0x33, 0xAD, 0x33, 0xB5, 0x53, +0xB5, 0x53, 0xAD, 0x33, 0xAD, 0x32, 0xAD, 0x12, +0xA4, 0xF2, 0xA4, 0xF2, 0xA4, 0xD1, 0xA4, 0xD1, +0x9C, 0xB1, 0x94, 0x70, 0x94, 0x4F, 0x94, 0x6F, +0x3A, 0x07, 0x42, 0x27, 0x52, 0xAA, 0x5A, 0xCA, +0x6B, 0x2D, 0x6B, 0x4D, 0xA5, 0x14, 0xAD, 0x13, +0xC5, 0xB6, 0xC5, 0xB7, 0xA4, 0xB2, 0x6B, 0x2B, +0xBD, 0xB5, 0xB5, 0x93, 0xAD, 0x31, 0x9C, 0x8E, +0xAC, 0xCF, 0xA4, 0x8E, 0x9C, 0x6E, 0xD6, 0x35, +0xD6, 0x35, 0xD6, 0x56, 0xD6, 0x56, 0xD6, 0x76, +0xD6, 0x56, 0xDE, 0x97, 0xDE, 0x76, 0xDE, 0x76, +0xDE, 0x77, 0xD6, 0x56, 0xD6, 0x36, 0xD6, 0x76, +0xCE, 0x15, 0xCE, 0x15, 0xCE, 0x15, 0xD6, 0x36, +0xD6, 0x56, 0xD6, 0x56, 0xCE, 0x15, 0xD6, 0x56, +0xCD, 0xF3, 0xA4, 0xAE, 0x73, 0x29, 0x94, 0x4E, +0x9C, 0xAF, 0xAD, 0x31, 0xBD, 0x93, 0xBD, 0x93, +0xC5, 0xB3, 0xBD, 0xB3, 0xC5, 0xD3, 0xB5, 0x72, +0xC5, 0xD4, 0xC5, 0xF4, 0xC5, 0xB4, 0x9C, 0xB0, +0x39, 0x85, 0x29, 0x44, 0x42, 0x28, 0x52, 0xAA, +0x52, 0xAA, 0x6B, 0x4D, 0x5A, 0xEC, 0x84, 0x10, +0x94, 0x92, 0x8C, 0x51, 0xB5, 0xB7, 0x8C, 0x52, +0x7B, 0xCF, 0x94, 0xB2, 0xA5, 0x14, 0x8C, 0x51, +0x63, 0x0D, 0x5A, 0xEB, 0x5A, 0xCA, 0x6B, 0x2C, +0x6B, 0x2B, 0x7B, 0x8D, 0xAC, 0xF2, 0x94, 0x90, +0x9C, 0xB0, 0xA4, 0xF1, 0xA5, 0x12, 0xBD, 0xB4, +0xB5, 0x94, 0xBD, 0xF5, 0xBD, 0xD5, 0xC5, 0xB4, +0xAC, 0xEF, 0xB4, 0xEF, 0xD5, 0xF3, 0xDD, 0xF3, +0xD5, 0xD2, 0xC5, 0x50, 0xC5, 0x91, 0xDE, 0x54, +0xDE, 0x33, 0xDE, 0x33, 0xCD, 0xB1, 0xBD, 0x50, +0xB5, 0x10, 0xAC, 0xEF, 0xBD, 0x30, 0xCD, 0xB2, +0xC5, 0x71, 0x9C, 0x6D, 0x94, 0x4E, 0x8B, 0xED, +0x6B, 0x2A, 0x6B, 0x0A, 0x62, 0xC9, 0x62, 0xC9, +0x62, 0xC9, 0x4A, 0x27, 0x42, 0x07, 0x41, 0xE7, +0x41, 0xE7, 0x39, 0xA5, 0x29, 0x44, 0x29, 0x24, +0x29, 0x23, 0x31, 0x65, 0x42, 0x28, 0x4A, 0x28, +0x39, 0xC6, 0x31, 0x65, 0x31, 0x85, 0x29, 0x44, +0x42, 0x07, 0x4A, 0x48, 0x39, 0xA6, 0x41, 0xE7, +0x5A, 0xAA, 0x6B, 0x4C, 0x52, 0x8A, 0x84, 0x10, +0x9C, 0xF4, 0x9C, 0xF4, 0xBD, 0xD7, 0xB5, 0x75, +0xC5, 0xD6, 0xBD, 0x32, 0xBD, 0x51, 0xA4, 0xAF, +0x9C, 0x8E, 0xA4, 0x8F, 0x9C, 0x8F, 0xAC, 0xD0, +0x9C, 0x8F, 0x9C, 0x6E, 0x9C, 0x6E, 0x9C, 0x6E, +0xAC, 0xF1, 0xAD, 0x12, 0x9C, 0xB1, 0x9C, 0xB0, +0x9C, 0xB0, 0xAD, 0x12, 0xB5, 0x32, 0xA4, 0xD0, +0xBD, 0x72, 0xC5, 0xB3, 0xD5, 0xF4, 0xD6, 0x34, +0xD6, 0x14, 0xDE, 0x55, 0xD6, 0x35, 0xD6, 0x14, +0xD6, 0x14, 0xEE, 0xD7, 0xF6, 0xF7, 0xF6, 0xF7, +0xEE, 0xD7, 0xEE, 0xD7, 0xEE, 0x96, 0xE6, 0x75, +0xCD, 0xB2, 0xDE, 0x34, 0xDE, 0x14, 0xE6, 0x54, +0xDE, 0x54, 0xCD, 0xB2, 0xA4, 0x8E, 0xBD, 0x93, +0xC5, 0xD4, 0xAD, 0x32, 0xBD, 0xD4, 0xB5, 0xB4, +0xC6, 0x15, 0xC6, 0x15, 0xBD, 0xD5, 0xBD, 0xB4, +0xB5, 0x93, 0xBD, 0xB4, 0xB5, 0x73, 0xAD, 0x11, +0xBD, 0x52, 0xDE, 0x35, 0xE6, 0x76, 0xBD, 0x93, +0x94, 0x2F, 0x41, 0xE7, 0x29, 0x44, 0x29, 0x44, +0x21, 0x24, 0x39, 0xC6, 0x7B, 0xEE, 0x8C, 0x0F, +0x8C, 0x10, 0x4A, 0x28, 0x52, 0x49, 0x41, 0xE7, +0x73, 0x4C, 0x83, 0xCF, 0x73, 0x4C, 0x72, 0xEA, +0x83, 0x8D, 0x93, 0xCE, 0x94, 0x0F, 0x94, 0x0F, +0x6A, 0xCB, 0x62, 0xAA, 0x8B, 0xEF, 0xB5, 0x33, +0xC5, 0x95, 0x7B, 0x6D, 0x6A, 0xCB, 0x5A, 0x89, +0x83, 0xAD, 0xA4, 0xB0, 0xC5, 0xD4, 0xBD, 0xB3, +0xBD, 0x72, 0xDE, 0x76, 0xDE, 0x77, 0x94, 0x2F, +0x41, 0xE7, 0x41, 0xE7, 0x4A, 0x07, 0x52, 0x69, +0x94, 0x70, 0xA4, 0xD1, 0x7B, 0x8C, 0x52, 0x89, +0x31, 0x45, 0x18, 0xC3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, +0x08, 0x83, 0x08, 0x83, 0x08, 0x83, 0x08, 0x83, +0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xC4, 0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC4, +0x19, 0x04, 0x31, 0x66, 0x5A, 0xAA, 0x9C, 0xB1, +0xA4, 0xD1, 0x73, 0x4C, 0x5A, 0xAB, 0x31, 0x87, +0x21, 0x26, 0x21, 0x26, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x21, 0x26, 0x21, 0x26, 0x29, 0x67, +0x29, 0x87, 0x21, 0x46, 0x21, 0x46, 0x21, 0x05, +0x18, 0xE5, 0x21, 0x05, 0x29, 0x67, 0x31, 0x87, +0x39, 0xC7, 0x5A, 0xAA, 0x94, 0x4F, 0xCD, 0xF5, +0xDE, 0x56, 0xCD, 0xD4, 0x9C, 0x90, 0x94, 0x6F, +0x94, 0x4F, 0x8C, 0x2F, 0x94, 0x70, 0x94, 0x6F, +0x8C, 0x2E, 0x94, 0x4F, 0x9C, 0xD1, 0xAD, 0x33, +0xAD, 0x33, 0xA4, 0xF2, 0xA4, 0xF1, 0x9C, 0xD1, +0x3A, 0x07, 0x42, 0x06, 0x42, 0x27, 0x62, 0xEB, +0x84, 0x10, 0x52, 0xAA, 0x73, 0xAF, 0xC5, 0xD7, +0x9C, 0x71, 0x9C, 0x71, 0x9C, 0x71, 0x8C, 0x0D, +0xAD, 0x32, 0xB5, 0x93, 0x83, 0xED, 0x8B, 0xEC, +0xAC, 0xCF, 0xA4, 0x6D, 0x94, 0x2D, 0x9C, 0x8F, +0xA4, 0xB0, 0xA4, 0xB0, 0x9C, 0x6F, 0xA4, 0xF1, +0x94, 0x4E, 0x9C, 0x90, 0xA4, 0xF1, 0xAD, 0x12, +0x9C, 0x90, 0x9C, 0x90, 0xA4, 0xF1, 0xAD, 0x11, +0x7B, 0x8C, 0x83, 0xAC, 0x8C, 0x0E, 0xAD, 0x11, +0xBD, 0x93, 0xCD, 0xF5, 0xCE, 0x15, 0xBD, 0x72, +0xC5, 0xB2, 0xAC, 0xCF, 0x8B, 0xEC, 0xA5, 0x11, +0xAD, 0x11, 0xB5, 0x93, 0xBD, 0x93, 0xCE, 0x15, +0xCE, 0x35, 0xC5, 0xF4, 0xD6, 0x55, 0xC5, 0xF4, +0xBD, 0xB3, 0xB5, 0x73, 0xBD, 0x73, 0xBD, 0x93, +0x7B, 0x8C, 0x63, 0x0B, 0x6B, 0x2B, 0x4A, 0x28, +0x52, 0x89, 0x73, 0x8E, 0x5A, 0xEC, 0x73, 0xAE, +0x7B, 0xEF, 0x8C, 0x72, 0xAD, 0x55, 0x83, 0xF0, +0x73, 0x8E, 0xB5, 0x96, 0xAD, 0x76, 0x84, 0x10, +0x84, 0x10, 0x62, 0xEC, 0x39, 0xE7, 0x6B, 0x6D, +0xAD, 0x34, 0xB5, 0x75, 0xC5, 0xF6, 0xAD, 0x33, +0xA5, 0x33, 0xC6, 0x16, 0xCE, 0x36, 0xC6, 0x16, +0xC6, 0x15, 0xCE, 0x36, 0xC5, 0xF5, 0xCE, 0x15, +0xC5, 0x72, 0xB5, 0x0F, 0xEE, 0xB6, 0xD5, 0xD2, +0xE6, 0x54, 0xE6, 0x54, 0xEE, 0x75, 0xEE, 0xD6, +0xEE, 0xD6, 0xEE, 0xB5, 0xCD, 0x91, 0xD6, 0x14, +0xCD, 0xD3, 0xBD, 0x72, 0xC5, 0x71, 0xDE, 0x14, +0xC5, 0x91, 0xAC, 0xEF, 0xC5, 0xB3, 0xA4, 0xF0, +0x83, 0xED, 0x94, 0x2E, 0xA4, 0xF0, 0xA4, 0xF0, +0x9C, 0x90, 0x73, 0x6C, 0x73, 0x6C, 0x63, 0x0B, +0x62, 0xEB, 0x42, 0x07, 0x29, 0x44, 0x29, 0x24, +0x21, 0x03, 0x21, 0x03, 0x20, 0xE3, 0x29, 0x44, +0x39, 0xA6, 0x29, 0x64, 0x29, 0x24, 0x29, 0x64, +0x39, 0xA6, 0x42, 0x07, 0x39, 0xA6, 0x29, 0x24, +0x4A, 0x08, 0x63, 0x0C, 0x8C, 0x51, 0xA5, 0x35, +0x94, 0xB3, 0x9C, 0xB3, 0xA4, 0xF4, 0xB5, 0xB6, +0xD6, 0x78, 0xA4, 0xD0, 0xA4, 0x8F, 0x94, 0x2D, +0x9C, 0x6E, 0x9C, 0x6E, 0xA4, 0x8E, 0xAC, 0xF0, +0xAC, 0xCF, 0xB5, 0x10, 0xAC, 0xF0, 0xAC, 0xCF, +0xBD, 0x51, 0xBD, 0x72, 0xD6, 0x36, 0xD6, 0x36, +0xD6, 0x36, 0xC5, 0xB4, 0xBD, 0x73, 0xB5, 0x52, +0xB5, 0x32, 0xB5, 0x11, 0xAC, 0xF0, 0xAC, 0xD0, +0xB5, 0x11, 0xB5, 0x31, 0xB4, 0xF1, 0xBD, 0x31, +0xB5, 0x10, 0xAC, 0xD0, 0xAC, 0xD0, 0xAC, 0xD0, +0xB4, 0xF0, 0xB4, 0xF0, 0xBD, 0x31, 0xBD, 0x31, +0xBD, 0x31, 0xBD, 0x10, 0xBD, 0x51, 0xB5, 0x31, +0xA4, 0xAF, 0xA4, 0xAF, 0xB5, 0x31, 0xB5, 0x52, +0xB5, 0x52, 0xB5, 0x72, 0xC5, 0xF4, 0xC5, 0xF5, +0xC6, 0x15, 0xC5, 0xF5, 0xC6, 0x15, 0xCE, 0x56, +0xCE, 0x36, 0xBD, 0xB4, 0x7B, 0xAC, 0xAC, 0xF1, +0xAC, 0xF0, 0xCD, 0xD4, 0xDE, 0x55, 0xDE, 0x55, +0xE6, 0x97, 0xC5, 0xB4, 0x6B, 0x2A, 0x39, 0xA5, +0x21, 0x03, 0x39, 0xE7, 0x6B, 0x2C, 0x6B, 0x2C, +0x73, 0x8E, 0x39, 0xC7, 0x73, 0x8E, 0x73, 0x6D, +0x5A, 0xAA, 0x62, 0xCA, 0x62, 0xCA, 0x6A, 0xCA, +0x6A, 0xEB, 0x6A, 0xAA, 0x73, 0x0B, 0x8B, 0xEE, +0x5A, 0x69, 0x7B, 0xAE, 0x62, 0x8A, 0x73, 0x2C, +0x8B, 0xCF, 0x83, 0xAE, 0x83, 0xAE, 0x8C, 0x0F, +0x73, 0x2B, 0x6A, 0xEA, 0x83, 0x8D, 0x94, 0x2E, +0xB5, 0x52, 0xEE, 0xD8, 0xBD, 0x94, 0x42, 0x08, +0x18, 0xC4, 0x10, 0xA3, 0x10, 0x82, 0x10, 0x83, +0x18, 0xE4, 0x29, 0x25, 0x20, 0xE4, 0x20, 0xE4, +0x18, 0xC3, 0x18, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0x83, 0x08, 0x83, 0x10, 0x83, +0x08, 0x83, 0x08, 0x83, 0x10, 0x83, 0x10, 0x83, +0x10, 0x83, 0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xC4, 0x10, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC4, +0x19, 0x04, 0x29, 0x46, 0x39, 0xC7, 0x84, 0x0E, +0xBD, 0xD4, 0x8B, 0xEE, 0x6B, 0x2C, 0x39, 0xC7, +0x29, 0x46, 0x21, 0x26, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x21, 0x26, 0x21, 0x26, 0x29, 0x87, +0x21, 0x26, 0x21, 0x26, 0x21, 0x26, 0x21, 0x05, +0x21, 0x05, 0x18, 0xE5, 0x19, 0x05, 0x31, 0x67, +0x39, 0xE8, 0x4A, 0x49, 0x5A, 0xAA, 0xAC, 0xF1, +0xF7, 0x19, 0xCD, 0xF4, 0xAD, 0x12, 0x8C, 0x0E, +0x9C, 0xB0, 0x94, 0x90, 0xA4, 0xF1, 0xA4, 0xD1, +0x94, 0x70, 0x94, 0x70, 0xAD, 0x12, 0xBD, 0xB4, +0xBD, 0x93, 0xA4, 0xF1, 0x83, 0xEE, 0x83, 0xEE, +0x73, 0x8D, 0x52, 0xA9, 0x39, 0xE6, 0x42, 0x07, +0x4A, 0x48, 0x4A, 0x48, 0x6B, 0x4D, 0x94, 0x71, +0x8C, 0x31, 0x39, 0xC7, 0x41, 0xE7, 0x9C, 0xB1, +0xD6, 0x77, 0xCE, 0x16, 0xBD, 0xB5, 0xA4, 0xB0, +0xA4, 0x8E, 0xA4, 0x6E, 0x8B, 0xCB, 0x83, 0xAC, +0x83, 0xAC, 0x94, 0x0D, 0x8C, 0x0D, 0x7B, 0x8B, +0x83, 0x8C, 0x83, 0xAC, 0x73, 0x4B, 0x73, 0x2A, +0x6A, 0xEA, 0x6B, 0x0A, 0x62, 0xC9, 0x62, 0xA9, +0x5A, 0xA9, 0x73, 0x2B, 0x7B, 0x4B, 0x7B, 0x8C, +0x7B, 0x8C, 0x83, 0xAC, 0x9C, 0x8F, 0xBD, 0x72, +0xCD, 0xF3, 0xAC, 0xEF, 0x9C, 0x6E, 0xBD, 0xB3, +0xC5, 0xF4, 0xAD, 0x31, 0x94, 0x4D, 0x94, 0x2D, +0x94, 0x4D, 0x9C, 0xAF, 0xC5, 0xD3, 0xC5, 0xD3, +0xD6, 0x55, 0xD6, 0x76, 0xDE, 0x97, 0xDE, 0x97, +0xBD, 0x94, 0x8C, 0x2F, 0xCE, 0x16, 0xC5, 0xF6, +0xA4, 0xF2, 0x8C, 0x30, 0x39, 0xE8, 0x5A, 0xEC, +0x63, 0x0C, 0x7B, 0xF0, 0x94, 0xB3, 0x5A, 0xEC, +0x84, 0x10, 0xB5, 0x96, 0xB5, 0x76, 0x73, 0x8E, +0x9C, 0xF4, 0x31, 0xA7, 0x73, 0x8D, 0x94, 0xB2, +0xD6, 0x79, 0xDE, 0xDA, 0xE6, 0xFB, 0x8C, 0x30, +0x4A, 0x69, 0xBD, 0xB5, 0xCE, 0x77, 0xCE, 0x56, +0xC6, 0x15, 0xCE, 0x56, 0xBD, 0xD4, 0xC5, 0xB3, +0xBD, 0x30, 0xBD, 0x50, 0xF6, 0xD6, 0xE6, 0x33, +0xDE, 0x13, 0xDE, 0x33, 0xE6, 0x33, 0xDE, 0x33, +0xE6, 0x54, 0xD5, 0xF2, 0xC5, 0x51, 0xD6, 0x14, +0xCD, 0xB2, 0xCD, 0xD3, 0xCD, 0xD3, 0xDE, 0x54, +0xC5, 0x50, 0xBD, 0x30, 0xCE, 0x14, 0xBD, 0x72, +0x7B, 0xAC, 0x73, 0x6B, 0xAD, 0x32, 0xC5, 0xD4, +0xBD, 0x73, 0x9C, 0x8F, 0x94, 0x4F, 0x8C, 0x2F, +0x8C, 0x2F, 0x73, 0x8C, 0x5A, 0xA9, 0x31, 0x65, +0x29, 0x23, 0x29, 0x64, 0x29, 0x44, 0x21, 0x03, +0x29, 0x24, 0x29, 0x44, 0x31, 0x85, 0x31, 0xA5, +0x41, 0xE6, 0x31, 0x85, 0x41, 0xE7, 0x52, 0x49, +0x62, 0xCB, 0x6B, 0x2C, 0xA5, 0x14, 0xAD, 0x55, +0xA5, 0x14, 0xA5, 0x14, 0xA4, 0xF4, 0xB5, 0xB7, +0xCE, 0x59, 0xBD, 0xB5, 0x9C, 0x90, 0xA5, 0x11, +0xB5, 0x73, 0xB5, 0x92, 0xBD, 0xB3, 0xC5, 0xB3, +0xC5, 0xD4, 0xBD, 0x72, 0xAC, 0xF0, 0x7B, 0x8A, +0xA4, 0xAF, 0xC5, 0xB4, 0xE6, 0x97, 0xCD, 0xD4, +0xD6, 0x15, 0xCD, 0xF5, 0xB5, 0x32, 0xCD, 0xF4, +0xCD, 0xD4, 0xC5, 0x72, 0xC5, 0x93, 0xD6, 0x15, +0xD6, 0x55, 0xDE, 0x97, 0xCD, 0xF4, 0xDE, 0x56, +0xDE, 0x56, 0xDE, 0x56, 0xCD, 0xB4, 0xBD, 0x52, +0xBD, 0x73, 0xBD, 0x52, 0xBD, 0x52, 0xC5, 0x72, +0xC5, 0x72, 0xC5, 0x73, 0xBD, 0x52, 0xA4, 0xB0, +0xAC, 0xF1, 0xAC, 0xF1, 0xB5, 0x12, 0xB5, 0x32, +0xAD, 0x31, 0xA4, 0xD0, 0xA4, 0xF0, 0xAD, 0x11, +0xAD, 0x11, 0xB5, 0x73, 0xB5, 0x52, 0xAD, 0x11, +0xAC, 0xF1, 0xAC, 0xF1, 0xAD, 0x11, 0xAD, 0x32, +0xAD, 0x11, 0xA4, 0xD0, 0x9C, 0x6F, 0x94, 0x4F, +0x94, 0x4F, 0x9C, 0x6F, 0x94, 0x2E, 0x7B, 0xAC, +0x41, 0xE7, 0x4A, 0x69, 0x7B, 0xEF, 0x8C, 0x30, +0x84, 0x10, 0x39, 0xC7, 0x8C, 0x71, 0x8C, 0x51, +0x9C, 0xB2, 0x9C, 0xD3, 0x83, 0xCF, 0x8C, 0x10, +0x83, 0xCE, 0x73, 0x6C, 0x6B, 0x0C, 0x5A, 0x8A, +0x62, 0xCB, 0x83, 0xCE, 0x7B, 0xAE, 0x73, 0x2C, +0x62, 0xCA, 0x9C, 0x50, 0x9C, 0x71, 0x8B, 0xEF, +0x94, 0x30, 0x73, 0x2C, 0x6A, 0xCB, 0x7B, 0x4C, +0x6B, 0x0B, 0xB5, 0x32, 0x7B, 0x8D, 0x20, 0xE4, +0x10, 0x83, 0x10, 0xA2, 0x10, 0xA3, 0x10, 0x83, +0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, +0x10, 0xA3, 0x10, 0x83, 0x08, 0x83, 0x10, 0x83, +0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0x83, 0x10, 0xA3, 0x18, 0xC4, 0x10, 0xA3, +0x10, 0x83, 0x08, 0x83, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x18, 0xC4, 0x20, 0xE4, 0x31, 0x66, 0x6B, 0x2B, +0xB5, 0x93, 0x9C, 0x70, 0x73, 0x6D, 0x42, 0x08, +0x29, 0x87, 0x21, 0x26, 0x19, 0x05, 0x21, 0x05, +0x19, 0x05, 0x21, 0x05, 0x21, 0x25, 0x29, 0x87, +0x19, 0x05, 0x19, 0x05, 0x19, 0x05, 0x21, 0x05, +0x18, 0xE5, 0x19, 0x05, 0x29, 0x87, 0x31, 0xA8, +0x39, 0xC8, 0x39, 0xC8, 0x41, 0xC8, 0x73, 0x2C, +0xE6, 0x97, 0xC5, 0xD4, 0xAD, 0x32, 0x9C, 0x90, +0xAD, 0x53, 0xAD, 0x53, 0xB5, 0x73, 0xAD, 0x33, +0xA4, 0xD1, 0x9C, 0xB0, 0xBD, 0xB4, 0xBD, 0xB3, +0xC5, 0xD4, 0xB5, 0x73, 0x94, 0x90, 0xA4, 0xF2, +0x9C, 0xF3, 0x84, 0x2F, 0x7B, 0xCD, 0x6B, 0x2B, +0x41, 0xE6, 0x21, 0x23, 0x31, 0x85, 0x4A, 0x48, +0x6B, 0x2C, 0x7B, 0xAE, 0x39, 0xC6, 0x63, 0x0B, +0xBD, 0x95, 0xD6, 0x78, 0xDE, 0xB9, 0xD6, 0x37, +0xAC, 0xF2, 0x8B, 0xED, 0x94, 0x2D, 0x9C, 0x6E, +0xA4, 0x8E, 0xA4, 0xAF, 0xAC, 0xD0, 0xA4, 0x8E, +0xB5, 0x11, 0xB5, 0x31, 0xA4, 0xAF, 0xA4, 0x8F, +0xAC, 0xD0, 0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0xAF, +0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0x8F, +0x9C, 0x6E, 0x9C, 0x4E, 0x9C, 0x6E, 0xA4, 0x8E, +0xAC, 0xCE, 0xB4, 0xEF, 0xAC, 0xCF, 0xA4, 0xAE, +0xAC, 0xCF, 0xAC, 0xF0, 0x94, 0x2D, 0x94, 0x4D, +0x94, 0x2D, 0xB5, 0x11, 0xB5, 0x51, 0x94, 0x4D, +0xA4, 0xAE, 0xAD, 0x10, 0xAD, 0x10, 0xB5, 0x32, +0x9C, 0x4F, 0xAD, 0x11, 0xD6, 0x76, 0xE6, 0xD8, +0xBD, 0x94, 0x8C, 0x30, 0x42, 0x28, 0x4A, 0x48, +0x4A, 0x69, 0x5A, 0xCB, 0x7B, 0xEF, 0x52, 0x8A, +0x7B, 0xF0, 0xB5, 0x96, 0x8C, 0x51, 0x9C, 0xF3, +0x8C, 0x31, 0x9C, 0xB2, 0xAD, 0x55, 0x8C, 0x51, +0x9C, 0xB3, 0x94, 0x92, 0x94, 0x92, 0x63, 0x0C, +0x52, 0x6A, 0x84, 0x0F, 0xE7, 0x1A, 0xD6, 0x97, +0xD6, 0x77, 0xCE, 0x56, 0xCE, 0x36, 0xC5, 0xD4, +0xB5, 0x10, 0xC5, 0x91, 0xF6, 0xF6, 0xE6, 0x33, +0xDD, 0xF2, 0xD5, 0xD2, 0xDE, 0x33, 0xE6, 0x33, +0xD5, 0xD2, 0xCD, 0x91, 0xCD, 0xF3, 0xD6, 0x34, +0xD6, 0x34, 0xD5, 0xF4, 0xC5, 0x71, 0xE6, 0x54, +0xC5, 0x50, 0xBD, 0x50, 0xD6, 0x35, 0xC5, 0xD3, +0x9C, 0x6F, 0xAD, 0x32, 0xCE, 0x15, 0xCE, 0x15, +0xBD, 0x93, 0xC5, 0xB4, 0xA4, 0xD1, 0x94, 0x70, +0x94, 0x90, 0x8C, 0x4F, 0x94, 0x4F, 0x6B, 0x2B, +0x31, 0x85, 0x29, 0x64, 0x31, 0x85, 0x31, 0x65, +0x29, 0x44, 0x20, 0xE3, 0x29, 0x24, 0x31, 0x85, +0x31, 0x85, 0x31, 0xA5, 0x52, 0x69, 0x5A, 0xCB, +0x63, 0x0C, 0x6B, 0x2C, 0x73, 0x8E, 0x7B, 0xAF, +0x7B, 0xF0, 0x83, 0xF0, 0x94, 0xB3, 0x94, 0x92, +0xBD, 0xB6, 0xCE, 0x38, 0xAD, 0x54, 0xB5, 0x73, +0xC6, 0x15, 0xC5, 0xF4, 0xC5, 0xD3, 0xC5, 0xF4, +0xC5, 0xF4, 0xA4, 0xCF, 0xB5, 0x51, 0x94, 0x2E, +0xA4, 0xB0, 0xBD, 0xB3, 0xDE, 0x97, 0xCD, 0xF4, +0xD6, 0x35, 0xD6, 0x35, 0xB5, 0x31, 0xBD, 0x72, +0xCD, 0xF4, 0xC5, 0xB3, 0xB5, 0x31, 0xD5, 0xF4, +0xD6, 0x15, 0xDE, 0x76, 0xDE, 0x56, 0xD6, 0x15, +0xC5, 0xB3, 0xDE, 0x76, 0xE6, 0xB7, 0xDE, 0x55, +0xDE, 0x55, 0xDE, 0x35, 0xCD, 0xB3, 0xDE, 0x35, +0xB5, 0x31, 0xAC, 0xF1, 0x9C, 0x70, 0x8C, 0x0E, +0x9C, 0x8F, 0x9C, 0x8F, 0x9C, 0x8F, 0xA4, 0xD0, +0x9C, 0x8F, 0x94, 0x4E, 0xA4, 0xD0, 0xA4, 0xAF, +0x94, 0x2E, 0xA4, 0xD0, 0xA4, 0xF1, 0xA4, 0xF0, +0xA4, 0xF1, 0x9C, 0xB0, 0xAD, 0x12, 0xB5, 0x52, +0xB5, 0x32, 0xB5, 0x32, 0xB5, 0x53, 0xBD, 0x73, +0xC5, 0xB4, 0xBD, 0x93, 0xAD, 0x32, 0xAD, 0x12, +0x8C, 0x2F, 0x6B, 0x4C, 0x73, 0x8D, 0x7B, 0xCF, +0x7B, 0xAF, 0x39, 0xC7, 0x5A, 0xCA, 0x42, 0x08, +0x4A, 0x69, 0x6B, 0x4D, 0x7B, 0xCF, 0x9C, 0xD3, +0xAD, 0x34, 0x9C, 0x91, 0x83, 0xEE, 0x73, 0x6D, +0x6B, 0x0B, 0x52, 0x69, 0x6B, 0x0C, 0x7B, 0x8E, +0x8B, 0xEF, 0x83, 0xAD, 0x7B, 0x4C, 0x93, 0xEF, +0x8B, 0xEF, 0xB5, 0x13, 0xA4, 0xB2, 0x7B, 0x6D, +0x6A, 0xEB, 0x83, 0xAF, 0x41, 0xE7, 0x18, 0xC4, +0x18, 0xE4, 0x18, 0xC3, 0x10, 0xA3, 0x10, 0x83, +0x10, 0x83, 0x10, 0x82, 0x10, 0x83, 0x10, 0x83, +0x10, 0xA3, 0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC3, +0x18, 0xC4, 0x10, 0xA3, 0x18, 0xC3, 0x18, 0xE4, +0x31, 0x86, 0x4A, 0x69, 0x29, 0x65, 0x10, 0x83, +0x08, 0x83, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, +0x10, 0xA3, 0x18, 0xE4, 0x21, 0x04, 0x41, 0xC7, +0x83, 0xCE, 0xA4, 0xB1, 0x8C, 0x2F, 0x7B, 0xAE, +0x52, 0xAA, 0x31, 0x86, 0x21, 0x25, 0x21, 0x05, +0x19, 0x05, 0x18, 0xE5, 0x21, 0x25, 0x21, 0x46, +0x18, 0xE5, 0x18, 0xE5, 0x18, 0xE5, 0x18, 0xE4, +0x21, 0x25, 0x29, 0x46, 0x29, 0x66, 0x29, 0x66, +0x21, 0x46, 0x21, 0x25, 0x29, 0x66, 0x4A, 0x28, +0xBD, 0x94, 0xC5, 0xD4, 0xB5, 0x53, 0x9C, 0xB1, +0xAD, 0x32, 0xAD, 0x32, 0xBD, 0xB4, 0xA4, 0xD1, +0xA4, 0xF2, 0xA4, 0xF1, 0xBD, 0xB4, 0xAD, 0x32, +0xC5, 0xF5, 0xAD, 0x53, 0x9C, 0xB0, 0xAD, 0x33, +0x94, 0xD3, 0x84, 0x2F, 0x94, 0x6F, 0xAD, 0x32, +0x9C, 0xD0, 0x5A, 0xA8, 0x29, 0x64, 0x31, 0xA6, +0x39, 0xE7, 0x5A, 0xEB, 0x52, 0x69, 0x4A, 0x48, +0x6B, 0x4C, 0x94, 0x91, 0xA4, 0xF3, 0xC5, 0xF7, +0xE6, 0xDB, 0xBD, 0xB6, 0x52, 0x68, 0x6B, 0x09, +0xB5, 0x31, 0xAC, 0xCF, 0xAC, 0xCF, 0xAC, 0xF0, +0xBD, 0x92, 0xAC, 0xF0, 0x94, 0x4E, 0x8C, 0x2D, +0xB5, 0x52, 0xB5, 0x31, 0xB5, 0x30, 0xA4, 0x8E, +0x9C, 0x8E, 0x9C, 0x6E, 0xA4, 0xAE, 0x9C, 0x6E, +0x9C, 0x6E, 0x9C, 0x8E, 0xA4, 0x8E, 0xAC, 0xCF, +0xAC, 0xCF, 0xB5, 0x10, 0xBD, 0x30, 0xB4, 0xEF, +0xB5, 0x10, 0xBD, 0x30, 0xB5, 0x30, 0xB5, 0x10, +0xB4, 0xEF, 0xAC, 0xCF, 0xAC, 0xCE, 0xAC, 0xCF, +0xAC, 0xEF, 0xB5, 0x10, 0xAC, 0xCF, 0xA4, 0xAF, +0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0xCF, 0xA4, 0xCF, +0x8B, 0xCD, 0x6B, 0x0B, 0x5A, 0xCA, 0x42, 0x48, +0x3A, 0x07, 0x42, 0x07, 0x52, 0xAA, 0x4A, 0x69, +0x6B, 0x6D, 0x8C, 0x72, 0x73, 0x8E, 0x94, 0xB3, +0x83, 0xF0, 0x94, 0x72, 0x94, 0x71, 0x7B, 0xAF, +0x5A, 0xCC, 0xB5, 0x76, 0xBD, 0xB6, 0x94, 0x92, +0x83, 0xF0, 0x8C, 0x71, 0x7B, 0xEF, 0xB5, 0x74, +0xCE, 0x57, 0xD6, 0x97, 0xD6, 0x76, 0xD6, 0x75, +0xB5, 0x10, 0xAC, 0xCE, 0xE6, 0x54, 0xEE, 0x95, +0xE6, 0x13, 0xDE, 0x13, 0xE6, 0x54, 0xEE, 0x75, +0xC5, 0x71, 0xCD, 0xB2, 0xD5, 0xF3, 0xDE, 0x55, +0xCD, 0xD3, 0xC5, 0x92, 0xC5, 0x91, 0xE6, 0x75, +0xCD, 0x91, 0xBD, 0x51, 0xDE, 0x96, 0xDE, 0x55, +0xBD, 0x92, 0xC5, 0xD4, 0xC5, 0xD4, 0xC5, 0xB3, +0xC5, 0xB3, 0xBD, 0x73, 0xAD, 0x11, 0xAD, 0x32, +0xAD, 0x32, 0xA4, 0xD1, 0xA4, 0xF1, 0x9C, 0x90, +0x29, 0x44, 0x29, 0x44, 0x31, 0x85, 0x41, 0xE7, +0x29, 0x24, 0x21, 0x03, 0x31, 0x65, 0x42, 0x07, +0x42, 0x07, 0x52, 0x69, 0x7B, 0xCF, 0xA5, 0x34, +0x7B, 0xAE, 0x5A, 0xAA, 0x63, 0x0C, 0x73, 0x8E, +0x6B, 0x4D, 0x7B, 0xCF, 0x84, 0x10, 0x94, 0x92, +0xA5, 0x35, 0xC6, 0x18, 0xCE, 0x38, 0xB5, 0x95, +0xCE, 0x15, 0xCE, 0x35, 0xB5, 0x72, 0xBD, 0xB3, +0xBD, 0xB3, 0xC5, 0xF4, 0xC5, 0xB3, 0xB5, 0x52, +0xAC, 0xD0, 0xC5, 0xB3, 0xE6, 0xB7, 0xC5, 0xB3, +0xB5, 0x51, 0xCD, 0xD4, 0xCD, 0xD3, 0xCD, 0xF4, +0xD6, 0x14, 0xD5, 0xF4, 0xC5, 0x92, 0xD5, 0xF4, +0xDE, 0x55, 0xDE, 0x76, 0xDE, 0x96, 0xDE, 0x75, +0xE6, 0xD7, 0xE6, 0xB7, 0xDE, 0x96, 0xD6, 0x34, +0xDE, 0x54, 0xE6, 0x75, 0xDE, 0x55, 0xDE, 0x34, +0xAC, 0xD0, 0xBD, 0x94, 0x94, 0x4F, 0x84, 0x0E, +0x8C, 0x2F, 0x94, 0x8F, 0xA4, 0xD0, 0xAD, 0x11, +0x94, 0x2E, 0x9C, 0xB0, 0xBD, 0x93, 0xA4, 0xF0, +0x9C, 0xAF, 0x94, 0x4E, 0x9C, 0xB0, 0xB5, 0x52, +0xA4, 0xF1, 0xA4, 0xD0, 0xBD, 0xB4, 0xB5, 0x72, +0xA4, 0xB0, 0xA4, 0xD0, 0xA4, 0xD0, 0xA4, 0xB0, +0xA4, 0xD0, 0xAD, 0x11, 0xB5, 0x53, 0xCE, 0x15, +0xBD, 0x94, 0xA4, 0xF2, 0x94, 0x70, 0x84, 0x0F, +0x6B, 0x2C, 0x4A, 0x48, 0x4A, 0x48, 0x4A, 0x28, +0x31, 0x85, 0x29, 0x45, 0x29, 0x44, 0x39, 0xE7, +0x52, 0xAA, 0x6B, 0x4D, 0x73, 0x8E, 0x7B, 0xAE, +0x9C, 0xD2, 0x8C, 0x30, 0x63, 0x0C, 0x62, 0xAA, +0x7B, 0x6D, 0x62, 0xCA, 0x6A, 0xEB, 0x83, 0x8D, +0x94, 0x0F, 0xB5, 0x13, 0xB5, 0x13, 0x6B, 0x0B, +0x5A, 0x8A, 0x5A, 0x69, 0x49, 0xE8, 0x18, 0xC4, +0x21, 0x25, 0x21, 0x45, 0x10, 0xA3, 0x10, 0x82, +0x10, 0xA3, 0x10, 0x83, 0x10, 0x82, 0x10, 0x82, +0x10, 0x83, 0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xC3, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x4A, 0x28, 0x8C, 0x50, +0x94, 0x70, 0x9C, 0x90, 0x73, 0x6C, 0x31, 0xA6, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xC3, 0x18, 0xE4, 0x21, 0x05, +0x4A, 0x28, 0x83, 0xCE, 0xAD, 0x12, 0x9C, 0xB1, +0x63, 0x0B, 0x39, 0xE8, 0x29, 0x66, 0x21, 0x05, +0x18, 0xE4, 0x19, 0x05, 0x19, 0x05, 0x19, 0x05, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC4, 0x21, 0x46, +0x29, 0x66, 0x21, 0x25, 0x21, 0x25, 0x21, 0x05, +0x19, 0x05, 0x19, 0x05, 0x31, 0x87, 0x42, 0x08, +0x83, 0xEE, 0xBD, 0x93, 0xAD, 0x32, 0x9C, 0xB1, +0x9C, 0xD1, 0xAD, 0x32, 0xB5, 0x73, 0xA4, 0xF1, +0xA5, 0x12, 0xA4, 0xF2, 0xB5, 0x73, 0xA4, 0xD1, +0xC6, 0x15, 0xBD, 0x94, 0xA4, 0xF1, 0xA5, 0x12, +0x9C, 0xF3, 0x8C, 0x50, 0x9C, 0xD0, 0xAD, 0x52, +0xB5, 0x92, 0xB5, 0x93, 0x94, 0x6F, 0x4A, 0x47, +0x39, 0xC6, 0x41, 0xE7, 0x62, 0xEB, 0xAD, 0x34, +0x8C, 0x50, 0x6B, 0x0B, 0x7B, 0x8D, 0x7B, 0x8E, +0xC6, 0x18, 0xC5, 0xF7, 0x9C, 0xD2, 0xA4, 0xF2, +0xBD, 0xB3, 0xA4, 0xAF, 0xA4, 0xAF, 0xBD, 0xD4, +0xBD, 0xB3, 0xB5, 0x73, 0xAD, 0x32, 0x9C, 0xD1, +0x7B, 0x8C, 0x6B, 0x0A, 0x6B, 0x2A, 0x8C, 0x0D, +0xA4, 0xF0, 0xA4, 0xD0, 0x94, 0x6E, 0x94, 0x4E, +0x9C, 0xAF, 0x9C, 0x6F, 0x94, 0x4E, 0x8C, 0x0D, +0x8B, 0xEC, 0x8C, 0x0D, 0x94, 0x2D, 0x9C, 0x6E, +0xA4, 0xCF, 0xAC, 0xCF, 0x9C, 0x6D, 0xA4, 0xCF, +0xAC, 0xF0, 0xA4, 0x8E, 0x9C, 0x6D, 0x9C, 0x4D, +0x94, 0x0C, 0x9C, 0x6E, 0x9C, 0x8E, 0x9C, 0x6E, +0xA4, 0x8E, 0xA4, 0xCF, 0xAC, 0xCF, 0xA4, 0xCF, +0xA4, 0xB0, 0x73, 0x6C, 0x73, 0x8D, 0x4A, 0x48, +0x29, 0x65, 0x31, 0x85, 0x4A, 0x68, 0x42, 0x28, +0x5A, 0xCB, 0x6B, 0x6E, 0x5A, 0xEC, 0x6B, 0x2D, +0x73, 0x8E, 0x21, 0x05, 0x63, 0x0C, 0x94, 0x72, +0x7B, 0xAF, 0x8C, 0x31, 0x39, 0xC8, 0x63, 0x0C, +0xD6, 0x99, 0xE6, 0xFB, 0xAD, 0x35, 0x5A, 0xAA, +0x7B, 0xAD, 0xC5, 0xD5, 0xBD, 0xB4, 0xB5, 0x51, +0xAC, 0xAE, 0xB4, 0xEF, 0xBD, 0x30, 0xDE, 0x54, +0xE6, 0x75, 0xE6, 0x54, 0xE6, 0x75, 0xEE, 0x95, +0xE6, 0x75, 0xDE, 0x13, 0xDE, 0x13, 0xCD, 0xB2, +0xCD, 0x91, 0xDE, 0x34, 0xEE, 0x95, 0xE6, 0x54, +0xC5, 0x30, 0xBD, 0x71, 0xEE, 0xF7, 0xEE, 0xD7, +0xE6, 0xB6, 0xEE, 0xD7, 0xEE, 0xB6, 0xE6, 0xB6, +0xE6, 0x76, 0xD6, 0x15, 0xCD, 0xD4, 0xD6, 0x56, +0xCE, 0x15, 0xC5, 0xB3, 0xC5, 0xD4, 0xCE, 0x16, +0x62, 0xCA, 0x94, 0x70, 0x9C, 0x6F, 0xB5, 0x53, +0x94, 0x2E, 0x41, 0xE6, 0x29, 0x44, 0x42, 0x07, +0x4A, 0x48, 0x41, 0xE7, 0x6B, 0x2C, 0x73, 0x6D, +0x5A, 0xCA, 0x41, 0xE7, 0x5A, 0xAA, 0x52, 0xAA, +0x4A, 0x28, 0x6B, 0x2C, 0x7B, 0xAE, 0x7B, 0xCF, +0x9C, 0xD3, 0xBD, 0xB7, 0xCE, 0x59, 0xCE, 0x37, +0xBD, 0xB4, 0xC5, 0xD3, 0xCE, 0x14, 0xCE, 0x15, +0xCE, 0x35, 0xC5, 0xD4, 0xC5, 0xB3, 0xCD, 0xF5, +0xA4, 0xB0, 0xBD, 0x93, 0xE6, 0xB7, 0xCD, 0xF4, +0xD6, 0x15, 0xCE, 0x14, 0xCD, 0xD3, 0xC5, 0x92, +0xD6, 0x14, 0xCD, 0xB3, 0xCD, 0xB3, 0xD5, 0xF3, +0xDE, 0x55, 0xDE, 0x55, 0xDE, 0x75, 0xDE, 0x75, +0xE6, 0xB6, 0xD6, 0x35, 0xDE, 0x76, 0xDE, 0x55, +0xDE, 0x55, 0xDE, 0x75, 0xD6, 0x14, 0xD6, 0x14, +0xAC, 0xD0, 0xBD, 0x94, 0x83, 0xEE, 0x8C, 0x2E, +0x9C, 0xD1, 0x94, 0x90, 0x94, 0x6F, 0x9C, 0x8F, +0x9C, 0xB0, 0xAD, 0x11, 0xBD, 0x93, 0xAD, 0x11, +0x8C, 0x0E, 0x84, 0x2E, 0x73, 0x8C, 0x83, 0xED, +0xA4, 0xF1, 0xB5, 0x53, 0xC5, 0xF5, 0xCE, 0x35, +0xB5, 0x52, 0xAD, 0x11, 0xB5, 0x52, 0xB5, 0x73, +0xB5, 0x73, 0xB5, 0x52, 0xBD, 0x94, 0xC5, 0xF5, +0xBD, 0xB5, 0xBD, 0xB4, 0xC5, 0xF5, 0xBD, 0x94, +0xBD, 0xB5, 0xAD, 0x53, 0xAD, 0x73, 0xB5, 0x94, +0x9C, 0xD1, 0x4A, 0x48, 0x20, 0xE3, 0x21, 0x24, +0x21, 0x24, 0x29, 0x44, 0x29, 0x45, 0x39, 0xA6, +0x63, 0x0C, 0x7B, 0xEF, 0xA5, 0x13, 0x94, 0x71, +0x73, 0x4D, 0x73, 0x2C, 0x73, 0x2C, 0x7B, 0x4C, +0x83, 0x6D, 0x8B, 0xEF, 0xA4, 0x91, 0x52, 0x28, +0x31, 0x65, 0x52, 0x28, 0x4A, 0x28, 0x39, 0x87, +0x18, 0xC3, 0x19, 0x04, 0x21, 0x05, 0x18, 0xC3, +0x18, 0xC4, 0x10, 0xC3, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC3, 0x10, 0xC3, +0x10, 0xA3, 0x18, 0xC3, 0x18, 0xE4, 0x21, 0x04, +0x52, 0x69, 0x7B, 0xAD, 0x9C, 0x70, 0xA4, 0xB0, +0x9C, 0x90, 0xAC, 0xF2, 0xAC, 0xF2, 0x83, 0xEE, +0x41, 0xE7, 0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x18, 0xC3, +0x29, 0x46, 0x5A, 0xAA, 0x94, 0x6F, 0xAD, 0x12, +0x73, 0x6C, 0x5A, 0xCB, 0x42, 0x29, 0x29, 0x66, +0x21, 0x25, 0x19, 0x05, 0x19, 0x05, 0x19, 0x05, +0x18, 0xE4, 0x18, 0xE4, 0x21, 0x26, 0x29, 0x67, +0x21, 0x25, 0x19, 0x05, 0x21, 0x05, 0x19, 0x05, +0x21, 0x05, 0x29, 0x46, 0x31, 0x87, 0x39, 0xC7, +0x52, 0x8A, 0x9C, 0xB1, 0xAD, 0x12, 0x9C, 0xB0, +0x9C, 0xB0, 0xA5, 0x12, 0xAD, 0x12, 0xA4, 0xF1, +0xAD, 0x53, 0xAD, 0x53, 0xAD, 0x32, 0xB5, 0x73, +0xCE, 0x15, 0xBD, 0xB4, 0xA4, 0xF2, 0xAD, 0x53, +0x9C, 0xF2, 0x8C, 0x70, 0xA5, 0x11, 0xAD, 0x31, +0xAD, 0x32, 0xBD, 0xB3, 0xBD, 0xB3, 0xAD, 0x52, +0x63, 0x0A, 0x3A, 0x06, 0x39, 0xE6, 0x63, 0x0B, +0xA5, 0x13, 0x63, 0x0B, 0x5A, 0xCA, 0x84, 0x10, +0x84, 0x10, 0x8C, 0x10, 0x9C, 0xB2, 0xDE, 0x99, +0xC5, 0xF5, 0xA4, 0x8E, 0xAC, 0xCF, 0xC5, 0xF4, +0xBD, 0x93, 0xAD, 0x32, 0xAD, 0x73, 0xB5, 0x74, +0xA4, 0xF2, 0x8C, 0x0E, 0x7B, 0xCD, 0x8C, 0x4F, +0xA4, 0xF1, 0xA4, 0xF1, 0xA5, 0x11, 0xA4, 0xF1, +0xA4, 0xF1, 0xA4, 0xF1, 0xAD, 0x12, 0xAD, 0x32, +0xAD, 0x32, 0xAD, 0x32, 0xAD, 0x12, 0xB5, 0x73, +0xBD, 0x72, 0xA4, 0xAE, 0x9C, 0x6E, 0xA5, 0x11, +0xAD, 0x32, 0xB5, 0x52, 0xB5, 0x52, 0xA5, 0x11, +0x9C, 0x8F, 0xA4, 0xD0, 0xA4, 0xF0, 0xA4, 0xF0, +0xA4, 0xD0, 0xA4, 0xF0, 0xA4, 0xCF, 0x9C, 0x8F, +0xA4, 0xD0, 0x94, 0x6F, 0x8C, 0x0E, 0xA4, 0xF1, +0x6B, 0x2B, 0x31, 0x65, 0x31, 0x85, 0x39, 0xC7, +0x39, 0xC7, 0x62, 0xEC, 0x5A, 0xCB, 0x62, 0xEB, +0x7B, 0x8E, 0x52, 0x6A, 0x29, 0x66, 0x31, 0x86, +0x63, 0x0C, 0x62, 0xEC, 0x52, 0x8B, 0x94, 0x92, +0xD6, 0x59, 0xDE, 0x9A, 0x8C, 0x31, 0x7B, 0x8E, +0x41, 0xA7, 0x41, 0xC7, 0x7B, 0xAD, 0xCD, 0xD5, +0xBD, 0x31, 0xAC, 0xCF, 0xAC, 0xCF, 0xAC, 0xCE, +0xAC, 0xAE, 0xAC, 0xAE, 0xAC, 0x8D, 0xA4, 0x6D, +0xAC, 0x8E, 0xAC, 0x8D, 0xAC, 0xAD, 0xB4, 0xCE, +0xB4, 0xEE, 0xBD, 0x0F, 0xBD, 0x0F, 0xB4, 0xEE, +0xB4, 0xCE, 0xBD, 0x50, 0xCD, 0xB3, 0xCD, 0xD3, +0xD6, 0x14, 0xDE, 0x55, 0xE6, 0x75, 0xE6, 0x75, +0xDE, 0x75, 0xDE, 0x75, 0xE6, 0x76, 0xEE, 0xB6, +0xE6, 0x96, 0xE6, 0x76, 0xE6, 0x96, 0xEE, 0xB7, +0xE6, 0x76, 0xEE, 0xD8, 0xE6, 0xD7, 0xE6, 0x97, +0xD6, 0x35, 0xAC, 0xF1, 0x39, 0x85, 0x31, 0xA5, +0x4A, 0x27, 0x31, 0x85, 0x62, 0xCA, 0x39, 0xA6, +0x31, 0x65, 0x4A, 0x28, 0x4A, 0x49, 0x52, 0x69, +0x52, 0x89, 0x6B, 0x4C, 0x73, 0x8E, 0x7B, 0xCF, +0x94, 0x92, 0xB5, 0x76, 0xC6, 0x18, 0xC6, 0x17, +0xB5, 0x94, 0xA5, 0x11, 0xBD, 0x93, 0xB5, 0x52, +0xBD, 0x93, 0xAD, 0x31, 0xA4, 0xD0, 0xAC, 0xF1, +0xA4, 0xD0, 0xBD, 0xB4, 0xE6, 0xD8, 0xCD, 0xF4, +0xDE, 0x56, 0xE6, 0x97, 0xD6, 0x14, 0xC5, 0x72, +0xBD, 0x51, 0xAC, 0xCF, 0xBD, 0x31, 0xCD, 0xD3, +0xE6, 0x76, 0xE6, 0x96, 0xE6, 0xB6, 0xE6, 0xD7, +0xE6, 0xB7, 0xE6, 0xB7, 0xE6, 0x96, 0xE6, 0x96, +0xDE, 0x75, 0xDE, 0x34, 0xCD, 0xD3, 0xCD, 0xD3, +0xAC, 0xF0, 0xBD, 0x94, 0x83, 0xEE, 0x94, 0x90, +0xB5, 0x73, 0xB5, 0xB4, 0xB5, 0x73, 0xAD, 0x53, +0xB5, 0x94, 0xC5, 0xF4, 0xCE, 0x35, 0xBD, 0xB4, +0x9C, 0xB1, 0x9C, 0xF1, 0x7B, 0xAD, 0x8C, 0x4F, +0xAD, 0x52, 0xB5, 0x73, 0xC5, 0xD4, 0xBD, 0xD3, +0xBD, 0x93, 0xAD, 0x11, 0xB5, 0x73, 0xBD, 0x93, +0xB5, 0x73, 0xB5, 0x32, 0xC5, 0xF5, 0xC5, 0xF5, +0xBD, 0xB4, 0xBD, 0xB5, 0xC6, 0x16, 0xBD, 0xD5, +0xBD, 0xD5, 0xC5, 0xF6, 0xC6, 0x16, 0xCE, 0x16, +0xC5, 0xF6, 0xA4, 0xF2, 0x9C, 0xD2, 0x8C, 0x70, +0x5A, 0xCA, 0x31, 0x85, 0x29, 0x44, 0x21, 0x24, +0x21, 0x24, 0x31, 0x85, 0x52, 0xAA, 0x7B, 0xEF, +0x9C, 0xB2, 0xB5, 0x35, 0x7B, 0x6D, 0x73, 0x4C, +0x73, 0x2C, 0x6A, 0xEB, 0x7B, 0x6D, 0x7B, 0x8E, +0x5A, 0x8A, 0x41, 0xC7, 0x39, 0x86, 0x5A, 0x8A, +0x4A, 0x08, 0x20, 0xE4, 0x18, 0xC4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x18, 0xC4, 0x29, 0x25, +0x4A, 0x28, 0x52, 0x89, 0x73, 0x4C, 0x9C, 0x90, +0xD6, 0x36, 0xDE, 0x97, 0xD6, 0x35, 0xC5, 0xB3, +0xC5, 0xD4, 0xBD, 0x93, 0xBD, 0xB4, 0xBD, 0x73, +0x8C, 0x0E, 0x39, 0xC6, 0x10, 0xC3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, +0x18, 0xC4, 0x29, 0x45, 0x83, 0xEE, 0xAC, 0xF1, +0xA4, 0xB0, 0x94, 0x2F, 0x6B, 0x2C, 0x42, 0x08, +0x29, 0x46, 0x21, 0x25, 0x19, 0x04, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE5, 0x21, 0x46, 0x21, 0x25, +0x19, 0x05, 0x19, 0x05, 0x19, 0x05, 0x19, 0x05, +0x21, 0x25, 0x29, 0x46, 0x29, 0x46, 0x29, 0x66, +0x41, 0xE8, 0x83, 0xEF, 0xA4, 0xB1, 0x9C, 0xB1, +0xA4, 0xF2, 0x9C, 0xB1, 0xA4, 0xF1, 0x9C, 0xB1, +0x9C, 0xD1, 0xB5, 0x94, 0x9C, 0xB0, 0xBD, 0x93, +0xB5, 0x93, 0xAD, 0x53, 0x9C, 0xB1, 0x9C, 0xD1, +0x94, 0xD1, 0x8C, 0x6F, 0xA5, 0x11, 0xA5, 0x11, +0xA5, 0x31, 0xAD, 0x52, 0xB5, 0x92, 0xB5, 0x92, +0xB5, 0x93, 0x52, 0xC8, 0x31, 0xA5, 0x31, 0xA6, +0x39, 0xE7, 0x42, 0x07, 0x4A, 0x48, 0x83, 0xEF, +0x73, 0x6D, 0x73, 0x6D, 0x6B, 0x2D, 0xC6, 0x18, +0xE6, 0xFB, 0x94, 0x2F, 0xA4, 0xB0, 0xC5, 0xD4, +0xB5, 0x52, 0xBD, 0xB4, 0xBD, 0xB5, 0xB5, 0x74, +0xAD, 0x53, 0xAD, 0x53, 0x9C, 0xD2, 0xA5, 0x33, +0xB5, 0x74, 0xAD, 0x73, 0xAD, 0x33, 0xAD, 0x33, +0xAD, 0x53, 0xAD, 0x53, 0xAD, 0x53, 0xAD, 0x53, +0xAD, 0x33, 0xB5, 0x73, 0xBD, 0xD4, 0xC5, 0xD4, +0xBD, 0xB2, 0xA4, 0xCE, 0xA4, 0xF0, 0xAD, 0x32, +0xC5, 0xF5, 0xCE, 0x57, 0xD6, 0x77, 0xBD, 0xB4, +0xAD, 0x32, 0xB5, 0x94, 0xAD, 0x52, 0xAD, 0x52, +0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x12, +0xAD, 0x32, 0xBD, 0xB4, 0xBD, 0x93, 0xCE, 0x56, +0xBD, 0xB3, 0x9C, 0xAF, 0x7B, 0xCD, 0x29, 0x44, +0x8C, 0x71, 0xCE, 0x59, 0xC6, 0x18, 0x9C, 0xB2, +0xBD, 0xD6, 0xCE, 0x38, 0xBD, 0xB6, 0x94, 0x92, +0xA5, 0x34, 0xAD, 0x35, 0xBD, 0x97, 0xCD, 0xF8, +0xDE, 0x7A, 0xD6, 0x59, 0xDE, 0xBA, 0xCD, 0xF8, +0x6A, 0xEC, 0x28, 0xE4, 0x39, 0xA7, 0x8B, 0xEF, +0x83, 0xAE, 0x41, 0xC7, 0xAC, 0xF1, 0xB4, 0xEF, +0xAC, 0xCF, 0xC5, 0x71, 0xD6, 0x14, 0xD6, 0x14, +0xD5, 0xF4, 0xD5, 0xF3, 0xCD, 0xB2, 0xAC, 0xCF, +0xAC, 0xEF, 0xAC, 0xCF, 0xA4, 0xAE, 0xAC, 0xCF, +0xA4, 0xAE, 0xA4, 0x8E, 0xA4, 0x6E, 0x9C, 0x4D, +0x9C, 0x4D, 0x9C, 0x2C, 0x94, 0x2C, 0x9C, 0x4D, +0xAC, 0xAE, 0xAC, 0xAE, 0xAC, 0xAE, 0xAC, 0xAE, +0xAC, 0xAE, 0xAC, 0xCF, 0xAC, 0xAE, 0xA4, 0x6E, +0xA4, 0x6D, 0x9C, 0x4D, 0x9C, 0x4D, 0xA4, 0x8F, +0xAC, 0xCF, 0xA4, 0xAE, 0x7B, 0x6B, 0x4A, 0x06, +0x39, 0xC6, 0x29, 0x44, 0x31, 0x85, 0x39, 0xC6, +0x41, 0xE7, 0x39, 0xC6, 0x39, 0xA6, 0x52, 0x69, +0x5A, 0xAA, 0x6B, 0x4C, 0x7B, 0xAE, 0x84, 0x0F, +0x8C, 0x51, 0xA5, 0x34, 0xB5, 0xB6, 0xBD, 0xD6, +0xD6, 0x98, 0xCE, 0x36, 0xCE, 0x35, 0xCE, 0x15, +0xC5, 0xF4, 0xBD, 0xD4, 0xB5, 0x72, 0xAD, 0x31, +0xA4, 0xF0, 0xB5, 0x52, 0xE6, 0xD7, 0xCD, 0xD3, +0xD6, 0x35, 0xEE, 0xD7, 0xD6, 0x14, 0xB5, 0x30, +0xB4, 0xF0, 0xBD, 0x31, 0xC5, 0x71, 0xCD, 0xD3, +0xE6, 0x75, 0xDE, 0x55, 0xD6, 0x14, 0xD6, 0x14, +0xDE, 0x55, 0xDE, 0x75, 0xD6, 0x34, 0xCD, 0xF3, +0xD5, 0xF3, 0xD6, 0x34, 0xCD, 0xD2, 0xCD, 0xB3, +0xAC, 0xF1, 0xBD, 0x74, 0x8C, 0x2E, 0x9C, 0xD1, +0xAD, 0x53, 0xB5, 0x94, 0xBD, 0xD5, 0xBD, 0xB4, +0xC5, 0xF5, 0xBD, 0xD4, 0xCE, 0x15, 0xC6, 0x15, +0xAD, 0x53, 0xAD, 0x32, 0x8C, 0x2F, 0x9C, 0xB0, +0xB5, 0x94, 0xC5, 0xF5, 0xCE, 0x35, 0xC5, 0xF4, +0xAD, 0x52, 0xA4, 0xD0, 0xAD, 0x32, 0xBD, 0xD4, +0xB5, 0x73, 0xA4, 0xF1, 0xCE, 0x15, 0xCE, 0x15, +0xBD, 0x94, 0xB5, 0x73, 0xBD, 0xB4, 0xBD, 0xB4, +0xAD, 0x33, 0xBD, 0xB5, 0xC5, 0xF5, 0xC6, 0x16, +0xCE, 0x36, 0xCE, 0x16, 0xCE, 0x36, 0xD6, 0x97, +0xCE, 0x36, 0xB5, 0x73, 0x83, 0xCE, 0x42, 0x07, +0x31, 0x85, 0x29, 0x65, 0x29, 0x45, 0x29, 0x65, +0x52, 0x8A, 0x8C, 0x51, 0x94, 0x71, 0x8C, 0x0F, +0x5A, 0x89, 0x5A, 0x8A, 0x62, 0xAA, 0x94, 0x30, +0xAC, 0xF3, 0x73, 0x2C, 0x4A, 0x08, 0x49, 0xE7, +0x6A, 0xCA, 0x5A, 0x69, 0x31, 0x86, 0x10, 0xA3, +0x18, 0xC3, 0x10, 0xA3, 0x21, 0x04, 0x52, 0xAA, +0x4A, 0x29, 0x42, 0x29, 0x52, 0xAA, 0x94, 0x91, +0x9C, 0xB1, 0x94, 0x70, 0xA4, 0xD1, 0xBD, 0x94, +0xAC, 0xF1, 0x94, 0x6F, 0xAC, 0xF0, 0xB5, 0x52, +0xB5, 0x52, 0x9C, 0xB0, 0x9C, 0x8F, 0x94, 0x4E, +0x9C, 0x90, 0x83, 0xCE, 0x31, 0x86, 0x18, 0xE4, +0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, +0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, 0x08, 0x82, +0x10, 0xA3, 0x29, 0x24, 0x8C, 0x0F, 0xB5, 0x52, +0xBD, 0x73, 0xB5, 0x32, 0x94, 0x6F, 0x63, 0x0A, +0x39, 0xC7, 0x29, 0x66, 0x21, 0x05, 0x18, 0xE4, +0x19, 0x04, 0x19, 0x05, 0x21, 0x25, 0x19, 0x05, +0x18, 0xE4, 0x18, 0xE4, 0x19, 0x05, 0x21, 0x25, +0x21, 0x25, 0x21, 0x45, 0x21, 0x45, 0x29, 0x66, +0x31, 0x87, 0x73, 0x4C, 0xB5, 0x33, 0xBD, 0x94, +0xB5, 0x53, 0xAD, 0x32, 0xAD, 0x12, 0xA4, 0xD1, +0x9C, 0xB0, 0xA4, 0xD1, 0x9C, 0xB0, 0xA4, 0xD1, +0xA4, 0xD0, 0x94, 0x70, 0x8C, 0x0F, 0x8C, 0x2F, +0xB5, 0xF6, 0x7C, 0x2D, 0x94, 0xCF, 0xAD, 0x72, +0xAD, 0x72, 0xB5, 0x93, 0xC6, 0x15, 0xB5, 0xB2, +0xAD, 0x4F, 0xA5, 0x4F, 0x8C, 0x4D, 0x31, 0xA5, +0x29, 0x65, 0x39, 0xE6, 0x42, 0x28, 0x6B, 0x4C, +0x52, 0xAA, 0x52, 0xAA, 0x6B, 0x4D, 0xCE, 0x59, +0xCE, 0x59, 0xAD, 0x34, 0xCE, 0x58, 0xB5, 0x53, +0xB5, 0x93, 0xC5, 0xF5, 0xB5, 0xB5, 0xAD, 0x74, +0xAD, 0x53, 0xB5, 0x74, 0xA5, 0x13, 0xAD, 0x74, +0xAD, 0x74, 0xB5, 0x74, 0xA5, 0x32, 0xA4, 0xF2, +0x9C, 0xF2, 0xB5, 0x73, 0xAD, 0x53, 0xB5, 0x53, +0xAD, 0x33, 0xB5, 0x73, 0xB5, 0x93, 0xC6, 0x15, +0xC5, 0xD3, 0xA4, 0xAE, 0xAD, 0x11, 0xAD, 0x32, +0xB5, 0x94, 0xBD, 0xB4, 0xC5, 0xF6, 0xAD, 0x53, +0xB5, 0x73, 0xC5, 0xF5, 0xB5, 0x73, 0xB5, 0x73, +0xAD, 0x53, 0xBD, 0xB4, 0xB5, 0x53, 0xAD, 0x32, +0xA4, 0xF1, 0xB5, 0x73, 0xBD, 0xB4, 0xB5, 0x93, +0xA5, 0x11, 0x9C, 0xAF, 0xAD, 0x11, 0x52, 0x68, +0x84, 0x30, 0xB5, 0xB6, 0xCE, 0x18, 0x8C, 0x30, +0xC6, 0x18, 0xE6, 0xDB, 0xBD, 0xD7, 0xCE, 0x59, +0xBD, 0xD7, 0xCE, 0x59, 0xDE, 0xBB, 0xDE, 0xBA, +0xC5, 0xD7, 0xB5, 0x55, 0xD6, 0x38, 0xA4, 0xB2, +0xB5, 0x35, 0x8B, 0xEF, 0x9C, 0x71, 0xAD, 0x13, +0xBD, 0x95, 0xBD, 0x96, 0xD6, 0x17, 0xCD, 0xB4, +0xB4, 0xF0, 0xC5, 0x92, 0xCD, 0xD3, 0xC5, 0x92, +0xD5, 0xF3, 0xCD, 0xD3, 0xCD, 0xB3, 0xA4, 0x8E, +0x9C, 0x8F, 0x9C, 0x8F, 0x94, 0x6E, 0xAD, 0x10, +0x94, 0x6E, 0xAD, 0x31, 0xA4, 0xD0, 0x9C, 0x8F, +0xA4, 0xD0, 0x9C, 0xAF, 0x8C, 0x0C, 0xAC, 0xCF, +0x9C, 0x2C, 0x9C, 0x2C, 0x83, 0xAA, 0x8B, 0xCB, +0x8B, 0xEC, 0x7B, 0x6A, 0x83, 0xAB, 0x94, 0x0D, +0x8B, 0xCB, 0x83, 0xAB, 0x8B, 0xEC, 0x94, 0x2D, +0x9C, 0x4D, 0x9C, 0x6E, 0xA4, 0xAF, 0x94, 0x4E, +0x41, 0xE6, 0x31, 0x86, 0x39, 0xC6, 0x42, 0x07, +0x42, 0x07, 0x39, 0xA6, 0x4A, 0x28, 0x52, 0x89, +0x5A, 0xCA, 0x63, 0x0B, 0x6B, 0x2C, 0x6B, 0x6D, +0x84, 0x0F, 0x84, 0x30, 0xAD, 0x55, 0xAD, 0x55, +0xD6, 0x99, 0xB5, 0x74, 0xAD, 0x11, 0xB5, 0x52, +0xB5, 0x51, 0xB5, 0x51, 0xA4, 0xF0, 0xA4, 0xF0, +0xA4, 0xAF, 0x9C, 0x8F, 0xB5, 0x31, 0xB5, 0x31, +0xB5, 0x10, 0xC5, 0xB3, 0xCD, 0xB3, 0xD6, 0x14, +0xD6, 0x35, 0xDE, 0x56, 0xE6, 0x76, 0xDE, 0x34, +0xE6, 0x96, 0xDE, 0x75, 0xDE, 0x55, 0xDE, 0x34, +0xDE, 0x75, 0xDE, 0x55, 0xE6, 0x75, 0xDE, 0x55, +0xDE, 0x54, 0xEE, 0xB6, 0xE6, 0x55, 0xDE, 0x35, +0xB5, 0x32, 0xB5, 0x73, 0x8C, 0x4F, 0xA5, 0x32, +0xB5, 0x94, 0xB5, 0xB4, 0xB5, 0x94, 0xA5, 0x12, +0xBD, 0xD4, 0xC5, 0xF4, 0xC6, 0x15, 0xB5, 0x93, +0xAD, 0x53, 0xAD, 0x73, 0x9C, 0xB1, 0xA5, 0x12, +0xB5, 0xB4, 0xCE, 0x35, 0xD6, 0x76, 0xCE, 0x15, +0xAD, 0x11, 0xA4, 0xD1, 0xB5, 0x52, 0xBD, 0x93, +0xB5, 0x52, 0xA4, 0xF1, 0xC5, 0xD4, 0xC5, 0xF5, +0xAD, 0x32, 0xA5, 0x12, 0xB5, 0x53, 0xBD, 0x94, +0xAD, 0x32, 0xBD, 0xD5, 0xD6, 0x36, 0xC5, 0xD5, +0xCE, 0x36, 0xC5, 0xF5, 0xCE, 0x36, 0xCE, 0x56, +0xCE, 0x35, 0xD6, 0x76, 0xD6, 0x56, 0xBD, 0xD5, +0x8C, 0x2F, 0x4A, 0x27, 0x29, 0x65, 0x29, 0x65, +0x21, 0x45, 0x31, 0xA6, 0x42, 0x08, 0x94, 0x51, +0x9C, 0x92, 0x4A, 0x08, 0x5A, 0x8A, 0x62, 0xAA, +0x83, 0xAE, 0xA4, 0x91, 0x7B, 0x6D, 0x52, 0x28, +0x52, 0x27, 0x6A, 0xA9, 0x5A, 0x69, 0x52, 0x28, +0x31, 0x86, 0x31, 0x66, 0x39, 0xC7, 0x6B, 0x2C, +0x8C, 0x30, 0x9C, 0xD2, 0xAD, 0x34, 0xCE, 0x36, +0xDE, 0x97, 0xCE, 0x36, 0x9C, 0xB0, 0xAD, 0x32, +0xD6, 0x56, 0xCE, 0x15, 0xCE, 0x35, 0xCE, 0x15, +0xCE, 0x14, 0xDE, 0x96, 0xDE, 0x76, 0xCE, 0x15, +0xCD, 0xF5, 0xC5, 0xB4, 0x8B, 0xEE, 0x5A, 0xAA, +0x29, 0x65, 0x10, 0xA3, 0x10, 0x83, 0x10, 0x83, +0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, 0x10, 0x83, +0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, +0x10, 0x83, 0x10, 0x83, 0x10, 0x83, 0x10, 0x83, +0x10, 0xA3, 0x21, 0x04, 0x83, 0xCE, 0xD6, 0x15, +0xD5, 0xF4, 0xC5, 0x72, 0xBD, 0x72, 0x9C, 0x8F, +0x73, 0x4C, 0x41, 0xE7, 0x29, 0x45, 0x21, 0x05, +0x19, 0x04, 0x19, 0x04, 0x19, 0x05, 0x19, 0x04, +0x18, 0xE4, 0x18, 0xE4, 0x21, 0x25, 0x21, 0x25, +0x21, 0x25, 0x21, 0x25, 0x21, 0x25, 0x29, 0x46, +0x39, 0xC7, 0x6B, 0x2C, 0x9C, 0x90, 0xA4, 0xD1, +0x9C, 0xB0, 0x94, 0x4F, 0x9C, 0x90, 0x9C, 0x90, +0x9C, 0xB0, 0xA4, 0xD0, 0xA4, 0xD0, 0xA4, 0xF1, +0xB5, 0x52, 0xAD, 0x12, 0xAD, 0x32, 0xB5, 0x52, +0x95, 0x32, 0x63, 0xCA, 0x8C, 0xEF, 0xAD, 0x72, +0xAD, 0x52, 0xA5, 0x31, 0xA5, 0x6F, 0x8C, 0xCA, +0x7C, 0x68, 0xAD, 0xAD, 0xB5, 0xB1, 0xAD, 0x31, +0x52, 0xA8, 0x31, 0x85, 0x42, 0x28, 0x5A, 0xCA, +0x4A, 0x28, 0x5A, 0xEB, 0x84, 0x10, 0xAD, 0x75, +0xA5, 0x34, 0xBE, 0x18, 0xEF, 0x7D, 0xDE, 0xB9, +0xB5, 0x94, 0xC5, 0xF5, 0xBD, 0xF6, 0xC5, 0xF6, +0xBD, 0xD5, 0x9C, 0xB1, 0x94, 0x70, 0xBD, 0xB5, +0xB5, 0xB5, 0xB5, 0xB4, 0xB5, 0x94, 0xB5, 0x73, +0xB5, 0x74, 0xB5, 0x94, 0xAD, 0x32, 0xBD, 0x94, +0xBD, 0xB4, 0xBD, 0x94, 0xBD, 0x94, 0xBD, 0xB3, +0xC5, 0xB3, 0xAC, 0xCE, 0xAC, 0xF0, 0xB5, 0x53, +0xAD, 0x12, 0xAD, 0x32, 0xB5, 0x94, 0xAD, 0x53, +0xB5, 0x94, 0xBD, 0xD5, 0xB5, 0x94, 0xC5, 0xD5, +0xB5, 0x94, 0xB5, 0x94, 0xB5, 0x73, 0xAD, 0x32, +0x9C, 0xD0, 0xAD, 0x52, 0xBD, 0xB4, 0xB5, 0x73, +0xA4, 0xF1, 0x9C, 0xB0, 0xA4, 0xD0, 0x83, 0xED, +0x62, 0xEB, 0x9C, 0xD3, 0xB5, 0x96, 0x83, 0xEF, +0x9C, 0xD3, 0xBD, 0xB7, 0xAD, 0x34, 0x94, 0x92, +0x73, 0x8E, 0x7B, 0xCF, 0xA5, 0x14, 0xC5, 0xF7, +0x94, 0x72, 0x5A, 0xAA, 0x7B, 0xAE, 0xB5, 0x55, +0xD6, 0x38, 0xDE, 0x79, 0xAC, 0xF3, 0x94, 0x50, +0x6B, 0x0B, 0x6B, 0x0C, 0x73, 0x4D, 0xA4, 0x91, +0xD5, 0xF5, 0xD6, 0x15, 0xE6, 0x97, 0xD5, 0xF4, +0xD6, 0x14, 0xDE, 0x34, 0xCD, 0xB2, 0xAC, 0xCF, +0x9C, 0xB0, 0xA5, 0x12, 0x9C, 0xF1, 0xAD, 0x52, +0x9C, 0xD0, 0xAD, 0x53, 0xA5, 0x32, 0xAD, 0x53, +0xB5, 0x73, 0xB5, 0x73, 0xA4, 0xAF, 0xAC, 0xCF, +0xBD, 0x31, 0x9C, 0x8E, 0x9C, 0x8F, 0xB5, 0x72, +0xB5, 0x72, 0xB5, 0x52, 0x9C, 0x8F, 0xA4, 0xF1, +0x8C, 0x2E, 0x94, 0x4F, 0x94, 0x6F, 0x8C, 0x0E, +0x7B, 0xAC, 0x7B, 0x8C, 0x73, 0x4B, 0x83, 0xED, +0x83, 0xEE, 0x4A, 0x27, 0x31, 0x85, 0x31, 0x65, +0x39, 0xA6, 0x41, 0xE7, 0x4A, 0x48, 0x4A, 0x68, +0x5A, 0xAA, 0x63, 0x0C, 0x73, 0x6D, 0x73, 0xAE, +0x7B, 0xEF, 0x7B, 0xCF, 0x84, 0x10, 0xA5, 0x14, +0xCE, 0x59, 0xC5, 0xF7, 0xA4, 0xB0, 0xA4, 0xCF, +0xA4, 0xCF, 0xAC, 0xCF, 0xA4, 0xCF, 0xA4, 0xAF, +0xA4, 0xAF, 0xAC, 0xF1, 0xA4, 0xB0, 0xAC, 0xF0, +0xAD, 0x11, 0xAC, 0xF1, 0xAC, 0xF0, 0xAC, 0xF0, +0xAC, 0xD0, 0xAC, 0xF0, 0xB5, 0x11, 0xBD, 0x31, +0xC5, 0x92, 0xC5, 0xB3, 0xC5, 0x92, 0xC5, 0x92, +0xC5, 0x93, 0xCD, 0xD4, 0xCD, 0xF4, 0xD6, 0x14, +0xDE, 0x55, 0xD6, 0x14, 0xC5, 0x92, 0xC5, 0x93, +0xAC, 0xF1, 0xA4, 0xD1, 0x83, 0xED, 0x94, 0x90, +0xB5, 0x73, 0xB5, 0x94, 0xB5, 0x94, 0xB5, 0x94, +0xCE, 0x36, 0xD6, 0x77, 0xD6, 0x77, 0xBD, 0xD4, +0xB5, 0x73, 0xB5, 0x73, 0x9C, 0xF1, 0xA5, 0x12, +0xAD, 0x32, 0xCE, 0x56, 0xD6, 0x76, 0xCE, 0x56, +0xAD, 0x52, 0xAD, 0x11, 0xBD, 0x93, 0xAD, 0x52, +0xAD, 0x32, 0xA4, 0xF1, 0xC5, 0xD4, 0xBD, 0xB4, +0xAD, 0x32, 0xBD, 0x73, 0xBD, 0x73, 0xC5, 0xB4, +0x94, 0x6F, 0x83, 0xED, 0xBD, 0x93, 0xB5, 0x53, +0xBD, 0xB3, 0xBD, 0xB4, 0xC5, 0xF4, 0xCE, 0x15, +0xCE, 0x15, 0xCE, 0x35, 0xCE, 0x35, 0xD6, 0x76, +0xDE, 0x97, 0xCE, 0x15, 0x94, 0x6F, 0x4A, 0x27, +0x31, 0x85, 0x29, 0x65, 0x31, 0x85, 0x4A, 0x49, +0x83, 0xCF, 0x62, 0xEB, 0x52, 0x69, 0x4A, 0x28, +0x4A, 0x28, 0x5A, 0x69, 0x62, 0x8A, 0x4A, 0x07, +0x52, 0x28, 0x52, 0x07, 0x62, 0x89, 0x83, 0x8D, +0x62, 0x8A, 0x4A, 0x08, 0x4A, 0x29, 0x52, 0x69, +0x83, 0xCF, 0xCE, 0x57, 0xDE, 0xD8, 0xDE, 0x97, +0xE6, 0xD8, 0xBD, 0x73, 0xA4, 0xD1, 0xB5, 0x32, +0xE6, 0xF8, 0xE6, 0xD7, 0xDE, 0x97, 0xE6, 0xB7, +0xDE, 0x75, 0xDE, 0x75, 0xDE, 0x75, 0xDE, 0x96, +0xDE, 0x76, 0xDE, 0x55, 0xD6, 0x15, 0xBD, 0x73, +0x83, 0xCD, 0x39, 0xA6, 0x31, 0x65, 0x18, 0xE4, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, 0x08, 0x83, +0x08, 0x83, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0x83, 0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC3, 0xA4, 0xD2, 0xE6, 0x76, +0xDE, 0x34, 0xD5, 0xF4, 0xD6, 0x14, 0xBD, 0x72, +0x8C, 0x2E, 0x62, 0xEA, 0x31, 0x86, 0x29, 0x45, +0x21, 0x25, 0x21, 0x25, 0x21, 0x25, 0x19, 0x05, +0x18, 0xE4, 0x19, 0x04, 0x21, 0x25, 0x19, 0x05, +0x19, 0x05, 0x19, 0x05, 0x21, 0x05, 0x21, 0x46, +0x39, 0xE8, 0x7B, 0x8D, 0x8C, 0x0E, 0x8C, 0x0E, +0x9C, 0x6F, 0x94, 0x4F, 0x94, 0x6F, 0x9C, 0x8F, +0x9C, 0xB0, 0x94, 0x4E, 0x83, 0xED, 0x9C, 0x90, +0xAD, 0x12, 0xAD, 0x11, 0xAC, 0xF1, 0xA4, 0xD1, +0x64, 0x0A, 0x64, 0x09, 0x95, 0x50, 0xBE, 0x55, +0x8C, 0x8E, 0x84, 0x4B, 0x74, 0x46, 0x6C, 0x65, +0x74, 0x65, 0xA5, 0x8B, 0xA5, 0x0D, 0xA4, 0xEE, +0xA5, 0x10, 0x73, 0x6B, 0x41, 0xE6, 0x42, 0x28, +0x4A, 0x28, 0x5A, 0xCA, 0x63, 0x2C, 0x7C, 0x10, +0x8C, 0x51, 0xAD, 0x55, 0xD6, 0xBA, 0xEF, 0x5C, +0xCE, 0x58, 0x9C, 0xD1, 0xA4, 0xD1, 0xA4, 0xF1, +0xAD, 0x33, 0xA5, 0x12, 0xA4, 0xF1, 0xA5, 0x12, +0xA5, 0x12, 0xAD, 0x33, 0xAD, 0x53, 0xAD, 0x53, +0xAD, 0x33, 0xAD, 0x53, 0xAD, 0x73, 0xB5, 0x74, +0xBD, 0xB4, 0xBD, 0xB4, 0xB5, 0x73, 0xB5, 0x92, +0xC5, 0xD3, 0xAC, 0xCF, 0x94, 0x2D, 0x9C, 0xD0, +0xAD, 0x52, 0xAD, 0x53, 0xAD, 0x53, 0xA5, 0x12, +0xA5, 0x12, 0xB5, 0x53, 0xAD, 0x53, 0xBD, 0xB5, +0xAD, 0x53, 0xB5, 0x53, 0xAD, 0x52, 0xAD, 0x32, +0xA4, 0xF1, 0xAD, 0x52, 0xBD, 0xB4, 0xB5, 0x73, +0xA4, 0xF1, 0x9C, 0xB0, 0xA4, 0xD0, 0x94, 0x6F, +0x39, 0xA6, 0x5A, 0xCB, 0x83, 0xEF, 0x73, 0x8E, +0x62, 0xEC, 0x7B, 0xEF, 0x6B, 0x6D, 0x52, 0x8A, +0x21, 0x04, 0x42, 0x08, 0xA5, 0x34, 0xCE, 0x59, +0xD6, 0x9A, 0xA5, 0x14, 0x62, 0xCB, 0x9C, 0x71, +0xAD, 0x14, 0xB5, 0x14, 0x7B, 0x4D, 0x94, 0x0F, +0xAC, 0xB2, 0x6B, 0x0C, 0x62, 0xCB, 0xA4, 0xB2, +0xEE, 0xFB, 0xF7, 0x3B, 0xDE, 0x57, 0xBD, 0x74, +0xB5, 0x32, 0xB5, 0x12, 0xB4, 0xF1, 0xA4, 0xAF, +0xAD, 0x53, 0xBE, 0x16, 0xB5, 0x94, 0xB5, 0xB4, +0xAD, 0x94, 0xBD, 0xF6, 0xB5, 0xB5, 0xB5, 0xD5, +0xB5, 0xB4, 0xB5, 0x93, 0xAC, 0xF0, 0xAC, 0xCF, +0xAD, 0x10, 0x9C, 0x8E, 0xB5, 0x52, 0xBD, 0x93, +0xBD, 0xB3, 0xBD, 0xB3, 0xBD, 0xB3, 0xB5, 0x73, +0xA4, 0xD1, 0xA5, 0x12, 0xAD, 0x12, 0xB5, 0x74, +0xB5, 0x74, 0xAD, 0x12, 0xA4, 0xD1, 0xAD, 0x32, +0xC5, 0xD4, 0xA4, 0xD0, 0x52, 0x47, 0x31, 0xA5, +0x29, 0x64, 0x31, 0x85, 0x42, 0x07, 0x4A, 0x28, +0x5A, 0xCA, 0x6B, 0x4C, 0x6B, 0x2C, 0x6B, 0x4C, +0x6B, 0x4C, 0x73, 0xAE, 0x7B, 0xEF, 0xAD, 0x55, +0xBD, 0xD7, 0xD6, 0x79, 0xBD, 0xB6, 0xB5, 0x73, +0xAD, 0x32, 0xAD, 0x32, 0xA4, 0xF0, 0xA4, 0xB0, +0xA4, 0xB0, 0x9C, 0xAF, 0x7B, 0xAC, 0x9C, 0x8F, +0x9C, 0xB0, 0xA4, 0xD1, 0xAD, 0x11, 0xAC, 0xD1, +0xA4, 0xD0, 0x9C, 0x90, 0xA4, 0xD0, 0xA4, 0xD0, +0xAC, 0xD1, 0xAC, 0xF1, 0xAD, 0x11, 0xB5, 0x11, +0xB5, 0x11, 0xAD, 0x11, 0xAC, 0xF0, 0xAC, 0xF1, +0xAC, 0xF0, 0xAC, 0xF1, 0xBD, 0x72, 0xBD, 0x72, +0xBD, 0x73, 0xBD, 0x94, 0xBD, 0x94, 0xB5, 0x73, +0xAD, 0x32, 0xAD, 0x12, 0xA4, 0xF1, 0x94, 0x6F, +0x94, 0x6F, 0x9C, 0xB0, 0x9C, 0xB0, 0x9C, 0x90, +0x94, 0x4F, 0x8C, 0x2E, 0x94, 0x4F, 0x9C, 0xB0, +0xAD, 0x32, 0xB5, 0x73, 0xC5, 0xF5, 0xCE, 0x35, +0xB5, 0x52, 0xAD, 0x32, 0xBD, 0x93, 0xAD, 0x52, +0xAD, 0x32, 0xA4, 0xD0, 0xCE, 0x15, 0xD6, 0x56, +0xCD, 0xD4, 0xCD, 0xD4, 0xD5, 0xF5, 0xDE, 0x76, +0xBD, 0x93, 0xB5, 0x53, 0xCE, 0x36, 0xCE, 0x36, +0xCE, 0x15, 0xCE, 0x15, 0xD6, 0x56, 0xD6, 0x55, +0xDE, 0x76, 0xD6, 0x56, 0xD6, 0x55, 0xD6, 0x35, +0xDE, 0x55, 0xDE, 0x55, 0xD6, 0x15, 0xBD, 0x73, +0x8C, 0x0E, 0x4A, 0x27, 0x31, 0x85, 0x29, 0x45, +0x31, 0xA6, 0x7B, 0xAE, 0x94, 0x91, 0x62, 0xEB, +0x41, 0xC7, 0x5A, 0x69, 0x5A, 0x8A, 0x4A, 0x08, +0x6A, 0xEB, 0x6A, 0xCB, 0x5A, 0x69, 0x7B, 0x4C, +0x83, 0x6D, 0x83, 0xAE, 0x5A, 0xAA, 0x5A, 0x8A, +0x73, 0x4C, 0xA4, 0xD2, 0xC6, 0x15, 0xE6, 0xB7, +0xEE, 0xF8, 0xAC, 0xD1, 0xAD, 0x12, 0xB5, 0x32, +0xD6, 0x76, 0xD6, 0x55, 0xDE, 0x76, 0xE6, 0xB6, +0xDE, 0x55, 0xE6, 0x95, 0xE6, 0x95, 0xDE, 0x75, +0xE6, 0x75, 0xE6, 0x96, 0xE6, 0xD7, 0xDE, 0x35, +0xC5, 0x94, 0xA4, 0xB1, 0xAD, 0x12, 0x4A, 0x28, +0x10, 0xC3, 0x10, 0x83, 0x08, 0x83, 0x10, 0x82, +0x10, 0x83, 0x08, 0x83, 0x08, 0x83, 0x08, 0x82, +0x08, 0x82, 0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, +0x18, 0xE4, 0x21, 0x04, 0xBD, 0x94, 0xE6, 0xB7, +0xDE, 0x34, 0xD5, 0xF3, 0xC5, 0xB2, 0xBD, 0x52, +0xA4, 0xD0, 0x83, 0xAC, 0x41, 0xE7, 0x39, 0xC6, +0x29, 0x66, 0x21, 0x46, 0x21, 0x25, 0x19, 0x04, +0x18, 0xE4, 0x21, 0x05, 0x21, 0x05, 0x19, 0x05, +0x19, 0x04, 0x19, 0x04, 0x21, 0x05, 0x29, 0x66, +0x4A, 0x49, 0x8C, 0x50, 0x94, 0x6F, 0x8B, 0xED, +0xB5, 0x32, 0xB5, 0x32, 0xB5, 0x32, 0xA4, 0xD0, +0x94, 0x6F, 0x8C, 0x0E, 0x8C, 0x2E, 0xA4, 0xF1, +0xB5, 0x53, 0xAD, 0x12, 0xB5, 0x52, 0xBD, 0x73, +0x64, 0x29, 0x64, 0x49, 0x8D, 0x4E, 0xBE, 0x75, +0x94, 0xCF, 0x74, 0x09, 0x74, 0x86, 0x6C, 0x64, +0x6C, 0x64, 0x8D, 0x09, 0x8C, 0x8B, 0x9C, 0xAD, +0xAD, 0x50, 0xB5, 0x50, 0x8C, 0x0C, 0x4A, 0x67, +0x39, 0xC6, 0x4A, 0x48, 0x52, 0xCA, 0x63, 0x0C, +0x8C, 0x92, 0xA5, 0x35, 0xBD, 0xF8, 0xBD, 0xD7, +0xDE, 0xFB, 0x9C, 0xD2, 0xA4, 0xF2, 0x94, 0x2E, +0x9C, 0x6E, 0x9C, 0x6E, 0x9C, 0x6E, 0x94, 0x4E, +0x8C, 0x0C, 0x94, 0x2D, 0x9C, 0x6E, 0x94, 0x2D, +0x83, 0xEC, 0x83, 0xCC, 0x7B, 0xAC, 0x84, 0x0D, +0x94, 0x8F, 0x9C, 0x8F, 0xA4, 0xD0, 0xAD, 0x10, +0xB5, 0x10, 0xA4, 0x8E, 0xAC, 0xAF, 0x94, 0x2D, +0x83, 0xCC, 0x8C, 0x2E, 0xA4, 0xD1, 0xA5, 0x12, +0xBD, 0xD5, 0xAD, 0x73, 0xAD, 0x32, 0xB5, 0x73, +0xA4, 0xF1, 0xA4, 0xF1, 0x9C, 0xD1, 0xA4, 0xF1, +0xA5, 0x12, 0xB5, 0x74, 0xBD, 0x94, 0xB5, 0x53, +0xA4, 0xF1, 0xA4, 0xF1, 0x9C, 0xD0, 0xA5, 0x11, +0x5A, 0xC9, 0x6B, 0x2B, 0x73, 0x8D, 0x6B, 0x0B, +0x6B, 0x4B, 0x6B, 0x4C, 0x52, 0x48, 0x31, 0x65, +0x6B, 0x6D, 0x63, 0x0B, 0x8C, 0x30, 0xBD, 0xB6, +0xD6, 0x79, 0xBD, 0x96, 0xB5, 0x54, 0xC5, 0xB6, +0x9C, 0x91, 0x7B, 0x4D, 0x9C, 0x51, 0xCD, 0xD6, +0x9C, 0x51, 0x8B, 0xCF, 0xA4, 0xB2, 0x9C, 0x51, +0x94, 0x51, 0x94, 0x71, 0x8C, 0x31, 0xAD, 0x34, +0xCE, 0x38, 0xDE, 0xBA, 0xDE, 0xB9, 0xC5, 0xF6, +0xBD, 0xB5, 0xA5, 0x33, 0xB5, 0x94, 0xBD, 0xF5, +0xBD, 0xF6, 0xBD, 0xD5, 0xAD, 0x94, 0xBD, 0xF6, +0xBD, 0xF5, 0xB5, 0x73, 0xB5, 0x52, 0xAC, 0xEF, +0xB5, 0x51, 0x9C, 0x8F, 0xBD, 0xB3, 0xCE, 0x35, +0xB5, 0x93, 0xA4, 0xF0, 0xBD, 0xD4, 0xBD, 0x93, +0xAD, 0x32, 0xB5, 0x53, 0xAD, 0x12, 0xB5, 0x94, +0xAD, 0x12, 0xA4, 0xF2, 0xAD, 0x32, 0xB5, 0x52, +0xC5, 0xB3, 0xCD, 0xF4, 0x8C, 0x0E, 0x42, 0x06, +0x29, 0x64, 0x29, 0x43, 0x31, 0x85, 0x42, 0x07, +0x4A, 0x48, 0x52, 0x89, 0x6B, 0x4C, 0x73, 0x8D, +0x6B, 0x4D, 0x73, 0xAE, 0x7B, 0xEF, 0x94, 0xB3, +0xA5, 0x14, 0xAD, 0x75, 0xCE, 0x58, 0xD6, 0x78, +0xCE, 0x57, 0xBD, 0xB4, 0xAD, 0x11, 0xA5, 0x11, +0x94, 0x8F, 0x7B, 0xCC, 0x73, 0x6B, 0x8C, 0x4F, +0x94, 0x6F, 0xA4, 0xD1, 0xB5, 0x53, 0x94, 0x4F, +0xA5, 0x11, 0xB5, 0x32, 0xB5, 0x52, 0xA4, 0xD0, +0xA4, 0xF1, 0xAD, 0x11, 0x9C, 0xAF, 0xA4, 0xB0, +0xB5, 0x52, 0xBD, 0xB3, 0xB5, 0x32, 0xA4, 0xD0, +0xA4, 0xD0, 0xA4, 0xF0, 0x94, 0x6E, 0x9C, 0x6F, +0xB5, 0x52, 0xA4, 0xD0, 0x9C, 0x6F, 0x9C, 0x8F, +0xA4, 0xD0, 0xA4, 0xB0, 0xAD, 0x11, 0x94, 0x6F, +0xAC, 0xF1, 0xB5, 0x32, 0xB5, 0x32, 0xB5, 0x52, +0xAC, 0xF1, 0xAC, 0xF1, 0xA4, 0xF1, 0xA4, 0xD0, +0xA4, 0xF1, 0xAD, 0x31, 0xAD, 0x32, 0xAD, 0x11, +0xA4, 0xD0, 0xA4, 0xF1, 0xA4, 0xF1, 0xAD, 0x31, +0xBD, 0x73, 0xB5, 0x32, 0xAD, 0x32, 0xB5, 0x32, +0xAC, 0xF0, 0xAC, 0xD0, 0xA4, 0xB0, 0xB5, 0x32, +0xBD, 0x72, 0xAD, 0x11, 0xAD, 0x11, 0xB5, 0x52, +0xBD, 0x93, 0xC5, 0xB4, 0xCE, 0x15, 0xC5, 0xB3, +0xCD, 0xF4, 0xDE, 0x56, 0xDE, 0x55, 0xD6, 0x35, +0xDE, 0x55, 0xD6, 0x15, 0xD5, 0xF4, 0xC5, 0xB3, +0xC5, 0xB3, 0xB5, 0x52, 0x6B, 0x0A, 0x31, 0x65, +0x29, 0x45, 0x31, 0x85, 0x52, 0x8A, 0x94, 0x71, +0x94, 0x71, 0x73, 0x2D, 0x52, 0x69, 0x52, 0x29, +0x52, 0x28, 0x73, 0x2C, 0x73, 0x0C, 0x5A, 0x48, +0x73, 0x0B, 0x73, 0x0C, 0x94, 0x10, 0x73, 0x4C, +0x6B, 0x0B, 0xA4, 0xB2, 0xBD, 0x95, 0xA4, 0xD1, +0xDE, 0x98, 0xBD, 0x73, 0xB5, 0x32, 0xBD, 0x73, +0xD6, 0x56, 0xDE, 0x75, 0xDE, 0x96, 0xE6, 0x96, +0xDE, 0x54, 0xE6, 0x75, 0xEE, 0xB6, 0xE6, 0x95, +0xE6, 0x75, 0xE6, 0x95, 0xE6, 0x95, 0xD6, 0x14, +0xDE, 0x35, 0xDE, 0x76, 0xE6, 0x97, 0x8B, 0xED, +0x4A, 0x28, 0x20, 0xE4, 0x10, 0x83, 0x08, 0x63, +0x10, 0x83, 0x10, 0x83, 0x08, 0x82, 0x08, 0x82, +0x08, 0x82, 0x10, 0x83, 0x10, 0xA3, 0x18, 0xC3, +0x18, 0xE4, 0x39, 0xA6, 0xD6, 0x56, 0xD6, 0x14, +0xD6, 0x13, 0xD6, 0x14, 0xDE, 0x75, 0xD6, 0x34, +0xC5, 0x93, 0x9C, 0x4E, 0x73, 0x4B, 0x62, 0xEA, +0x42, 0x07, 0x31, 0x86, 0x29, 0x46, 0x29, 0x25, +0x21, 0x05, 0x21, 0x05, 0x21, 0x04, 0x19, 0x04, +0x18, 0xE4, 0x18, 0xE4, 0x21, 0x25, 0x31, 0xA7, +0x73, 0x8D, 0xA4, 0xF1, 0x83, 0xCC, 0x6B, 0x0A, +0xAD, 0x12, 0xAD, 0x32, 0xAD, 0x32, 0xBD, 0x93, +0xB5, 0x73, 0xB5, 0x73, 0xAD, 0x32, 0xA4, 0xD1, +0xAD, 0x12, 0xBD, 0x73, 0xCE, 0x15, 0xDE, 0x76, +0x64, 0x08, 0x64, 0x48, 0x74, 0xCB, 0x7C, 0x8C, +0x84, 0xCE, 0x8C, 0xCC, 0x74, 0x88, 0x6C, 0x65, +0x95, 0xCD, 0x74, 0x49, 0x7C, 0x4B, 0x8C, 0x6D, +0x83, 0xEB, 0x73, 0x6A, 0x8C, 0x0C, 0x9C, 0xAE, +0x52, 0x67, 0x39, 0xC6, 0x4A, 0x48, 0x5A, 0xCA, +0x6B, 0x8D, 0x8C, 0x51, 0xA5, 0x15, 0xC6, 0x19, +0xB5, 0x76, 0x8C, 0x51, 0xEF, 0x5C, 0xB5, 0x53, +0xAC, 0xF0, 0xAC, 0xF0, 0xAC, 0xF0, 0xAC, 0xEF, +0xB4, 0xEF, 0xB5, 0x10, 0xB5, 0x10, 0xB5, 0x10, +0xB5, 0x10, 0xB5, 0x10, 0xB5, 0x30, 0xAC, 0xCF, +0xAC, 0xAF, 0xAC, 0xAF, 0x9C, 0x4D, 0x9C, 0x6D, +0xA4, 0x6E, 0xAC, 0xEF, 0xB4, 0xEF, 0xB4, 0xCF, +0xB4, 0xEF, 0xB4, 0xF0, 0xA4, 0x8E, 0x94, 0x4E, +0x94, 0x4E, 0x8C, 0x2D, 0x8C, 0x0D, 0x8C, 0x0D, +0x83, 0xCD, 0x8C, 0x0D, 0x8C, 0x0D, 0x8C, 0x2E, +0x94, 0x4E, 0xAD, 0x11, 0xA4, 0xF1, 0x9C, 0x8F, +0x8C, 0x2E, 0x94, 0x4E, 0x9C, 0xB0, 0xAD, 0x11, +0x8C, 0x2E, 0x73, 0x8C, 0xCD, 0xF5, 0xBD, 0x92, +0xC5, 0xD4, 0xD6, 0x35, 0xAC, 0xF0, 0x94, 0x2E, +0x5A, 0xAA, 0x8C, 0x51, 0xA5, 0x14, 0xB5, 0x96, +0xCE, 0x59, 0xDE, 0x9A, 0xAD, 0x14, 0xBD, 0x96, +0xB5, 0x54, 0xA4, 0xB2, 0xBD, 0x96, 0xC5, 0xB6, +0xCD, 0xF8, 0xC5, 0x96, 0x8B, 0xCF, 0x83, 0xAE, +0x9C, 0x92, 0x7B, 0xAE, 0xB5, 0x76, 0xBD, 0xB6, +0xC5, 0xF7, 0xAD, 0x75, 0xB5, 0xB6, 0xE6, 0xFC, +0xE7, 0x3C, 0x9C, 0xF3, 0x94, 0x91, 0x9C, 0xD1, +0x9D, 0x12, 0xAD, 0x74, 0xB5, 0xB5, 0xC6, 0x57, +0xCE, 0x77, 0xCE, 0x56, 0xB5, 0x52, 0xAC, 0xF0, +0xB5, 0x52, 0x9C, 0xAF, 0xAD, 0x11, 0xB5, 0x52, +0xBD, 0x93, 0x94, 0x6F, 0xC5, 0xD4, 0xCE, 0x15, +0xBD, 0xB4, 0xBD, 0xD5, 0xAD, 0x53, 0xAD, 0x32, +0xA4, 0xD1, 0xAD, 0x32, 0xAD, 0x52, 0xAD, 0x11, +0xB5, 0x52, 0xCE, 0x14, 0xAC, 0xF0, 0x7B, 0xAC, +0x39, 0xC5, 0x31, 0x84, 0x39, 0xA6, 0x4A, 0x27, +0x5A, 0xCA, 0x62, 0xEB, 0x6B, 0x4C, 0x6B, 0x4D, +0x63, 0x0C, 0x63, 0x0C, 0x6B, 0x4D, 0x73, 0x6E, +0x94, 0xB3, 0xAD, 0x76, 0xC6, 0x38, 0xBD, 0xD6, +0xA5, 0x13, 0xA5, 0x33, 0x94, 0x90, 0xB5, 0x73, +0xB5, 0x93, 0x84, 0x2E, 0x84, 0x2F, 0x9C, 0xD1, +0xA4, 0xF1, 0xA4, 0xD1, 0xB5, 0x73, 0x94, 0x6F, +0x9C, 0xB0, 0xAD, 0x11, 0xAD, 0x12, 0xA4, 0xD0, +0xBD, 0xB4, 0xAD, 0x52, 0x9C, 0xD0, 0x9C, 0xB0, +0xB5, 0x93, 0xCE, 0x35, 0xC6, 0x14, 0xC5, 0xF5, +0xB5, 0x73, 0xAD, 0x11, 0xAD, 0x11, 0xB5, 0x73, +0xBD, 0x93, 0xAD, 0x31, 0xAD, 0x31, 0xAC, 0xF1, +0xAD, 0x31, 0x9C, 0x8F, 0xA4, 0xF1, 0xBD, 0x94, +0xB5, 0x52, 0xB5, 0x52, 0x9C, 0xB0, 0xB5, 0x52, +0xDE, 0x76, 0xCD, 0xF4, 0xD6, 0x35, 0xD6, 0x55, +0xD6, 0x35, 0xB5, 0x52, 0x9C, 0x90, 0xA4, 0xD0, +0xA4, 0xD0, 0xBD, 0x93, 0xAD, 0x11, 0xB5, 0x73, +0xB5, 0x52, 0xAC, 0xF1, 0x94, 0x2E, 0x94, 0x2E, +0xA4, 0x8F, 0xB5, 0x11, 0xB5, 0x52, 0x9C, 0x6F, +0x9C, 0x6F, 0x94, 0x2E, 0x9C, 0x4F, 0x9C, 0x6F, +0xA4, 0xB0, 0xA4, 0xB0, 0xA4, 0x90, 0x9C, 0x6F, +0xA4, 0x8F, 0x9C, 0x6F, 0x9C, 0x6E, 0x9C, 0x4E, +0x9C, 0x2E, 0x9C, 0x6E, 0xA4, 0x8F, 0x9C, 0x4F, +0x94, 0x2E, 0x9C, 0x6F, 0xA4, 0xB0, 0x8C, 0x0E, +0x4A, 0x27, 0x29, 0x65, 0x29, 0x45, 0x52, 0x69, +0x8C, 0x50, 0x8C, 0x30, 0xA4, 0xF3, 0x94, 0x51, +0x73, 0x6D, 0x62, 0x8A, 0x5A, 0x69, 0x5A, 0x89, +0x5A, 0x69, 0x62, 0xAA, 0x73, 0x0B, 0x7B, 0x6D, +0x5A, 0x8A, 0x62, 0xCB, 0x9C, 0x71, 0xAC, 0xD2, +0x83, 0xAD, 0x94, 0x2F, 0x9C, 0x70, 0xBD, 0x93, +0xEF, 0x18, 0xEE, 0xF7, 0xEE, 0xF7, 0xEE, 0xD6, +0xE6, 0xB6, 0xE6, 0x95, 0xE6, 0x95, 0xEE, 0xB5, +0xE6, 0x95, 0xE6, 0x74, 0xDE, 0x54, 0xDE, 0x34, +0xEE, 0xB6, 0xF6, 0xF7, 0xEE, 0xD7, 0xBD, 0x72, +0x9C, 0x6F, 0x6B, 0x0B, 0x31, 0x65, 0x10, 0x83, +0x10, 0xA3, 0x10, 0x83, 0x08, 0x82, 0x08, 0x82, +0x08, 0x82, 0x10, 0x83, 0x10, 0x83, 0x18, 0xC4, +0x18, 0xE4, 0x73, 0x8C, 0xE6, 0xF8, 0xD6, 0x13, +0xDE, 0x54, 0xDE, 0x54, 0xDE, 0x54, 0xDE, 0x54, +0xCE, 0x14, 0xB5, 0x52, 0xA4, 0xD0, 0x83, 0xED, +0x62, 0xEA, 0x39, 0xE7, 0x39, 0xE7, 0x39, 0xC7, +0x29, 0x46, 0x21, 0x25, 0x21, 0x04, 0x21, 0x04, +0x18, 0xE4, 0x21, 0x05, 0x29, 0x66, 0x52, 0x6A, +0xBD, 0xB5, 0xCE, 0x35, 0x94, 0x6F, 0x62, 0xC9, +0xAD, 0x12, 0xCE, 0x15, 0xC5, 0xF5, 0xCE, 0x15, +0xCE, 0x15, 0xC5, 0xD4, 0xBD, 0x94, 0xBD, 0x94, +0xC5, 0xD5, 0xCE, 0x15, 0xD6, 0x35, 0xD6, 0x35, +0x53, 0xC6, 0x64, 0x67, 0x5B, 0xC7, 0x53, 0x66, +0x74, 0x8C, 0x7C, 0xAC, 0x74, 0x69, 0x5B, 0xE5, +0xA6, 0x30, 0x95, 0x6F, 0x94, 0xEE, 0xA5, 0x0F, +0xB5, 0x92, 0xAD, 0x51, 0xA4, 0xF0, 0xB5, 0x50, +0xAD, 0x10, 0x62, 0xE9, 0x42, 0x07, 0x3A, 0x07, +0x4A, 0x89, 0x6B, 0x6D, 0x8C, 0x71, 0xAD, 0x76, +0x84, 0x11, 0x94, 0x72, 0xBD, 0xD7, 0x84, 0x30, +0x52, 0x68, 0x83, 0xED, 0x9C, 0x8F, 0x8C, 0x0C, +0x94, 0x4D, 0x9C, 0x6E, 0xA4, 0xAE, 0xB5, 0x31, +0xAC, 0xF0, 0xB5, 0x10, 0xB5, 0x30, 0xAC, 0xCF, +0xB5, 0x10, 0xAC, 0xCF, 0x9C, 0x6E, 0xA4, 0x8E, +0xA4, 0xAE, 0xA4, 0xAF, 0xAC, 0xAE, 0xB4, 0xEF, +0xAC, 0xCF, 0xB5, 0x10, 0xB4, 0xEF, 0xAC, 0xAF, +0xA4, 0x8E, 0xAC, 0xD0, 0xAC, 0xD0, 0xA4, 0xAF, +0xAC, 0xCF, 0xAC, 0xCF, 0xAC, 0xCF, 0xAC, 0xF0, +0xAC, 0xCF, 0xA4, 0xCF, 0xA4, 0xAF, 0xA4, 0xAE, +0xA4, 0xAF, 0xAC, 0xEF, 0xAC, 0xCF, 0xAC, 0xF0, +0xB5, 0x51, 0x7B, 0xAC, 0xA4, 0xD0, 0xA4, 0x8E, +0xB5, 0x10, 0xBD, 0x31, 0xB4, 0xEF, 0xC5, 0x52, +0x73, 0x2B, 0x4A, 0x07, 0x62, 0xCB, 0x8C, 0x30, +0x94, 0x51, 0xAD, 0x55, 0xE7, 0x1C, 0xA4, 0xF4, +0x52, 0x4A, 0x73, 0x6E, 0x73, 0x6E, 0x73, 0x4E, +0x73, 0x4E, 0x94, 0x72, 0x83, 0xCF, 0x9C, 0x72, +0x8C, 0x10, 0xA4, 0xF4, 0xC5, 0xD7, 0xA5, 0x14, +0x73, 0x6D, 0x52, 0x6A, 0x73, 0xAF, 0xB5, 0xB7, +0xCE, 0x59, 0xCE, 0x59, 0xBD, 0xD7, 0x9C, 0xD2, +0xB5, 0x94, 0xC6, 0x37, 0xC6, 0x37, 0xC6, 0x16, +0xBE, 0x15, 0xC6, 0x15, 0xAD, 0x11, 0xB5, 0x31, +0xB5, 0x51, 0x94, 0x4D, 0xBD, 0x92, 0x9C, 0xAF, +0xAD, 0x31, 0xAD, 0x11, 0xBD, 0xB3, 0xD6, 0x56, +0xC5, 0xF4, 0xC5, 0xF4, 0xB5, 0x52, 0xA4, 0xF1, +0x94, 0x8F, 0xA5, 0x11, 0xAD, 0x32, 0xA4, 0xF1, +0xAD, 0x10, 0xD5, 0xF4, 0xB5, 0x31, 0xA4, 0x8F, +0x62, 0xC9, 0x39, 0xA5, 0x39, 0xC6, 0x4A, 0x48, +0x4A, 0x48, 0x4A, 0x48, 0x62, 0xEB, 0x5A, 0xEB, +0x52, 0x8A, 0x52, 0x8A, 0x5A, 0xEB, 0x7B, 0xCF, +0x94, 0x93, 0xA5, 0x14, 0xB5, 0xB6, 0xCE, 0x59, +0xA5, 0x34, 0xAD, 0x54, 0x94, 0x90, 0xB5, 0x93, +0xB5, 0x73, 0x94, 0xB0, 0xA5, 0x12, 0xB5, 0xB4, +0xAD, 0x33, 0xA4, 0xD1, 0xBD, 0x94, 0x9C, 0x90, +0xB5, 0x73, 0xBD, 0xB4, 0xBD, 0xD4, 0xAD, 0x11, +0xBD, 0xB4, 0xB5, 0x93, 0xAD, 0x52, 0xA5, 0x32, +0xA4, 0xF1, 0xC5, 0xF4, 0xC6, 0x15, 0xBD, 0xB3, +0xAD, 0x52, 0xAD, 0x32, 0xAD, 0x52, 0xB5, 0x93, +0xBD, 0xB4, 0xC6, 0x15, 0xBD, 0xD4, 0xBD, 0xD4, +0xC5, 0xF4, 0xA4, 0xD0, 0xB5, 0x52, 0xBD, 0x73, +0xB5, 0x31, 0xC5, 0xB3, 0xBD, 0x93, 0xC5, 0xB3, +0xCD, 0xD3, 0xC5, 0xB2, 0xCD, 0xB3, 0xCD, 0xF3, +0xD6, 0x35, 0xB5, 0x32, 0x9C, 0x6F, 0xA4, 0xF1, +0xAD, 0x52, 0xC5, 0xD5, 0xC5, 0xD5, 0xC5, 0xD4, +0xB5, 0x52, 0xB5, 0x32, 0x8C, 0x2E, 0xA4, 0xD1, +0xB5, 0x73, 0xC5, 0xD4, 0xBD, 0xB4, 0x94, 0x6F, +0xA4, 0xB0, 0xAD, 0x12, 0xAC, 0xF1, 0x9C, 0x8F, +0x9C, 0x4E, 0x9C, 0x8F, 0xA4, 0xB0, 0xA4, 0xB0, +0x9C, 0x6F, 0xA4, 0x8F, 0x9C, 0x8F, 0xA4, 0xB0, +0xA4, 0xD0, 0xA4, 0xD0, 0xAC, 0xF1, 0xAC, 0xD1, +0xA4, 0xD0, 0xAC, 0xF1, 0xB5, 0x53, 0xBD, 0x73, +0xAC, 0xF1, 0x73, 0x6C, 0x39, 0xA6, 0x29, 0x24, +0x39, 0x86, 0x5A, 0xAA, 0x8C, 0x30, 0xAD, 0x14, +0xBD, 0x96, 0xAD, 0x14, 0x8C, 0x10, 0x62, 0xEB, +0x4A, 0x08, 0x49, 0xE7, 0x62, 0xAA, 0x94, 0x0F, +0x8B, 0xEF, 0x62, 0xCA, 0x7B, 0x6D, 0x94, 0x0F, +0x8C, 0x0F, 0x5A, 0x8A, 0x5A, 0x8A, 0x83, 0xAD, +0xAD, 0x11, 0xAC, 0xF0, 0xAC, 0xF0, 0xAC, 0xF0, +0xAC, 0xF0, 0xB5, 0x30, 0xC5, 0x51, 0xC5, 0x71, +0xC5, 0x71, 0xC5, 0x92, 0xCD, 0xB2, 0xCD, 0xB3, +0xD5, 0xF3, 0xD6, 0x14, 0xD6, 0x14, 0xC5, 0xB3, +0xBD, 0x52, 0xAC, 0xF1, 0x7B, 0x6C, 0x20, 0xE4, +0x10, 0x82, 0x10, 0x83, 0x08, 0x82, 0x08, 0x82, +0x08, 0x82, 0x10, 0x83, 0x10, 0xA3, 0x18, 0xC4, +0x18, 0xE4, 0x9C, 0xD1, 0xDE, 0x96, 0xCD, 0xD3, +0xDE, 0x55, 0xDE, 0x54, 0xDE, 0x54, 0xDE, 0x75, +0xDE, 0x55, 0xC5, 0xD3, 0xC5, 0xD4, 0xA4, 0xF1, +0x94, 0x6F, 0x73, 0x6C, 0x6B, 0x4B, 0x4A, 0x69, +0x39, 0xC7, 0x29, 0x66, 0x29, 0x46, 0x21, 0x05, +0x21, 0x25, 0x29, 0x66, 0x52, 0x8A, 0xA4, 0xF2, +0xDE, 0xB8, 0xDE, 0xB7, 0xD6, 0x56, 0xB5, 0x73, +0xBD, 0x93, 0xD6, 0x76, 0xCE, 0x15, 0xD6, 0x56, +0xCE, 0x35, 0xC5, 0xD4, 0xC5, 0xF4, 0xD6, 0x56, +0xD6, 0x36, 0xD6, 0x56, 0xCE, 0x14, 0xCD, 0xF4, +0x4B, 0x65, 0x43, 0x23, 0x53, 0xA5, 0x64, 0x28, +0x7C, 0xCC, 0x84, 0xCD, 0x74, 0x6A, 0x5B, 0xC6, +0x85, 0x2C, 0x9D, 0xD0, 0x74, 0x0A, 0x94, 0xED, +0xAD, 0x70, 0xA5, 0x10, 0x8C, 0x4C, 0xA4, 0xCF, +0xB5, 0x92, 0xBD, 0xD3, 0x63, 0x2A, 0x39, 0xE7, +0x3A, 0x07, 0x4A, 0x69, 0x5B, 0x0B, 0x6B, 0x4D, +0x9C, 0xD3, 0xBD, 0xB7, 0xAD, 0x55, 0x63, 0x2C, +0x73, 0x6D, 0x7B, 0xCE, 0xBD, 0xB5, 0xB5, 0x73, +0xAD, 0x32, 0xA4, 0xF1, 0xB5, 0x53, 0xC5, 0xD4, +0xBD, 0x93, 0xDE, 0x76, 0xC5, 0xB3, 0xAC, 0xEF, +0xBD, 0xB3, 0xB5, 0x72, 0xB5, 0x52, 0xAD, 0x31, +0xAD, 0x31, 0xAC, 0xF0, 0xA4, 0xCF, 0xAC, 0xF0, +0xAC, 0xF0, 0xB5, 0x10, 0xAC, 0xCF, 0xA4, 0xCF, +0xAD, 0x10, 0xB5, 0x31, 0xAC, 0xF0, 0xA4, 0xAF, +0xA4, 0xAF, 0xB5, 0x10, 0xAD, 0x10, 0xAC, 0xF0, +0xAD, 0x10, 0xA4, 0xAF, 0xAC, 0xAF, 0xB5, 0x30, +0xB5, 0x30, 0xAC, 0xEF, 0xAC, 0xCF, 0xA4, 0x8E, +0xB5, 0x30, 0x73, 0x8B, 0xA4, 0xF0, 0xBD, 0x71, +0xBD, 0x30, 0xBD, 0x30, 0xC5, 0x71, 0xCD, 0xB2, +0xBD, 0x31, 0x73, 0x2B, 0x5A, 0x89, 0x52, 0x49, +0x7B, 0xAF, 0xCE, 0x59, 0xCE, 0x39, 0xDE, 0xBB, +0xCE, 0x39, 0x5A, 0xAB, 0x10, 0xA4, 0x18, 0xC4, +0x10, 0x83, 0x4A, 0x4A, 0x94, 0x51, 0x7B, 0x8E, +0x94, 0x51, 0xBD, 0xD7, 0x94, 0x72, 0x83, 0xCF, +0x8C, 0x51, 0xA4, 0xF3, 0xBD, 0xF8, 0xBD, 0xD7, +0xC5, 0xF8, 0xD6, 0x9A, 0xE7, 0x3D, 0xEF, 0x3C, +0xB5, 0x96, 0x94, 0x91, 0x94, 0xB0, 0x94, 0x8F, +0xA4, 0xF0, 0xB5, 0x52, 0xB5, 0x10, 0xAC, 0xEF, +0xB5, 0x31, 0xA4, 0xAF, 0xA4, 0xCF, 0x83, 0xAB, +0x9C, 0xAF, 0xA4, 0xCF, 0xB5, 0x51, 0xCE, 0x14, +0xC5, 0xF4, 0xCE, 0x15, 0xBD, 0xB3, 0xB5, 0x73, +0xAD, 0x11, 0xAD, 0x32, 0xB5, 0x52, 0xAD, 0x32, +0xBD, 0x72, 0xCE, 0x14, 0xB4, 0xF0, 0xA4, 0xB0, +0x8C, 0x0E, 0x4A, 0x27, 0x31, 0x64, 0x39, 0xC6, +0x52, 0x89, 0x5A, 0xCA, 0x63, 0x2C, 0x5A, 0xEB, +0x4A, 0x69, 0x5A, 0xEB, 0x6B, 0x4D, 0x7B, 0xF0, +0x8C, 0x31, 0x94, 0x93, 0xB5, 0x96, 0xD6, 0xBA, +0xC6, 0x38, 0xAD, 0x75, 0xAD, 0x53, 0xB5, 0xB4, +0xB5, 0xD4, 0xB5, 0xB4, 0xB5, 0xB4, 0xA5, 0x53, +0xAD, 0x32, 0x9C, 0xB0, 0xBD, 0xB4, 0xA4, 0xD1, +0xBD, 0x94, 0xBD, 0xD5, 0xC5, 0xF5, 0xA5, 0x12, +0xB5, 0x93, 0xBD, 0xD5, 0xBD, 0xB4, 0xBD, 0xD5, +0xA5, 0x12, 0xBD, 0xB4, 0xC5, 0xF5, 0xBD, 0xD4, +0xAD, 0x32, 0xB5, 0x73, 0xA5, 0x11, 0xA5, 0x11, +0xB5, 0x73, 0xB5, 0x73, 0xAD, 0x32, 0xAD, 0x32, +0xBD, 0xB3, 0x9C, 0x8F, 0xB5, 0x52, 0xC5, 0x93, +0xC5, 0xB3, 0xD6, 0x34, 0xC5, 0xD3, 0xD6, 0x14, +0xD6, 0x34, 0xDE, 0x34, 0xDE, 0x34, 0xE6, 0x95, +0xE6, 0x75, 0xC5, 0xB3, 0xA4, 0xB0, 0xAD, 0x12, +0xBD, 0x94, 0xB5, 0x93, 0xB5, 0x73, 0xB5, 0x73, +0xB5, 0x53, 0xBD, 0xB4, 0x9C, 0xB0, 0xB5, 0x53, +0xB5, 0x53, 0xBD, 0xB4, 0xCE, 0x15, 0x94, 0x4E, +0xAD, 0x11, 0xB5, 0x73, 0xAD, 0x11, 0xA4, 0xD0, +0xA4, 0xB0, 0x9C, 0x8F, 0xA4, 0xAF, 0xA4, 0xD0, +0x9C, 0x8F, 0xA4, 0xD0, 0xAD, 0x11, 0xB5, 0x32, +0xAC, 0xF1, 0xAC, 0xD1, 0xAD, 0x11, 0x9C, 0x8F, +0x9C, 0x8F, 0xA4, 0x8F, 0x8B, 0xED, 0x83, 0x8B, +0x94, 0x2E, 0x8C, 0x0D, 0x94, 0x4E, 0x52, 0x68, +0x29, 0x44, 0x39, 0x86, 0x41, 0xE7, 0x52, 0x49, +0x6A, 0xEC, 0x8C, 0x30, 0xB5, 0x55, 0xBD, 0xD7, +0x94, 0x92, 0x6B, 0x0C, 0x41, 0xC7, 0x73, 0x2C, +0x9C, 0x50, 0x9C, 0x91, 0x73, 0x2C, 0x73, 0x4D, +0x7B, 0x8D, 0x52, 0x69, 0x6B, 0x0C, 0x83, 0xEF, +0x94, 0x2F, 0xB5, 0x32, 0xB5, 0x32, 0xB5, 0x32, +0xB5, 0x32, 0xB5, 0x12, 0xB5, 0x12, 0xB5, 0x12, +0xAC, 0xF2, 0xAD, 0x12, 0xB5, 0x53, 0xB5, 0x12, +0xAC, 0xF1, 0xA4, 0xD1, 0xAC, 0xF1, 0xAD, 0x11, +0xAD, 0x11, 0xAD, 0x11, 0x94, 0x4F, 0x39, 0xA6, +0x10, 0x82, 0x10, 0x82, 0x10, 0x82, 0x10, 0x82, +0x10, 0x82, 0x10, 0x82, 0x10, 0xC3, 0x18, 0xC3, +0x31, 0xA7, 0x94, 0x70, 0xA4, 0xD0, 0xAD, 0x11, +0xB5, 0x31, 0xBD, 0x92, 0xBD, 0x92, 0xBD, 0x72, +0xBD, 0x72, 0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x11, +0xA4, 0xF1, 0x8C, 0x2E, 0x83, 0xED, 0x6B, 0x0B, +0x52, 0x89, 0x42, 0x08, 0x31, 0xA7, 0x31, 0x86, +0x39, 0xA7, 0x4A, 0x69, 0x7B, 0xCE, 0x9C, 0xD1, +0xBD, 0xD4, 0xB5, 0x52, 0xBD, 0xB4, 0x94, 0x4F, +0x83, 0xED, 0xDE, 0x97, 0xD6, 0x77, 0xD6, 0x56, +0xD6, 0x56, 0xD6, 0x57, 0xD6, 0x77, 0xD6, 0x77, +0xBD, 0xB4, 0xB5, 0x73, 0xBD, 0x93, 0xBD, 0x73, +0x32, 0xA3, 0x6C, 0x4A, 0x9D, 0xD2, 0x9D, 0xB2, +0x74, 0x4C, 0x7C, 0x8C, 0x7C, 0xAB, 0x7C, 0x8A, +0x6C, 0x49, 0x74, 0x6A, 0x8D, 0x0C, 0x84, 0xA9, +0x84, 0xCA, 0x8C, 0xAC, 0x8C, 0x6C, 0xA4, 0xCE, +0xC5, 0xD3, 0xC6, 0x15, 0xC5, 0xF5, 0x7B, 0xCE, +0x39, 0xE6, 0x39, 0xE6, 0x42, 0x48, 0x5A, 0xEB, +0x84, 0x31, 0x84, 0x10, 0x94, 0x92, 0x73, 0x6D, +0x7B, 0xAF, 0xBD, 0xD7, 0xD6, 0x79, 0xC6, 0x16, +0xBD, 0xD5, 0xBD, 0xD5, 0xCE, 0x57, 0xCE, 0x56, +0xAD, 0x31, 0xC5, 0xD3, 0xBD, 0x72, 0xB5, 0x30, +0xC5, 0xD4, 0xB5, 0xB4, 0xB5, 0xB4, 0xBD, 0xD4, +0xBD, 0xD4, 0xBD, 0xB4, 0xBD, 0xD4, 0xC5, 0xF4, +0xC5, 0xF4, 0xC5, 0xD3, 0xBD, 0xB3, 0xC5, 0xD4, +0xCE, 0x35, 0xD6, 0x55, 0xD6, 0x76, 0xD6, 0x76, +0xCE, 0x35, 0xCE, 0x14, 0xC5, 0xD4, 0xBD, 0x93, +0xC5, 0xD3, 0xBD, 0x92, 0xAC, 0xCF, 0xAC, 0xEF, +0xAC, 0xCF, 0x9C, 0x4D, 0x94, 0x4D, 0x94, 0x0C, +0x94, 0x2D, 0x5A, 0xC9, 0x73, 0xAC, 0x8C, 0x2D, +0x94, 0x4D, 0x8B, 0xEC, 0xA4, 0xAE, 0x9C, 0x6D, +0x9C, 0x4D, 0x94, 0x2F, 0x5A, 0xA9, 0x52, 0x69, +0x8C, 0x31, 0xAD, 0x55, 0x62, 0xEC, 0xB5, 0x97, +0xE6, 0xFC, 0xE7, 0x1C, 0x9C, 0xB3, 0x52, 0x8A, +0x31, 0x87, 0x52, 0xAB, 0x39, 0xC7, 0x4A, 0x29, +0x8C, 0x51, 0x94, 0x92, 0x62, 0xEC, 0x83, 0xEF, +0xA4, 0xF3, 0xAD, 0x75, 0xB5, 0xB7, 0xBD, 0xB7, +0xBD, 0xF8, 0xD6, 0x9B, 0xD6, 0x9A, 0xCE, 0x59, +0xCE, 0x59, 0xC5, 0xF7, 0xAD, 0x54, 0xA4, 0xD1, +0xA4, 0xAF, 0xA4, 0x8E, 0xAC, 0xEF, 0xB5, 0x0F, +0xAD, 0x10, 0xAC, 0xEF, 0xB4, 0xEF, 0xAC, 0xEF, +0xAC, 0xCF, 0xAC, 0xEF, 0xAC, 0xCF, 0xAC, 0xEF, +0xAD, 0x10, 0xB5, 0x31, 0xB5, 0x30, 0xB5, 0x51, +0xB5, 0x52, 0xCD, 0xD4, 0xAC, 0xF1, 0xC5, 0x93, +0xA4, 0xD0, 0xAC, 0xF0, 0x9C, 0x4E, 0xB5, 0x11, +0xAC, 0xD1, 0x6B, 0x0A, 0x42, 0x07, 0x42, 0x27, +0x4A, 0x68, 0x4A, 0x48, 0x52, 0x8A, 0x5A, 0xCB, +0x52, 0xAA, 0x5A, 0xEB, 0x73, 0x8E, 0x84, 0x11, +0x84, 0x11, 0x94, 0xB3, 0xB5, 0x96, 0xB5, 0x97, +0xC6, 0x39, 0xCE, 0x79, 0xB5, 0x94, 0xBD, 0xF5, +0xBD, 0xF5, 0xA5, 0x12, 0xA5, 0x32, 0xAD, 0x53, +0xB5, 0xB4, 0x9C, 0xB1, 0xBD, 0xB4, 0xA4, 0xF2, +0xB5, 0x73, 0xBD, 0xB4, 0xC6, 0x16, 0xB5, 0x94, +0xBD, 0xB4, 0xBD, 0xF5, 0xBD, 0xF5, 0xC6, 0x36, +0xB5, 0x73, 0xB5, 0x94, 0xBD, 0xD4, 0xC6, 0x16, +0xBD, 0xD5, 0xB5, 0xB4, 0xB5, 0xB4, 0xAD, 0x32, +0x9C, 0xD1, 0x9C, 0xD1, 0x9C, 0xD0, 0xBD, 0xB4, +0xAD, 0x31, 0x9C, 0x8F, 0xB5, 0x52, 0xC5, 0xB3, +0xCD, 0xD2, 0xD6, 0x13, 0xC5, 0x92, 0xCD, 0xF3, +0xDE, 0x34, 0xDE, 0x54, 0xDE, 0x54, 0xE6, 0xB5, +0xDE, 0x55, 0xD6, 0x14, 0xA4, 0xB0, 0xAD, 0x32, +0xBD, 0x94, 0xB5, 0x94, 0xB5, 0x94, 0xBD, 0x94, +0xBD, 0xB4, 0xBD, 0xB5, 0xAD, 0x53, 0xB5, 0x73, +0xBD, 0x94, 0xC5, 0xD4, 0xD6, 0x56, 0x94, 0x4E, +0xAD, 0x32, 0xBD, 0x93, 0xA4, 0xF1, 0xA4, 0x90, +0xA4, 0xD0, 0x9C, 0x8F, 0xA4, 0xAF, 0xA4, 0xD0, +0xA4, 0xD0, 0xAD, 0x11, 0xB5, 0x52, 0xBD, 0x73, +0xBD, 0x72, 0xBD, 0x72, 0xB5, 0x52, 0xB5, 0x31, +0xB5, 0x31, 0xB5, 0x31, 0x9C, 0x8F, 0x8B, 0xED, +0x8B, 0xCC, 0x94, 0x2D, 0xAC, 0xF0, 0xA4, 0xD0, +0x83, 0xED, 0x52, 0x67, 0x29, 0x65, 0x29, 0x45, +0x39, 0x85, 0x41, 0xC7, 0x4A, 0x69, 0x7B, 0xCF, +0x9C, 0xF3, 0x94, 0x71, 0x41, 0xE8, 0x5A, 0x8A, +0x73, 0x0B, 0x94, 0x30, 0x8B, 0xEF, 0x5A, 0xAA, +0x4A, 0x49, 0x52, 0x49, 0x4A, 0x28, 0x73, 0x6D, +0x94, 0x50, 0x8C, 0x0E, 0xB5, 0x32, 0xAC, 0xF1, +0xCD, 0xF5, 0xBD, 0x93, 0xB5, 0x12, 0xB5, 0x52, +0xBD, 0x73, 0xBD, 0x52, 0xBD, 0x94, 0xBD, 0x73, +0xB5, 0x52, 0xAD, 0x32, 0xBD, 0x73, 0xB5, 0x73, +0xB5, 0x73, 0xB5, 0x53, 0xAD, 0x33, 0x4A, 0x48, +0x18, 0xA3, 0x10, 0x82, 0x10, 0x82, 0x10, 0x82, +0x10, 0x82, 0x10, 0xA3, 0x18, 0xE4, 0x18, 0xE4, +0x63, 0x2C, 0xB5, 0x53, 0xAC, 0xF1, 0xB5, 0x32, +0xB5, 0x73, 0xAD, 0x32, 0xAD, 0x32, 0xB5, 0x52, +0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x52, +0xAD, 0x32, 0xA4, 0xD1, 0x94, 0x4F, 0x8B, 0xEE, +0x73, 0x6C, 0x63, 0x0B, 0x52, 0x89, 0x52, 0x89, +0x63, 0x0B, 0x84, 0x0E, 0x83, 0xEE, 0x83, 0xCE, +0xA4, 0xD1, 0xAD, 0x32, 0xA4, 0xD1, 0x73, 0x8C, +0x62, 0xEB, 0x73, 0x4C, 0x7B, 0x8D, 0x83, 0xCD, +0x83, 0xEE, 0x83, 0xEE, 0x83, 0xEE, 0x73, 0x6C, +0x62, 0xEA, 0x73, 0x4C, 0x7B, 0x6C, 0x94, 0x2E, +0x85, 0x0E, 0xA5, 0xF3, 0xA5, 0xD4, 0xA5, 0xB4, +0xA5, 0xB3, 0x7C, 0x8D, 0x84, 0xCC, 0x8C, 0xCC, +0x85, 0x0C, 0x4B, 0x45, 0x64, 0x06, 0x6C, 0x25, +0x7C, 0x68, 0xA5, 0x2E, 0xA4, 0xEE, 0x9C, 0xCE, +0x8C, 0x4D, 0xAD, 0x72, 0xC5, 0xF5, 0xBD, 0xD5, +0x8C, 0x4F, 0x39, 0xE6, 0x42, 0x48, 0x63, 0x4D, +0x8C, 0x51, 0x84, 0x31, 0x7B, 0xEF, 0x73, 0x6E, +0x7B, 0xAF, 0xC6, 0x18, 0xCE, 0x79, 0xEF, 0x7D, +0xC6, 0x37, 0xB5, 0xB5, 0xCE, 0x57, 0xC5, 0xD5, +0xA4, 0xF1, 0xD6, 0x36, 0xBD, 0x51, 0xAC, 0xCF, +0xBD, 0x93, 0xBD, 0xD4, 0xBD, 0xD5, 0xC5, 0xF5, +0xBD, 0xF4, 0xBD, 0xF4, 0xBD, 0xD4, 0xC5, 0xD4, +0xC5, 0xF4, 0xC5, 0xF4, 0xBD, 0xD4, 0xC5, 0xF4, +0xC5, 0xD4, 0xC5, 0xF4, 0xCE, 0x35, 0xCE, 0x14, +0xCE, 0x15, 0xCE, 0x15, 0xD6, 0x56, 0xC5, 0xD4, +0xC5, 0xF4, 0xC5, 0xD3, 0xAC, 0xCF, 0xAC, 0xEF, +0xBD, 0x93, 0xB5, 0x72, 0xAD, 0x31, 0xA4, 0xD0, +0x8C, 0x0D, 0x7B, 0xAC, 0x8C, 0x6F, 0x94, 0x8F, +0x8C, 0x4D, 0x84, 0x0D, 0xA4, 0xF0, 0x9C, 0xAF, +0x94, 0x4E, 0x84, 0x0E, 0x7B, 0xAD, 0x62, 0xEA, +0x52, 0xAA, 0x73, 0xAF, 0x8C, 0x72, 0xC6, 0x18, +0xCE, 0x7A, 0xD6, 0xBB, 0xC5, 0xF8, 0xB5, 0x76, +0x94, 0x72, 0x8C, 0x31, 0x63, 0x0C, 0x7B, 0xEF, +0x6B, 0x2C, 0x7B, 0xAE, 0x7B, 0xAF, 0x8C, 0x31, +0x9C, 0xD3, 0xB5, 0x76, 0xB5, 0x96, 0x9C, 0xD4, +0xC6, 0x18, 0xBD, 0xB7, 0x9C, 0xD4, 0xA5, 0x15, +0xBD, 0xF8, 0xD6, 0x9A, 0xE7, 0x1B, 0xDE, 0x78, +0xCD, 0xD3, 0xC5, 0x71, 0xCD, 0xF3, 0xCD, 0xD2, +0xBD, 0x50, 0xC5, 0x91, 0xC5, 0x91, 0xBD, 0x30, +0xBD, 0x50, 0xBD, 0x50, 0xB5, 0x10, 0xAC, 0xEF, +0xB4, 0xEF, 0xAC, 0xCE, 0xA4, 0xAE, 0xAC, 0xEF, +0xB4, 0xEF, 0xAC, 0xCF, 0xAC, 0xCF, 0xAC, 0xF0, +0xAC, 0xAF, 0x9C, 0x6E, 0xA4, 0xAF, 0xAC, 0xAF, +0x9C, 0x6F, 0x73, 0x4B, 0x52, 0x48, 0x39, 0xA5, +0x3A, 0x06, 0x4A, 0x48, 0x4A, 0x48, 0x4A, 0x69, +0x52, 0x89, 0x52, 0x8A, 0x6B, 0x6D, 0x7B, 0xEF, +0x84, 0x10, 0x8C, 0x31, 0xAD, 0x35, 0xAD, 0x76, +0xB5, 0xD7, 0xC6, 0x58, 0xB5, 0xB5, 0xA5, 0x12, +0xBD, 0xB4, 0xA5, 0x32, 0xAD, 0x53, 0xBD, 0xF6, +0xAD, 0x32, 0x94, 0x90, 0xBD, 0x94, 0xA4, 0xF1, +0xCE, 0x36, 0xBD, 0xF5, 0xC6, 0x36, 0xCE, 0x37, +0xC6, 0x16, 0xBD, 0xF5, 0xBD, 0xD5, 0xBD, 0xD5, +0xBD, 0xD5, 0xB5, 0xB4, 0xBD, 0xF5, 0xBD, 0xF5, +0xC6, 0x36, 0xC5, 0xF5, 0xC6, 0x16, 0xC6, 0x16, +0xBD, 0xD5, 0xAD, 0x52, 0xAD, 0x52, 0xC5, 0xF5, +0x94, 0x6E, 0xA4, 0xF0, 0xB5, 0x32, 0xC5, 0xB3, +0xD6, 0x13, 0xDE, 0x55, 0xDE, 0x34, 0xD6, 0x14, +0xDE, 0x54, 0xDE, 0x54, 0xDE, 0x54, 0xDE, 0x54, +0xDE, 0x54, 0xD6, 0x34, 0xA4, 0xF0, 0xAD, 0x32, +0xB5, 0x93, 0xB5, 0x73, 0xBD, 0xB4, 0xBD, 0xD5, +0xC5, 0xD5, 0xC5, 0xF5, 0xBD, 0xB4, 0xBD, 0xB4, +0xC5, 0xD5, 0xCE, 0x15, 0xCE, 0x15, 0x9C, 0x8F, +0xB5, 0x32, 0xC5, 0xD4, 0xBD, 0x73, 0xAD, 0x11, +0xB5, 0x11, 0xAC, 0xD0, 0xA4, 0xD0, 0xAC, 0xF1, +0xAC, 0xF1, 0xAC, 0xF0, 0xAD, 0x11, 0xAD, 0x11, +0xAC, 0xF0, 0xAD, 0x31, 0xB5, 0x31, 0xAD, 0x10, +0xB5, 0x31, 0xB5, 0x31, 0xB5, 0x31, 0xAD, 0x10, +0xA4, 0xAF, 0x9C, 0x6E, 0x9C, 0x6E, 0xAD, 0x11, +0xBD, 0xB3, 0xB5, 0x92, 0x73, 0x6B, 0x29, 0x65, +0x21, 0x24, 0x21, 0x03, 0x29, 0x45, 0x31, 0xA6, +0x3A, 0x07, 0x39, 0xC7, 0x39, 0xA6, 0x52, 0x49, +0x4A, 0x28, 0x5A, 0x69, 0x83, 0xCE, 0x83, 0xCE, +0x4A, 0x28, 0x62, 0xCB, 0x52, 0x69, 0x52, 0x8A, +0x73, 0x4D, 0x94, 0x71, 0x94, 0x2F, 0x94, 0x4F, +0xBD, 0x73, 0xEE, 0xD7, 0xD6, 0x15, 0xDE, 0x55, +0xDE, 0x35, 0xCD, 0xD3, 0xC5, 0xB3, 0xCD, 0xD4, +0xCD, 0xB3, 0xD6, 0x55, 0xC5, 0xD4, 0xAD, 0x11, +0xB5, 0x73, 0xB5, 0x73, 0xBD, 0x94, 0x42, 0x07, +0x10, 0xA3, 0x10, 0x82, 0x10, 0x82, 0x10, 0x82, +0x10, 0xA3, 0x10, 0xC3, 0x18, 0xE4, 0x18, 0xE4, +0x73, 0x8D, 0x9C, 0xD1, 0xAD, 0x11, 0xB5, 0x73, +0xAC, 0xF1, 0xB5, 0x73, 0xA4, 0xD0, 0x94, 0x4F, +0xA4, 0xD0, 0xA4, 0xD1, 0x94, 0x4F, 0x9C, 0x6F, +0x9C, 0x8F, 0xA4, 0xD1, 0x94, 0x4F, 0xA4, 0xD0, +0x8C, 0x2E, 0x8C, 0x0E, 0x7B, 0xAD, 0x8C, 0x0F, +0xA5, 0x12, 0xB5, 0x73, 0xBD, 0xB5, 0xBD, 0x94, +0xBD, 0x94, 0xBD, 0x94, 0xBD, 0x94, 0xB5, 0x53, +0xAD, 0x33, 0xAD, 0x33, 0xAD, 0x13, 0xA4, 0xF2, +0xA4, 0xF2, 0xA4, 0xD2, 0x9C, 0xD2, 0x9C, 0x91, +0x94, 0x70, 0x8C, 0x2F, 0x94, 0x4F, 0x8C, 0x0E, +0x8C, 0xEF, 0x7C, 0x8E, 0xAD, 0xF5, 0x9D, 0x93, +0x8D, 0x31, 0x7C, 0xAD, 0x64, 0x09, 0x74, 0x49, +0x85, 0x0C, 0x63, 0xC7, 0x4B, 0x43, 0x63, 0xE5, +0x6B, 0xE7, 0x6B, 0xC8, 0x8C, 0x8B, 0x6B, 0x87, +0x8C, 0x8D, 0xAD, 0x72, 0xB5, 0x73, 0xB5, 0x73, +0xBD, 0xD4, 0x7B, 0xCD, 0x4A, 0x68, 0x63, 0x0B, +0x6B, 0x2C, 0x6B, 0x4C, 0x6B, 0x2C, 0x5A, 0xAB, +0x8C, 0x71, 0x9C, 0xF3, 0xC6, 0x39, 0xE6, 0xFC, +0xDE, 0xFB, 0xD6, 0xBA, 0x9C, 0xD2, 0x73, 0x6D, +0x9C, 0xB2, 0xAD, 0x53, 0x83, 0xCC, 0xA4, 0x8F, +0xB5, 0x73, 0xC5, 0xF5, 0xC6, 0x16, 0xC6, 0x16, +0xC6, 0x15, 0xBD, 0xF5, 0xBD, 0xD4, 0xBD, 0xD4, +0xBD, 0xD4, 0xC5, 0xF5, 0xC6, 0x15, 0xD6, 0x56, +0xC5, 0xD4, 0xB5, 0x93, 0xBD, 0x93, 0xB5, 0x93, +0xBD, 0xB3, 0xB5, 0x73, 0xBD, 0xD4, 0xB5, 0x73, +0xC5, 0xF4, 0xC5, 0xB2, 0xAC, 0xAE, 0xA4, 0xF0, +0xBD, 0xB3, 0xB5, 0x72, 0xA4, 0xF1, 0xA4, 0xF1, +0xA4, 0xD0, 0xA4, 0xF1, 0xB5, 0x73, 0xA4, 0xF1, +0x9C, 0x8F, 0x9C, 0x8F, 0x9C, 0x8F, 0xA4, 0xD0, +0xAD, 0x32, 0x94, 0x90, 0x83, 0xEE, 0x84, 0x0E, +0x7B, 0x8D, 0x5A, 0xAA, 0x84, 0x10, 0xAD, 0x55, +0xD6, 0x9A, 0xB5, 0xB7, 0xC5, 0xF8, 0xDE, 0xDB, +0xAD, 0x35, 0xAD, 0x14, 0x52, 0x8A, 0x42, 0x08, +0x52, 0xAA, 0x4A, 0x69, 0x62, 0xEC, 0x7B, 0xAE, +0xAD, 0x55, 0x94, 0x71, 0x94, 0x92, 0xC5, 0xF8, +0xAD, 0x76, 0xA5, 0x35, 0xC5, 0xF8, 0xBD, 0xD7, +0xCE, 0x39, 0xBD, 0xD7, 0x9C, 0xF3, 0xB5, 0x95, +0x94, 0x4F, 0xD6, 0x13, 0xDE, 0x34, 0xD5, 0xF3, +0xB5, 0x2F, 0xC5, 0x91, 0xDE, 0x33, 0xDE, 0x74, +0xE6, 0xB5, 0xDE, 0x74, 0xE6, 0x95, 0xE6, 0x95, +0xD6, 0x33, 0xB5, 0x30, 0xBD, 0x30, 0xB5, 0x10, +0xAC, 0xAE, 0xB5, 0x10, 0xB5, 0x30, 0xAC, 0xEF, +0xBD, 0x50, 0xBD, 0x50, 0xC5, 0x51, 0xBD, 0x51, +0xB5, 0x10, 0x9C, 0x6F, 0x62, 0xEA, 0x42, 0x07, +0x42, 0x07, 0x42, 0x27, 0x39, 0xE6, 0x4A, 0x68, +0x52, 0xA9, 0x5A, 0xAA, 0x5A, 0xCB, 0x63, 0x2C, +0x6B, 0x4D, 0x7B, 0xCF, 0x9C, 0xF3, 0x94, 0x92, +0x73, 0xAE, 0xA5, 0x55, 0xBD, 0xF6, 0xBD, 0x73, +0xBD, 0x52, 0xB5, 0x11, 0x9C, 0xB0, 0x9C, 0xB1, +0x94, 0x4F, 0xAD, 0x12, 0xBD, 0x94, 0x9C, 0xB0, +0xB5, 0x94, 0xBD, 0xD4, 0xAD, 0x53, 0xAD, 0x12, +0xB5, 0x74, 0xBD, 0xB4, 0xB5, 0x73, 0xAD, 0x53, +0xAD, 0x32, 0xBD, 0xB4, 0xBD, 0xB4, 0xC6, 0x15, +0xD6, 0x77, 0xCE, 0x56, 0xCE, 0x56, 0xD6, 0x97, +0xCE, 0x77, 0xC6, 0x36, 0xC6, 0x15, 0xA4, 0xF0, +0x9C, 0x6F, 0xB5, 0x52, 0xB5, 0x32, 0xBD, 0x72, +0xD6, 0x14, 0xD6, 0x14, 0xD6, 0x34, 0xE6, 0x75, +0xDE, 0x75, 0xDE, 0x54, 0xDE, 0x54, 0xDE, 0x75, +0xDE, 0x54, 0xCD, 0xF3, 0xAC, 0xF0, 0xA4, 0xF1, +0xA5, 0x11, 0xA4, 0xF1, 0xB5, 0x74, 0xC6, 0x15, +0xCE, 0x36, 0xD6, 0x56, 0xC5, 0xF5, 0xC5, 0xF5, +0xCE, 0x15, 0xD6, 0x76, 0xBD, 0xB4, 0x9C, 0x8F, +0xB5, 0x11, 0xCD, 0xD4, 0xC5, 0xB3, 0xBD, 0x52, +0xAC, 0xF0, 0xAC, 0xF1, 0x9C, 0x8F, 0xA4, 0xD0, +0xA4, 0xB0, 0xA4, 0xB0, 0xA4, 0xAF, 0xA4, 0xAF, +0xA4, 0xCF, 0xAC, 0xF0, 0xAC, 0xF0, 0xA4, 0xAF, +0xAC, 0xF0, 0xBD, 0x31, 0xBD, 0x51, 0xB5, 0x31, +0xAC, 0xF0, 0xA4, 0xAF, 0x94, 0x4E, 0xAD, 0x11, +0xAD, 0x31, 0xB5, 0x72, 0xAD, 0x32, 0x5A, 0xCA, +0x31, 0x85, 0x29, 0x44, 0x29, 0x44, 0x29, 0x65, +0x31, 0xA6, 0x31, 0xA6, 0x39, 0xC7, 0x42, 0x07, +0x31, 0x85, 0x39, 0x86, 0x4A, 0x28, 0x73, 0x4D, +0x83, 0xAE, 0x62, 0xEB, 0x62, 0xCB, 0x83, 0xAE, +0x73, 0x4C, 0x6B, 0x0C, 0x9C, 0x91, 0xAC, 0xF3, +0xB5, 0x32, 0xF6, 0xF8, 0xE6, 0xB6, 0xDE, 0x75, +0xDE, 0x55, 0xDE, 0x75, 0xDE, 0x55, 0xD6, 0x14, +0xDE, 0x55, 0xDE, 0x76, 0xB5, 0x31, 0xDE, 0xB7, +0xDE, 0xB8, 0xDE, 0xB8, 0xBD, 0x95, 0x29, 0x45, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0x82, 0x10, 0x82, +0x10, 0xA3, 0x10, 0xC3, 0x10, 0xC3, 0x21, 0x04, +0x8C, 0x0F, 0xBD, 0x94, 0xD6, 0x97, 0xCE, 0x35, +0xC5, 0xD4, 0xCE, 0x56, 0xCE, 0x15, 0xC5, 0xD4, +0xBD, 0xB4, 0xBD, 0x93, 0xAD, 0x12, 0xAD, 0x32, +0xAD, 0x12, 0xA4, 0xF1, 0x9C, 0xB0, 0xA4, 0xF1, +0x9C, 0xD0, 0x94, 0x8F, 0x9C, 0xD0, 0xA4, 0xF1, +0xA4, 0xD1, 0xA4, 0xF1, 0xA5, 0x12, 0x9C, 0xD1, +0x9C, 0x90, 0xA4, 0xD1, 0xA4, 0xD1, 0xA4, 0xF1, +0xB5, 0x53, 0xAD, 0x33, 0xAD, 0x12, 0xA4, 0xD1, +0xA4, 0xD1, 0x9C, 0xB0, 0x9C, 0xB0, 0xA4, 0xF1, +0xA4, 0xF1, 0xA4, 0xD1, 0xAD, 0x12, 0xAD, 0x12, +0x74, 0x4D, 0x5B, 0x8A, 0x74, 0x4E, 0x7C, 0xAF, +0x8D, 0x50, 0x84, 0xED, 0x6C, 0x49, 0x64, 0x06, +0x74, 0x68, 0x74, 0x69, 0x43, 0x02, 0x74, 0x48, +0x63, 0xC7, 0x53, 0x66, 0x5B, 0x86, 0x7C, 0x49, +0xB5, 0xD1, 0xB5, 0x72, 0xC6, 0x35, 0xC6, 0x15, +0xC6, 0x15, 0xBD, 0xB4, 0xAD, 0x33, 0x5A, 0xAA, +0x41, 0xE7, 0x4A, 0x28, 0x42, 0x08, 0x4A, 0x29, +0x7B, 0xEF, 0x9C, 0xF4, 0xC6, 0x39, 0xA5, 0x35, +0xAD, 0x55, 0xEF, 0x5D, 0xE7, 0x1C, 0xC6, 0x18, +0xAD, 0x55, 0x73, 0x8D, 0x94, 0x4F, 0xA4, 0xAF, +0xB5, 0x52, 0xBD, 0xD4, 0xC6, 0x15, 0xCE, 0x36, +0xCE, 0x36, 0xBD, 0xD4, 0xBD, 0xF5, 0xCE, 0x36, +0xC6, 0x15, 0xC5, 0xF4, 0xC6, 0x15, 0xCE, 0x56, +0xCE, 0x35, 0xC5, 0xF4, 0xC5, 0xF5, 0xC6, 0x15, +0xCE, 0x56, 0xBD, 0xF4, 0xC5, 0xF5, 0xB5, 0x73, +0xBD, 0xB3, 0xB5, 0x50, 0xAC, 0xEF, 0xA4, 0xAF, +0xB5, 0x93, 0xBD, 0xB3, 0xAD, 0x32, 0xA4, 0xF1, +0xA5, 0x11, 0xB5, 0x93, 0xAD, 0x32, 0xA5, 0x11, +0x9C, 0x8F, 0x94, 0x6F, 0x9C, 0x8F, 0x9C, 0xAF, +0xB5, 0x73, 0xAD, 0x53, 0x8C, 0x0E, 0x83, 0xEE, +0x8C, 0x2E, 0x8C, 0x4F, 0x6B, 0x2B, 0x73, 0xAE, +0x94, 0x72, 0x8C, 0x72, 0x94, 0x92, 0xA5, 0x14, +0x9C, 0xD3, 0xDE, 0xDB, 0xB5, 0x96, 0x52, 0x8A, +0x21, 0x24, 0x29, 0x45, 0x42, 0x28, 0x62, 0xEB, +0x7B, 0xCF, 0x62, 0xEC, 0xAD, 0x55, 0xB5, 0x96, +0x94, 0xB3, 0xB5, 0x96, 0xCE, 0x39, 0xAD, 0x35, +0x83, 0xF0, 0x73, 0xAF, 0x84, 0x31, 0xB5, 0x75, +0xA4, 0xF3, 0xB5, 0x54, 0xCD, 0xD3, 0xDE, 0x54, +0xC5, 0xB1, 0xCD, 0xB1, 0xD6, 0x34, 0xDE, 0x54, +0xD6, 0x13, 0xD6, 0x33, 0xDE, 0x74, 0xDE, 0x33, +0xCD, 0xB1, 0xAC, 0xCE, 0xC5, 0xB2, 0xAC, 0xEF, +0x8B, 0xEB, 0xAD, 0x0F, 0xBD, 0x51, 0xB5, 0x30, +0xD5, 0xF3, 0xCD, 0x92, 0xD5, 0xF3, 0xC5, 0x92, +0xC5, 0x92, 0xA4, 0xD0, 0x9C, 0x8F, 0x52, 0x68, +0x39, 0xC6, 0x31, 0x85, 0x42, 0x07, 0x4A, 0x48, +0x52, 0x89, 0x5A, 0xEB, 0x63, 0x0B, 0x63, 0x2C, +0x6B, 0x6D, 0x8C, 0x51, 0x8C, 0x51, 0x8C, 0x30, +0x6B, 0x6D, 0xA5, 0x34, 0xCE, 0x58, 0xC5, 0xB3, +0xC5, 0x93, 0xA4, 0xAF, 0xA4, 0xD0, 0xA4, 0xD1, +0xAD, 0x32, 0xA4, 0xF1, 0xBD, 0x94, 0xBD, 0x94, +0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x53, +0xAD, 0x32, 0xAC, 0xF2, 0xAD, 0x12, 0xAD, 0x12, +0xAD, 0x12, 0xA4, 0xB1, 0x9C, 0xB0, 0xA4, 0xD1, +0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x11, +0xAD, 0x73, 0xAD, 0x52, 0xBD, 0xB4, 0x9C, 0xB0, +0x9C, 0x8F, 0xAD, 0x11, 0xA4, 0xB0, 0xB5, 0x11, +0xB4, 0xF0, 0xAC, 0xF0, 0xB5, 0x30, 0xC5, 0x71, +0xBD, 0x51, 0xB4, 0xF0, 0xC5, 0x72, 0xCD, 0xD3, +0xC5, 0xB2, 0xC5, 0x92, 0xAC, 0xF0, 0xA4, 0xD0, +0x8C, 0x2E, 0x8C, 0x2E, 0xA4, 0xD1, 0xC5, 0xD4, +0xCE, 0x35, 0xC5, 0xF5, 0xBD, 0x93, 0xCE, 0x36, +0xD6, 0x77, 0xCE, 0x36, 0xB5, 0x32, 0x9C, 0x8F, +0xBD, 0x52, 0xD6, 0x35, 0xD6, 0x35, 0xCD, 0xD3, +0xBD, 0x93, 0xA4, 0xD0, 0x8B, 0xED, 0xA4, 0xD0, +0x94, 0x0D, 0x9C, 0x8F, 0xA4, 0xAF, 0xA4, 0xAF, +0xA4, 0xAF, 0xA4, 0xCF, 0xAC, 0xF0, 0xAC, 0xF0, +0xAC, 0xF0, 0xAC, 0xF0, 0xB5, 0x10, 0xAC, 0xCF, +0x9C, 0x8E, 0x9C, 0x8F, 0xA4, 0xAF, 0xAC, 0xF0, +0xAC, 0xF0, 0xAD, 0x11, 0xA4, 0xF0, 0xAD, 0x32, +0x9C, 0xB0, 0x6B, 0x2B, 0x42, 0x07, 0x29, 0x44, +0x29, 0x65, 0x39, 0xE6, 0x42, 0x07, 0x41, 0xE7, +0x4A, 0x48, 0x39, 0xC6, 0x29, 0x45, 0x39, 0x86, +0x5A, 0x8A, 0x83, 0xAE, 0x4A, 0x08, 0x5A, 0x69, +0x83, 0xAE, 0x73, 0x4D, 0x5A, 0x69, 0x83, 0xEF, +0xA4, 0xB2, 0xAC, 0xD1, 0xCD, 0xB4, 0xD6, 0x14, +0xDE, 0x76, 0xE6, 0x76, 0xDE, 0x55, 0xDE, 0x35, +0xE6, 0x76, 0xD6, 0x14, 0xC5, 0x93, 0xE6, 0xB7, +0xE6, 0xD8, 0xDE, 0xB7, 0x9C, 0x90, 0x29, 0x04, +0x10, 0xA3, 0x10, 0x82, 0x10, 0xA3, 0x10, 0x82, +0x10, 0xA3, 0x18, 0xC3, 0x18, 0xE4, 0x29, 0x65, +0x9C, 0x91, 0xBD, 0xB4, 0xD6, 0x56, 0xD6, 0x56, +0xC5, 0xD4, 0xCE, 0x15, 0xBD, 0x93, 0xC6, 0x15, +0xCE, 0x35, 0xCE, 0x15, 0xC5, 0xD5, 0xBD, 0xD4, +0xB5, 0x93, 0xBD, 0x94, 0xAD, 0x53, 0xBD, 0x93, +0xB5, 0x73, 0xB5, 0x93, 0xAD, 0x32, 0xB5, 0x53, +0xB5, 0x73, 0xBD, 0xB4, 0xBD, 0xD5, 0xC5, 0xD5, +0xA4, 0xF1, 0xA4, 0xF1, 0xA4, 0xD0, 0xAD, 0x11, +0xCD, 0xD4, 0xC5, 0xB3, 0xC5, 0xB3, 0xC5, 0xB3, +0xC5, 0xD4, 0xC5, 0xB3, 0xC5, 0x93, 0xCD, 0xD4, +0xCD, 0xD4, 0xC5, 0x93, 0xC5, 0xB3, 0xC5, 0xB3, +0x53, 0x48, 0x4B, 0x48, 0x5B, 0xCA, 0x64, 0x0B, +0x85, 0x0E, 0xA5, 0xD0, 0x74, 0x8A, 0x5B, 0xE5, +0x5B, 0xE5, 0x53, 0x64, 0x63, 0xE6, 0x74, 0x48, +0x63, 0xC7, 0x53, 0x86, 0x8C, 0xCB, 0xA5, 0x2D, +0x9C, 0xCD, 0x8C, 0x2C, 0x9C, 0x8F, 0x9C, 0x8F, +0xA4, 0xCF, 0xAD, 0x10, 0xAD, 0x11, 0x73, 0x6B, +0x39, 0xC5, 0x39, 0xC6, 0x42, 0x07, 0x4A, 0x28, +0x5A, 0xCB, 0x84, 0x30, 0xA5, 0x35, 0x7B, 0xF0, +0xBD, 0xD7, 0xDE, 0xBB, 0xDE, 0xBB, 0xCE, 0x7A, +0x9C, 0xF4, 0x8C, 0x30, 0xA4, 0xD1, 0xB5, 0x51, +0xCE, 0x35, 0xCE, 0x35, 0xCE, 0x56, 0xCE, 0x35, +0xCE, 0x36, 0xC6, 0x35, 0xCE, 0x36, 0xCE, 0x77, +0xCE, 0x77, 0xCE, 0x36, 0xC6, 0x36, 0xCE, 0x56, +0xCE, 0x36, 0xCE, 0x56, 0xCE, 0x56, 0xCE, 0x56, +0xD6, 0x77, 0xCE, 0x56, 0xD6, 0x77, 0xCE, 0x36, +0xCE, 0x15, 0xB5, 0x51, 0xAC, 0xEF, 0x9C, 0xAF, +0xB5, 0x72, 0xAD, 0x52, 0x9C, 0xD0, 0xA4, 0xF1, +0xAD, 0x32, 0xB5, 0x53, 0x9C, 0xD0, 0xA4, 0xF1, +0x8C, 0x2E, 0x9C, 0xB0, 0x9C, 0xD0, 0x94, 0x8F, +0xAD, 0x53, 0xAD, 0x52, 0x8C, 0x2E, 0x8C, 0x2E, +0xA4, 0xF1, 0xB5, 0x73, 0xA4, 0xF2, 0x7B, 0xAD, +0x52, 0x8A, 0x7B, 0xAF, 0x84, 0x10, 0x9C, 0xD3, +0x5A, 0xCB, 0x9C, 0xD3, 0xDE, 0xBB, 0xBD, 0xB7, +0xA4, 0xF4, 0x63, 0x0C, 0x31, 0x86, 0x4A, 0x49, +0x6B, 0x4D, 0x73, 0x6E, 0xAD, 0x76, 0x9C, 0xD3, +0x9C, 0xD3, 0xBD, 0xD7, 0xA5, 0x14, 0x9C, 0xB3, +0x9C, 0xF4, 0xB5, 0x96, 0xC6, 0x18, 0xCE, 0x59, +0xD6, 0x9A, 0xE7, 0x1C, 0xDE, 0xB9, 0xA4, 0xD1, +0x7B, 0x8B, 0xC5, 0xD3, 0xD5, 0xF3, 0xCD, 0xF2, +0xD5, 0xF2, 0xD6, 0x33, 0xD6, 0x12, 0xD6, 0x13, +0xC5, 0x71, 0xB5, 0x10, 0xAD, 0x10, 0xB5, 0x30, +0xAD, 0x10, 0xAC, 0xEF, 0xB5, 0x30, 0xC5, 0xB2, +0xCD, 0x91, 0xB5, 0x10, 0x7B, 0x6A, 0x94, 0x6E, +0x9C, 0x6F, 0x6B, 0x0A, 0x94, 0x4E, 0x62, 0xE9, +0x39, 0xC6, 0x29, 0x44, 0x31, 0x64, 0x41, 0xE6, +0x52, 0x89, 0x62, 0xEB, 0x5A, 0xEB, 0x5A, 0xEB, +0x73, 0x8E, 0x84, 0x10, 0x73, 0x8E, 0x6B, 0x2C, +0x94, 0x92, 0xBD, 0xD7, 0xB5, 0xB6, 0xC5, 0xD5, +0x9C, 0x6F, 0x94, 0x2E, 0xAD, 0x11, 0xB5, 0x11, +0xAD, 0x11, 0x94, 0x2E, 0xA4, 0xB0, 0xB5, 0x53, +0x9C, 0xB0, 0x94, 0x4F, 0x94, 0x2E, 0xA4, 0xB0, +0xB5, 0x53, 0xBD, 0x53, 0xAD, 0x12, 0xA4, 0xF1, +0xB5, 0x32, 0xB5, 0x52, 0xBD, 0x93, 0xBD, 0x93, +0xB5, 0x32, 0xB5, 0x52, 0xBD, 0x93, 0xBD, 0x73, +0xB5, 0x73, 0xBD, 0x73, 0xB5, 0x53, 0xB5, 0x32, +0xBD, 0x94, 0xBD, 0x94, 0xBD, 0x94, 0xBD, 0x94, +0xBD, 0x93, 0xBD, 0x93, 0xBD, 0x73, 0xBD, 0x52, +0xB5, 0x32, 0xB5, 0x32, 0xAC, 0xF1, 0xAD, 0x11, +0xB5, 0x31, 0xBD, 0x72, 0xBD, 0x73, 0xC5, 0xD5, +0xC5, 0xD5, 0xC5, 0xB4, 0xAD, 0x12, 0xA4, 0xB0, +0x9C, 0x8F, 0x94, 0x2E, 0x83, 0xED, 0x8C, 0x0E, +0x94, 0x2F, 0x8C, 0x0E, 0x8C, 0x0E, 0x8C, 0x0D, +0x9C, 0x6F, 0xBD, 0x93, 0xD6, 0x35, 0xBD, 0x72, +0xAC, 0xF0, 0x9C, 0x6E, 0x94, 0x2D, 0x9C, 0x6F, +0x83, 0xCC, 0x8B, 0xED, 0x9C, 0x6E, 0xA4, 0x8F, +0xA4, 0xCF, 0xA4, 0xAF, 0xAD, 0x10, 0xAD, 0x10, +0xA4, 0xCF, 0xA4, 0x8F, 0xA4, 0x8F, 0xA4, 0x8F, +0x9C, 0x6E, 0x9C, 0x6E, 0x9C, 0x8F, 0xA4, 0xCF, +0x9C, 0xAF, 0xB5, 0x51, 0xAD, 0x31, 0xB5, 0x72, +0xA5, 0x11, 0xA5, 0x11, 0x9C, 0xD1, 0x5A, 0xCA, +0x31, 0x65, 0x31, 0x85, 0x31, 0xA6, 0x39, 0xE6, +0x52, 0x69, 0x4A, 0x28, 0x29, 0x45, 0x29, 0x04, +0x31, 0x65, 0x4A, 0x28, 0x52, 0x89, 0x41, 0xE7, +0x62, 0xAA, 0x7B, 0x4D, 0x62, 0xAA, 0x52, 0x49, +0x8B, 0xEF, 0xA4, 0x92, 0x94, 0x30, 0x9C, 0x2F, +0xD6, 0x36, 0xD6, 0x35, 0xCD, 0xD3, 0xCD, 0xD4, +0xCD, 0xD3, 0xD6, 0x14, 0xD6, 0x35, 0xE6, 0xD7, +0xE6, 0xD7, 0xD6, 0x35, 0x7B, 0x8D, 0x21, 0x04, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC3, 0x18, 0xE4, 0x73, 0x6D, +0xAD, 0x33, 0xC5, 0xD4, 0xD6, 0x56, 0xCE, 0x35, +0xC5, 0xD4, 0xCE, 0x15, 0xB5, 0x73, 0xAD, 0x32, +0xC5, 0xD4, 0xCE, 0x15, 0xC5, 0xF5, 0xCE, 0x15, +0xC5, 0xD5, 0xBD, 0xD4, 0xBD, 0xB4, 0xC5, 0xF5, +0xBD, 0xD4, 0xC5, 0xF5, 0xB5, 0x93, 0xC5, 0xF5, +0xBD, 0xB4, 0xBD, 0xB4, 0xC5, 0xF5, 0xC5, 0xF5, +0xA4, 0xF1, 0xB5, 0x52, 0xD6, 0x35, 0xE6, 0x76, +0xD6, 0x15, 0xD6, 0x34, 0xD6, 0x35, 0xD6, 0x15, +0xDE, 0x35, 0xD6, 0x35, 0xD6, 0x35, 0xD6, 0x15, +0xDE, 0x76, 0xDE, 0x55, 0xD6, 0x14, 0xDE, 0x55, +0x84, 0xAD, 0x6C, 0x4C, 0x7C, 0xAE, 0x63, 0xEB, +0x5B, 0xA8, 0x74, 0xAB, 0x74, 0x8A, 0x63, 0xE6, +0x53, 0x84, 0x4B, 0x24, 0x6C, 0x27, 0x6B, 0xE7, +0x6B, 0xE7, 0x7C, 0x6A, 0x9C, 0xED, 0xA4, 0xCD, +0xA4, 0x8E, 0x9C, 0x8D, 0xA4, 0x8E, 0xAC, 0xEF, +0xB5, 0x10, 0xAC, 0xEF, 0xA4, 0xAE, 0xA4, 0xAF, +0xA4, 0x8F, 0x6B, 0x09, 0x39, 0xC5, 0x39, 0xE7, +0x42, 0x28, 0x5A, 0xCB, 0x6B, 0x4D, 0x8C, 0x51, +0x9C, 0xB3, 0x94, 0x92, 0xC6, 0x18, 0xDE, 0xBB, +0xC6, 0x39, 0x9C, 0xD2, 0xBD, 0x94, 0xAD, 0x10, +0xB5, 0x51, 0xBD, 0x71, 0xBD, 0x72, 0xB5, 0x71, +0xAD, 0x30, 0xAC, 0xF0, 0xAD, 0x31, 0xB5, 0x72, +0xBD, 0xB3, 0xBD, 0xB3, 0xBD, 0x93, 0xB5, 0x73, +0xBD, 0xB4, 0xC6, 0x15, 0xC6, 0x35, 0xCE, 0x56, +0xCE, 0x76, 0xD6, 0x77, 0xD6, 0x97, 0xCE, 0x56, +0xCE, 0x15, 0xAC, 0xF0, 0xAC, 0xAE, 0xA4, 0xCF, +0xB5, 0x72, 0xB5, 0x73, 0xA5, 0x11, 0xA5, 0x11, +0xB5, 0x73, 0xB5, 0x73, 0xAD, 0x32, 0xA5, 0x11, +0x9C, 0xD0, 0xA4, 0xF1, 0xA5, 0x12, 0xA4, 0xF1, +0xAD, 0x32, 0xAD, 0x73, 0x94, 0x8F, 0x94, 0x6F, +0x9C, 0xF1, 0xAD, 0x12, 0x9C, 0x90, 0x9C, 0x90, +0x6B, 0x4C, 0x42, 0x28, 0x6B, 0x4D, 0x9C, 0xB2, +0x83, 0xF0, 0x9C, 0xD3, 0xBD, 0xB7, 0xC5, 0xF8, +0xE7, 0x1C, 0xB5, 0x76, 0x9C, 0xB3, 0x8C, 0x51, +0xA5, 0x34, 0x9C, 0xD3, 0xA5, 0x34, 0x8C, 0x51, +0x7B, 0xAF, 0xC5, 0xF8, 0x7B, 0xAF, 0x8C, 0x51, +0xC6, 0x39, 0xBD, 0xD8, 0xAD, 0x35, 0x94, 0x72, +0x83, 0xF0, 0xC6, 0x39, 0xC5, 0xF7, 0x94, 0x92, +0x5A, 0xAA, 0x8C, 0x2E, 0xD6, 0x34, 0xD6, 0x13, +0xD6, 0x34, 0xD6, 0x13, 0xCE, 0x13, 0xD6, 0x33, +0xBD, 0x71, 0xB5, 0x30, 0xB5, 0x30, 0xC5, 0xB2, +0xBD, 0x71, 0xAD, 0x10, 0xBD, 0x51, 0xC5, 0x71, +0xB4, 0xEF, 0xAC, 0xCF, 0x73, 0x2A, 0x8C, 0x0D, +0x94, 0x4E, 0x94, 0x4E, 0x8C, 0x0D, 0x83, 0xCC, +0x52, 0x88, 0x39, 0xA5, 0x29, 0x64, 0x31, 0xA5, +0x42, 0x27, 0x52, 0x89, 0x5A, 0xCA, 0x63, 0x2C, +0x73, 0x8E, 0x63, 0x2C, 0x4A, 0x49, 0x73, 0x8E, +0x94, 0xB2, 0x9C, 0xF4, 0xA4, 0xF4, 0xCE, 0x38, +0x9C, 0x91, 0x94, 0x6F, 0xBD, 0x72, 0xBD, 0x92, +0xC5, 0x92, 0xBD, 0x73, 0xCD, 0xF4, 0xB5, 0x32, +0x94, 0x6F, 0xB5, 0x33, 0xAD, 0x12, 0x94, 0x4F, +0xB5, 0x73, 0xC5, 0xD5, 0xBD, 0x94, 0x9C, 0xB0, +0x7B, 0x8C, 0x83, 0xED, 0x8B, 0xED, 0x94, 0x6E, +0xBD, 0x93, 0xC5, 0xB4, 0xD6, 0x56, 0xC5, 0xB4, +0xA4, 0xD0, 0xA4, 0xD1, 0xBD, 0x73, 0xBD, 0x52, +0xBD, 0x73, 0xBD, 0x73, 0xB5, 0x32, 0xAD, 0x11, +0xBD, 0x72, 0xB5, 0x31, 0xBD, 0x52, 0xBD, 0x73, +0xC5, 0x93, 0xC5, 0x93, 0xBD, 0x52, 0xBD, 0x52, +0xBD, 0x52, 0xB5, 0x31, 0xC5, 0x93, 0xC5, 0x94, +0xBD, 0x73, 0xC5, 0x93, 0xC5, 0x94, 0xC5, 0xB4, +0xB5, 0x53, 0xAD, 0x12, 0x9C, 0xB0, 0xA4, 0xB0, +0xBD, 0x53, 0xB5, 0x53, 0xBD, 0x74, 0xB5, 0x33, +0xA4, 0xB0, 0x94, 0x2E, 0x8B, 0xED, 0x8B, 0xCC, +0x83, 0xCC, 0x7B, 0x8B, 0x83, 0xAC, 0x8B, 0xCC, +0x7B, 0x6B, 0x73, 0x4A, 0x83, 0xAB, 0x83, 0xEC, +0x8C, 0x0D, 0x94, 0x4E, 0x9C, 0x8F, 0x94, 0x4E, +0x8B, 0xCC, 0x83, 0xAC, 0x83, 0x8B, 0x83, 0xCC, +0x94, 0x4E, 0x9C, 0xAF, 0xA4, 0xD0, 0x9C, 0xAF, +0x94, 0x4E, 0xAD, 0x10, 0xBD, 0x93, 0xBD, 0xB3, +0xB5, 0x72, 0xBD, 0xB3, 0xC6, 0x15, 0xBD, 0xD4, +0x8C, 0x4F, 0x4A, 0x27, 0x31, 0xA6, 0x39, 0xC6, +0x39, 0xA6, 0x31, 0x85, 0x31, 0x85, 0x29, 0x45, +0x29, 0x24, 0x29, 0x04, 0x41, 0xE7, 0x5A, 0xAA, +0x4A, 0x28, 0x6A, 0xEB, 0x62, 0xCA, 0x73, 0x4C, +0x94, 0x30, 0x9C, 0x71, 0xA4, 0xD2, 0x83, 0xAE, +0x8B, 0xCE, 0xA4, 0xB0, 0x9C, 0x8F, 0x9C, 0x6F, +0xAD, 0x11, 0xBD, 0x73, 0xB5, 0x52, 0xD6, 0x56, +0xDE, 0x56, 0xB5, 0x32, 0x4A, 0x08, 0x18, 0xC4, +0x10, 0xA2, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC3, 0x29, 0x45, 0x9C, 0xD2, +0xB5, 0x53, 0xBD, 0xB4, 0xD6, 0x56, 0xCE, 0x15, +0xC5, 0xF5, 0xCE, 0x15, 0xB5, 0x52, 0xAD, 0x32, +0xC5, 0xD4, 0xC5, 0xD4, 0xC5, 0xD4, 0xC5, 0xF4, +0xCE, 0x36, 0xC5, 0xF5, 0xAD, 0x52, 0xC5, 0xF5, +0xC5, 0xF5, 0xC5, 0xF5, 0xBD, 0xB4, 0xC5, 0xF5, +0xB5, 0x93, 0xBD, 0xF5, 0xCE, 0x15, 0xCE, 0x15, +0xA4, 0xD1, 0xB5, 0x52, 0xD6, 0x35, 0xDE, 0x55, +0xD6, 0x14, 0xD6, 0x35, 0xD6, 0x35, 0xD6, 0x15, +0xD6, 0x15, 0xCD, 0xF4, 0xBD, 0x72, 0xDE, 0x35, +0xD6, 0x15, 0xD6, 0x35, 0xD6, 0x35, 0xD6, 0x35, +0x84, 0xAD, 0x64, 0x0B, 0x74, 0x8D, 0x74, 0x8C, +0x53, 0x66, 0x4B, 0x66, 0x6C, 0x2A, 0x64, 0x08, +0x63, 0xE7, 0x6B, 0xE7, 0x63, 0xA6, 0x6B, 0xE7, +0x95, 0x2D, 0xA5, 0x4F, 0xBD, 0xB2, 0xC5, 0xD3, +0xCD, 0xF3, 0xC5, 0xB2, 0xC5, 0xB2, 0xD6, 0x55, +0xDE, 0x55, 0xCD, 0xD3, 0xA4, 0x8E, 0xA4, 0xAF, +0xAC, 0xCF, 0xA4, 0xCF, 0x83, 0xCC, 0x4A, 0x27, +0x39, 0xC6, 0x42, 0x28, 0x52, 0x8A, 0x52, 0xAA, +0x84, 0x10, 0x6B, 0x6D, 0x52, 0x8A, 0x8C, 0x51, +0x84, 0x30, 0x4A, 0x69, 0x7B, 0xAD, 0xCE, 0x16, +0xA4, 0xAF, 0xAC, 0xAF, 0xB5, 0x10, 0xB5, 0x30, +0xB5, 0x10, 0xB5, 0x30, 0xAC, 0xCF, 0xAC, 0xCF, +0xA4, 0xAE, 0xA4, 0xAE, 0xAC, 0xCF, 0xAC, 0xCF, +0xA4, 0xCF, 0xA4, 0x8F, 0xA4, 0x8E, 0x9C, 0x4E, +0x9C, 0x4D, 0x9C, 0x2D, 0x9C, 0x2D, 0x9C, 0x4D, +0x9C, 0x4C, 0xA4, 0x6D, 0xAC, 0xAE, 0x9C, 0x8E, +0xAD, 0x10, 0xB5, 0x52, 0xAD, 0x31, 0xAD, 0x32, +0xAD, 0x31, 0x9C, 0xAF, 0xAD, 0x31, 0xA4, 0xF0, +0xA4, 0xD0, 0xAD, 0x31, 0xB5, 0x52, 0xB5, 0x93, +0xB5, 0x93, 0xBD, 0xB4, 0xA5, 0x11, 0xA4, 0xF1, +0xA4, 0xD0, 0x94, 0x6F, 0x9C, 0xB0, 0x9C, 0xB0, +0x94, 0x8F, 0x7B, 0x8C, 0x73, 0x4C, 0x73, 0x6D, +0x5A, 0xCB, 0xA5, 0x14, 0xBD, 0x96, 0xDE, 0xBB, +0xA5, 0x14, 0x94, 0x92, 0x7B, 0xAF, 0x9C, 0xB3, +0x9C, 0xF4, 0xA5, 0x14, 0x84, 0x10, 0x6B, 0x2D, +0x31, 0xA6, 0x94, 0xB3, 0xCE, 0x39, 0xB5, 0x96, +0xC5, 0xF8, 0xA4, 0xF4, 0xAD, 0x35, 0xB5, 0x76, +0xA5, 0x14, 0xCE, 0x39, 0xDE, 0xDB, 0xC6, 0x39, +0x7B, 0xEF, 0x73, 0x8E, 0xBD, 0x93, 0xCD, 0xF3, +0xCD, 0xF3, 0xD6, 0x14, 0xC5, 0x92, 0xCD, 0xB2, +0xAC, 0xEF, 0xAD, 0x30, 0xAD, 0x10, 0xA4, 0xCF, +0xB5, 0x31, 0xB5, 0x30, 0xB5, 0x10, 0xB4, 0xEF, +0x9C, 0x4D, 0xA4, 0x8E, 0x8B, 0xEC, 0xAC, 0xF0, +0xA4, 0xCF, 0x9C, 0x6E, 0x9C, 0x8F, 0xAC, 0xF0, +0x8C, 0x0D, 0x42, 0x07, 0x31, 0x85, 0x31, 0x85, +0x41, 0xE6, 0x42, 0x07, 0x42, 0x28, 0x52, 0x8A, +0x4A, 0x48, 0x4A, 0x68, 0x63, 0x0B, 0x83, 0xEF, +0x84, 0x10, 0x94, 0x92, 0xA5, 0x14, 0xBD, 0xD7, +0xCE, 0x59, 0xA4, 0xF2, 0xBD, 0x73, 0xBD, 0x72, +0xBD, 0x92, 0xBD, 0x93, 0xC5, 0xD4, 0xBD, 0xB4, +0xAD, 0x32, 0xBD, 0xB4, 0xBD, 0xB4, 0xB5, 0x53, +0xB5, 0x73, 0xC5, 0xD4, 0xCD, 0xF4, 0xA4, 0xF1, +0x94, 0x6F, 0x94, 0x4F, 0x8C, 0x0E, 0xAD, 0x12, +0xC5, 0xF4, 0xCD, 0xF4, 0xCE, 0x15, 0xB5, 0x52, +0xAC, 0xF1, 0xBD, 0x73, 0xD6, 0x35, 0xD6, 0x14, +0xCD, 0xD3, 0xC5, 0x93, 0xC5, 0xB3, 0xBD, 0x72, +0xA4, 0xD0, 0x94, 0x4E, 0xA4, 0xCF, 0xAC, 0xF0, +0xAD, 0x11, 0xAD, 0x10, 0x9C, 0x6F, 0x9C, 0x6E, +0x9C, 0x6E, 0xAC, 0xD0, 0xAC, 0xF0, 0xA4, 0xAF, +0x9C, 0x6E, 0x9C, 0x8F, 0xAC, 0xF1, 0xA4, 0xD0, +0xA4, 0xB0, 0x9C, 0x6F, 0x9C, 0x8F, 0x9C, 0x6F, +0xA4, 0xD0, 0xA4, 0xB0, 0xAD, 0x12, 0xB5, 0x53, +0xAD, 0x12, 0xAC, 0xF1, 0xB5, 0x32, 0xAD, 0x12, +0xAD, 0x12, 0xB5, 0x32, 0xB5, 0x32, 0xB5, 0x32, +0xB5, 0x11, 0xAC, 0xF1, 0xAC, 0xF0, 0xAC, 0xF0, +0xB5, 0x31, 0xB5, 0x11, 0xAC, 0xD0, 0x9C, 0x8F, +0x9C, 0x90, 0x9C, 0x90, 0xA4, 0xD0, 0xA4, 0xD0, +0xA4, 0xD0, 0xA4, 0xD0, 0xAD, 0x11, 0xB5, 0x52, +0xB5, 0x32, 0xA4, 0xF0, 0xAC, 0xF0, 0xA4, 0xD0, +0x94, 0x6E, 0x9C, 0x6F, 0xA4, 0xF1, 0xAD, 0x12, +0xAD, 0x11, 0x83, 0xED, 0x41, 0xC6, 0x39, 0xA6, +0x31, 0x85, 0x31, 0xA6, 0x6B, 0x2C, 0x63, 0x0B, +0x39, 0x86, 0x29, 0x25, 0x31, 0x45, 0x4A, 0x08, +0x4A, 0x48, 0x4A, 0x28, 0x5A, 0x89, 0x6B, 0x0C, +0x8B, 0xEF, 0x8B, 0xEF, 0x9C, 0x70, 0x83, 0xCE, +0x73, 0x2C, 0x8B, 0xCE, 0x83, 0xCD, 0x8B, 0xEE, +0xA4, 0xB1, 0x9C, 0x91, 0x52, 0x69, 0x52, 0x48, +0x52, 0x68, 0x42, 0x07, 0x21, 0x04, 0x18, 0xC3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0x82, 0x18, 0xC3, 0x73, 0x6C, 0xAD, 0x32, +0xB5, 0x53, 0xC5, 0xD5, 0xD6, 0x56, 0xCE, 0x15, +0xCE, 0x15, 0xC5, 0xF5, 0xB5, 0x73, 0xB5, 0x93, +0xC5, 0xF4, 0xC5, 0xF4, 0xC5, 0xF4, 0xCE, 0x15, +0xCE, 0x15, 0xC5, 0xD4, 0xC5, 0xD4, 0xC6, 0x15, +0xC6, 0x15, 0xC5, 0xD5, 0xC5, 0xD5, 0xBD, 0xD4, +0xC5, 0xF5, 0xC6, 0x15, 0xCE, 0x35, 0xAD, 0x32, +0xA4, 0xF0, 0xC5, 0xD4, 0xD6, 0x14, 0xDE, 0x55, +0xD6, 0x14, 0xD6, 0x14, 0xDE, 0x76, 0xD6, 0x14, +0xCD, 0xF4, 0xCD, 0xD4, 0xC5, 0xB3, 0xD6, 0x35, +0xD6, 0x14, 0xD6, 0x35, 0xD6, 0x15, 0xDE, 0x35, +0x6C, 0x2A, 0x5B, 0xEA, 0x6C, 0x6B, 0x64, 0x29, +0x5B, 0xE6, 0x64, 0x08, 0x53, 0x67, 0x53, 0x88, +0x8D, 0x0E, 0x95, 0x0D, 0x74, 0x28, 0x84, 0xAB, +0xA5, 0x8F, 0xAD, 0xB1, 0xA5, 0x50, 0x94, 0xAE, +0xC6, 0x14, 0xD6, 0x75, 0xD6, 0x75, 0xDE, 0x75, +0xD6, 0x54, 0xD6, 0x14, 0xA4, 0x8E, 0x83, 0xCB, +0x9C, 0x8E, 0xA4, 0xF0, 0xAD, 0x11, 0xAD, 0x32, +0x63, 0x0B, 0x39, 0xA6, 0x42, 0x07, 0x42, 0x28, +0x63, 0x0C, 0x6B, 0x2D, 0x5A, 0xAB, 0x4A, 0x49, +0x41, 0xE7, 0x62, 0xEB, 0x9C, 0xD3, 0xEF, 0x7D, +0xDE, 0xDA, 0x8C, 0x0F, 0x8C, 0x0D, 0xA4, 0x8E, +0x94, 0x2C, 0x94, 0x2C, 0xAC, 0xAE, 0xAC, 0xAE, +0xA4, 0xAE, 0xA4, 0x8E, 0xA4, 0x8E, 0x9C, 0x6D, +0x9C, 0x6D, 0xA4, 0x8E, 0xAC, 0xCF, 0xB4, 0xEF, +0xAC, 0xEF, 0xB4, 0xF0, 0xB5, 0x10, 0xB5, 0x10, +0xB5, 0x10, 0xB5, 0x10, 0xB5, 0x10, 0xB5, 0x10, +0xAD, 0x0F, 0xAC, 0xEF, 0xB5, 0x10, 0xAC, 0xF0, +0xAC, 0xCF, 0xA4, 0xAE, 0xAC, 0xCF, 0xA4, 0xAF, +0xA4, 0xAF, 0xA4, 0xAE, 0xA4, 0xAE, 0x9C, 0x8E, +0x9C, 0x8F, 0x9C, 0x8F, 0x94, 0x6E, 0x9C, 0x6E, +0x9C, 0x6E, 0x9C, 0x6E, 0x94, 0x4E, 0x8C, 0x0D, +0x8C, 0x0D, 0xAC, 0xF1, 0x94, 0x4F, 0x5A, 0xCA, +0x39, 0xE7, 0x73, 0x8E, 0x94, 0x92, 0xA5, 0x14, +0x94, 0x71, 0xAD, 0x35, 0x94, 0x71, 0x63, 0x0C, +0x84, 0x10, 0xC5, 0xF7, 0x94, 0x51, 0x62, 0xEB, +0x62, 0xEC, 0x4A, 0x69, 0xB5, 0xB6, 0xC6, 0x39, +0x8C, 0x51, 0xB5, 0xB7, 0xBD, 0xF8, 0xA4, 0xF4, +0xBD, 0xB7, 0xC5, 0xF8, 0xD6, 0x9B, 0xE6, 0xFD, +0xBD, 0xD7, 0xC6, 0x17, 0xC5, 0xF5, 0xD6, 0x35, +0xD6, 0x55, 0xD6, 0x34, 0xC5, 0xB2, 0xCD, 0xD3, +0xB5, 0x30, 0xB5, 0x71, 0x9C, 0xAF, 0x8C, 0x2D, +0xB5, 0x72, 0xA4, 0xEF, 0xB5, 0x30, 0xB5, 0x10, +0x93, 0xEC, 0xA4, 0xAF, 0x9C, 0x6E, 0xBD, 0x92, +0xA4, 0xCF, 0xAC, 0xF0, 0xAD, 0x31, 0xB5, 0x51, +0xB5, 0x31, 0x73, 0x4B, 0x39, 0xA5, 0x39, 0xC6, +0x39, 0xA5, 0x39, 0xC6, 0x39, 0xA6, 0x42, 0x07, +0x4A, 0x48, 0x42, 0x28, 0x4A, 0x48, 0x63, 0x2C, +0x7B, 0xCF, 0x9C, 0xD3, 0x9C, 0xF4, 0xB5, 0xB7, +0xCE, 0x7A, 0xBD, 0xD6, 0xAD, 0x52, 0xB5, 0x51, +0xB5, 0x72, 0xC5, 0xB3, 0xC5, 0xB3, 0xC5, 0xD4, +0xBD, 0x94, 0xBD, 0xB4, 0xBD, 0xB4, 0xB5, 0x94, +0xC5, 0xD4, 0xCD, 0xF5, 0xC5, 0xD4, 0x9C, 0x90, +0x94, 0x4F, 0x8C, 0x2E, 0x94, 0x4F, 0xBD, 0x93, +0xCE, 0x35, 0xD6, 0x35, 0xD6, 0x55, 0xB5, 0x52, +0xAC, 0xF1, 0xBD, 0x73, 0xCD, 0xF4, 0xDE, 0x55, +0xDE, 0x35, 0xD6, 0x34, 0xD6, 0x35, 0xDE, 0x76, +0xD6, 0x15, 0xC5, 0xD4, 0xC5, 0xD4, 0xC5, 0xD4, +0xAD, 0x31, 0xB5, 0x32, 0xC5, 0xD4, 0xC5, 0xB4, +0xBD, 0x93, 0xC5, 0xB4, 0xB5, 0x52, 0x9C, 0x8F, +0x83, 0xEC, 0x8C, 0x2E, 0xB5, 0x52, 0xA4, 0xF1, +0xA4, 0xD1, 0x9C, 0x8F, 0xA4, 0xF1, 0xA4, 0xD1, +0xA4, 0xF1, 0xA4, 0xD0, 0xA4, 0xD0, 0xA4, 0xD0, +0xA4, 0xF1, 0xAD, 0x12, 0xA4, 0xD1, 0x94, 0x4F, +0x94, 0x4F, 0x8C, 0x2E, 0x9C, 0x90, 0xA4, 0xB0, +0xB5, 0x31, 0xBD, 0x52, 0xC5, 0x92, 0xD6, 0x14, +0xDE, 0x34, 0xD5, 0xF3, 0xBD, 0x72, 0xAC, 0xF1, +0xBD, 0x73, 0xA4, 0xD1, 0xAC, 0xD0, 0xB5, 0x11, +0xB5, 0x31, 0xBD, 0x52, 0xBD, 0x52, 0xBD, 0x52, +0xB5, 0x32, 0xBD, 0x32, 0xB5, 0x31, 0xBD, 0x52, +0xB5, 0x32, 0xB5, 0x32, 0xB5, 0x31, 0xB5, 0x32, +0xB5, 0x52, 0xBD, 0x52, 0xA4, 0xD1, 0x83, 0xCD, +0x41, 0xE6, 0x31, 0x85, 0x52, 0xAA, 0x94, 0x50, +0x94, 0x71, 0x7B, 0x8E, 0x41, 0xE8, 0x29, 0x25, +0x39, 0xC6, 0x4A, 0x08, 0x41, 0xE7, 0x4A, 0x08, +0x62, 0xCB, 0x73, 0x4C, 0x8B, 0xEF, 0x94, 0x50, +0x8B, 0xCF, 0x8B, 0xCE, 0x7B, 0x6D, 0x62, 0xCA, +0x8C, 0x2F, 0x7B, 0x8D, 0x18, 0xC3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0x82, +0x10, 0xA3, 0x18, 0xC3, 0x18, 0xE4, 0x18, 0xE3, +0x10, 0xA3, 0x52, 0x89, 0xA5, 0x12, 0x94, 0x4F, +0xA4, 0xB0, 0xA4, 0xF1, 0xAD, 0x52, 0xAD, 0x32, +0xB5, 0x52, 0xA4, 0xF1, 0xA4, 0xF1, 0xAD, 0x52, +0xB5, 0x93, 0xC5, 0xD4, 0xC5, 0xF5, 0xC5, 0xF5, +0xCE, 0x36, 0xB5, 0x73, 0xCE, 0x16, 0xCE, 0x56, +0xCE, 0x15, 0xC5, 0xD5, 0xC5, 0xF5, 0xC5, 0xF5, +0xC6, 0x15, 0xCE, 0x15, 0xD6, 0x56, 0xBD, 0xD4, +0xA4, 0xD0, 0xBD, 0xB3, 0xC5, 0xB3, 0xD6, 0x14, +0xCD, 0xB3, 0xBD, 0x72, 0xCD, 0xF4, 0xD6, 0x14, +0xD5, 0xF4, 0xCD, 0xD3, 0xD6, 0x14, 0xD6, 0x15, +0xD6, 0x35, 0xCD, 0xD4, 0xD6, 0x14, 0xD6, 0x35, +0x4B, 0x46, 0x53, 0x87, 0x5C, 0x08, 0x64, 0x27, +0x64, 0x26, 0x74, 0x8A, 0x9D, 0x90, 0x8C, 0xEE, +0x84, 0xAE, 0x95, 0x2E, 0x6B, 0xA8, 0xA5, 0x8F, +0x7C, 0x4A, 0x4B, 0x25, 0x74, 0x2A, 0xB5, 0xF3, +0xD6, 0x96, 0xD6, 0x75, 0xD6, 0x54, 0xCE, 0x34, +0xCE, 0x13, 0xD6, 0x14, 0xA4, 0xAE, 0xB5, 0x72, +0xC6, 0x15, 0xCE, 0x35, 0xCE, 0x35, 0xCE, 0x35, +0xCE, 0x16, 0x8C, 0x2F, 0x39, 0xC6, 0x39, 0xC6, +0x42, 0x28, 0x52, 0x8A, 0x5A, 0xAA, 0x5A, 0xEB, +0x52, 0x8A, 0x52, 0x69, 0x9C, 0xD3, 0xE7, 0x3C, +0xEF, 0x7D, 0xD6, 0xBA, 0xC5, 0xF7, 0xAD, 0x11, +0xA4, 0xEF, 0xA4, 0xAE, 0xA4, 0x8E, 0xB5, 0x10, +0xA4, 0xAF, 0x94, 0x2D, 0xA4, 0xCF, 0xAC, 0xF0, +0xA4, 0xCF, 0xB5, 0x31, 0xBD, 0x72, 0xA4, 0xAF, +0x94, 0x0D, 0xA4, 0x8F, 0xA4, 0xAE, 0xAC, 0xEF, +0xB5, 0x30, 0xAC, 0xCF, 0xAC, 0xAE, 0xAC, 0xCF, +0xB5, 0x10, 0xAC, 0xCF, 0x94, 0x2C, 0x8B, 0xEB, +0xA4, 0x8E, 0xB5, 0x10, 0xB5, 0x0F, 0xBD, 0x30, +0xBD, 0x50, 0xBD, 0x50, 0xB5, 0x30, 0xB4, 0xEF, +0xAC, 0xCF, 0xA4, 0xAE, 0xAC, 0xCE, 0xAC, 0xCF, +0xAC, 0xCF, 0xB4, 0xEF, 0xB4, 0xEF, 0xAC, 0xAE, +0xA4, 0xAE, 0xB4, 0xF0, 0xB5, 0x10, 0x83, 0xAC, +0x8C, 0x0D, 0x83, 0xCD, 0x52, 0x89, 0x73, 0xAE, +0x94, 0x92, 0x7B, 0xAE, 0x7B, 0xAF, 0x6B, 0x4D, +0xBD, 0xB7, 0xBD, 0xD7, 0xD6, 0xBB, 0x94, 0x92, +0x7B, 0xCF, 0x31, 0x66, 0x42, 0x08, 0x6B, 0x8E, +0xAD, 0x76, 0xCE, 0x39, 0x9C, 0xF4, 0xA5, 0x15, +0xC6, 0x19, 0xC6, 0x39, 0xC6, 0x39, 0xD6, 0xBB, +0xD6, 0xBB, 0xDE, 0xDB, 0xBD, 0xB6, 0x94, 0x2F, +0xAD, 0x31, 0xAD, 0x31, 0xBD, 0x72, 0xC5, 0x92, +0xAD, 0x10, 0xAD, 0x31, 0xB5, 0x72, 0xBD, 0x92, +0xC5, 0xF4, 0xAD, 0x30, 0xCD, 0xF3, 0xB5, 0x30, +0x93, 0xEC, 0xA4, 0x6E, 0x94, 0x4D, 0xC5, 0xD3, +0xB5, 0x52, 0xB5, 0x51, 0xA4, 0xF0, 0xBD, 0x72, +0xBD, 0x93, 0xA4, 0xD0, 0x4A, 0x48, 0x39, 0xA5, +0x31, 0x85, 0x31, 0x85, 0x39, 0xA6, 0x4A, 0x28, +0x52, 0x8A, 0x4A, 0x28, 0x4A, 0x69, 0x6B, 0x2C, +0x73, 0x8E, 0x84, 0x31, 0x9C, 0xD3, 0xAD, 0x76, +0xC6, 0x19, 0xCE, 0x38, 0xAD, 0x32, 0xA4, 0xF0, +0xBD, 0x72, 0xC5, 0xB4, 0xBD, 0x72, 0xBD, 0x73, +0xB5, 0x73, 0xBD, 0x94, 0xBD, 0x94, 0xBD, 0xB4, +0xCE, 0x15, 0xCE, 0x15, 0xCD, 0xF5, 0xBD, 0x73, +0xA4, 0xD1, 0x94, 0x6F, 0x9C, 0xB0, 0xC5, 0xD4, +0xD6, 0x35, 0xDE, 0x75, 0xD6, 0x14, 0xB5, 0x11, +0xAD, 0x12, 0xC5, 0xB4, 0xCD, 0xF4, 0xD6, 0x34, +0xD6, 0x34, 0xD5, 0xF3, 0xC5, 0xB2, 0xD6, 0x14, +0xC5, 0xB3, 0xB5, 0x52, 0xA4, 0xAF, 0xA4, 0xAF, +0xA4, 0xF1, 0x9C, 0xB0, 0x9C, 0xAF, 0xAD, 0x11, +0xB5, 0x31, 0xAD, 0x11, 0xAD, 0x11, 0x9C, 0xB0, +0x94, 0x4E, 0xAD, 0x11, 0xBD, 0xB4, 0xAD, 0x11, +0xAD, 0x12, 0xB5, 0x53, 0xA4, 0xF1, 0x9C, 0xB0, +0xAD, 0x12, 0x9C, 0xB0, 0xA5, 0x11, 0xA4, 0xD1, +0xAD, 0x32, 0xCD, 0xF5, 0xC5, 0xD4, 0xB5, 0x73, +0xAD, 0x32, 0xAD, 0x32, 0xB5, 0x73, 0xAD, 0x32, +0xAD, 0x11, 0xCD, 0xD3, 0xDE, 0x34, 0xD6, 0x13, +0xDE, 0x33, 0xCD, 0xD2, 0xBD, 0x51, 0x9C, 0x8F, +0xB5, 0x53, 0xA4, 0x8F, 0xAC, 0xD0, 0xB5, 0x11, +0xAC, 0xAF, 0xA4, 0x6F, 0x9C, 0x4E, 0x94, 0x2E, +0x7B, 0x8B, 0x83, 0xCC, 0x94, 0x2E, 0xA4, 0x8F, +0xA4, 0x8F, 0xA4, 0xD0, 0xA4, 0xD0, 0xAC, 0xF1, +0xAC, 0xD0, 0xA4, 0xB0, 0x9C, 0x6F, 0x94, 0x4F, +0x83, 0xCD, 0x4A, 0x27, 0x29, 0x45, 0x31, 0xA6, +0x5A, 0xCB, 0x94, 0x51, 0x83, 0xAE, 0x5A, 0x6A, +0x4A, 0x08, 0x39, 0xC7, 0x41, 0xE7, 0x4A, 0x08, +0x41, 0xE7, 0x4A, 0x29, 0x5A, 0x8A, 0x62, 0xCB, +0x52, 0x49, 0x73, 0x4D, 0x83, 0xCE, 0x8C, 0x10, +0x6B, 0x0B, 0x52, 0x8A, 0x31, 0x87, 0x31, 0x87, +0x10, 0xA3, 0x10, 0x82, 0x10, 0xA3, 0x10, 0xA3, +0x18, 0xE4, 0x29, 0x45, 0x19, 0x04, 0x10, 0xC3, +0x18, 0xE4, 0x73, 0x8D, 0x94, 0x70, 0x94, 0x50, +0x94, 0x70, 0x94, 0x4F, 0x8C, 0x0F, 0x8C, 0x2F, +0x8C, 0x2F, 0x94, 0x70, 0x94, 0x70, 0x8C, 0x2F, +0x8C, 0x0F, 0x8C, 0x0E, 0x8C, 0x2F, 0x8C, 0x2F, +0x8C, 0x2F, 0x7B, 0xCD, 0x8C, 0x4F, 0x94, 0x70, +0x84, 0x0E, 0x84, 0x0E, 0x9C, 0xD1, 0xA4, 0xF1, +0xAD, 0x11, 0xB5, 0x73, 0xA4, 0xD1, 0x94, 0x6F, +0xA4, 0xD0, 0x94, 0x6F, 0x83, 0xAC, 0x94, 0x2E, +0x9C, 0x6F, 0xB5, 0x31, 0xCD, 0xD4, 0xCD, 0xF4, +0xCD, 0xF4, 0xCD, 0xD4, 0xDE, 0x56, 0xE6, 0xB7, +0xEE, 0xD7, 0xEE, 0xD7, 0xE6, 0x96, 0xDE, 0x75, +0x53, 0xA7, 0x63, 0xE9, 0x64, 0x29, 0x4B, 0x64, +0x64, 0x05, 0x53, 0x86, 0x74, 0x8C, 0x74, 0x4C, +0x74, 0x4A, 0x7C, 0xAA, 0x84, 0xAC, 0x9D, 0x4E, +0x53, 0x66, 0x74, 0x6A, 0xBE, 0x33, 0xC6, 0x14, +0xC5, 0xF4, 0xCE, 0x54, 0xC6, 0x13, 0xCE, 0x13, +0xC5, 0xD3, 0xCD, 0xF3, 0xA4, 0x8E, 0xC5, 0xF3, +0xCE, 0x35, 0xC5, 0xF4, 0xC5, 0xF4, 0xC5, 0xF4, +0xC5, 0xD4, 0xCE, 0x15, 0xAD, 0x53, 0x4A, 0x48, +0x29, 0x45, 0x31, 0xA6, 0x39, 0xC6, 0x4A, 0x49, +0x42, 0x07, 0x4A, 0x69, 0x52, 0x8A, 0x5A, 0xEB, +0x7B, 0xEF, 0xD6, 0xBB, 0xF7, 0x9E, 0xCE, 0x37, +0xAD, 0x52, 0xBD, 0x92, 0xAC, 0xF0, 0xBD, 0x92, +0xB5, 0x72, 0xB5, 0x72, 0xAD, 0x31, 0xB5, 0x73, +0xC5, 0xD4, 0xCE, 0x35, 0xC5, 0xF4, 0xBD, 0xB3, +0xBD, 0xB3, 0xC5, 0xD4, 0xBD, 0xB3, 0xCE, 0x35, +0xB5, 0x51, 0xBD, 0x72, 0xBD, 0x72, 0xB5, 0x31, +0xBD, 0x72, 0xAC, 0xEF, 0x94, 0x2C, 0x9C, 0x8E, +0x9C, 0x6D, 0x9C, 0x4D, 0x9C, 0x8E, 0xC5, 0x92, +0xD5, 0xF3, 0xD6, 0x13, 0xCD, 0xF3, 0xC5, 0xB2, +0xB5, 0x31, 0xAD, 0x10, 0xAD, 0x31, 0xB5, 0x10, +0xBD, 0x71, 0xBD, 0x92, 0xB5, 0x30, 0xAC, 0xEF, +0xAC, 0xCF, 0xBD, 0x71, 0xBD, 0x30, 0xA4, 0xAE, +0xA4, 0xCF, 0x9C, 0xB0, 0x83, 0xCD, 0x5A, 0xA9, +0x5A, 0xCA, 0x4A, 0x48, 0x6B, 0x0C, 0x73, 0x8E, +0xC6, 0x39, 0xBD, 0xD7, 0x7B, 0xEF, 0x94, 0x92, +0xBD, 0xF7, 0x84, 0x30, 0x31, 0x86, 0x42, 0x49, +0x9C, 0xF3, 0xAD, 0x55, 0xAD, 0x55, 0xBD, 0xF8, +0xBD, 0xB7, 0xC6, 0x19, 0xCE, 0x39, 0xCE, 0x7A, +0xAD, 0x76, 0xC6, 0x19, 0xBD, 0xF7, 0x8C, 0x30, +0x8C, 0x0F, 0x94, 0x2E, 0x94, 0x0D, 0x8B, 0xEC, +0x83, 0x8B, 0x7B, 0x6A, 0x83, 0xCC, 0x83, 0xCC, +0x83, 0xAC, 0x8B, 0xEC, 0x94, 0x2D, 0x73, 0x29, +0x83, 0xAB, 0x94, 0x0C, 0x73, 0x29, 0xA4, 0xD0, +0x9C, 0x8F, 0xA4, 0xD0, 0xB5, 0x72, 0xB5, 0x72, +0xB5, 0x31, 0xAD, 0x31, 0x7B, 0xCD, 0x42, 0x07, +0x39, 0xC6, 0x42, 0x07, 0x4A, 0x28, 0x4A, 0x28, +0x5A, 0xAA, 0x5A, 0xCA, 0x5A, 0xAA, 0x73, 0x8D, +0x73, 0x8E, 0x7C, 0x10, 0x84, 0x51, 0x9C, 0xD4, +0xB5, 0xD7, 0xC6, 0x38, 0xBD, 0xB5, 0xAD, 0x32, +0xC5, 0xB3, 0xC5, 0xD4, 0xBD, 0x93, 0xB5, 0x73, +0xB5, 0x73, 0xBD, 0x94, 0xBD, 0xB4, 0xBD, 0xD4, +0xC5, 0xF4, 0xC5, 0xB4, 0xBD, 0x93, 0xBD, 0x73, +0xC5, 0xB4, 0xBD, 0x93, 0xB5, 0x93, 0xC5, 0xF4, +0xD6, 0x14, 0xD6, 0x35, 0xC5, 0xD3, 0xB5, 0x31, +0xAD, 0x11, 0xC5, 0xB3, 0xCD, 0xF4, 0xD6, 0x34, +0xD6, 0x14, 0xC5, 0x92, 0xBD, 0x92, 0xD6, 0x14, +0xC5, 0x93, 0xAD, 0x11, 0xA4, 0xF0, 0x9C, 0x8F, +0x94, 0x6E, 0x8C, 0x2D, 0x94, 0x8F, 0x9C, 0xAF, +0xA5, 0x11, 0xBD, 0x92, 0xBD, 0x93, 0xA4, 0xF1, +0xA4, 0xF1, 0xBD, 0x93, 0xBD, 0xB4, 0xAD, 0x32, +0xAD, 0x53, 0xBD, 0xB4, 0xAD, 0x52, 0xB5, 0x53, +0xBD, 0xB4, 0xAD, 0x32, 0x9C, 0xB0, 0xA4, 0xD1, +0xB5, 0x52, 0xC5, 0xD4, 0xBD, 0x93, 0xC5, 0xD4, +0xB5, 0x73, 0xA5, 0x12, 0xAD, 0x32, 0xAD, 0x32, +0xAD, 0x12, 0xB5, 0x52, 0xC5, 0x92, 0xC5, 0x91, +0xC5, 0xB1, 0xBD, 0x51, 0xB5, 0x31, 0xB5, 0x32, +0xBD, 0x73, 0xB5, 0x11, 0xAC, 0xCF, 0x9C, 0x6E, +0x9C, 0x6E, 0xA4, 0xB0, 0xA4, 0xB0, 0xAD, 0x11, +0xA4, 0xD0, 0x9C, 0xB0, 0xA4, 0xD0, 0xB5, 0x31, +0xAC, 0xF1, 0xA4, 0xD0, 0xA4, 0xAF, 0xBD, 0x73, +0xBD, 0x93, 0xC5, 0xF5, 0xBD, 0x73, 0x9C, 0x90, +0x9C, 0xB0, 0x9C, 0x6F, 0x6B, 0x2B, 0x31, 0x65, +0x29, 0x25, 0x31, 0x65, 0x4A, 0x28, 0x62, 0xEB, +0x7B, 0x8E, 0x7B, 0xAE, 0x62, 0xCB, 0x4A, 0x08, +0x4A, 0x08, 0x41, 0xC7, 0x4A, 0x08, 0x62, 0xAA, +0x52, 0x69, 0x49, 0xE8, 0x73, 0x0C, 0xAC, 0xD2, +0xAC, 0xD2, 0x62, 0xCB, 0x20, 0xE4, 0x21, 0x05, +0x21, 0x04, 0x21, 0x04, 0x21, 0x25, 0x29, 0x45, +0x21, 0x25, 0x18, 0xE4, 0x19, 0x04, 0x18, 0xE4, +0x4A, 0x69, 0xA4, 0xF2, 0xAD, 0x33, 0xAD, 0x33, +0xB5, 0x53, 0xAD, 0x12, 0xAD, 0x32, 0xB5, 0x73, +0xB5, 0x53, 0xB5, 0x53, 0xB5, 0x53, 0xB5, 0x53, +0xB5, 0x53, 0xB5, 0x73, 0xAD, 0x53, 0xB5, 0x53, +0xAD, 0x33, 0xAD, 0x33, 0xA5, 0x12, 0xA5, 0x12, +0xA5, 0x12, 0xA5, 0x13, 0xA4, 0xF2, 0xA4, 0xF2, +0x9C, 0xD1, 0x9C, 0xD1, 0x9C, 0xD1, 0xA4, 0xF2, +0xA4, 0xF2, 0xA4, 0xF2, 0xA4, 0xF2, 0x9C, 0xB1, +0x94, 0x50, 0x8C, 0x2E, 0x8C, 0x0E, 0x8C, 0x2E, +0x8C, 0x0E, 0x8C, 0x0D, 0x94, 0x4E, 0x9C, 0x8F, +0xA4, 0xAF, 0xA4, 0xCF, 0x9C, 0x6E, 0x9C, 0x6E, +0x4B, 0x27, 0x7C, 0xAC, 0x74, 0x4A, 0x43, 0x03, +0x84, 0xEC, 0x8D, 0x0F, 0x63, 0xEB, 0x74, 0x4C, +0x64, 0x28, 0x6C, 0x47, 0x95, 0x2E, 0x6B, 0xE9, +0x64, 0x07, 0x7C, 0xAB, 0xB6, 0x13, 0xBD, 0xF4, +0xBD, 0xB3, 0xBD, 0xD3, 0xC5, 0xD3, 0xC5, 0xD3, +0xC5, 0xD3, 0xCE, 0x14, 0x9C, 0x4D, 0xAD, 0x10, +0x9C, 0xAF, 0xAD, 0x52, 0xC5, 0xF5, 0xC6, 0x15, +0xC5, 0xF4, 0xBD, 0xB4, 0xD6, 0x56, 0xC5, 0xF6, +0x5A, 0xEA, 0x29, 0x44, 0x31, 0x85, 0x31, 0xA6, +0x42, 0x07, 0x63, 0x2C, 0x6B, 0x4D, 0x4A, 0x49, +0x41, 0xE8, 0x73, 0x8E, 0xA5, 0x34, 0x4A, 0x49, +0x6B, 0x4C, 0xAD, 0x11, 0xAC, 0xF0, 0xBD, 0x93, +0xB5, 0x73, 0xBD, 0x92, 0xB5, 0x52, 0xB5, 0x52, +0xBD, 0xD4, 0xC5, 0xF4, 0x9C, 0x8F, 0xB5, 0x52, +0xC5, 0xF4, 0xBD, 0xB3, 0xB5, 0x52, 0xC5, 0xD4, +0xBD, 0xB3, 0xBD, 0x92, 0xB5, 0x31, 0xBD, 0x92, +0xB5, 0x30, 0xA4, 0xAE, 0xAD, 0x30, 0xB5, 0x51, +0xBD, 0x92, 0xAC, 0xCF, 0x9C, 0x8E, 0xBD, 0x92, +0xC5, 0xD2, 0xA4, 0xCF, 0xCD, 0xF4, 0xCD, 0xF3, +0xCE, 0x14, 0xBD, 0xD3, 0xC5, 0xF4, 0xCD, 0xD4, +0xC5, 0xD3, 0xCE, 0x14, 0xC5, 0xB3, 0xBD, 0xB3, +0xBD, 0x72, 0xC5, 0xB2, 0xC5, 0xB2, 0xBD, 0x92, +0xBD, 0x92, 0xB5, 0x73, 0x9C, 0xD0, 0x8C, 0x4F, +0x73, 0x6C, 0x39, 0xA6, 0x52, 0xAA, 0x5A, 0xCB, +0x8C, 0x51, 0xBD, 0xB6, 0x73, 0x8E, 0xB5, 0x76, +0xDE, 0xDB, 0xE7, 0x3C, 0x9C, 0xD3, 0x39, 0xE7, +0x5A, 0xCB, 0xAD, 0x76, 0xC6, 0x19, 0xB5, 0x97, +0xAD, 0x76, 0xB5, 0x76, 0xB5, 0x76, 0x8C, 0x52, +0x73, 0x8F, 0xD6, 0x7A, 0xDE, 0xFB, 0xC5, 0xF7, +0xC5, 0x95, 0xBD, 0x32, 0xBD, 0x52, 0xC5, 0x72, +0xBD, 0x31, 0xB5, 0x31, 0xB5, 0x31, 0xB5, 0x11, +0xB4, 0xF0, 0xAC, 0xCF, 0xAC, 0xAF, 0xAC, 0xD0, +0xB4, 0xF0, 0xB5, 0x10, 0xA4, 0xCF, 0x9C, 0x6E, +0x9C, 0x6E, 0x9C, 0x4D, 0x94, 0x0C, 0x83, 0xCB, +0x8C, 0x0C, 0x94, 0x4D, 0x94, 0x4E, 0x6B, 0x2A, +0x31, 0xA5, 0x42, 0x07, 0x42, 0x07, 0x42, 0x07, +0x4A, 0x48, 0x52, 0x89, 0x52, 0xAA, 0x52, 0xAA, +0x6B, 0x4D, 0x7B, 0xF0, 0x94, 0x92, 0x9C, 0xF4, +0xAD, 0x55, 0xAD, 0x55, 0xCE, 0x58, 0xB5, 0x74, +0xB5, 0x52, 0xB5, 0x32, 0xA4, 0xF1, 0xA4, 0xD0, +0xAD, 0x32, 0xB5, 0x73, 0xBD, 0x93, 0xBD, 0xD4, +0xC5, 0xF4, 0xC5, 0xD4, 0xB5, 0x72, 0xC5, 0xB3, +0xCD, 0xF4, 0xCE, 0x35, 0xCE, 0x15, 0xCD, 0xF4, +0xD6, 0x35, 0xD6, 0x55, 0xCE, 0x14, 0xB5, 0x31, +0xAC, 0xF1, 0xBD, 0xB3, 0xBD, 0x52, 0xCD, 0xD3, +0xD6, 0x14, 0xCD, 0xD3, 0xCD, 0xF4, 0xD6, 0x35, +0xD6, 0x14, 0xC5, 0xB3, 0xC5, 0x93, 0xC5, 0xB3, +0xAD, 0x31, 0x9C, 0x8F, 0xAD, 0x11, 0xB5, 0x72, +0xBD, 0x93, 0xCD, 0xF4, 0xCE, 0x14, 0xBD, 0x92, +0xBD, 0xB2, 0xC5, 0xD3, 0xC5, 0xF4, 0xAD, 0x32, +0xAD, 0x32, 0xC5, 0xD4, 0xBD, 0x94, 0xBD, 0x94, +0xC5, 0xD5, 0xBD, 0xB4, 0xAD, 0x12, 0x9C, 0xB0, +0xBD, 0xB4, 0xC5, 0xD4, 0xB5, 0x52, 0xBD, 0xB4, +0xB5, 0x73, 0xA5, 0x12, 0xB5, 0x53, 0xB5, 0x93, +0xBD, 0x94, 0xB5, 0x53, 0xBD, 0x72, 0xCD, 0xF3, +0xC5, 0x92, 0xA4, 0xD0, 0xB5, 0x52, 0xB5, 0x52, +0xB5, 0x32, 0x9C, 0x4E, 0x94, 0x0D, 0x9C, 0x4E, +0xA4, 0xB0, 0xA4, 0xB0, 0x9C, 0x8F, 0xA4, 0xD0, +0xAC, 0xF1, 0xA4, 0xB0, 0x9C, 0x6F, 0xA4, 0xD0, +0x9C, 0x6F, 0xA4, 0xB0, 0xBD, 0x93, 0xB5, 0x53, +0x9C, 0x8F, 0x9C, 0xB0, 0xA4, 0xB0, 0x9C, 0xB0, +0xBD, 0x93, 0xC5, 0xD4, 0xCD, 0xF4, 0x83, 0xCC, +0x41, 0xE6, 0x29, 0x44, 0x29, 0x44, 0x39, 0xC6, +0x52, 0x69, 0x7B, 0x8E, 0xA4, 0xD3, 0x83, 0xEF, +0x4A, 0x28, 0x52, 0x29, 0x52, 0x29, 0x52, 0x49, +0x62, 0xEB, 0x5A, 0x8A, 0x4A, 0x08, 0x7B, 0x8D, +0x94, 0x50, 0xA4, 0xD3, 0x73, 0x4D, 0x20, 0xE4, +0x18, 0xE4, 0x19, 0x04, 0x21, 0x25, 0x21, 0x25, +0x21, 0x04, 0x18, 0xE4, 0x18, 0xC4, 0x5A, 0xCB, +0x84, 0x0E, 0x8C, 0x2F, 0x94, 0x6F, 0xA4, 0xF2, +0xB5, 0x74, 0xCD, 0xF6, 0xB5, 0x73, 0x8C, 0x2F, +0x94, 0x4F, 0xB5, 0x74, 0x9C, 0x70, 0x9C, 0x90, +0x9C, 0xB0, 0x9C, 0x90, 0x94, 0x70, 0x83, 0xEE, +0x8C, 0x0E, 0x94, 0x50, 0xA4, 0xF2, 0xCE, 0x57, +0xBD, 0xB4, 0x9C, 0x90, 0xAD, 0x12, 0xAD, 0x33, +0xAD, 0x12, 0xAD, 0x32, 0xAD, 0x32, 0xAD, 0x32, +0xAD, 0x12, 0xB5, 0x32, 0xB5, 0x73, 0xB5, 0x32, +0xBD, 0x74, 0xB5, 0x53, 0xAD, 0x12, 0xB5, 0x32, +0xB5, 0x53, 0xB5, 0x53, 0xAD, 0x32, 0xB5, 0x32, +0xB5, 0x32, 0xAD, 0x11, 0xAC, 0xF1, 0xAC, 0xF1, +0x32, 0x24, 0x5B, 0x88, 0x6B, 0xC9, 0x42, 0xA4, +0x7C, 0xAD, 0xA5, 0x93, 0xB6, 0x36, 0x74, 0x4C, +0x64, 0x27, 0x63, 0xE5, 0x74, 0x68, 0x74, 0x6A, +0x6C, 0x69, 0x7C, 0xAC, 0xBE, 0x54, 0xBD, 0xD3, +0xB5, 0xB2, 0xBD, 0xD3, 0xC5, 0xF4, 0xBD, 0xD4, +0xC6, 0x14, 0xD6, 0x55, 0xA4, 0x8E, 0x8C, 0x0C, +0x6B, 0x2A, 0xBD, 0xB4, 0xC6, 0x15, 0xC5, 0xF4, +0xC6, 0x15, 0xC5, 0xF5, 0xC5, 0xF5, 0xD6, 0x77, +0xCE, 0x36, 0x7B, 0x8C, 0x31, 0x85, 0x31, 0x85, +0x42, 0x07, 0x4A, 0x48, 0x42, 0x07, 0x42, 0x08, +0x52, 0x8A, 0x42, 0x28, 0x52, 0x6A, 0x73, 0x8E, +0x41, 0xC7, 0x39, 0xC7, 0xB5, 0x95, 0xB5, 0x93, +0xAD, 0x11, 0xBD, 0xD4, 0xB5, 0x72, 0xB5, 0x72, +0xC5, 0xF4, 0xBD, 0x93, 0xB5, 0x93, 0xCE, 0x15, +0xC5, 0xF4, 0xB5, 0x93, 0xB5, 0x52, 0xBD, 0xD4, +0xBD, 0xB3, 0xB5, 0x51, 0xAD, 0x31, 0xA4, 0xEF, +0xAD, 0x10, 0xA4, 0xCF, 0xAC, 0xEF, 0xB5, 0x30, +0xC5, 0x71, 0x9C, 0x6D, 0xA4, 0xCF, 0xBD, 0xB3, +0xCD, 0xF4, 0x83, 0xED, 0xC5, 0xD4, 0xC5, 0xD3, +0xC5, 0xF4, 0xBD, 0xD3, 0xCE, 0x15, 0xCE, 0x35, +0xC5, 0xD3, 0xC5, 0xF4, 0xBD, 0xB3, 0xC5, 0xD4, +0xAD, 0x11, 0xBD, 0x93, 0xBD, 0x92, 0xB5, 0x71, +0xB5, 0x51, 0xC5, 0xD4, 0xA5, 0x11, 0xAD, 0x11, +0x9C, 0x8F, 0x8C, 0x0D, 0x73, 0x6B, 0x52, 0x68, +0x5A, 0xCA, 0x7B, 0xAE, 0x83, 0xEF, 0xB5, 0x76, +0xC6, 0x18, 0xB5, 0x96, 0xB5, 0x96, 0x7B, 0xCE, +0x42, 0x08, 0x6B, 0x2D, 0xC6, 0x39, 0x9C, 0xB3, +0x52, 0x8B, 0x39, 0xE8, 0xA5, 0x15, 0xCE, 0x7A, +0x9C, 0xD3, 0x52, 0x8A, 0x8C, 0x51, 0xDE, 0xBA, +0xEE, 0xFB, 0xD6, 0x17, 0x8B, 0xCE, 0x8B, 0xED, +0x7B, 0x6B, 0x7B, 0x8B, 0x83, 0xAB, 0x7B, 0x8B, +0x83, 0xAC, 0x83, 0x8C, 0x7B, 0x6B, 0x8B, 0xED, +0xAD, 0x10, 0xAC, 0xF0, 0xA4, 0xAF, 0xBD, 0x51, +0xC5, 0xB3, 0xC5, 0x92, 0xB5, 0x31, 0xAC, 0xEF, +0xA4, 0xCF, 0xA4, 0xCF, 0xA4, 0xCF, 0x9C, 0x6F, +0x4A, 0x27, 0x39, 0xA5, 0x39, 0xA6, 0x31, 0x85, +0x42, 0x27, 0x52, 0xA9, 0x4A, 0x89, 0x52, 0xAA, +0x63, 0x2C, 0x73, 0x8E, 0x94, 0xB3, 0x8C, 0x72, +0x8C, 0x52, 0x9C, 0xF4, 0xCE, 0x59, 0xB5, 0x75, +0x94, 0x70, 0x94, 0x4F, 0x8C, 0x0E, 0x8C, 0x0E, +0x8C, 0x2F, 0x94, 0x4F, 0x9C, 0x6F, 0x9C, 0xAF, +0x9C, 0xB0, 0x9C, 0x8F, 0x94, 0x6E, 0x9C, 0x8F, +0xA4, 0xB0, 0xA4, 0xB0, 0xAD, 0x11, 0xBD, 0x72, +0xBD, 0x72, 0xBD, 0x93, 0xB5, 0x52, 0xAD, 0x11, +0xAC, 0xF1, 0xAD, 0x31, 0xCE, 0x15, 0xD6, 0x35, +0xD6, 0x34, 0xD6, 0x14, 0xDE, 0x76, 0xD6, 0x35, +0xDE, 0x55, 0xD6, 0x14, 0xCD, 0xF4, 0xDE, 0xB7, +0xCD, 0xF4, 0xBD, 0xB3, 0xCD, 0xF4, 0xCE, 0x14, +0xD6, 0x35, 0xD6, 0x14, 0xD6, 0x34, 0xD6, 0x34, +0xDE, 0x55, 0xD6, 0x14, 0xCE, 0x15, 0xB5, 0x53, +0xB5, 0x52, 0xC5, 0xD4, 0xB5, 0x93, 0xBD, 0xB4, +0xBD, 0xB4, 0xBD, 0x94, 0xAD, 0x12, 0x83, 0xED, +0x9C, 0xD1, 0xCE, 0x36, 0xB5, 0x73, 0xBD, 0xB4, +0xB5, 0x73, 0xAD, 0x12, 0xBD, 0xB4, 0xBD, 0xB4, +0xBD, 0x94, 0xB5, 0x53, 0xBD, 0x93, 0xC5, 0xF3, +0xBD, 0x92, 0xA4, 0xD0, 0x9C, 0xAF, 0xAC, 0xF1, +0xAC, 0xF1, 0x94, 0x4E, 0x94, 0x2D, 0x94, 0x4E, +0x9C, 0x4E, 0x94, 0x4E, 0x9C, 0x6E, 0xAC, 0xF1, +0xB5, 0x32, 0xA4, 0xB0, 0x9C, 0x4E, 0x9C, 0x8F, +0x9C, 0x6F, 0xA4, 0xD0, 0xC5, 0xD4, 0xB5, 0x52, +0x9C, 0x6E, 0xA4, 0xAF, 0x9C, 0x8F, 0x9C, 0x4F, +0x9C, 0x8F, 0xAC, 0xF0, 0xBD, 0x92, 0xA4, 0xAF, +0x94, 0x4F, 0x63, 0x0A, 0x39, 0xA6, 0x29, 0x44, +0x31, 0x65, 0x39, 0xC7, 0x4A, 0x49, 0x63, 0x0C, +0x4A, 0x49, 0x62, 0xEB, 0x94, 0x51, 0x7B, 0xCF, +0x39, 0xA6, 0x62, 0xCB, 0x5A, 0x8A, 0x4A, 0x29, +0x5A, 0xAA, 0x9C, 0x71, 0xBD, 0x75, 0x83, 0xAE, +0x31, 0x66, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE3, 0x18, 0xE4, 0x5A, 0xCA, 0xD6, 0x76, +0xEF, 0x18, 0xDE, 0xB7, 0xCD, 0xF5, 0xBD, 0x94, +0xAD, 0x53, 0xBD, 0xB4, 0xC5, 0xF5, 0x94, 0x90, +0xBD, 0xD5, 0xDE, 0xB8, 0xAD, 0x32, 0x94, 0x70, +0x8C, 0x4F, 0xA4, 0xF2, 0xA5, 0x12, 0xAD, 0x33, +0xB5, 0x94, 0xB5, 0x74, 0xBD, 0x94, 0xD6, 0x56, +0xDE, 0xB8, 0x94, 0x70, 0xB5, 0x53, 0xB5, 0x32, +0xAD, 0x11, 0xC5, 0xD3, 0xCD, 0xD4, 0xCD, 0xD4, +0xC5, 0xB3, 0xCD, 0xF4, 0xCE, 0x14, 0xBD, 0x93, +0xBD, 0x72, 0xBD, 0x73, 0xD6, 0x35, 0xD6, 0x14, +0xBD, 0x92, 0xC5, 0xB3, 0xCD, 0xF4, 0xD6, 0x14, +0xDE, 0x55, 0xD6, 0x35, 0xD6, 0x14, 0xCD, 0xF4, +0x63, 0xCB, 0x4A, 0xE6, 0x74, 0x0A, 0x4A, 0xC5, +0x63, 0xCA, 0x9D, 0x52, 0xA5, 0x73, 0x5B, 0x48, +0x64, 0x08, 0x4B, 0x23, 0x63, 0xE7, 0x6C, 0x69, +0x7C, 0xCB, 0x7C, 0x8B, 0x8C, 0xAD, 0x9D, 0x0D, +0xA5, 0x4D, 0xAD, 0x6F, 0xA4, 0xCF, 0xA4, 0xCF, +0xAD, 0x30, 0xBD, 0x91, 0xA4, 0xAE, 0x94, 0x0C, +0xAD, 0x52, 0xD6, 0x96, 0xDE, 0xB7, 0xD6, 0x76, +0xD6, 0x76, 0xD6, 0x97, 0xD6, 0x76, 0xD6, 0x97, +0xD6, 0x97, 0xC5, 0xF4, 0x94, 0x6F, 0x4A, 0x67, +0x39, 0xC6, 0x41, 0xE7, 0x39, 0xE7, 0x52, 0xAA, +0x73, 0x8E, 0x4A, 0x69, 0x5A, 0xCA, 0x73, 0x6D, +0x83, 0xAE, 0x73, 0xAE, 0xEF, 0x7C, 0xEF, 0x5B, +0xBD, 0xB5, 0xAD, 0x32, 0xAD, 0x31, 0xAD, 0x11, +0xC5, 0xD4, 0xB5, 0x93, 0xBD, 0xB3, 0xBD, 0xB4, +0xB5, 0x72, 0xB5, 0x72, 0xAD, 0x31, 0xAD, 0x31, +0xA4, 0xF0, 0xA4, 0xEF, 0xA4, 0xCF, 0x94, 0x6D, +0xA4, 0xEF, 0xA4, 0xEF, 0xC5, 0x91, 0xCD, 0xD2, +0xD6, 0x34, 0x9C, 0x6D, 0xAD, 0x11, 0xC5, 0xF4, +0xCE, 0x55, 0xB5, 0x93, 0xAD, 0x52, 0xB5, 0x93, +0xBD, 0xB3, 0xB5, 0x52, 0xB5, 0x92, 0xBD, 0xD3, +0xBD, 0xB3, 0xC5, 0xD4, 0xBD, 0xD4, 0xC6, 0x15, +0xB5, 0x93, 0xC5, 0xD4, 0xBD, 0x92, 0xAD, 0x51, +0x94, 0x4E, 0xA4, 0xF0, 0xA4, 0xF1, 0xAD, 0x31, +0xBD, 0x71, 0xDE, 0x54, 0xCD, 0xD3, 0xB5, 0x52, +0x6A, 0xEA, 0x4A, 0x28, 0x7B, 0xCF, 0xA5, 0x14, +0x7B, 0xAF, 0x83, 0xF0, 0xAD, 0x75, 0xC5, 0xF7, +0x52, 0x8A, 0x42, 0x49, 0x73, 0xAF, 0xB5, 0x96, +0xA5, 0x14, 0x73, 0x8E, 0xAD, 0x76, 0xAD, 0x35, +0x52, 0x6A, 0x5A, 0xAB, 0xA5, 0x14, 0xDE, 0x9A, +0xF7, 0x3C, 0xEF, 0x1C, 0xB5, 0x75, 0x7B, 0xAD, +0x7B, 0xAC, 0x8C, 0x0E, 0x8C, 0x2E, 0x83, 0xED, +0x7B, 0xCD, 0x83, 0xCD, 0x8C, 0x2E, 0x8C, 0x2E, +0x94, 0x6F, 0x7B, 0xAC, 0x7B, 0xAB, 0xA4, 0xAF, +0x9C, 0x6E, 0x9C, 0x8E, 0xAC, 0xCF, 0xB5, 0x31, +0xA4, 0xD0, 0xA4, 0xB0, 0x9C, 0x8F, 0xA4, 0xB0, +0x7B, 0x8C, 0x41, 0xE6, 0x39, 0xC6, 0x39, 0xC6, +0x41, 0xE7, 0x52, 0xA9, 0x42, 0x28, 0x52, 0x8A, +0x5A, 0xEB, 0x63, 0x2C, 0x6B, 0x4D, 0x73, 0x6E, +0x7B, 0xAF, 0x9C, 0xF4, 0xBD, 0xF8, 0xCE, 0x59, +0xB5, 0x54, 0xAD, 0x12, 0xB5, 0x53, 0xAD, 0x12, +0xA4, 0xB1, 0x9C, 0x6F, 0x9C, 0x90, 0xA4, 0xD0, +0xAC, 0xF1, 0xAC, 0xF1, 0xAC, 0xF1, 0xA4, 0xD0, +0x9C, 0x6F, 0x9C, 0x6F, 0x9C, 0x6F, 0xA4, 0xB0, +0xA4, 0xD0, 0xA4, 0xD0, 0xAC, 0xF1, 0xB5, 0x52, +0xBD, 0x73, 0xB5, 0x52, 0xA4, 0xB0, 0xA4, 0x8F, +0x9C, 0x8F, 0x9C, 0x6E, 0xA4, 0xD0, 0xB5, 0x52, +0xC5, 0xD3, 0xC5, 0xB3, 0xBD, 0x92, 0xCD, 0xF4, +0xC5, 0xB3, 0xC5, 0xB3, 0xCE, 0x14, 0xD6, 0x55, +0xD6, 0x34, 0xD6, 0x35, 0xD6, 0x34, 0xDE, 0x75, +0xDE, 0x76, 0xDE, 0x55, 0xCD, 0xF4, 0xA4, 0xF1, +0xAC, 0xF1, 0xBD, 0x93, 0xB5, 0x53, 0xBD, 0x94, +0xBD, 0xD4, 0xBD, 0xB4, 0xBD, 0xB4, 0xAD, 0x53, +0xA4, 0xF1, 0xC5, 0xF5, 0xB5, 0x93, 0xC5, 0xF5, +0xB5, 0x73, 0xAD, 0x53, 0xBD, 0xB5, 0xBD, 0xB4, +0xBD, 0xB4, 0xAD, 0x12, 0xBD, 0x93, 0xBD, 0xB3, +0xC5, 0xB3, 0xAD, 0x31, 0xA4, 0xF0, 0xAD, 0x11, +0xAD, 0x32, 0xA4, 0xF0, 0x9C, 0x8E, 0xA4, 0xD0, +0x9C, 0x6E, 0xA4, 0xD0, 0xAC, 0xF0, 0xB5, 0x31, +0xB5, 0x31, 0xA4, 0xD0, 0xA4, 0x8F, 0x9C, 0x8F, +0xA4, 0xD0, 0x9C, 0x6E, 0x94, 0x2D, 0x9C, 0x8F, +0x94, 0x6E, 0x94, 0x4E, 0xAC, 0xF1, 0xAC, 0xF1, +0xAC, 0xF0, 0xA4, 0xD0, 0xBD, 0x72, 0xAC, 0xF0, +0xAC, 0xF0, 0xB5, 0x52, 0x83, 0xEE, 0x39, 0xC6, +0x29, 0x44, 0x29, 0x44, 0x29, 0x45, 0x29, 0x45, +0x29, 0x65, 0x41, 0xE7, 0x6B, 0x2D, 0x7B, 0xCF, +0x4A, 0x49, 0x62, 0xEB, 0x5A, 0x8A, 0x52, 0x6A, +0x41, 0xE8, 0x5A, 0xAB, 0x83, 0xAE, 0xA4, 0xD3, +0x94, 0x51, 0x41, 0xE8, 0x10, 0x82, 0x10, 0xA3, +0x21, 0x04, 0x52, 0x68, 0xD6, 0x55, 0xEF, 0x18, +0xEE, 0xD7, 0xE6, 0xD7, 0xE6, 0xB7, 0xDE, 0xB8, +0xCE, 0x57, 0xC6, 0x16, 0xC6, 0x16, 0xC6, 0x16, +0xCE, 0x77, 0xD6, 0x97, 0xCE, 0x57, 0xBD, 0xF6, +0xCE, 0x37, 0xD6, 0x98, 0xDE, 0xB8, 0xDE, 0xB8, +0xDE, 0xB8, 0xDE, 0xB8, 0xE6, 0xD9, 0xE6, 0xB8, +0xDE, 0xB8, 0xA4, 0xF2, 0xBD, 0xB4, 0xD6, 0x34, +0xD6, 0x34, 0xDE, 0x74, 0xDE, 0x75, 0xDE, 0x75, +0xDE, 0x55, 0xDE, 0x75, 0xE6, 0x96, 0xD6, 0x34, +0xDE, 0x55, 0xDE, 0x55, 0xE6, 0x95, 0xE6, 0x95, +0xE6, 0x75, 0xE6, 0x95, 0xE6, 0x95, 0xEE, 0xB6, +0xE6, 0x95, 0xE6, 0xB5, 0xE6, 0xB6, 0xEE, 0xD6, +0x74, 0x2C, 0x53, 0x47, 0x63, 0xC8, 0x6C, 0x09, +0x5B, 0x89, 0x74, 0x2C, 0x74, 0x0B, 0x53, 0x27, +0x6C, 0x29, 0x43, 0x03, 0x53, 0x65, 0x53, 0xA7, +0x6C, 0x69, 0x74, 0x89, 0x8C, 0xEA, 0x95, 0x49, +0x9D, 0x6A, 0x9C, 0xCA, 0x94, 0x8B, 0x84, 0x2A, +0x9C, 0xEE, 0xAD, 0x0F, 0xA4, 0x8D, 0x94, 0x2C, +0x8B, 0xCB, 0x8C, 0x0C, 0x94, 0x2D, 0x94, 0x4D, +0x9C, 0x6D, 0x9C, 0x6E, 0xA4, 0xF0, 0xAC, 0xF0, +0x94, 0x2D, 0x83, 0xCC, 0x9C, 0x6E, 0x9C, 0x6F, +0x52, 0x47, 0x39, 0xC6, 0x42, 0x07, 0x4A, 0x48, +0x52, 0xAA, 0x52, 0x89, 0x4A, 0x49, 0x41, 0xE7, +0x63, 0x0C, 0x63, 0x0C, 0xBD, 0xD7, 0xEF, 0x5D, +0xEF, 0x7D, 0xDE, 0xBA, 0x94, 0x91, 0x6B, 0x2B, +0x9C, 0xD0, 0xBD, 0xB4, 0xC5, 0xF4, 0xBD, 0xD4, +0xBD, 0xB3, 0xB5, 0x93, 0xAD, 0x52, 0xB5, 0x72, +0xAD, 0x31, 0xA5, 0x10, 0x8C, 0x0C, 0x94, 0x4D, +0xA4, 0xAE, 0xC5, 0xB1, 0xD6, 0x12, 0xD6, 0x12, +0xDE, 0x54, 0x8B, 0xCB, 0x8C, 0x2D, 0xAD, 0x31, +0xB5, 0x92, 0xA5, 0x11, 0xA5, 0x11, 0x9C, 0xD1, +0xAD, 0x52, 0xA5, 0x11, 0xB5, 0xB3, 0xAD, 0x52, +0xB5, 0x72, 0xBD, 0xB3, 0xBD, 0xD3, 0xBD, 0xD4, +0xC5, 0xF4, 0xC5, 0xF4, 0xBD, 0x92, 0xA4, 0xF0, +0x9C, 0xB0, 0x8C, 0x2E, 0x83, 0xED, 0x94, 0x6E, +0xB5, 0x30, 0xDE, 0x34, 0xC5, 0x91, 0xC5, 0xB2, +0xA4, 0xAF, 0x8C, 0x0D, 0x6B, 0x2B, 0x84, 0x10, +0x73, 0xAF, 0xA5, 0x14, 0x9C, 0xF3, 0xB5, 0x75, +0xA5, 0x14, 0x52, 0x8A, 0x39, 0xE8, 0x73, 0xAF, +0xC6, 0x18, 0xA5, 0x14, 0xBD, 0xF7, 0xBD, 0xD7, +0x9C, 0xB2, 0xC5, 0xD7, 0xDE, 0xDA, 0xE6, 0xBA, +0xF7, 0x5D, 0xEE, 0xFB, 0xDE, 0x79, 0x94, 0x70, +0x9C, 0x90, 0xA4, 0xF1, 0xAD, 0x12, 0xAD, 0x12, +0x9C, 0xB0, 0x9C, 0xB0, 0x9C, 0xB0, 0xA4, 0xF1, +0xBD, 0xB4, 0xAD, 0x12, 0x8C, 0x2E, 0x9C, 0xB0, +0x9C, 0xAF, 0x9C, 0x8F, 0xAC, 0xF0, 0xBD, 0x72, +0xB5, 0x52, 0x94, 0x6F, 0xB5, 0x93, 0xC5, 0xF5, +0xB5, 0x53, 0x52, 0x48, 0x39, 0xA5, 0x39, 0xC6, +0x31, 0x85, 0x42, 0x28, 0x42, 0x28, 0x5A, 0xEB, +0x6B, 0x4C, 0x63, 0x0C, 0x63, 0x2C, 0x7B, 0xAF, +0x8C, 0x72, 0xA5, 0x35, 0xB5, 0xB7, 0xC6, 0x18, +0xCE, 0x17, 0x9C, 0x91, 0xAC, 0xF1, 0xC5, 0xD5, +0xBD, 0xB4, 0xAD, 0x32, 0xBD, 0x93, 0xAC, 0xF1, +0xA4, 0xD0, 0xAC, 0xF1, 0xA4, 0xF1, 0xA4, 0xF1, +0xAD, 0x12, 0xAC, 0xF1, 0xA4, 0xD0, 0xAC, 0xF1, +0xA4, 0x90, 0xA4, 0xD0, 0xA4, 0xF0, 0xAC, 0xF0, +0xAC, 0xF1, 0xAD, 0x12, 0xB5, 0x52, 0xB5, 0x32, +0xB5, 0x52, 0xB5, 0x12, 0xB5, 0x32, 0xA4, 0x8F, +0x8B, 0xED, 0xA4, 0xD0, 0xB5, 0x31, 0xB5, 0x31, +0xAD, 0x10, 0xAD, 0x11, 0xA4, 0xD0, 0xAC, 0xF0, +0xA4, 0xD0, 0xAC, 0xF0, 0xAD, 0x10, 0xB5, 0x11, +0xB5, 0x10, 0xAD, 0x10, 0xB5, 0x11, 0xB5, 0x31, +0xB5, 0x72, 0xB5, 0x52, 0xA4, 0xF1, 0xA4, 0xD0, +0x9C, 0xB0, 0xAD, 0x11, 0xAD, 0x32, 0xAD, 0x11, +0x9C, 0xD0, 0xA4, 0xF1, 0xA4, 0xD1, 0x9C, 0xB0, +0x94, 0x90, 0xA4, 0xF1, 0xA4, 0xF1, 0xA4, 0xF1, +0xAD, 0x32, 0x9C, 0xB1, 0xA4, 0xF1, 0xAD, 0x32, +0xBD, 0x93, 0xAC, 0xF0, 0xB5, 0x52, 0xAD, 0x11, +0xB5, 0x52, 0xAD, 0x31, 0xAD, 0x10, 0xBD, 0x93, +0xAC, 0xF0, 0xB5, 0x32, 0xBD, 0x73, 0xB5, 0x31, +0xC5, 0xB3, 0xAD, 0x11, 0xAD, 0x11, 0xA4, 0xD0, +0xA4, 0xD0, 0x9C, 0x6F, 0xA4, 0xB0, 0xAC, 0xF1, +0xA4, 0xD0, 0x9C, 0xAF, 0xB5, 0x52, 0xB5, 0x11, +0xAC, 0xF1, 0xAD, 0x11, 0xAD, 0x11, 0xAC, 0xF0, +0xB5, 0x52, 0xBD, 0x73, 0xBD, 0xD4, 0xA4, 0xD1, +0x5A, 0xCA, 0x31, 0x85, 0x29, 0x24, 0x21, 0x03, +0x29, 0x24, 0x29, 0x65, 0x29, 0x65, 0x39, 0xC7, +0x41, 0xE7, 0x4A, 0x28, 0x5A, 0xAB, 0x52, 0x49, +0x4A, 0x29, 0x4A, 0x08, 0x83, 0xAF, 0x83, 0xAE, +0xB5, 0x34, 0xA4, 0xD3, 0x41, 0xE8, 0x18, 0xC4, +0x63, 0x0B, 0xAC, 0xF1, 0xF7, 0x18, 0xE6, 0xD7, +0xE6, 0xD6, 0xE6, 0xB6, 0xDE, 0x96, 0xE6, 0xD8, +0xE6, 0xD8, 0xDE, 0xB8, 0xDE, 0xB8, 0xDE, 0xB8, +0xDE, 0xB8, 0xDE, 0x97, 0xDE, 0x97, 0xDE, 0x98, +0xDE, 0xD8, 0xDE, 0xD8, 0xDE, 0xB7, 0xDE, 0xB8, +0xE6, 0xD8, 0xE6, 0xF8, 0xE6, 0xF8, 0xE6, 0xD8, +0xDE, 0xB8, 0xAD, 0x12, 0xA4, 0xD0, 0xE6, 0xB6, +0xE6, 0x95, 0xE6, 0x74, 0xE6, 0x75, 0xDE, 0x75, +0xE6, 0x96, 0xDE, 0x75, 0xDE, 0x55, 0xDE, 0x75, +0xDE, 0x75, 0xDE, 0x75, 0xE6, 0x95, 0xE6, 0x95, +0xEE, 0xB5, 0xEE, 0xB5, 0xE6, 0x95, 0xE6, 0x95, +0xE6, 0x54, 0xDE, 0x54, 0xDE, 0x34, 0xDE, 0x34, +0x6C, 0x0A, 0x6C, 0x2A, 0x6C, 0x4A, 0x63, 0xE9, +0x6B, 0xEA, 0x8C, 0xCE, 0x42, 0x85, 0x3A, 0x84, +0x53, 0x86, 0x74, 0x68, 0x53, 0xA6, 0x43, 0x45, +0x64, 0x68, 0x5C, 0x25, 0x95, 0x6A, 0xA5, 0xAA, +0x9D, 0x69, 0x84, 0x88, 0x7C, 0x48, 0x8C, 0xEC, +0xAD, 0x6F, 0xCD, 0xF3, 0xCD, 0xD3, 0xCD, 0xD2, +0xC5, 0x92, 0xAC, 0xEF, 0xB5, 0x30, 0xC5, 0x92, +0xCD, 0xF3, 0xD5, 0xF4, 0xD5, 0xF3, 0xCD, 0xB2, +0xCD, 0xD3, 0xCD, 0xD2, 0xA4, 0x8E, 0x9C, 0x6D, +0xB5, 0x52, 0x6B, 0x2A, 0x41, 0xE7, 0x4A, 0x48, +0x52, 0x89, 0x52, 0x69, 0x42, 0x28, 0x39, 0xC6, +0x41, 0xE7, 0x41, 0xE7, 0x39, 0xC7, 0x7B, 0xF0, +0xC6, 0x18, 0xEF, 0x7D, 0xEF, 0x3D, 0xAD, 0x34, +0x8C, 0x0E, 0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x31, +0xBD, 0x93, 0xA4, 0xF0, 0xA4, 0xF0, 0xAD, 0x31, +0xAD, 0x10, 0xA4, 0xF0, 0x94, 0x6E, 0x94, 0x4D, +0xA4, 0xAE, 0xDE, 0x74, 0xE6, 0x74, 0xDE, 0x33, +0xD6, 0x13, 0x8C, 0x0C, 0x94, 0x4E, 0x9C, 0xAF, +0x9C, 0xB0, 0x8C, 0x4E, 0x8C, 0x4E, 0x94, 0x90, +0x9C, 0xB0, 0x8C, 0x4E, 0xA5, 0x32, 0xB5, 0x73, +0xB5, 0x52, 0xB5, 0x52, 0xB5, 0x72, 0xBD, 0xB3, +0xBD, 0xD4, 0xBD, 0x93, 0xB5, 0x72, 0x9C, 0xAF, +0xAD, 0x10, 0xA5, 0x11, 0xA4, 0xF0, 0xAD, 0x10, +0xAD, 0x0F, 0xDE, 0x34, 0xCD, 0xD2, 0xD5, 0xF3, +0xAC, 0xAE, 0x8B, 0xEC, 0x9C, 0x8F, 0x73, 0x6C, +0x8C, 0x30, 0x7B, 0xCF, 0x7B, 0xAF, 0x94, 0x72, +0xB5, 0x75, 0xB5, 0x75, 0x42, 0x07, 0x4A, 0x49, +0x7B, 0xAE, 0x6B, 0x4D, 0x9C, 0xD3, 0xAD, 0x14, +0xCD, 0xF7, 0xBD, 0x75, 0xC5, 0xF7, 0xD6, 0x38, +0xCE, 0x18, 0xE6, 0xBA, 0xCE, 0x17, 0xB5, 0x34, +0xBD, 0xB4, 0xB5, 0x73, 0xAD, 0x12, 0xB5, 0x53, +0xB5, 0x93, 0xB5, 0x73, 0xAD, 0x32, 0x9C, 0x8F, +0xAD, 0x32, 0xA4, 0xD1, 0x94, 0x90, 0xA4, 0xF1, +0xB5, 0x73, 0xAC, 0xF0, 0xAD, 0x10, 0xCD, 0xF4, +0xC6, 0x14, 0xA4, 0xD0, 0x6B, 0x6B, 0xA5, 0x11, +0xC5, 0xD4, 0x7B, 0xCD, 0x41, 0xE6, 0x39, 0xC6, +0x31, 0x85, 0x39, 0xC6, 0x4A, 0x28, 0x4A, 0x69, +0x4A, 0x69, 0x5A, 0xCA, 0x63, 0x2D, 0x73, 0x8F, +0x84, 0x31, 0x94, 0x93, 0x9C, 0xD3, 0xB5, 0x76, +0xA5, 0x14, 0xAD, 0x13, 0xA4, 0xF1, 0xC5, 0xF5, +0xB5, 0x73, 0xAD, 0x11, 0xB5, 0x73, 0xCE, 0x36, +0xC5, 0xF5, 0xC5, 0xF5, 0xC5, 0xD4, 0xC5, 0xF5, +0xCD, 0xF5, 0xC5, 0xB4, 0xBD, 0x93, 0xBD, 0x93, +0xBD, 0xB4, 0xB5, 0x32, 0xB5, 0x32, 0xA4, 0xD0, +0xB5, 0x32, 0xBD, 0x94, 0xCE, 0x15, 0xBD, 0xB3, +0xCE, 0x15, 0xA4, 0xB0, 0xC5, 0x93, 0xDE, 0x76, +0xCE, 0x14, 0xBD, 0x72, 0xB5, 0x31, 0xA4, 0xD0, +0xAC, 0xF1, 0xAC, 0xF1, 0xAC, 0xF1, 0xB5, 0x32, +0xBD, 0x72, 0xB5, 0x52, 0xB5, 0x31, 0xB5, 0x32, +0xBD, 0x72, 0xB5, 0x52, 0xAC, 0xD0, 0xB5, 0x31, +0xBD, 0x72, 0xAD, 0x11, 0xA4, 0xB0, 0xA4, 0xD1, +0xA4, 0xF1, 0xA4, 0xF1, 0x9C, 0x90, 0xA4, 0xD0, +0xAD, 0x12, 0xA4, 0xF1, 0xA4, 0xD1, 0xAD, 0x11, +0xA4, 0xF1, 0x9C, 0xB0, 0xA4, 0xD1, 0xA4, 0xF1, +0xA4, 0xF2, 0x9C, 0xB1, 0x9C, 0xB0, 0x94, 0x4F, +0x94, 0x4E, 0x94, 0x4E, 0x8C, 0x0D, 0x94, 0x4E, +0xA4, 0xB0, 0xA4, 0xB0, 0xB5, 0x11, 0xAC, 0xD0, +0xB5, 0x11, 0xAC, 0xD0, 0xAC, 0xF0, 0xB5, 0x32, +0xBD, 0x52, 0xA4, 0xD0, 0xA4, 0x8F, 0xA4, 0xD0, +0xA4, 0xAF, 0xA4, 0xD0, 0xAD, 0x11, 0xAC, 0xF0, +0xB5, 0x31, 0xB5, 0x52, 0xBD, 0x72, 0xC5, 0x93, +0xCD, 0xF4, 0xC5, 0xB3, 0xBD, 0x93, 0xBD, 0x72, +0xC5, 0x93, 0xAC, 0xF1, 0xC5, 0xB4, 0xC5, 0xF5, +0xC5, 0xD5, 0x73, 0x6C, 0x39, 0xC6, 0x29, 0x44, +0x29, 0x45, 0x29, 0x65, 0x29, 0x44, 0x29, 0x65, +0x31, 0xA6, 0x29, 0x45, 0x42, 0x28, 0x62, 0xEB, +0x5A, 0xAA, 0x4A, 0x49, 0x4A, 0x08, 0x7B, 0x8E, +0x83, 0xAE, 0xB5, 0x33, 0x7B, 0x8E, 0x5A, 0x8A, +0x94, 0x50, 0xBD, 0x53, 0xF7, 0x18, 0xEE, 0xD7, +0xE6, 0xB6, 0xDE, 0x75, 0xD6, 0x35, 0xDE, 0x56, +0xDE, 0x97, 0xE6, 0xD8, 0xE6, 0xD8, 0xDE, 0xB7, +0xE6, 0xF8, 0xE6, 0xF8, 0xE6, 0xD8, 0xE6, 0xF8, +0xE6, 0xD8, 0xE6, 0xD8, 0xDE, 0xD7, 0xDE, 0xD7, +0xE6, 0xD8, 0xDE, 0x97, 0xD6, 0x56, 0xE6, 0xF8, +0xDE, 0xB8, 0xA4, 0xF1, 0xE6, 0x96, 0xEE, 0xD6, +0xE6, 0x74, 0xDE, 0x33, 0xD6, 0x13, 0xD5, 0xF3, +0xD6, 0x34, 0xD6, 0x54, 0xD6, 0x34, 0xD6, 0x13, +0xD6, 0x13, 0xDE, 0x34, 0xE6, 0x74, 0xE6, 0x75, +0xDE, 0x53, 0xE6, 0x53, 0xE6, 0x74, 0xE6, 0x53, +0xDE, 0x53, 0xDE, 0x33, 0xDE, 0x34, 0xDE, 0x54, +0x5B, 0x88, 0x5B, 0xE9, 0x53, 0x87, 0x4B, 0x46, +0x6C, 0x29, 0x74, 0x6A, 0x64, 0x08, 0x53, 0x86, +0x53, 0xC6, 0x6C, 0x68, 0x5C, 0x07, 0x3A, 0xE3, +0x53, 0xE6, 0x74, 0xA8, 0xA5, 0xEB, 0x7C, 0xA6, +0x63, 0xE3, 0x74, 0x46, 0x7C, 0x87, 0x8C, 0xEA, +0xAD, 0x4E, 0xC5, 0xB1, 0xCD, 0xD2, 0xC5, 0x91, +0xD6, 0x13, 0xCD, 0xD2, 0xB5, 0x30, 0xB5, 0x30, +0xC5, 0x92, 0xC5, 0x71, 0xD5, 0xF3, 0xD5, 0xF3, +0xD5, 0xD3, 0xD6, 0x13, 0xCD, 0xB2, 0xD6, 0x14, +0xBD, 0xB3, 0x62, 0xEA, 0x4A, 0x27, 0x31, 0xA6, +0x42, 0x07, 0x39, 0xE6, 0x39, 0xA6, 0x4A, 0x28, +0x5A, 0xAA, 0x4A, 0x48, 0x39, 0xC7, 0x42, 0x08, +0x42, 0x08, 0x73, 0x8E, 0xB5, 0x96, 0x7B, 0xAE, +0xAD, 0x13, 0x94, 0x70, 0x8C, 0x0E, 0x8B, 0xEC, +0x94, 0x0D, 0x8B, 0xEC, 0x94, 0x2C, 0x9C, 0x8E, +0x9C, 0x6D, 0x94, 0x2C, 0x8B, 0xEB, 0x8B, 0xEB, +0x9C, 0x6D, 0xAC, 0xEE, 0xBD, 0x2F, 0xBD, 0x2F, +0xBD, 0x30, 0xA4, 0xAE, 0x8B, 0xEC, 0x7B, 0x6A, +0x6B, 0x09, 0x62, 0xE9, 0x63, 0x09, 0x7B, 0xAC, +0x7B, 0xAC, 0x6B, 0x4B, 0xA4, 0xD1, 0xBD, 0xD4, +0xBD, 0xB3, 0xBD, 0x92, 0xB5, 0x72, 0xBD, 0xB3, +0xB5, 0x92, 0xA4, 0xF0, 0xAD, 0x10, 0x9C, 0x8E, +0x9C, 0x8E, 0x9C, 0x8E, 0x94, 0x6D, 0xB5, 0x51, +0xAC, 0xEF, 0xDE, 0x54, 0xDE, 0x34, 0xDE, 0x34, +0xAC, 0xAE, 0x9C, 0x2D, 0xAC, 0xCF, 0xB5, 0x31, +0xA4, 0xF1, 0x8C, 0x30, 0x31, 0x66, 0x62, 0xEB, +0x94, 0x71, 0xAD, 0x34, 0x6B, 0x4C, 0x42, 0x28, +0x52, 0x8A, 0x73, 0x8E, 0x7B, 0xCF, 0x9C, 0x92, +0x83, 0xCF, 0x73, 0x6D, 0xB5, 0x96, 0xBD, 0xD6, +0xEF, 0x1B, 0xDE, 0x9A, 0xAD, 0x35, 0xAD, 0x55, +0xB5, 0x95, 0xBD, 0xD6, 0x94, 0x90, 0x94, 0x70, +0xAD, 0x53, 0xA4, 0xF2, 0x9C, 0xD1, 0x94, 0x4F, +0x8C, 0x2F, 0xCE, 0x38, 0xE6, 0xFB, 0xBD, 0xB5, +0xAD, 0x31, 0x9C, 0x8F, 0xAC, 0xF0, 0xCE, 0x14, +0xCE, 0x35, 0xBD, 0xD4, 0xA4, 0xF1, 0x8C, 0x2E, +0xAD, 0x31, 0x94, 0x70, 0x4A, 0x28, 0x31, 0xA5, +0x39, 0xC6, 0x42, 0x07, 0x42, 0x28, 0x4A, 0x49, +0x42, 0x28, 0x52, 0xAA, 0x63, 0x0C, 0x6B, 0x4D, +0x6B, 0x6E, 0x73, 0xAF, 0x84, 0x11, 0xA5, 0x35, +0xAD, 0x75, 0xDE, 0x9A, 0xB5, 0x54, 0xCE, 0x16, +0xBD, 0x93, 0xAC, 0xF1, 0x94, 0x6F, 0xCE, 0x36, +0xD6, 0x76, 0xD6, 0x56, 0xCE, 0x15, 0xC5, 0xF4, +0xBD, 0x73, 0xAC, 0xF1, 0xA4, 0xB0, 0xAD, 0x32, +0xB5, 0x73, 0xBD, 0x93, 0xD6, 0x36, 0xCD, 0xF4, +0xBD, 0x73, 0xCD, 0xF4, 0xC5, 0x93, 0xB5, 0x72, +0xC5, 0xB3, 0xAD, 0x11, 0xC5, 0xB3, 0xDE, 0x55, +0xCD, 0xD4, 0xBD, 0x72, 0xC5, 0xD4, 0xC5, 0xB3, +0xC5, 0x93, 0xC5, 0x93, 0xC5, 0xB3, 0xCD, 0xD4, +0xCD, 0xD4, 0xD6, 0x15, 0xAD, 0x11, 0xAD, 0x11, +0xBD, 0x93, 0xB5, 0x72, 0xB5, 0x73, 0xB5, 0x73, +0x9C, 0x8F, 0xA4, 0xF1, 0xAD, 0x32, 0xBD, 0x94, +0xAD, 0x32, 0xA4, 0xD1, 0xAD, 0x11, 0x9C, 0xB0, +0x73, 0x6B, 0x7B, 0xAC, 0x83, 0xCD, 0x94, 0x6F, +0x9C, 0x6F, 0x9C, 0x90, 0xA4, 0xF1, 0xB5, 0x53, +0xB5, 0x53, 0xB5, 0x32, 0xB5, 0x32, 0xB5, 0x52, +0xB5, 0x31, 0xAD, 0x31, 0xAD, 0x11, 0xAC, 0xD0, +0xA4, 0xD0, 0xA4, 0x8F, 0x9C, 0x4E, 0x9C, 0x4E, +0x9C, 0x4E, 0x9C, 0x4E, 0xA4, 0xB0, 0xAC, 0xD0, +0xA4, 0xAF, 0xAC, 0xD0, 0xA4, 0xD0, 0xAC, 0xD0, +0xAC, 0xF0, 0xAC, 0xD0, 0xAC, 0xD0, 0xA4, 0xAF, +0x9C, 0x8F, 0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0x8F, +0xA4, 0x8F, 0x9C, 0x6E, 0xAC, 0xD0, 0xA4, 0x8F, +0x94, 0x2E, 0x94, 0x2E, 0x9C, 0x8F, 0xAD, 0x11, +0xAD, 0x32, 0xA4, 0xD0, 0x73, 0x6B, 0x42, 0x07, +0x31, 0x85, 0x29, 0x65, 0x29, 0x44, 0x31, 0x85, +0x42, 0x07, 0x42, 0x07, 0x4A, 0x28, 0x39, 0xC6, +0x62, 0xEB, 0x6B, 0x0C, 0x49, 0xE7, 0x5A, 0x8A, +0x83, 0xAE, 0x83, 0x8D, 0x73, 0x6D, 0x73, 0x2C, +0x73, 0x2C, 0x6A, 0xEA, 0xBD, 0x73, 0xCD, 0xF4, +0xC5, 0xB3, 0xC5, 0x93, 0xAC, 0xF1, 0xC5, 0xB4, +0xBD, 0x93, 0xCE, 0x15, 0xD6, 0x56, 0xD6, 0x35, +0xE6, 0xB7, 0xDE, 0x97, 0xDE, 0xB7, 0xE6, 0xB8, +0xE6, 0xB7, 0xE6, 0xB7, 0xE6, 0xD8, 0xE6, 0xB7, +0xE6, 0xF8, 0xDE, 0x97, 0xDE, 0x77, 0xE6, 0xF8, +0xDE, 0xB7, 0xA4, 0xD0, 0xF7, 0x18, 0xEE, 0xD6, +0xE6, 0x75, 0xDE, 0x33, 0xD5, 0xF3, 0xD6, 0x14, +0xDE, 0x55, 0xDE, 0x54, 0xDE, 0x55, 0xE6, 0x75, +0xDE, 0x54, 0xDE, 0x54, 0xDE, 0x54, 0xDE, 0x54, +0xDE, 0x33, 0xDE, 0x33, 0xDE, 0x13, 0xE6, 0x54, +0xDE, 0x33, 0xDE, 0x33, 0xE6, 0x74, 0xE6, 0x95, +0x21, 0xE3, 0x4B, 0x27, 0x32, 0xC4, 0x3A, 0xC4, +0x53, 0xA6, 0x43, 0x24, 0x43, 0x44, 0x3B, 0x04, +0x64, 0x08, 0x3B, 0x03, 0x53, 0xC6, 0x43, 0x45, +0x5B, 0xC7, 0x9D, 0xCE, 0x63, 0xC6, 0x6C, 0x08, +0x8C, 0xEC, 0xB5, 0xF0, 0xCE, 0x51, 0xC5, 0xF0, +0xBD, 0x8F, 0xBD, 0x70, 0xBD, 0x30, 0xB5, 0x0F, +0xCD, 0xB2, 0xCD, 0xB2, 0xBD, 0x71, 0xC5, 0x92, +0xCD, 0xB2, 0xCD, 0xD3, 0xD6, 0x14, 0xD5, 0xF3, +0xD5, 0xF3, 0xD5, 0xD3, 0xD6, 0x13, 0xD6, 0x14, +0x6A, 0xEA, 0x7B, 0xCD, 0x73, 0x6B, 0x4A, 0x27, +0x39, 0x85, 0x31, 0xA6, 0x31, 0xA6, 0x41, 0xE7, +0x52, 0x89, 0x62, 0xEB, 0x52, 0x89, 0x63, 0x0B, +0x73, 0x4D, 0x7B, 0x8E, 0x8C, 0x51, 0x73, 0x6E, +0xC6, 0x38, 0xEF, 0x3C, 0xB5, 0x75, 0x8C, 0x0E, +0x9C, 0x8F, 0xA4, 0xAF, 0x8B, 0xEC, 0x83, 0xCB, +0x8C, 0x0C, 0xA4, 0xAE, 0xB4, 0xEF, 0xB5, 0x10, +0xBD, 0x51, 0xC5, 0x91, 0xC5, 0x71, 0xAC, 0xCE, +0xB4, 0xEF, 0xBD, 0x50, 0xBD, 0x31, 0xAC, 0xAF, +0x9C, 0x6E, 0xA4, 0xAE, 0xAC, 0xCF, 0xA4, 0xAE, +0x9C, 0x4D, 0x94, 0x2D, 0x94, 0x2D, 0x94, 0x2D, +0x9C, 0x4D, 0xA4, 0xAE, 0xA4, 0x8E, 0xA4, 0x8E, +0x9C, 0x8E, 0x9C, 0x8E, 0xA4, 0xAE, 0xA4, 0xAE, +0xAC, 0xCF, 0xA4, 0xAE, 0x94, 0x0C, 0x9C, 0x6D, +0xA4, 0x8D, 0xCD, 0xF2, 0xCD, 0xF3, 0xBD, 0x51, +0x8B, 0xCB, 0x8B, 0xEC, 0xAC, 0xCE, 0xAC, 0xEF, +0xAD, 0x10, 0x6B, 0x0A, 0x39, 0xA6, 0x31, 0xA6, +0x6B, 0x2C, 0x8C, 0x30, 0x73, 0x6C, 0x5A, 0xCB, +0x6B, 0x6D, 0x6B, 0x2C, 0x7B, 0xAE, 0x8C, 0x30, +0x94, 0x30, 0x94, 0x30, 0x73, 0x4D, 0x94, 0x71, +0xE6, 0xFB, 0x94, 0x92, 0x6B, 0x2D, 0xA5, 0x14, +0x5A, 0xAB, 0x94, 0x91, 0x84, 0x0F, 0x8C, 0x50, +0x94, 0x91, 0x9C, 0xB2, 0x94, 0x51, 0x9C, 0x91, +0xC6, 0x18, 0xEF, 0x5D, 0xCE, 0x59, 0x9C, 0xD2, +0xA4, 0xF1, 0xA4, 0xCF, 0xB5, 0x10, 0xCE, 0x14, +0xC5, 0xD3, 0x9C, 0xD0, 0xB5, 0x52, 0xAD, 0x72, +0xB5, 0x73, 0xB5, 0x74, 0x6B, 0x2B, 0x39, 0xC6, +0x42, 0x07, 0x5A, 0xAA, 0x52, 0xAA, 0x52, 0x8A, +0x63, 0x0B, 0x6B, 0x6D, 0x73, 0x8D, 0x5A, 0xCB, +0x52, 0x8A, 0x6B, 0x4D, 0x7B, 0xF0, 0x8C, 0x92, +0xA5, 0x35, 0xC6, 0x38, 0xBD, 0xF6, 0xCE, 0x16, +0xCE, 0x15, 0xAD, 0x32, 0xA4, 0xD1, 0xD6, 0x56, +0xDE, 0x97, 0xDE, 0x76, 0xD6, 0x76, 0xCE, 0x35, +0xBD, 0x93, 0xAD, 0x11, 0xA4, 0xF1, 0xA4, 0xF1, +0xA4, 0xF1, 0xB5, 0x73, 0xCE, 0x15, 0xCD, 0xF4, +0xB5, 0x52, 0xAD, 0x31, 0xAC, 0xF0, 0xBD, 0x93, +0xBD, 0x93, 0xB5, 0x11, 0xBD, 0x93, 0xCD, 0xD3, +0xC5, 0x92, 0xB5, 0x31, 0xC5, 0xB3, 0xC5, 0xB3, +0xBD, 0x52, 0xBD, 0x72, 0xB5, 0x51, 0xBD, 0x72, +0xC5, 0xB3, 0xCD, 0xF4, 0xB5, 0x32, 0x9C, 0x6F, +0xA4, 0xF1, 0xB5, 0x52, 0xC5, 0xD4, 0xD6, 0x57, +0xBD, 0xD5, 0xBD, 0xD4, 0xBD, 0xB4, 0xBD, 0x94, +0xBD, 0xB4, 0xC5, 0xD4, 0xB5, 0x52, 0xA4, 0xD1, +0x7B, 0xAC, 0x7B, 0xCD, 0x7B, 0xCC, 0x8C, 0x0E, +0x9C, 0x6F, 0x8C, 0x2E, 0x83, 0xED, 0x83, 0xAC, +0x83, 0x8C, 0x83, 0xAC, 0x7B, 0x8B, 0x83, 0xAC, +0x8B, 0xED, 0x9C, 0x6E, 0xA4, 0xB0, 0x9C, 0x6E, +0xA4, 0x8F, 0xA4, 0x8F, 0x94, 0x0D, 0x94, 0x2E, +0x83, 0xAB, 0x83, 0xAB, 0xA4, 0xB0, 0x9C, 0x6F, +0x8B, 0xED, 0x83, 0xAC, 0x8B, 0xED, 0x9C, 0x4E, +0x94, 0x2E, 0x9C, 0x4E, 0xA4, 0x8F, 0xA4, 0x8F, +0x9C, 0x4E, 0xAC, 0xD0, 0xAD, 0x11, 0xAC, 0xF0, +0xB5, 0x32, 0xAC, 0xF0, 0xAC, 0xF0, 0xAD, 0x11, +0xB5, 0x52, 0xBD, 0x73, 0xBD, 0x94, 0xBD, 0xB4, +0xBD, 0x93, 0xBD, 0x93, 0xBD, 0x94, 0xA4, 0xF2, +0x5A, 0xCA, 0x31, 0xA6, 0x29, 0x65, 0x31, 0x85, +0x39, 0xC6, 0x41, 0xE7, 0x4A, 0x68, 0x42, 0x07, +0x31, 0xA6, 0x52, 0x69, 0x5A, 0xAA, 0x6B, 0x0C, +0x5A, 0xAA, 0x4A, 0x28, 0x52, 0x49, 0x62, 0x8A, +0x8B, 0xCE, 0x62, 0xAA, 0x62, 0x89, 0x94, 0x4F, +0xA4, 0xB0, 0xAD, 0x11, 0x94, 0x4F, 0x9C, 0x90, +0x94, 0x6F, 0xA4, 0xD0, 0xB5, 0x52, 0xB5, 0x32, +0xBD, 0x73, 0xA4, 0xD0, 0x9C, 0xB0, 0xC5, 0xD5, +0xBD, 0x52, 0xBD, 0x73, 0xBD, 0x93, 0xBD, 0x93, +0xCE, 0x15, 0xDE, 0x97, 0xE6, 0xD8, 0xE6, 0xD8, +0xDE, 0x77, 0xAC, 0xF1, 0xF7, 0x18, 0xEE, 0xD6, +0xDE, 0x54, 0xDE, 0x54, 0xE6, 0x55, 0xD6, 0x13, +0xE6, 0x96, 0xDE, 0x34, 0xE6, 0x96, 0xEE, 0xB6, +0xDE, 0x75, 0xEE, 0xD6, 0xE6, 0x95, 0xE6, 0x95, +0xE6, 0x95, 0xE6, 0x74, 0xDE, 0x54, 0xEE, 0xB5, +0xE6, 0x75, 0xDE, 0x54, 0xDE, 0x34, 0xE6, 0x95, +0x21, 0xC4, 0x43, 0x27, 0x6C, 0x4B, 0x43, 0x05, +0x4B, 0x05, 0x53, 0x66, 0x5B, 0xC8, 0x43, 0x05, +0x64, 0x09, 0x22, 0x21, 0x3B, 0x03, 0x4B, 0x45, +0x7C, 0xAB, 0x7C, 0x6A, 0xA5, 0xD1, 0xC6, 0xD5, +0xCE, 0xD6, 0xE7, 0x17, 0xD6, 0x54, 0xC5, 0x70, +0xB5, 0x0F, 0xC5, 0x91, 0xB5, 0x30, 0xB4, 0xEF, +0xBD, 0x71, 0xC5, 0x92, 0xC5, 0x92, 0xCD, 0xD3, +0xCD, 0xF3, 0xD6, 0x14, 0xCD, 0xD3, 0xCD, 0xD2, +0xD5, 0xF3, 0xDE, 0x34, 0xD6, 0x14, 0xDE, 0x35, +0xDE, 0x56, 0xDE, 0x96, 0xAC, 0xEF, 0xAC, 0xCF, +0x94, 0x2E, 0x73, 0x6C, 0x39, 0xA6, 0x29, 0x44, +0x39, 0xC6, 0x4A, 0x68, 0x52, 0x89, 0x52, 0x69, +0x73, 0x8D, 0x83, 0xEF, 0x94, 0x71, 0x73, 0x6D, +0x9C, 0xD3, 0xEF, 0x5D, 0xF7, 0x9E, 0xD6, 0x79, +0x84, 0x0E, 0x8C, 0x2E, 0x8B, 0xEE, 0x8C, 0x2E, +0x8C, 0x2E, 0x8C, 0x0D, 0xAC, 0xCF, 0xAC, 0xAF, +0xC5, 0x72, 0xCD, 0xF3, 0xC5, 0xB2, 0xAC, 0xCF, +0xA4, 0xAE, 0xA4, 0xAF, 0xAC, 0xF0, 0xAC, 0xAF, +0xA4, 0x8E, 0xAC, 0xAF, 0xB5, 0x10, 0xCD, 0xD3, +0xBD, 0x51, 0xB5, 0x10, 0xBD, 0x30, 0xB5, 0x30, +0xB5, 0x30, 0xB5, 0x30, 0xB5, 0x10, 0xBD, 0x51, +0xB5, 0x30, 0xB5, 0x10, 0xA4, 0x6D, 0xAC, 0xAE, +0xC5, 0x71, 0xBD, 0x50, 0xA4, 0x8E, 0xA4, 0x6D, +0xAC, 0xCE, 0xB4, 0xCE, 0xA4, 0x8E, 0xA4, 0x8E, +0x8B, 0xCB, 0x94, 0x2D, 0xAC, 0xEF, 0xB5, 0x0F, +0xAC, 0xCF, 0xB5, 0x10, 0x6B, 0x0A, 0x41, 0xE7, +0x52, 0x89, 0x4A, 0x49, 0x42, 0x28, 0x31, 0x86, +0x52, 0x8A, 0x62, 0xEB, 0x73, 0x4D, 0x83, 0xEF, +0xCE, 0x17, 0xCD, 0xD6, 0xA4, 0xB2, 0x73, 0x4D, +0xC5, 0xF7, 0xAD, 0x75, 0xAD, 0x55, 0xB5, 0x75, +0x94, 0x72, 0xAD, 0x75, 0x94, 0x71, 0xAD, 0x55, +0xAD, 0x55, 0xC6, 0x18, 0xB5, 0x76, 0x94, 0x92, +0xBD, 0xB6, 0xCE, 0x59, 0xAD, 0x55, 0x8C, 0x30, +0xBD, 0xB4, 0xB5, 0x31, 0xAC, 0xF0, 0xBD, 0xB3, +0xC5, 0xF4, 0xB5, 0x52, 0xB5, 0x72, 0xBD, 0xD4, +0xBD, 0xD4, 0xAD, 0x52, 0x9C, 0xD1, 0x4A, 0x48, +0x5A, 0xCA, 0x73, 0x6D, 0x73, 0xAE, 0x7B, 0xAE, +0x83, 0xEF, 0x5A, 0xCB, 0x4A, 0x49, 0x52, 0x8A, +0x52, 0x8A, 0x6B, 0x4D, 0x7B, 0xAF, 0x84, 0x31, +0xA5, 0x14, 0xAD, 0x76, 0xCE, 0x58, 0xCE, 0x37, +0xB5, 0x73, 0xB5, 0x73, 0xAD, 0x32, 0xD6, 0x76, +0xDE, 0x96, 0xD6, 0x76, 0xD6, 0x76, 0xD6, 0x56, +0xBD, 0x73, 0xAD, 0x11, 0xAD, 0x11, 0x9C, 0xD0, +0x94, 0x8F, 0xC5, 0xB4, 0xCE, 0x15, 0xC5, 0xB3, +0xAD, 0x31, 0x9C, 0x8F, 0xA4, 0xF0, 0xBD, 0xB3, +0xBD, 0x93, 0xAD, 0x11, 0xC5, 0xB3, 0xC5, 0xB3, +0xBD, 0x51, 0xB5, 0x11, 0xBD, 0x73, 0xBD, 0x31, +0xB4, 0xF0, 0xBD, 0x52, 0xB5, 0x11, 0xBD, 0x52, +0xCD, 0xD3, 0xCD, 0xF4, 0xB5, 0x32, 0xAD, 0x11, +0xBD, 0x94, 0xB5, 0x73, 0xBD, 0x93, 0xBD, 0xB4, +0xAD, 0x32, 0xB5, 0x73, 0xBD, 0x93, 0xBD, 0x94, +0xB5, 0x52, 0xC5, 0xF5, 0xB5, 0x53, 0xAD, 0x32, +0x94, 0x6F, 0x9C, 0xB0, 0x9C, 0xB0, 0x9C, 0xB0, +0xB5, 0x73, 0xA4, 0xF1, 0x94, 0x6F, 0x83, 0xCC, +0x7B, 0x8B, 0x7B, 0x8C, 0x7B, 0xAC, 0x83, 0xCD, +0x83, 0xCD, 0x83, 0xAC, 0xA4, 0xAF, 0xB5, 0x31, +0xBD, 0x52, 0xBD, 0x72, 0xAC, 0xF1, 0xAC, 0xF1, +0xA4, 0x8F, 0x9C, 0x4E, 0xB5, 0x32, 0x94, 0x2E, +0x7B, 0x8C, 0x7B, 0xAC, 0x83, 0xCD, 0x9C, 0x6E, +0x8C, 0x0D, 0x8B, 0xCC, 0x8B, 0xED, 0x94, 0x0D, +0x94, 0x0D, 0xAC, 0xD0, 0xB5, 0x31, 0xB5, 0x31, +0xAC, 0xF0, 0x8B, 0xCD, 0x83, 0xAC, 0x9C, 0x6F, +0xAD, 0x11, 0xB5, 0x52, 0xA4, 0xD1, 0xC5, 0xB4, +0xB5, 0x52, 0xAD, 0x32, 0xAD, 0x12, 0xAD, 0x12, +0x9C, 0x90, 0x7B, 0xCD, 0x39, 0xC6, 0x31, 0x85, +0x29, 0x65, 0x39, 0xA6, 0x42, 0x28, 0x42, 0x28, +0x4A, 0x28, 0x4A, 0x28, 0x4A, 0x49, 0x7B, 0xAE, +0x83, 0xCE, 0x73, 0x2C, 0x5A, 0x69, 0x7B, 0x6D, +0xB5, 0x13, 0x94, 0x2F, 0x62, 0xCA, 0x62, 0xCA, +0x8C, 0x0E, 0xB5, 0x52, 0xBD, 0xB3, 0xAD, 0x12, +0xBD, 0x94, 0xBD, 0x73, 0xB5, 0x32, 0xB5, 0x32, +0xBD, 0x73, 0xB5, 0x73, 0xB5, 0x53, 0xB5, 0x53, +0xA4, 0xF1, 0xA4, 0xD1, 0xA4, 0xD1, 0xA4, 0xD1, +0xAC, 0xF1, 0xAC, 0xF1, 0xAC, 0xF2, 0xAD, 0x12, +0xAC, 0xF2, 0xA4, 0xD1, 0xB5, 0x32, 0xB5, 0x11, +0xAC, 0xD0, 0xC5, 0x72, 0xCD, 0xD3, 0xCD, 0xD3, +0xCD, 0xD3, 0xC5, 0x92, 0xCD, 0xD3, 0xCD, 0xF4, +0xD6, 0x14, 0xD5, 0xF4, 0xCD, 0xB3, 0xCD, 0xB3, +0xD6, 0x14, 0xDE, 0x34, 0xDE, 0x54, 0xE6, 0x75, +0xE6, 0x95, 0xEE, 0xD6, 0xE6, 0x95, 0xD5, 0xF3, +0x5B, 0x0B, 0x2A, 0x04, 0x32, 0x85, 0x42, 0xE5, +0x32, 0x63, 0x3A, 0x64, 0x3A, 0x65, 0x3A, 0x44, +0x53, 0x28, 0x53, 0x67, 0x4B, 0x45, 0x43, 0x04, +0x74, 0x2A, 0xA5, 0x8F, 0xA5, 0x6F, 0xA5, 0x70, +0xBE, 0x34, 0xE7, 0x18, 0xDE, 0xD7, 0xD6, 0x34, +0xB5, 0x0F, 0xCD, 0xD3, 0xBD, 0x50, 0xBD, 0x51, +0xBD, 0x72, 0xBD, 0x92, 0xBD, 0x92, 0xBD, 0x72, +0xC5, 0x92, 0xCD, 0xB2, 0xCD, 0xB2, 0xCD, 0xB2, +0xCD, 0xD2, 0xDE, 0x34, 0xC5, 0x71, 0xCD, 0xB2, +0xCD, 0xF4, 0xDE, 0x35, 0xB5, 0x0F, 0xAC, 0xEE, +0xAC, 0xF0, 0xBD, 0xD4, 0x9C, 0xD1, 0x52, 0x89, +0x29, 0x64, 0x31, 0x85, 0x39, 0xC6, 0x4A, 0x69, +0x39, 0xA6, 0x42, 0x07, 0x52, 0x89, 0x4A, 0x28, +0x5A, 0xCB, 0xCE, 0x38, 0xE7, 0x1C, 0x8C, 0x30, +0x29, 0x25, 0x29, 0x24, 0x39, 0xE7, 0x94, 0x91, +0x9C, 0xD1, 0x8C, 0x2E, 0xAC, 0xCF, 0xC5, 0x92, +0xD6, 0x35, 0xBD, 0x51, 0xB5, 0x31, 0xBD, 0x72, +0xBD, 0x52, 0xB5, 0x31, 0xBD, 0x52, 0xBD, 0x72, +0xBD, 0x72, 0xC5, 0x93, 0xC5, 0xB3, 0xCD, 0xD3, +0xC5, 0x92, 0xBD, 0x71, 0xD5, 0xF3, 0xBD, 0x51, +0xB5, 0x51, 0xBD, 0x51, 0xB5, 0x31, 0xBD, 0x52, +0xC5, 0x92, 0xDE, 0x35, 0xAC, 0xAF, 0xB4, 0xEF, +0xD5, 0xF3, 0xDD, 0xF3, 0xCD, 0xB2, 0xC5, 0x51, +0xC5, 0x51, 0xCD, 0x92, 0xCD, 0xB2, 0xBD, 0x31, +0xBD, 0x31, 0xAC, 0xCF, 0xA4, 0x6D, 0xA4, 0x8E, +0xAC, 0xCF, 0xC5, 0x71, 0xB4, 0xF0, 0x73, 0x4B, +0x83, 0xCE, 0x73, 0x6D, 0x42, 0x08, 0x39, 0xA7, +0x62, 0xEC, 0x73, 0x8E, 0x94, 0x92, 0xA4, 0xF3, +0xC5, 0xF7, 0xDE, 0x59, 0xA4, 0x92, 0xB5, 0x34, +0x6B, 0x0B, 0x52, 0x69, 0x4A, 0x69, 0x6B, 0x4D, +0x73, 0x8E, 0xBD, 0xB6, 0xB5, 0x96, 0xAD, 0x34, +0xC5, 0xF7, 0xB5, 0x75, 0xA5, 0x14, 0x62, 0xCB, +0x7B, 0xAF, 0xBD, 0xB6, 0x94, 0x92, 0x8C, 0x0E, +0x9C, 0x8E, 0xA4, 0xAE, 0xAD, 0x10, 0xAC, 0xF0, +0xAD, 0x10, 0xA5, 0x10, 0xAC, 0xF0, 0xAD, 0x11, +0xAD, 0x31, 0xA4, 0xF1, 0xB5, 0x73, 0x83, 0xEE, +0x63, 0x0B, 0x5A, 0xCA, 0x5A, 0xCA, 0x52, 0x89, +0x4A, 0x28, 0x4A, 0x69, 0x4A, 0x69, 0x4A, 0x69, +0x41, 0xE7, 0x5A, 0xCB, 0x63, 0x0C, 0x73, 0xAE, +0x8C, 0x31, 0x9C, 0xF4, 0xBD, 0xF8, 0xD6, 0xBA, +0xB5, 0x74, 0xAD, 0x32, 0x9C, 0x8F, 0xC5, 0xF4, +0xCE, 0x55, 0xD6, 0x55, 0xD6, 0x56, 0xCE, 0x15, +0xB5, 0x73, 0xB5, 0x72, 0xB5, 0x52, 0xA4, 0xD1, +0x9C, 0xD0, 0xBD, 0xD4, 0xD6, 0x35, 0xBD, 0x93, +0xA4, 0xB0, 0x94, 0x6F, 0x9C, 0xB0, 0xAD, 0x31, +0xBD, 0xB3, 0xB5, 0x32, 0xC5, 0xB4, 0xCD, 0xD3, +0xBD, 0x51, 0xB5, 0x32, 0xC5, 0x73, 0xC5, 0x52, +0xC5, 0x52, 0xBD, 0x52, 0xB5, 0x11, 0xBD, 0x72, +0xC5, 0xD3, 0xCD, 0xF4, 0xB5, 0x11, 0xB5, 0x53, +0xC5, 0xF5, 0xBD, 0xB4, 0xBD, 0xB4, 0xBD, 0xB4, +0xB5, 0x73, 0xAD, 0x52, 0xA5, 0x11, 0xBD, 0xB4, +0xBD, 0xD4, 0xCE, 0x36, 0xB5, 0x52, 0xB5, 0x73, +0xA4, 0xD0, 0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x52, +0xBD, 0x94, 0xBD, 0x93, 0xA4, 0xD1, 0x8C, 0x2E, +0x7B, 0xAC, 0x73, 0x2A, 0x73, 0x2A, 0x8C, 0x2E, +0x94, 0x4F, 0x94, 0x2E, 0x9C, 0x6F, 0xAC, 0xF0, +0xC5, 0x92, 0xBD, 0x72, 0xB5, 0x11, 0xB5, 0x10, +0x9C, 0x4E, 0x8B, 0xCC, 0xBD, 0x52, 0x94, 0x4E, +0x83, 0xED, 0x94, 0x4F, 0x9C, 0x90, 0xB5, 0x52, +0xBD, 0x93, 0xB5, 0x52, 0xAD, 0x11, 0xB5, 0x52, +0xA4, 0xD0, 0xB5, 0x11, 0xBD, 0x72, 0xC5, 0xB2, +0xB5, 0x31, 0xA4, 0xD0, 0x94, 0x2E, 0xA4, 0xD0, +0xBD, 0x73, 0xAD, 0x11, 0xBD, 0x93, 0xBD, 0xB3, +0xAD, 0x11, 0xB5, 0x73, 0xAD, 0x11, 0xAD, 0x32, +0xAD, 0x11, 0xCE, 0x36, 0x9C, 0xB1, 0x52, 0x89, +0x39, 0xA6, 0x39, 0xC6, 0x39, 0xA6, 0x42, 0x07, +0x4A, 0x48, 0x4A, 0x68, 0x52, 0x89, 0x4A, 0x28, +0x73, 0x8D, 0x94, 0x51, 0x73, 0x2C, 0x52, 0x48, +0x9C, 0x50, 0x94, 0x2F, 0x83, 0xAE, 0x73, 0x4C, +0x8C, 0x0E, 0xAD, 0x10, 0xBD, 0x93, 0xBD, 0x73, +0xE6, 0x97, 0xC5, 0xB4, 0xBD, 0x93, 0xC5, 0xB4, +0xBD, 0x93, 0xBD, 0x93, 0xC5, 0xD4, 0xB5, 0x52, +0xCD, 0xF5, 0xCE, 0x15, 0xCD, 0xF5, 0xCD, 0xD5, +0xC5, 0xD5, 0xCD, 0xF5, 0xCD, 0xD5, 0xC5, 0xD5, +0xC5, 0xB5, 0xC5, 0xB4, 0xBD, 0x94, 0xB5, 0x53, +0xB5, 0x53, 0xB5, 0x52, 0xB5, 0x32, 0xB5, 0x12, +0xB5, 0x12, 0xAC, 0xF1, 0xA4, 0xB0, 0xA4, 0xB0, +0xA4, 0xB0, 0x9C, 0x70, 0x9C, 0x70, 0x94, 0x4F, +0x94, 0x4E, 0x94, 0x4E, 0x9C, 0x4F, 0x9C, 0x8F, +0xAC, 0xF0, 0xB5, 0x31, 0xBD, 0x32, 0xAD, 0x11, +0x6B, 0xCD, 0x19, 0x42, 0x32, 0x65, 0x6C, 0x0A, +0x3A, 0x44, 0x53, 0x08, 0x42, 0x86, 0x6B, 0xCB, +0x6B, 0xEB, 0x5B, 0x47, 0x7C, 0x4B, 0x9D, 0x4F, +0xB5, 0xF2, 0xC6, 0x54, 0xCE, 0x54, 0x9C, 0xCD, +0xC5, 0xF3, 0xDE, 0x75, 0xBD, 0x72, 0xA4, 0x8E, +0xBD, 0x91, 0xCD, 0xD3, 0xBD, 0x51, 0xA4, 0xAE, +0xBD, 0x72, 0xB5, 0x30, 0xB5, 0x30, 0xB5, 0x51, +0xBD, 0x51, 0xCD, 0xD3, 0xD5, 0xF3, 0xBD, 0x51, +0xC5, 0x92, 0xD6, 0x14, 0xAC, 0xEF, 0xC5, 0xB2, +0xD6, 0x34, 0xDE, 0x34, 0xBD, 0x30, 0xB4, 0xCE, +0xA4, 0xCF, 0xBD, 0xB4, 0xB5, 0x53, 0xB5, 0x53, +0x7B, 0x8D, 0x39, 0xC6, 0x29, 0x44, 0x39, 0xC6, +0x41, 0xE6, 0x39, 0xA6, 0x31, 0x85, 0x5A, 0xEB, +0x62, 0xEC, 0x4A, 0x49, 0x5A, 0xEB, 0x83, 0xEF, +0x73, 0x8E, 0x4A, 0x48, 0x31, 0xA6, 0x6B, 0x4C, +0xAD, 0x53, 0x94, 0x70, 0xA4, 0x8F, 0xB5, 0x31, +0xAC, 0xF0, 0xB5, 0x31, 0xBD, 0x72, 0xA4, 0xF0, +0xA4, 0xD0, 0xA4, 0xD0, 0xB5, 0x31, 0xB5, 0x31, +0xBD, 0x72, 0xBD, 0x73, 0xBD, 0xB3, 0xBD, 0x92, +0xC5, 0xB3, 0xBD, 0x51, 0xB5, 0x31, 0xAC, 0xD0, +0xAC, 0xF1, 0xAD, 0x11, 0xA4, 0xD0, 0xB5, 0x31, +0xBD, 0x72, 0xD5, 0xF4, 0xAC, 0x8E, 0xAC, 0x8E, +0xC5, 0x51, 0xCD, 0x92, 0xD5, 0xD3, 0xDE, 0x14, +0xDD, 0xF3, 0xD5, 0xF3, 0xCD, 0xB2, 0xBD, 0x51, +0xBD, 0x71, 0xD5, 0xD3, 0xCD, 0xB2, 0xCD, 0x91, +0xCD, 0x92, 0xCD, 0xD2, 0xC5, 0x92, 0x8C, 0x0D, +0x6B, 0x2B, 0x6B, 0x4C, 0x39, 0xC6, 0x31, 0x66, +0x4A, 0x49, 0x4A, 0x69, 0x5A, 0xEB, 0x83, 0xEF, +0x9C, 0x92, 0x94, 0x51, 0x8C, 0x10, 0xBD, 0x54, +0xAC, 0xB2, 0x6A, 0xCB, 0x39, 0xA7, 0x73, 0x8E, +0x8C, 0x51, 0xBD, 0xB7, 0xAD, 0x55, 0x7B, 0xCF, +0xA4, 0xF3, 0x7B, 0xCF, 0x4A, 0x49, 0x5A, 0xCB, +0x7B, 0xAF, 0xCE, 0x18, 0xC5, 0xF7, 0xA4, 0xD1, +0x94, 0x2D, 0x9C, 0x4D, 0x9C, 0x6E, 0x8C, 0x0C, +0x8C, 0x0D, 0x94, 0x2D, 0xA4, 0xD0, 0x9C, 0x8F, +0xA4, 0xAF, 0xAD, 0x11, 0xB5, 0x31, 0x9C, 0xB0, +0x4A, 0x07, 0x42, 0x27, 0x42, 0x07, 0x41, 0xE7, +0x52, 0x69, 0x52, 0x89, 0x4A, 0x48, 0x4A, 0x49, +0x39, 0xC6, 0x42, 0x28, 0x63, 0x0C, 0x6B, 0x6E, +0x73, 0xAF, 0x8C, 0x72, 0xAD, 0x76, 0xC6, 0x18, +0xBD, 0xB6, 0xAD, 0x12, 0xA5, 0x11, 0xBD, 0xB4, +0xC5, 0xF5, 0xC6, 0x15, 0xC6, 0x15, 0xC6, 0x15, +0xBD, 0xD4, 0xBD, 0xD4, 0xBD, 0xB4, 0xB5, 0x73, +0xAD, 0x32, 0xC5, 0xD5, 0xCE, 0x15, 0xCE, 0x15, +0xC5, 0xD4, 0xBD, 0xB4, 0x9C, 0xB0, 0xAD, 0x31, +0xBD, 0x92, 0xAD, 0x11, 0xCD, 0xD4, 0xCD, 0xF3, +0xC5, 0x71, 0xBD, 0x72, 0xC5, 0x72, 0xBD, 0x31, +0xC5, 0x52, 0xC5, 0x93, 0xAC, 0xAF, 0xB5, 0x51, +0xC5, 0x93, 0xD6, 0x35, 0xAD, 0x11, 0xB5, 0x52, +0xC5, 0xF5, 0xBD, 0xD4, 0xBD, 0xB4, 0xB5, 0x94, +0xB5, 0x93, 0xBD, 0x94, 0xB5, 0xB4, 0xBD, 0xD4, +0xC5, 0xF5, 0xCE, 0x15, 0xB5, 0x32, 0xBD, 0x73, +0xAD, 0x32, 0xB5, 0x32, 0xA4, 0xF1, 0xAD, 0x12, +0xB5, 0x53, 0xB5, 0x73, 0x9C, 0xB0, 0x94, 0x70, +0x8C, 0x2F, 0x94, 0x70, 0x8C, 0x2E, 0xA4, 0xD1, +0x8C, 0x0E, 0x9C, 0x90, 0x94, 0x6E, 0xA4, 0xB0, +0xAC, 0xD0, 0xAC, 0xF0, 0x94, 0x4E, 0x83, 0xAC, +0x7B, 0x6B, 0x8B, 0xCD, 0xBD, 0x53, 0x94, 0x2E, +0x8C, 0x2E, 0x94, 0x6F, 0xA4, 0xF1, 0xB5, 0x72, +0xC5, 0xD4, 0xC5, 0xD4, 0xC5, 0xB3, 0xC5, 0xD4, +0xB5, 0x32, 0xB5, 0x51, 0xCD, 0xF4, 0xCE, 0x14, +0xBD, 0x72, 0xAD, 0x11, 0x83, 0xCD, 0xBD, 0x93, +0xBD, 0xB4, 0xB5, 0x52, 0xB5, 0x73, 0xB5, 0x52, +0xAC, 0xF1, 0xBD, 0xB3, 0xAD, 0x31, 0xAD, 0x32, +0xAD, 0x11, 0xCE, 0x35, 0xC5, 0xF5, 0xB5, 0x94, +0x63, 0x2B, 0x31, 0xA6, 0x31, 0xA5, 0x31, 0x85, +0x42, 0x07, 0x4A, 0x68, 0x52, 0x8A, 0x42, 0x28, +0x4A, 0x48, 0x63, 0x0B, 0x7B, 0x6D, 0x6A, 0xEB, +0x52, 0x28, 0x93, 0xEF, 0x9C, 0x70, 0x8B, 0xEE, +0x94, 0x6E, 0x9C, 0x8D, 0xA4, 0xEF, 0x9C, 0x6F, +0xDE, 0x56, 0xDE, 0x55, 0xDE, 0x35, 0xCD, 0xD4, +0xCD, 0xD4, 0xC5, 0xB3, 0xC5, 0x93, 0xCD, 0xD4, +0xD6, 0x35, 0xDE, 0x56, 0xDE, 0x76, 0xDE, 0x56, +0xCD, 0xD4, 0xC5, 0xD5, 0xCE, 0x15, 0xD6, 0x16, +0xDE, 0x77, 0xD6, 0x56, 0xD6, 0x36, 0xD6, 0x16, +0xCD, 0xD5, 0xD6, 0x16, 0xB5, 0x52, 0x9C, 0x90, +0xA4, 0xF1, 0xB5, 0x74, 0xB5, 0x32, 0xB5, 0x53, +0xBD, 0x94, 0xBD, 0x53, 0xB5, 0x33, 0xBD, 0x74, +0xCD, 0xF5, 0xD6, 0x36, 0xC5, 0xD5, 0xCE, 0x15, +0xD6, 0x76, 0xC5, 0xB4, 0xC5, 0xB4, 0xC5, 0xD5, +0x53, 0x0A, 0x29, 0xA4, 0x42, 0xA6, 0x6B, 0xC9, +0x31, 0xC3, 0x42, 0x46, 0x31, 0xE4, 0x52, 0xE9, +0x6B, 0xAC, 0x84, 0x8F, 0x7C, 0x4D, 0x84, 0x8E, +0x9D, 0x30, 0xA5, 0x31, 0xAD, 0x71, 0xA4, 0xCE, +0xC5, 0x91, 0xD6, 0x13, 0xBD, 0x50, 0x9C, 0x2D, +0xB5, 0x30, 0xBD, 0x72, 0x9C, 0x4D, 0xAC, 0xCF, +0xC5, 0xB2, 0xBD, 0x92, 0x9C, 0x8E, 0xCD, 0xD3, +0xB5, 0x31, 0xC5, 0xD3, 0xCD, 0xB3, 0xB5, 0x30, +0xD5, 0xF4, 0xD6, 0x14, 0xBD, 0x51, 0xCD, 0xF4, +0xDE, 0x76, 0xE6, 0x96, 0xBD, 0x10, 0xAC, 0xAE, +0xAC, 0xF0, 0xBD, 0x93, 0xAD, 0x52, 0xB5, 0x74, +0xAD, 0x32, 0x9C, 0x90, 0x52, 0x89, 0x31, 0x65, +0x31, 0xA5, 0x31, 0x65, 0x31, 0x86, 0x4A, 0x69, +0x63, 0x0C, 0x52, 0x8A, 0x42, 0x28, 0x7B, 0xCF, +0xA4, 0xD2, 0x94, 0x50, 0x73, 0x6D, 0x42, 0x28, +0x73, 0xAE, 0xC5, 0xF6, 0xB5, 0x32, 0xA4, 0xAF, +0x9C, 0x6F, 0xA4, 0xD0, 0xAD, 0x11, 0xA4, 0xF1, +0x9C, 0xAF, 0xA4, 0xB0, 0xA4, 0xB0, 0xA4, 0xB0, +0xA4, 0xF1, 0xA4, 0xF1, 0xAD, 0x32, 0xB5, 0x52, +0xB5, 0x52, 0xAD, 0x11, 0xAD, 0x10, 0xA4, 0xF0, +0xA4, 0xD0, 0xA4, 0xF1, 0x9C, 0xB0, 0xA4, 0xD0, +0xAC, 0xF0, 0xC5, 0x92, 0xAC, 0xCF, 0xB5, 0x10, +0xCD, 0x92, 0xCD, 0x92, 0xCD, 0x91, 0xCD, 0x92, +0xC5, 0x71, 0xC5, 0x71, 0xD5, 0xD3, 0xCD, 0x92, +0xC5, 0x71, 0xD5, 0xF3, 0xD5, 0xF3, 0xD5, 0xF3, +0xDE, 0x13, 0xD5, 0xF3, 0xCD, 0xB2, 0x9C, 0x4E, +0x6B, 0x0A, 0x6B, 0x0B, 0x39, 0xA6, 0x41, 0xE8, +0x73, 0xAF, 0x5A, 0xCB, 0x52, 0x8A, 0x73, 0x4D, +0x6B, 0x4D, 0x73, 0x8E, 0x9C, 0xB2, 0xA4, 0xB2, +0x93, 0xCE, 0x8B, 0xAE, 0x73, 0x2C, 0x6B, 0x0B, +0x52, 0x49, 0x8C, 0x51, 0x84, 0x30, 0x52, 0x6A, +0x62, 0xEB, 0x6B, 0x4D, 0x9C, 0xF3, 0xCE, 0x59, +0xDE, 0xBB, 0xCE, 0x18, 0xCD, 0xF7, 0xAD, 0x13, +0x83, 0xCD, 0x7B, 0xAC, 0x7B, 0xAC, 0x94, 0x4F, +0xAD, 0x11, 0x9C, 0x8F, 0x9C, 0x8F, 0x7B, 0xAC, +0x62, 0xE9, 0x62, 0xC9, 0x73, 0x4B, 0x73, 0x6B, +0x62, 0xCA, 0x31, 0x64, 0x39, 0xA6, 0x39, 0xC6, +0x4A, 0x68, 0x52, 0x69, 0x4A, 0x68, 0x52, 0x89, +0x42, 0x28, 0x4A, 0x49, 0x63, 0x0C, 0x6B, 0x4E, +0x73, 0x8F, 0x84, 0x31, 0x9C, 0xF4, 0xB5, 0x96, +0xAD, 0x34, 0x9C, 0xB1, 0xAD, 0x12, 0xA4, 0xD1, +0x9C, 0xB0, 0x9C, 0x90, 0x9C, 0x90, 0xA4, 0xF1, +0xB5, 0x52, 0xBD, 0x93, 0xBD, 0x94, 0xBD, 0x73, +0xB5, 0x73, 0xBD, 0xB4, 0xBD, 0x93, 0xB5, 0x52, +0xB5, 0x52, 0xB5, 0x73, 0xB5, 0x52, 0xC5, 0xF4, +0xD6, 0x56, 0xB5, 0x31, 0xC5, 0x73, 0xC5, 0xB3, +0xC5, 0x92, 0xD5, 0xF4, 0xD6, 0x14, 0xD5, 0xF4, +0xD5, 0xF4, 0xD6, 0x15, 0xB4, 0xF0, 0xAC, 0xCF, +0xBD, 0x72, 0xDE, 0x76, 0xAD, 0x11, 0xB5, 0x73, +0xD6, 0x77, 0xBD, 0xF5, 0xC5, 0xF5, 0xBD, 0xD4, +0xCE, 0x15, 0xBD, 0x93, 0xBD, 0xD4, 0xCE, 0x56, +0xBD, 0xD4, 0xC5, 0xD4, 0xAD, 0x32, 0xB5, 0x72, +0xB5, 0x73, 0xAD, 0x32, 0xA4, 0xD0, 0xA4, 0xF1, +0xB5, 0x73, 0xAD, 0x32, 0x9C, 0xB0, 0x9C, 0x90, +0x9C, 0x90, 0x9C, 0x90, 0x94, 0x6F, 0xA4, 0xD1, +0x94, 0x6F, 0xA4, 0xD1, 0xA4, 0xD0, 0xAD, 0x11, +0xA4, 0xD0, 0xA4, 0xD0, 0x62, 0xE9, 0x6B, 0x0A, +0x7B, 0x8C, 0xA4, 0x90, 0xBD, 0x53, 0x8C, 0x0E, +0x94, 0x6F, 0x9C, 0x90, 0xAD, 0x32, 0xBD, 0x93, +0xC5, 0xD4, 0xC5, 0xF4, 0xCD, 0xF4, 0xCD, 0xF4, +0xBD, 0x93, 0xB5, 0x51, 0xB5, 0x72, 0xBD, 0x92, +0xC5, 0xB3, 0xAC, 0xF1, 0x8C, 0x2E, 0xBD, 0xB4, +0xBD, 0x93, 0xAD, 0x11, 0xA4, 0xF0, 0xB5, 0x52, +0xA4, 0xF0, 0xC5, 0xD4, 0xAD, 0x11, 0xA4, 0xD0, +0xB5, 0x72, 0xCE, 0x15, 0xBD, 0xB3, 0xB5, 0x94, +0xB5, 0x74, 0x73, 0xAD, 0x42, 0x07, 0x31, 0xA6, +0x39, 0xC6, 0x42, 0x28, 0x52, 0x89, 0x52, 0x69, +0x4A, 0x69, 0x62, 0xEB, 0x8B, 0xEF, 0x73, 0x2C, +0x73, 0x2C, 0x73, 0x0B, 0x94, 0x0F, 0x83, 0x8C, +0x62, 0xC8, 0x83, 0xEB, 0xB5, 0x91, 0x7B, 0x6B, +0xAC, 0xD0, 0xE6, 0x96, 0xE6, 0x96, 0xE6, 0xB7, +0xE6, 0x76, 0xE6, 0x76, 0xDE, 0x56, 0xDE, 0x76, +0xE6, 0x76, 0xE6, 0x97, 0xE6, 0xB7, 0xE6, 0xB8, +0xDE, 0x77, 0xDE, 0x77, 0xD6, 0x56, 0xDE, 0x77, +0xDE, 0x97, 0xDE, 0x77, 0xDE, 0x57, 0xD6, 0x56, +0xDE, 0x56, 0xDE, 0x97, 0xDE, 0x77, 0xA4, 0xD1, +0x9C, 0x90, 0x9C, 0x90, 0x94, 0x50, 0x7B, 0xAD, +0x9C, 0x90, 0xC5, 0xB4, 0xD6, 0x15, 0xD6, 0x36, +0x9C, 0x70, 0xB5, 0x53, 0xDE, 0x76, 0xDE, 0x77, +0x9C, 0x90, 0x7B, 0x8C, 0x83, 0xCD, 0x94, 0x2F, +0x6B, 0x8B, 0x4A, 0x87, 0x53, 0x08, 0x52, 0xC7, +0x39, 0xE5, 0x52, 0xC8, 0x63, 0x6A, 0x73, 0xED, +0x73, 0xED, 0x84, 0x90, 0x9D, 0x53, 0x84, 0xAF, +0x9D, 0x51, 0x8C, 0xAE, 0x9C, 0xEF, 0xAC, 0xEF, +0xAC, 0xEE, 0xB5, 0x0F, 0xB4, 0xEF, 0xA4, 0x8E, +0x9C, 0x6D, 0xAC, 0xCF, 0xA4, 0xAE, 0xA4, 0x8E, +0xAC, 0xCF, 0xA4, 0x8E, 0x94, 0x0C, 0x9C, 0x4D, +0x9C, 0x6D, 0xA4, 0xAE, 0xA4, 0x6D, 0xA4, 0x8E, +0xB5, 0x10, 0xBD, 0x51, 0xB4, 0xEF, 0xBD, 0x31, +0xCD, 0xF4, 0xD6, 0x34, 0xC5, 0x71, 0xAC, 0xAE, +0xA4, 0xAE, 0xAD, 0x10, 0xA5, 0x11, 0xB5, 0x93, +0xBD, 0x94, 0xB5, 0x93, 0xAD, 0x32, 0x73, 0x6B, +0x31, 0x85, 0x31, 0x65, 0x31, 0x65, 0x42, 0x07, +0x4A, 0x48, 0x4A, 0x69, 0x63, 0x0C, 0x42, 0x28, +0x9C, 0xD2, 0xA4, 0xD2, 0x94, 0x70, 0x94, 0xB2, +0x84, 0x10, 0x94, 0x92, 0xE7, 0x1B, 0xAD, 0x12, +0x7B, 0x6B, 0xA4, 0xD0, 0xBD, 0x93, 0xA4, 0xD0, +0x9C, 0x8F, 0x94, 0x6F, 0x8C, 0x2E, 0x94, 0x4F, +0x94, 0x4F, 0x9C, 0x6F, 0xA4, 0xF1, 0xAD, 0x32, +0xB5, 0x72, 0xAD, 0x11, 0xAD, 0x11, 0xA4, 0xAF, +0xA4, 0xD0, 0xA4, 0xD1, 0xA4, 0xD0, 0xA4, 0xD0, +0xA4, 0xD0, 0xB5, 0x31, 0xB4, 0xEF, 0xC5, 0x72, +0xC5, 0x71, 0xC5, 0x71, 0xC5, 0x30, 0xBD, 0x10, +0xC5, 0x51, 0xBD, 0x30, 0xCD, 0x92, 0xB4, 0xF0, +0xB5, 0x10, 0xCD, 0xB2, 0xD5, 0xF3, 0xD5, 0xF3, +0xDE, 0x34, 0xDE, 0x54, 0xBD, 0x51, 0x8B, 0xED, +0x73, 0x6D, 0x94, 0x71, 0x94, 0x92, 0xBD, 0xB7, +0xBD, 0xD7, 0x63, 0x2C, 0x4A, 0x49, 0x5A, 0xAA, +0x5A, 0xCB, 0x62, 0xEB, 0x8C, 0x30, 0x94, 0x50, +0x9C, 0x91, 0x94, 0x0F, 0x94, 0x0F, 0xAC, 0xB2, +0x9C, 0x91, 0x9C, 0xB2, 0x83, 0xEF, 0x73, 0x6E, +0x8C, 0x51, 0xBD, 0xF7, 0xD6, 0x9A, 0xDE, 0xDB, +0xBD, 0xF7, 0xE6, 0xFB, 0xEF, 0x3C, 0xD6, 0x59, +0xAC, 0xF2, 0x9C, 0x90, 0x9C, 0x90, 0x94, 0x6F, +0x9C, 0x90, 0x9C, 0x6F, 0x8C, 0x2E, 0x7B, 0xAC, +0x7B, 0xAD, 0x7B, 0xAD, 0x94, 0x4F, 0x9C, 0xB0, +0x9C, 0xD1, 0x62, 0xEA, 0x39, 0xC6, 0x39, 0xA5, +0x41, 0xE6, 0x39, 0xC6, 0x39, 0xE7, 0x42, 0x28, +0x4A, 0x29, 0x52, 0xAA, 0x63, 0x2C, 0x63, 0x0C, +0x5A, 0xCC, 0x73, 0xAF, 0x7C, 0x10, 0x8C, 0x51, +0xAD, 0x34, 0xB5, 0x74, 0xBD, 0xB4, 0xAD, 0x12, +0xB5, 0x53, 0xBD, 0x94, 0xB5, 0x52, 0xB5, 0x52, +0xAD, 0x32, 0xA4, 0xF1, 0xAD, 0x11, 0xB5, 0x52, +0xAC, 0xF1, 0xA4, 0xD0, 0x9C, 0x90, 0x9C, 0xB0, +0xA4, 0xB0, 0x9C, 0x8F, 0x9C, 0x8F, 0xA4, 0xD0, +0xA4, 0xF0, 0xAC, 0xF1, 0xAC, 0xD0, 0xA4, 0xAF, +0x9C, 0x6E, 0xA4, 0x8F, 0xAC, 0xCF, 0xAC, 0xD0, +0xAC, 0xF0, 0xAC, 0xD0, 0x9C, 0x6E, 0x9C, 0x6E, +0x9C, 0x6E, 0xAD, 0x11, 0x94, 0x4E, 0x94, 0x2E, +0x9C, 0xB0, 0xAD, 0x32, 0xA4, 0xF1, 0x94, 0x4E, +0x9C, 0x90, 0x8C, 0x2E, 0x94, 0x6F, 0xB5, 0x93, +0xC6, 0x15, 0xC5, 0xF5, 0xA4, 0xD0, 0x83, 0xED, +0x7B, 0xAC, 0x83, 0xED, 0xAD, 0x11, 0xA4, 0xF1, +0xB5, 0x73, 0xAD, 0x32, 0xAD, 0x32, 0xAD, 0x11, +0xB5, 0x53, 0xB5, 0x53, 0xB5, 0x73, 0xA5, 0x11, +0xAD, 0x32, 0xB5, 0x32, 0xAC, 0xF1, 0xB5, 0x52, +0xA4, 0xAF, 0xA4, 0xD0, 0x6B, 0x0A, 0x94, 0x4F, +0x9C, 0x8F, 0xA4, 0x90, 0xBD, 0x73, 0x8C, 0x0D, +0x9C, 0x90, 0xA4, 0xD0, 0xB5, 0x73, 0xC5, 0xD4, +0xC5, 0xD4, 0xC5, 0xD4, 0xC5, 0xF4, 0xC5, 0xD3, +0xBD, 0x93, 0xB5, 0x51, 0xBD, 0x92, 0xB5, 0x72, +0xBD, 0x93, 0xC5, 0xB4, 0xAD, 0x11, 0xC5, 0xD4, +0xB5, 0x73, 0xAD, 0x11, 0xB5, 0x52, 0xBD, 0xB4, +0xAD, 0x11, 0xC5, 0xD4, 0xAC, 0xF1, 0xA4, 0xD1, +0xBD, 0x93, 0xCE, 0x15, 0xB5, 0x93, 0xAD, 0x73, +0xAD, 0x32, 0xB5, 0x73, 0x83, 0xEE, 0x42, 0x27, +0x39, 0xC6, 0x42, 0x07, 0x42, 0x28, 0x4A, 0x69, +0x4A, 0x49, 0x4A, 0x28, 0x5A, 0xAA, 0x83, 0xCE, +0x73, 0x0C, 0x73, 0x0B, 0x8B, 0xAD, 0x73, 0x2B, +0x5A, 0xC8, 0x5B, 0x27, 0x9D, 0x0E, 0xB5, 0xB2, +0xB5, 0x70, 0xBD, 0xD0, 0xBD, 0xF1, 0xEF, 0x17, +0xEE, 0xD7, 0xDE, 0x76, 0xEE, 0xD7, 0xEE, 0xD7, +0xE6, 0x97, 0xE6, 0xB7, 0xDE, 0x97, 0xE6, 0xB8, +0xDE, 0xB8, 0xE6, 0xB8, 0xE6, 0xB8, 0xE6, 0xB8, +0xDE, 0x98, 0xDE, 0x98, 0xDE, 0x77, 0xDE, 0x97, +0xDE, 0x97, 0xEE, 0xF8, 0xEE, 0xF8, 0xAD, 0x12, +0xAD, 0x33, 0xC5, 0xD5, 0xC5, 0xF5, 0xBD, 0xB5, +0x9C, 0xB1, 0xB5, 0x12, 0xD6, 0x15, 0xC5, 0xB4, +0x7B, 0xAC, 0x94, 0x70, 0x8C, 0x2F, 0xAD, 0x32, +0x8C, 0x2F, 0x8C, 0x2F, 0x9C, 0x91, 0x9C, 0xB1, +0x8C, 0x6F, 0x5A, 0xC8, 0x52, 0xC8, 0x5B, 0x2A, +0x84, 0x4F, 0x7C, 0x2E, 0x8C, 0x6E, 0x73, 0xCC, +0x73, 0xCD, 0x6B, 0xAC, 0x52, 0xE9, 0x4A, 0xA8, +0x94, 0xF0, 0x84, 0x2C, 0x94, 0x4D, 0xA4, 0xAE, +0xA4, 0x8E, 0xB4, 0xEF, 0xAC, 0xCE, 0xAC, 0xCF, +0xBD, 0x71, 0xB5, 0x0F, 0xAC, 0xAE, 0xAC, 0xAE, +0xAC, 0xCF, 0xA4, 0x8E, 0xA4, 0x8E, 0xA4, 0x8E, +0xA4, 0x8E, 0xAC, 0xAE, 0xAC, 0xCF, 0xAC, 0xCF, +0xAC, 0xCF, 0xB4, 0xEF, 0xB4, 0xEF, 0xAC, 0xCF, +0xAC, 0xAE, 0xAC, 0x8D, 0xAC, 0xAE, 0xAC, 0xAE, +0xA4, 0x8E, 0x9C, 0x4D, 0x94, 0x2D, 0x94, 0x2D, +0x94, 0x4E, 0x8C, 0x0D, 0x8C, 0x2D, 0x94, 0x4E, +0x8B, 0xEC, 0x62, 0xA8, 0x31, 0x84, 0x31, 0xA5, +0x39, 0xC6, 0x4A, 0x48, 0x63, 0x0C, 0x52, 0xAA, +0x52, 0xAA, 0x83, 0xCF, 0x84, 0x0F, 0x7B, 0xAE, +0x73, 0x6D, 0x73, 0x8E, 0xD6, 0xBA, 0xEF, 0x1B, +0xB5, 0x33, 0x8B, 0xAD, 0xB4, 0xF1, 0x94, 0x4F, +0x8C, 0x0E, 0x8C, 0x2E, 0x8C, 0x0E, 0x8C, 0x2F, +0x9C, 0x90, 0xA4, 0xD1, 0x94, 0x6F, 0x94, 0x6F, +0xA4, 0xF1, 0xA4, 0xF1, 0xA4, 0xB0, 0x94, 0x4E, +0x9C, 0xB0, 0xA4, 0xF1, 0x9C, 0xB0, 0xAD, 0x11, +0xB5, 0x52, 0xBD, 0x31, 0xC5, 0x72, 0xCD, 0xB3, +0xC5, 0x51, 0xC5, 0x51, 0xBD, 0x31, 0xAC, 0xAF, +0xB4, 0xF0, 0xC5, 0x51, 0xCD, 0x72, 0xBD, 0x31, +0xBD, 0x51, 0xCD, 0x92, 0xD5, 0xD3, 0xCD, 0x92, +0xD5, 0xF3, 0xDE, 0x55, 0xA4, 0xB0, 0xB5, 0x95, +0xBD, 0xD6, 0xC5, 0xF7, 0xB5, 0xB6, 0x6B, 0x4D, +0x6B, 0x4D, 0x42, 0x08, 0x29, 0x45, 0x31, 0xA6, +0x42, 0x07, 0x42, 0x08, 0x7B, 0xAE, 0x8C, 0x30, +0xAD, 0x14, 0x8B, 0xEF, 0x9C, 0x50, 0xA4, 0xD2, +0xB5, 0x34, 0xCE, 0x18, 0xCE, 0x38, 0xCE, 0x38, +0xAD, 0x34, 0xD6, 0x79, 0x9C, 0xD3, 0xAD, 0x14, +0x94, 0x72, 0xAD, 0x55, 0xCE, 0x59, 0xF7, 0x5C, +0xBD, 0xB5, 0xAC, 0xF2, 0xAC, 0xF1, 0x9C, 0x8F, +0xA4, 0xD0, 0x94, 0x6F, 0x7B, 0xAC, 0x8C, 0x0E, +0x83, 0xCD, 0x8C, 0x2E, 0x9C, 0xB1, 0xAD, 0x12, +0x9C, 0xB0, 0x8C, 0x2E, 0x42, 0x06, 0x31, 0x85, +0x39, 0xC6, 0x39, 0xC6, 0x39, 0xE6, 0x39, 0xE7, +0x42, 0x08, 0x52, 0xAA, 0x5A, 0xCB, 0x63, 0x2D, +0x63, 0x0D, 0x6B, 0x6E, 0x73, 0x8E, 0x84, 0x30, +0xA5, 0x34, 0xB5, 0x75, 0xC5, 0xD6, 0xC5, 0xB4, +0xCE, 0x36, 0xBD, 0xB4, 0xBD, 0x94, 0xBD, 0x93, +0xBD, 0x73, 0xB5, 0x52, 0xC5, 0xD4, 0xDE, 0x97, +0xDE, 0x97, 0xBD, 0x93, 0xAC, 0xF1, 0xCD, 0xF5, +0xC5, 0xB4, 0xAC, 0xF1, 0x9C, 0x4F, 0x8C, 0x0E, +0x8C, 0x0D, 0x8C, 0x0E, 0x9C, 0x8F, 0xAD, 0x32, +0xBD, 0x73, 0xAC, 0xF1, 0xA4, 0x90, 0xA4, 0xB0, +0xA4, 0xB0, 0xA4, 0xB0, 0xA4, 0xB0, 0xAD, 0x11, +0xA4, 0xB0, 0x9C, 0x6F, 0xA4, 0xB0, 0xAC, 0xD1, +0xA4, 0xD1, 0x9C, 0xB0, 0x94, 0x4E, 0x9C, 0x8F, +0xAC, 0xF1, 0xAC, 0xF1, 0xA4, 0xB0, 0x9C, 0x90, +0x9C, 0x8F, 0xA4, 0xB0, 0xA4, 0xB0, 0xA4, 0xD1, +0xA4, 0xD1, 0x94, 0x4F, 0x83, 0xED, 0x83, 0xCD, +0x8B, 0xCD, 0x83, 0xCD, 0x8B, 0xED, 0x83, 0xCD, +0x83, 0xCD, 0x8C, 0x0E, 0x8C, 0x2E, 0x8C, 0x0E, +0x94, 0x2E, 0x9C, 0xB0, 0xAD, 0x11, 0xB5, 0x52, +0xA4, 0xF1, 0x83, 0xED, 0x6B, 0x2A, 0x94, 0x2E, +0x9C, 0x8F, 0x94, 0x2E, 0xBD, 0x53, 0x8B, 0xED, +0x9C, 0x6F, 0x9C, 0xB0, 0xAD, 0x32, 0xB5, 0x73, +0xB5, 0x52, 0xB5, 0x72, 0xBD, 0x93, 0xBD, 0x93, +0xBD, 0x93, 0xB5, 0x72, 0xBD, 0xB3, 0xBD, 0x93, +0xBD, 0x93, 0xC5, 0xB4, 0xAD, 0x11, 0xBD, 0xB4, +0xBD, 0x94, 0xBD, 0x93, 0xC5, 0xF5, 0xBD, 0x93, +0xB5, 0x53, 0xBD, 0xB3, 0xA4, 0xF0, 0xAD, 0x32, +0xBD, 0x93, 0xC5, 0xD4, 0xA5, 0x11, 0xAD, 0x73, +0xA4, 0xF2, 0xB5, 0x73, 0xBD, 0xD4, 0xB5, 0x52, +0x52, 0x67, 0x31, 0x85, 0x31, 0x85, 0x39, 0xE6, +0x42, 0x27, 0x4A, 0x68, 0x4A, 0x48, 0x8C, 0x30, +0x83, 0xAE, 0x73, 0x2C, 0x8B, 0xCE, 0x8B, 0xCD, +0x5A, 0xC7, 0x53, 0x26, 0x5B, 0x66, 0x94, 0xEE, +0x94, 0x8C, 0xA5, 0x6D, 0xAD, 0xAE, 0xD6, 0x93, +0xB5, 0xB1, 0x84, 0x2C, 0xDE, 0xB5, 0xEE, 0xF7, +0xEE, 0xD8, 0xEE, 0xF8, 0xE6, 0xB8, 0xDE, 0x97, +0xDE, 0xD8, 0xDE, 0x98, 0xDE, 0xB8, 0xDE, 0xB8, +0xE6, 0xD8, 0xE6, 0xD8, 0xDE, 0xB7, 0xDE, 0x97, +0xDE, 0xB8, 0xE6, 0xF8, 0xE6, 0xD8, 0xAD, 0x12, +0xAD, 0x12, 0xCE, 0x36, 0xD6, 0x77, 0xCE, 0x36, +0xC5, 0xD5, 0xD6, 0x36, 0xD6, 0x15, 0xCD, 0xF5, +0xB5, 0x53, 0xC6, 0x15, 0xA4, 0xD1, 0xBD, 0xD5, +0xCE, 0x37, 0xC6, 0x16, 0xCE, 0x16, 0xC5, 0xF6, +0x7C, 0x0E, 0x3A, 0x06, 0x6B, 0xAD, 0x73, 0xEE, +0x8C, 0xD1, 0x9D, 0x12, 0x8C, 0x6F, 0x94, 0x8F, +0xA5, 0x11, 0xB5, 0x52, 0xAD, 0x31, 0x94, 0x6E, +0x6B, 0x29, 0x62, 0xC8, 0x5A, 0xA8, 0x73, 0x4A, +0x62, 0xE9, 0x73, 0x6A, 0xA4, 0xD0, 0xAC, 0xD0, +0x9C, 0x6D, 0xAC, 0xCF, 0xC5, 0x92, 0xC5, 0x92, +0xC5, 0x92, 0xBD, 0x30, 0xBD, 0x51, 0xCD, 0xB2, +0xB5, 0x10, 0xB4, 0xEF, 0xAC, 0xCF, 0xB5, 0x10, +0xA4, 0x8E, 0xAC, 0xCE, 0xAC, 0x8E, 0xAC, 0xAE, +0xB4, 0xCF, 0xBD, 0x30, 0xD5, 0xD3, 0xC5, 0x51, +0xB5, 0x0F, 0xAC, 0xEF, 0xBD, 0x50, 0xBD, 0x30, +0xB5, 0x10, 0xB5, 0x30, 0xB5, 0x10, 0xB5, 0x30, +0xBD, 0x30, 0xBD, 0x30, 0x94, 0x2D, 0x52, 0x47, +0x29, 0x64, 0x39, 0xE7, 0x62, 0xEB, 0x5A, 0xCA, +0x5A, 0xCA, 0x63, 0x0C, 0x41, 0xE7, 0x41, 0xE7, +0x5A, 0xEB, 0x7B, 0xF0, 0xD6, 0x9A, 0xE7, 0x1C, +0xF7, 0x7D, 0xD6, 0x38, 0x94, 0x2F, 0xA4, 0xD1, +0x9C, 0x6F, 0x94, 0x4E, 0x8C, 0x0E, 0x8C, 0x0E, +0x94, 0x4F, 0xB5, 0x73, 0x9C, 0xB0, 0x83, 0xCD, +0x8C, 0x0E, 0x83, 0xCC, 0x73, 0x6B, 0x83, 0xCC, +0x8C, 0x0E, 0x94, 0x4F, 0x9C, 0x6F, 0xA4, 0xD0, +0xAD, 0x11, 0xBD, 0x72, 0xCD, 0xB2, 0xD5, 0xD3, +0xCD, 0xB2, 0xD5, 0xD3, 0xE6, 0x35, 0xD5, 0xB3, +0xC5, 0x51, 0xCD, 0x92, 0xC5, 0x92, 0xCD, 0xD3, +0xCD, 0x92, 0xCD, 0xB3, 0xDE, 0x34, 0xC5, 0x71, +0xBD, 0x31, 0xBD, 0x72, 0xA4, 0xD1, 0x94, 0x71, +0x73, 0x6D, 0x7B, 0xCF, 0x6B, 0x2C, 0x42, 0x28, +0x5A, 0xCB, 0x52, 0xAA, 0x4A, 0x49, 0x21, 0x04, +0x29, 0x45, 0x31, 0x65, 0x5A, 0xAA, 0x73, 0x8D, +0x8B, 0xEF, 0xA4, 0xB2, 0x94, 0x30, 0xA4, 0xD2, +0xA4, 0xD2, 0xBD, 0x95, 0xA4, 0xD3, 0xD6, 0x59, +0xD6, 0x38, 0xDE, 0x79, 0x8C, 0x10, 0xAD, 0x34, +0x73, 0xAE, 0x52, 0x8A, 0x7B, 0xAF, 0xDE, 0xDB, +0xCE, 0x38, 0x94, 0x91, 0x9C, 0xB1, 0xAC, 0xF1, +0xB5, 0x32, 0xAC, 0xF1, 0x9C, 0x8F, 0xA4, 0xD0, +0x9C, 0x90, 0x9C, 0x90, 0xD6, 0x57, 0xBD, 0xD5, +0x94, 0x50, 0x83, 0xEE, 0x63, 0x0B, 0x41, 0xE7, +0x42, 0x07, 0x39, 0xC6, 0x39, 0xE7, 0x41, 0xE7, +0x42, 0x07, 0x52, 0x8A, 0x52, 0x8A, 0x63, 0x0C, +0x6B, 0x4D, 0x63, 0x0C, 0x63, 0x2D, 0x83, 0xF0, +0x94, 0x92, 0xB5, 0x75, 0xC5, 0xD6, 0xC5, 0xD6, +0x8C, 0x50, 0x62, 0xCA, 0xB5, 0x74, 0x9C, 0x70, +0xA4, 0xD1, 0xAD, 0x11, 0xB5, 0x73, 0xD6, 0x56, +0xE6, 0xD8, 0xBD, 0x93, 0xBD, 0x73, 0xD6, 0x36, +0xC5, 0xB4, 0xB5, 0x72, 0xBD, 0x93, 0xB5, 0x52, +0xB5, 0x32, 0xAD, 0x12, 0xAD, 0x11, 0xC5, 0xD4, +0xC5, 0xF5, 0xC5, 0xD4, 0xAD, 0x11, 0xA4, 0xB0, +0x94, 0x4E, 0x8C, 0x0D, 0x94, 0x4F, 0xA4, 0xB0, +0x94, 0x4F, 0xB5, 0x32, 0xC5, 0xD4, 0xBD, 0x93, +0x9C, 0x6F, 0x9C, 0x6F, 0x9C, 0xB0, 0xC5, 0xB4, +0xCD, 0xF5, 0xD6, 0x56, 0xC5, 0xD4, 0xBD, 0x73, +0xAD, 0x11, 0x9C, 0x6F, 0xB5, 0x52, 0xAD, 0x11, +0xA4, 0xF1, 0xA4, 0xB0, 0xAD, 0x11, 0xAD, 0x11, +0xAC, 0xD1, 0xAC, 0xD0, 0xA4, 0xD0, 0xA4, 0xD1, +0xA4, 0xB0, 0xA4, 0xB0, 0xA4, 0xB0, 0x9C, 0x90, +0x9C, 0x90, 0x9C, 0x6F, 0x94, 0x2E, 0x94, 0x2E, +0x94, 0x0E, 0x9C, 0x4F, 0xA4, 0xB0, 0x9C, 0x6F, +0x94, 0x4E, 0x9C, 0x6F, 0xB5, 0x32, 0x9C, 0x6F, +0x8C, 0x2E, 0x83, 0xED, 0x94, 0x4E, 0x94, 0x6F, +0x83, 0xED, 0x94, 0x4E, 0xA4, 0xD0, 0xA4, 0xF0, +0xB5, 0x52, 0xBD, 0xB3, 0xC5, 0xD4, 0xCE, 0x15, +0xCE, 0x15, 0xCE, 0x14, 0xB5, 0x52, 0xBD, 0xB4, +0xC5, 0xD4, 0xC5, 0xB3, 0xCE, 0x36, 0xC5, 0xD4, +0xBD, 0xB4, 0xC5, 0xF4, 0x9C, 0xB0, 0x94, 0x6F, +0xA4, 0xF0, 0xA4, 0xF1, 0x94, 0x4E, 0xAD, 0x32, +0xAD, 0x32, 0xB5, 0x73, 0xBD, 0xD4, 0xDE, 0xB6, +0xBD, 0xD4, 0x52, 0x88, 0x31, 0xA5, 0x29, 0x64, +0x39, 0xC6, 0x4A, 0x48, 0x4A, 0x48, 0x62, 0xCA, +0x5A, 0xAA, 0x73, 0x2C, 0x83, 0x6D, 0x83, 0x8D, +0x5A, 0xC8, 0x42, 0xA5, 0x5B, 0x87, 0x42, 0x64, +0x84, 0x2B, 0x84, 0x8A, 0xBE, 0x50, 0x94, 0xEC, +0x74, 0x49, 0x6C, 0x09, 0xC6, 0x12, 0xD6, 0x34, +0xD6, 0x35, 0xD6, 0x36, 0xBD, 0xB4, 0xA5, 0x12, +0xAD, 0x53, 0xBD, 0xB5, 0xDE, 0xB8, 0xCE, 0x36, +0xDE, 0xB8, 0xDE, 0xD8, 0xD6, 0x77, 0xD6, 0x77, +0xDE, 0xB8, 0xE6, 0xF8, 0xDE, 0xB8, 0xAD, 0x12, +0xAD, 0x12, 0xCE, 0x36, 0xD6, 0x57, 0xC5, 0xD5, +0xBD, 0xB3, 0xD6, 0x15, 0xCD, 0xB3, 0xDE, 0x55, +0xCD, 0xD4, 0xC5, 0xD4, 0xC5, 0xD5, 0xCE, 0x36, +0xD6, 0x77, 0xD6, 0x57, 0xCE, 0x16, 0xD6, 0x77, +0x3A, 0x47, 0x74, 0x0E, 0x7C, 0x90, 0x84, 0xB1, +0x9D, 0x54, 0xA5, 0x74, 0x94, 0xB0, 0x9C, 0xD0, +0xC5, 0xF4, 0xDE, 0x76, 0xCE, 0x14, 0xB5, 0x11, +0x94, 0x4F, 0x6B, 0x0A, 0x6B, 0x0A, 0x8C, 0x2E, +0x7B, 0xCC, 0x94, 0x6F, 0xC5, 0xD5, 0xC5, 0xB3, +0xA4, 0x8E, 0xC5, 0x71, 0xD5, 0xF4, 0xDE, 0x55, +0xDE, 0x55, 0xD6, 0x14, 0xCD, 0xB2, 0xDE, 0x75, +0xDE, 0x55, 0xDE, 0x34, 0xD5, 0xF3, 0xD6, 0x14, +0xCD, 0xD3, 0xC5, 0x92, 0xCD, 0xB2, 0xD6, 0x14, +0xDE, 0x35, 0xCD, 0xB2, 0xDE, 0x34, 0xC5, 0x71, +0xB5, 0x0F, 0xC5, 0x92, 0xBD, 0x30, 0xB4, 0xEF, +0xAC, 0xAE, 0x9C, 0x2C, 0x94, 0x2C, 0x7B, 0x8A, +0x83, 0xAB, 0x94, 0x0D, 0x9C, 0x6E, 0x83, 0xAC, +0x52, 0x68, 0x42, 0x27, 0x42, 0x28, 0x39, 0xE6, +0x42, 0x07, 0x39, 0xE7, 0x42, 0x07, 0x39, 0xE7, +0x42, 0x28, 0x84, 0x10, 0xBD, 0xD7, 0xAD, 0x55, +0xD6, 0xBB, 0xEF, 0x3D, 0xE6, 0xFB, 0xBD, 0x74, +0xB5, 0x11, 0xBD, 0x52, 0xBD, 0x31, 0xB5, 0x31, +0xAC, 0xF0, 0xAC, 0xF0, 0xAC, 0xD0, 0xA4, 0xAF, +0xA4, 0xAF, 0x9C, 0x6E, 0x9C, 0x6E, 0x9C, 0x4E, +0x9C, 0x6E, 0x9C, 0x6E, 0x94, 0x2D, 0x94, 0x4E, +0x9C, 0x6E, 0xB5, 0x10, 0xA4, 0x4D, 0x9C, 0x2C, +0x9C, 0x2C, 0xA4, 0x6D, 0xB4, 0xCF, 0xBD, 0x10, +0xBC, 0xF0, 0xB4, 0xF0, 0xB5, 0x31, 0xBD, 0x72, +0xC5, 0x72, 0xCD, 0xB3, 0xDE, 0x35, 0xE6, 0x75, +0xEE, 0x95, 0xEE, 0xB7, 0xC5, 0xB3, 0x83, 0xCD, +0x52, 0x68, 0x7B, 0xCD, 0x8C, 0x2F, 0x94, 0x71, +0x8C, 0x50, 0x8C, 0x51, 0x9C, 0xF3, 0x83, 0xEF, +0x73, 0xAE, 0x63, 0x2C, 0x42, 0x28, 0x4A, 0x48, +0x6B, 0x0B, 0x83, 0xCE, 0x9C, 0x71, 0xA4, 0xD2, +0x9C, 0x71, 0x9C, 0x91, 0xB5, 0x35, 0x8C, 0x10, +0xB5, 0x75, 0xCE, 0x38, 0x8C, 0x10, 0x5A, 0xEB, +0x39, 0xC7, 0x31, 0xA7, 0x6B, 0x2D, 0xE7, 0x3C, +0xF7, 0xBE, 0xEF, 0x3D, 0xE6, 0xDA, 0xB5, 0x53, +0xB5, 0x11, 0xC5, 0x92, 0xC5, 0x72, 0xBD, 0x72, +0xAC, 0xD0, 0x94, 0x2F, 0xB5, 0x95, 0xDE, 0xDB, +0xC6, 0x17, 0x8C, 0x30, 0x7B, 0xAD, 0x52, 0x69, +0x39, 0xE6, 0x39, 0xC6, 0x4A, 0x68, 0x4A, 0x48, +0x39, 0xE7, 0x39, 0xE7, 0x42, 0x08, 0x4A, 0x49, +0x52, 0x69, 0x4A, 0x6A, 0x6B, 0x2D, 0x6B, 0x6D, +0x7B, 0xCF, 0x83, 0xF0, 0x73, 0x8E, 0x7B, 0xEF, +0x63, 0x0C, 0x94, 0x92, 0xD6, 0x99, 0xAD, 0x13, +0x94, 0x6F, 0xA4, 0xD0, 0xA4, 0xF1, 0xC5, 0xD4, +0xDE, 0xB8, 0xB5, 0x53, 0xC5, 0xD4, 0xCD, 0xF5, +0xBD, 0x94, 0xAD, 0x11, 0xB5, 0x52, 0xAC, 0xF1, +0xAD, 0x11, 0xAD, 0x11, 0xBD, 0x73, 0xBD, 0xB4, +0xC5, 0xD4, 0xC5, 0xF4, 0xC5, 0xF5, 0xC5, 0xF5, +0xB5, 0x52, 0x9C, 0x8F, 0xAD, 0x32, 0xBD, 0x73, +0xBD, 0x93, 0xCD, 0xF5, 0xC5, 0xF5, 0xD6, 0x77, +0xC5, 0xB4, 0xAC, 0xF1, 0xC5, 0xD4, 0xBD, 0xB3, +0xC5, 0xB3, 0xCD, 0xF4, 0xD6, 0x15, 0xCD, 0xF4, +0xC5, 0xB4, 0xA4, 0xF1, 0xAD, 0x12, 0xAD, 0x52, +0xAD, 0x12, 0xB5, 0x52, 0xC5, 0xD4, 0xCD, 0xF5, +0xC5, 0xB3, 0xD6, 0x56, 0xC5, 0xD4, 0xA4, 0xD1, +0x9C, 0x90, 0x94, 0x6F, 0x9C, 0x6F, 0xBD, 0x73, +0xAC, 0xF1, 0xA4, 0xB0, 0xC5, 0xB4, 0xCD, 0xD4, +0xCD, 0xD4, 0xCD, 0xD4, 0xBD, 0x73, 0xBD, 0x73, +0xBD, 0x52, 0xA4, 0xD0, 0xAC, 0xF1, 0xB5, 0x11, +0xAC, 0xF0, 0xAC, 0xF1, 0xAC, 0xF1, 0x9C, 0xB0, +0xA4, 0xD1, 0xAC, 0xF1, 0xA4, 0xB0, 0x9C, 0x8F, +0xA4, 0xB0, 0x9C, 0x8F, 0x94, 0x4E, 0xA4, 0xD0, +0xA4, 0xD0, 0xA4, 0xD0, 0x9C, 0xB0, 0x94, 0x6F, +0xA4, 0xD0, 0xAD, 0x11, 0xB5, 0x52, 0xB5, 0x73, +0xB5, 0x73, 0xAD, 0x32, 0x8C, 0x2E, 0x83, 0xCD, +0x73, 0x6B, 0x6B, 0x2B, 0x73, 0x4B, 0x73, 0x6C, +0x83, 0xCD, 0x8C, 0x0E, 0x94, 0x6F, 0x9C, 0x8F, +0xA4, 0xD0, 0x83, 0xED, 0x52, 0x68, 0x42, 0x07, +0x42, 0x07, 0x39, 0xC6, 0x39, 0xE7, 0x39, 0xE7, +0x41, 0xE7, 0x5A, 0xAA, 0x7B, 0x6D, 0x83, 0xCE, +0x6A, 0xEA, 0x5A, 0xE9, 0x5B, 0x28, 0x42, 0x66, +0x52, 0xC7, 0x94, 0xEC, 0xA5, 0x8D, 0x6C, 0x08, +0x6C, 0x48, 0x6C, 0x49, 0xC6, 0x33, 0xE6, 0xB7, +0xC5, 0xB4, 0xB5, 0x73, 0xBD, 0xB5, 0xBD, 0xB5, +0xAD, 0x33, 0x9C, 0xB1, 0xB5, 0x94, 0x94, 0x70, +0x8C, 0x2F, 0x8C, 0x50, 0x94, 0x70, 0xA4, 0xF2, +0xC5, 0xF6, 0xEF, 0x3A, 0xDE, 0x97, 0xA4, 0xF1, +0xAD, 0x32, 0xCE, 0x36, 0xA4, 0xD1, 0x73, 0x4C, +0xAD, 0x11, 0xBD, 0x51, 0xBD, 0x72, 0xBD, 0x51, +0xC5, 0x93, 0xDE, 0x57, 0xD6, 0x56, 0xC5, 0xD5, +0xCE, 0x15, 0xD6, 0x36, 0xCD, 0xF5, 0xDE, 0x77, +0x53, 0x09, 0x5B, 0x2A, 0x5B, 0x4B, 0x63, 0x8C, +0x8C, 0xB0, 0x84, 0x2F, 0x8C, 0x6F, 0x9C, 0xD0, +0xA4, 0xF1, 0xC5, 0xD4, 0xBD, 0x72, 0xAC, 0xF0, +0xB5, 0x52, 0xA4, 0xB0, 0x9C, 0x8F, 0xB5, 0x52, +0xCD, 0xF5, 0xDE, 0x77, 0xE6, 0xD8, 0xE6, 0xB7, +0xAC, 0xAE, 0xDE, 0x34, 0xDE, 0x34, 0xD6, 0x14, +0xCD, 0xD3, 0xCD, 0xB2, 0xC5, 0x92, 0xC5, 0xB2, +0xDE, 0x34, 0xE6, 0x75, 0xD5, 0xF4, 0xDE, 0x75, +0xE6, 0xB6, 0xEE, 0xB7, 0xE6, 0x96, 0xDE, 0x55, +0xD5, 0xF3, 0xBD, 0x30, 0xB4, 0xEF, 0xAC, 0x8E, +0xAC, 0xAE, 0xB5, 0x10, 0xD5, 0xF3, 0xB4, 0xEF, +0x9C, 0x4D, 0x9C, 0x6E, 0xA4, 0xF0, 0x8C, 0x0E, +0x73, 0x6C, 0x73, 0x6B, 0x6B, 0x0A, 0x5A, 0xA9, +0x62, 0xC9, 0x52, 0x88, 0x39, 0xC6, 0x39, 0xE7, +0x31, 0xA6, 0x31, 0x65, 0x39, 0xE7, 0x39, 0xC6, +0x4A, 0x48, 0x7B, 0xEF, 0x94, 0xD3, 0x9C, 0xD4, +0xCE, 0x9B, 0xDE, 0xFC, 0xDE, 0xFB, 0xE7, 0x1B, +0xBD, 0x94, 0x8B, 0xEE, 0x94, 0x4E, 0x9C, 0x4D, +0xA4, 0xAF, 0xAC, 0xCF, 0xA4, 0x8E, 0xAC, 0xCF, +0xB4, 0xEF, 0xBD, 0x30, 0xBD, 0x31, 0xB5, 0x10, +0xB5, 0x10, 0xBD, 0x51, 0xBD, 0x30, 0xBD, 0x30, +0xB5, 0x10, 0xC5, 0x71, 0xC5, 0x71, 0xC5, 0x71, +0xCD, 0x91, 0xC5, 0x71, 0xC5, 0x71, 0xC5, 0x30, +0xBC, 0xEF, 0xAC, 0x8E, 0x9C, 0x2D, 0xB5, 0x74, +0xE6, 0xDA, 0xD6, 0x58, 0xA4, 0x90, 0x8B, 0xAC, +0x93, 0xEC, 0x9C, 0x0C, 0x94, 0x0C, 0x94, 0x0D, +0x8B, 0xCC, 0x7B, 0x6B, 0x8B, 0xEC, 0x94, 0x2E, +0x7B, 0xAC, 0x62, 0xE9, 0x5A, 0xA9, 0x62, 0xEB, +0x6B, 0x4D, 0x73, 0xAE, 0x5A, 0xAA, 0x73, 0x6D, +0x5A, 0xCA, 0x62, 0xCA, 0x62, 0xCA, 0x73, 0x2C, +0xAC, 0xD2, 0x9C, 0x71, 0xBD, 0x96, 0xAC, 0xF4, +0xA4, 0xF3, 0xCE, 0x18, 0xD6, 0x59, 0x9C, 0xB3, +0x4A, 0x49, 0x31, 0x66, 0x73, 0x8E, 0xDE, 0xBA, +0xD6, 0x9A, 0xEF, 0x3C, 0xEF, 0x1C, 0xD6, 0x58, +0x9C, 0x91, 0xCD, 0xD5, 0xC5, 0x72, 0xC5, 0x72, +0xA4, 0xB0, 0x94, 0x50, 0x6B, 0x2C, 0x94, 0x92, +0xCE, 0x59, 0xCE, 0x59, 0xA4, 0xF3, 0x73, 0x8D, +0x41, 0xE7, 0x39, 0xC6, 0x4A, 0x68, 0x42, 0x07, +0x39, 0xE7, 0x39, 0xC7, 0x39, 0xC7, 0x42, 0x08, +0x42, 0x28, 0x4A, 0x49, 0x5A, 0xCB, 0x63, 0x2D, +0x6B, 0x4D, 0x62, 0xEC, 0x5A, 0xAB, 0x52, 0xAA, +0x62, 0xEC, 0x9C, 0xF3, 0xBD, 0xD6, 0xDE, 0x99, +0xA4, 0xD1, 0xA4, 0xD1, 0xA4, 0xF1, 0xC5, 0xD4, +0xE6, 0xB8, 0xAD, 0x11, 0xC5, 0xD4, 0xC5, 0xF5, +0xC5, 0xF5, 0xA4, 0xD0, 0xB5, 0x52, 0xBD, 0x73, +0xB5, 0x52, 0xB5, 0x32, 0xBD, 0x73, 0xB5, 0x52, +0xC5, 0xD4, 0xBD, 0x93, 0xBD, 0x93, 0xB5, 0x73, +0xB5, 0x52, 0x9C, 0x6F, 0xB5, 0x52, 0xB5, 0x73, +0xBD, 0x73, 0xBD, 0x94, 0xBD, 0x94, 0xBD, 0xB4, +0xBD, 0x94, 0xA4, 0xB0, 0x9C, 0xB0, 0xBD, 0x93, +0xCD, 0xD4, 0xCD, 0xD3, 0xCD, 0xD3, 0xCD, 0xF4, +0xCE, 0x14, 0xC5, 0xB4, 0xBD, 0xB4, 0xCE, 0x36, +0xC5, 0xD5, 0xC5, 0xF5, 0xBD, 0x72, 0xAC, 0xF1, +0xAD, 0x10, 0xB5, 0x51, 0xA4, 0xF0, 0x83, 0xCD, +0x94, 0x4F, 0x94, 0x6F, 0x83, 0xAD, 0x94, 0x4F, +0x8B, 0xED, 0xAD, 0x11, 0x9C, 0x6E, 0xA4, 0xB0, +0xAC, 0xF0, 0xB5, 0x31, 0xAC, 0xF0, 0xAD, 0x11, +0xA4, 0xAF, 0x8B, 0xEC, 0x94, 0x2D, 0x94, 0x2D, +0x94, 0x2D, 0xBD, 0x72, 0xAC, 0xF0, 0x83, 0xCC, +0x8C, 0x2D, 0x9C, 0x6F, 0xAD, 0x11, 0xD6, 0x35, +0xBD, 0x93, 0xAD, 0x11, 0xAD, 0x11, 0xB5, 0x32, +0xA4, 0xD1, 0x9C, 0x90, 0x9C, 0x8F, 0x94, 0x4F, +0x8C, 0x2E, 0x8C, 0x0E, 0x7B, 0xAD, 0x7B, 0xAC, +0x83, 0xCD, 0x83, 0xEE, 0x8B, 0xEE, 0x9C, 0x90, +0x94, 0x70, 0x9C, 0x90, 0x9C, 0xD1, 0x9C, 0xB1, +0x9C, 0x90, 0x9C, 0x90, 0x94, 0x70, 0x94, 0x70, +0x9C, 0xB1, 0xA4, 0xF2, 0xA4, 0xD1, 0x7B, 0xAD, +0x4A, 0x48, 0x39, 0xA6, 0x31, 0xA5, 0x39, 0xC6, +0x42, 0x28, 0x4A, 0x28, 0x5A, 0xCA, 0x6B, 0x2C, +0x73, 0x4C, 0x6B, 0x2B, 0x63, 0x0A, 0x5A, 0xE8, +0x7C, 0x4B, 0x74, 0x49, 0x84, 0xAA, 0x5B, 0x47, +0x63, 0xA8, 0x74, 0x09, 0x9C, 0x8F, 0x9C, 0x4F, +0x94, 0x4F, 0x94, 0x70, 0x94, 0x6F, 0x9C, 0xB0, +0x9C, 0xB1, 0xA4, 0xF2, 0x94, 0x70, 0x94, 0x70, +0xA4, 0xF2, 0xA4, 0xF2, 0xAD, 0x54, 0x9C, 0xD2, +0xA4, 0xF2, 0xE6, 0xD8, 0xC5, 0xD4, 0x9C, 0xB0, +0xBD, 0x94, 0xE6, 0xB8, 0xCD, 0xF5, 0xCD, 0xF5, +0xD6, 0x16, 0xDE, 0x35, 0xBD, 0x73, 0x8B, 0xED, +0xAC, 0xD1, 0xDE, 0x77, 0xC5, 0xD4, 0xC5, 0xB3, +0xBD, 0x73, 0xBD, 0x73, 0xBD, 0x73, 0xCD, 0xD4, +0x5B, 0x2A, 0x84, 0x2E, 0x9C, 0xD0, 0x8C, 0x6E, +0xA5, 0x11, 0x84, 0x0D, 0x84, 0x0D, 0x8C, 0x4E, +0x9C, 0xAF, 0xCD, 0xF4, 0xA4, 0xCF, 0x94, 0x4D, +0x94, 0x4E, 0xB5, 0x32, 0xB5, 0x52, 0xBD, 0x52, +0xDE, 0x77, 0xE6, 0xB7, 0xE6, 0x97, 0xDE, 0x56, +0xAC, 0xAF, 0xDE, 0x75, 0xDE, 0x55, 0xD5, 0xF3, +0xD5, 0xF4, 0xC5, 0x71, 0xC5, 0x71, 0xC5, 0xB2, +0xCD, 0xD3, 0xD6, 0x34, 0xBD, 0x51, 0xD6, 0x14, +0xDE, 0x34, 0xDE, 0x75, 0xDE, 0x54, 0xCD, 0x92, +0xC5, 0x71, 0xCD, 0xB2, 0xDE, 0x35, 0xE6, 0x76, +0xE6, 0x96, 0xDE, 0x55, 0xEE, 0x96, 0xC5, 0x51, +0x9C, 0x4D, 0xA4, 0x8F, 0xAD, 0x11, 0xA4, 0xF1, +0x9C, 0x8F, 0x94, 0x4E, 0x8C, 0x0E, 0x83, 0xED, +0x83, 0xED, 0x83, 0xCD, 0x7B, 0x8C, 0x41, 0xE6, +0x39, 0xC6, 0x31, 0x85, 0x31, 0x85, 0x31, 0x85, +0x4A, 0x48, 0x5A, 0xCA, 0x73, 0xAE, 0x94, 0xB3, +0xBE, 0x18, 0xC6, 0x3A, 0xB5, 0x97, 0xCE, 0x7A, +0x7B, 0xCF, 0x4A, 0x49, 0xA4, 0xF2, 0x9C, 0xB0, +0x9C, 0x8F, 0x9C, 0x6E, 0x8B, 0xEC, 0x7B, 0x4A, +0x7B, 0x8B, 0x8B, 0xEC, 0x83, 0xAB, 0x83, 0xCC, +0x7B, 0x6B, 0x7B, 0x6A, 0x73, 0x09, 0x83, 0x6A, +0x8B, 0xAB, 0x8B, 0xCB, 0x94, 0x0C, 0xA4, 0x8E, +0xBD, 0x30, 0xD5, 0xD3, 0xC5, 0x51, 0xBD, 0x30, +0xC5, 0x50, 0xD5, 0xD2, 0xD5, 0xD4, 0xEF, 0x1B, +0xEF, 0x3C, 0xEF, 0x5D, 0xEF, 0x1B, 0x94, 0x4F, +0xB5, 0x12, 0xBD, 0x31, 0xBD, 0x31, 0xBD, 0x31, +0xB5, 0x10, 0xBD, 0x31, 0xBD, 0x72, 0xBD, 0x52, +0xC5, 0x93, 0xC5, 0x92, 0xAD, 0x10, 0xAC, 0xF0, +0x62, 0xC9, 0x31, 0xA6, 0x42, 0x07, 0x73, 0x8D, +0x83, 0xEF, 0x52, 0x49, 0x29, 0x24, 0x5A, 0x69, +0x83, 0xAE, 0x83, 0x8E, 0x94, 0x51, 0x83, 0xEF, +0x73, 0x6E, 0x6B, 0x4D, 0xA4, 0xF4, 0xD6, 0x79, +0x8C, 0x31, 0x41, 0xE8, 0x5A, 0xCB, 0x8C, 0x31, +0xB5, 0x76, 0xDE, 0xBA, 0xE6, 0xFB, 0xE6, 0xFC, +0xD6, 0x59, 0xF7, 0x5C, 0xDE, 0x37, 0xA4, 0x6F, +0x94, 0x0D, 0xA4, 0xB0, 0x8C, 0x0F, 0x6B, 0x4C, +0x84, 0x10, 0x94, 0x92, 0xC6, 0x18, 0xC5, 0xF7, +0x5A, 0xCA, 0x39, 0xC6, 0x39, 0xE6, 0x39, 0xC6, +0x42, 0x07, 0x39, 0xC6, 0x39, 0xC6, 0x42, 0x07, +0x42, 0x08, 0x42, 0x29, 0x4A, 0x49, 0x5A, 0xCB, +0x63, 0x2D, 0x52, 0x8A, 0x39, 0xE8, 0x31, 0x86, +0x39, 0xE7, 0x5A, 0xCB, 0x84, 0x10, 0xAD, 0x34, +0xB5, 0x53, 0xA4, 0xD1, 0xA5, 0x12, 0xCE, 0x15, +0xDE, 0x97, 0xA4, 0xF0, 0xBD, 0x93, 0xC5, 0xB4, +0xBD, 0x73, 0x9C, 0xB0, 0xB5, 0x52, 0xB5, 0x52, +0xBD, 0x73, 0xB5, 0x52, 0xB5, 0x52, 0xAC, 0xF1, +0xBD, 0x94, 0xBD, 0xB4, 0xBD, 0x73, 0xB5, 0x52, +0xAD, 0x32, 0xA4, 0xD0, 0xB5, 0x32, 0xB5, 0x52, +0xB5, 0x52, 0xBD, 0x93, 0xBD, 0xB4, 0xBD, 0x94, +0xA4, 0xD0, 0x9C, 0xB0, 0xA4, 0xF1, 0xCD, 0xF4, +0xD6, 0x34, 0xD6, 0x34, 0xD6, 0x14, 0xD6, 0x35, +0xD6, 0x35, 0xC5, 0xD4, 0xB5, 0x73, 0xC5, 0xD5, +0xD6, 0x77, 0xD6, 0x56, 0xCD, 0xD4, 0xBD, 0x93, +0xBD, 0x52, 0xBD, 0x51, 0xC5, 0xB3, 0xB5, 0x53, +0xBD, 0xB5, 0xB5, 0x73, 0x9C, 0xD1, 0x9C, 0x90, +0x83, 0xED, 0xB5, 0x32, 0x83, 0xCC, 0xA4, 0xB0, +0xB5, 0x31, 0xAD, 0x11, 0xAC, 0xF0, 0xAC, 0xF0, +0xA4, 0xB0, 0xA4, 0x8F, 0x8B, 0xEC, 0x8B, 0xEC, +0xA4, 0xAF, 0xB5, 0x31, 0x9C, 0x8F, 0x94, 0x6E, +0x94, 0x4F, 0x9C, 0x6F, 0xA4, 0xB0, 0xBD, 0x72, +0xC5, 0xB3, 0xCE, 0x14, 0xCE, 0x14, 0xC5, 0x93, +0xAD, 0x32, 0x8B, 0xED, 0x94, 0x2E, 0xB5, 0x73, +0xB5, 0x73, 0xAD, 0x11, 0xA4, 0xF1, 0xB5, 0x33, +0xC5, 0xD5, 0xBD, 0x94, 0xAD, 0x12, 0xB5, 0x53, +0xBD, 0xB4, 0xBD, 0xB4, 0xBD, 0xB4, 0xC5, 0xF5, +0xBD, 0xB4, 0xBD, 0xB4, 0xC5, 0xB4, 0xC5, 0xD4, +0xBD, 0xD4, 0xC5, 0xF5, 0xC5, 0xD5, 0xCD, 0xF5, +0xBD, 0xB4, 0x62, 0xC9, 0x41, 0xE7, 0x39, 0xE7, +0x39, 0xE6, 0x39, 0xE6, 0x4A, 0x48, 0x5A, 0xAA, +0x73, 0x6C, 0x6B, 0x2C, 0x4A, 0x47, 0x73, 0xEC, +0x7C, 0xAB, 0x74, 0x48, 0x53, 0x05, 0x6B, 0xC9, +0x53, 0x07, 0x7C, 0x0B, 0xBD, 0x73, 0xAC, 0xF2, +0xA4, 0xD2, 0xA4, 0xF2, 0xA4, 0xB1, 0xA4, 0xD1, +0x9C, 0xB1, 0x9C, 0xD1, 0x9C, 0xD1, 0x9C, 0x91, +0x9C, 0xD1, 0x9C, 0xB1, 0x9C, 0xB1, 0x8C, 0x2F, +0x94, 0x4F, 0xA5, 0x12, 0x94, 0x50, 0x9C, 0x90, +0xAD, 0x32, 0xCD, 0xD4, 0xCD, 0xB4, 0xCD, 0xB4, +0xC5, 0x73, 0xBD, 0x32, 0xC5, 0x94, 0xC5, 0x94, +0xC5, 0xB4, 0xBD, 0x73, 0xA4, 0x8F, 0x9C, 0x8F, +0x9C, 0x6F, 0x9C, 0x8F, 0xC5, 0x93, 0xD6, 0x36, +0xA5, 0x11, 0xB5, 0x72, 0xA4, 0xCF, 0x9C, 0x8E, +0x8C, 0x4D, 0x84, 0x0D, 0x83, 0xED, 0x94, 0x6E, +0x9C, 0x8F, 0xCE, 0x14, 0xAC, 0xF0, 0xAD, 0x10, +0xB5, 0x51, 0xAD, 0x11, 0xAD, 0x11, 0xAC, 0xD0, +0xD6, 0x35, 0xD6, 0x15, 0xDE, 0x55, 0xE6, 0x75, +0xAC, 0xAE, 0xD6, 0x13, 0xD6, 0x34, 0xCD, 0xD3, +0xC5, 0x71, 0xCD, 0xD2, 0xD6, 0x13, 0xDE, 0x76, +0xD5, 0xF4, 0xCD, 0xB3, 0xC5, 0xB3, 0xD6, 0x35, +0xDE, 0x34, 0xE6, 0x75, 0xD5, 0xF3, 0xC5, 0x51, +0xBD, 0x10, 0xC5, 0x51, 0xCD, 0xD3, 0xD6, 0x14, +0xDE, 0x35, 0xE6, 0x55, 0xE6, 0x55, 0xC5, 0x31, +0x9C, 0x4D, 0x9C, 0x6E, 0xB5, 0x52, 0xAD, 0x32, +0xAD, 0x11, 0xB5, 0x31, 0xB5, 0x52, 0xBD, 0x92, +0xCD, 0xF3, 0xCD, 0xF3, 0xD6, 0x14, 0x8C, 0x0D, +0x42, 0x06, 0x31, 0xA5, 0x31, 0x85, 0x31, 0x85, +0x39, 0xE7, 0x42, 0x28, 0x5A, 0xCA, 0x63, 0x0C, +0x9C, 0xF3, 0xAD, 0x96, 0xAD, 0x76, 0xB5, 0x97, +0x7B, 0xCF, 0x7B, 0xCF, 0xCE, 0x59, 0xBD, 0xD6, +0x94, 0x70, 0x94, 0x4F, 0x94, 0x4F, 0x83, 0xAC, +0x8C, 0x0D, 0xB5, 0x73, 0xAD, 0x11, 0xA4, 0xD0, +0x94, 0x2E, 0xA4, 0x8F, 0x8C, 0x0D, 0x9C, 0x2E, +0x94, 0x2D, 0x8C, 0x0C, 0x94, 0x4D, 0x8C, 0x0C, +0x8B, 0xEC, 0x9C, 0x4D, 0xA4, 0x8E, 0xB4, 0xCE, +0xC5, 0x50, 0xEE, 0x95, 0xE6, 0x35, 0xBD, 0x95, +0xC5, 0xF8, 0xDE, 0xFB, 0xDE, 0xBB, 0xD6, 0x79, +0xD6, 0x99, 0xB5, 0x74, 0x9C, 0xD1, 0x7B, 0xAC, +0x94, 0x6E, 0xB5, 0x52, 0xBD, 0x72, 0xAD, 0x11, +0xBD, 0x93, 0xC5, 0x93, 0xAC, 0xEF, 0xBD, 0x51, +0x83, 0xAC, 0x31, 0x65, 0x62, 0xEB, 0x6B, 0x2C, +0x63, 0x0B, 0x52, 0x69, 0x29, 0x45, 0x31, 0x45, +0x52, 0x48, 0x6B, 0x0B, 0x83, 0xAE, 0x7B, 0x8E, +0x63, 0x0B, 0x39, 0xC7, 0x83, 0xCF, 0xBD, 0x96, +0xBD, 0xB7, 0xAD, 0x55, 0x73, 0x8E, 0x6B, 0x4D, +0xAD, 0x35, 0xE7, 0x1C, 0xE7, 0x1C, 0xE6, 0xFC, +0xEF, 0x1C, 0xDE, 0x7A, 0xC5, 0xD6, 0xA4, 0x91, +0xB5, 0x12, 0x94, 0x2E, 0x94, 0x0E, 0x8B, 0xED, +0x7B, 0x6C, 0x62, 0xCA, 0x73, 0x6E, 0x8C, 0x30, +0x5A, 0xAA, 0x4A, 0x48, 0x42, 0x28, 0x42, 0x07, +0x39, 0xE7, 0x39, 0xE7, 0x42, 0x07, 0x4A, 0x49, +0x4A, 0x69, 0x52, 0x8A, 0x4A, 0x6A, 0x52, 0x8A, +0x52, 0x8A, 0x4A, 0x69, 0x39, 0xE8, 0x29, 0x45, +0x39, 0xC7, 0x52, 0x89, 0x5A, 0xAA, 0x52, 0x69, +0x8C, 0x30, 0xAD, 0x32, 0xC5, 0xD5, 0xDE, 0x77, +0xDE, 0x97, 0xAC, 0xF0, 0xC5, 0xD4, 0xD6, 0x35, +0xBD, 0x72, 0xB5, 0x52, 0xB5, 0x52, 0xB5, 0x32, +0xAD, 0x11, 0xA4, 0xD0, 0xB5, 0x52, 0xAC, 0xF1, +0xBD, 0x73, 0xC5, 0xB4, 0xBD, 0x93, 0xB5, 0x52, +0xB5, 0x32, 0xAD, 0x11, 0xB5, 0x31, 0xB5, 0x52, +0xB5, 0x73, 0xBD, 0x93, 0xCE, 0x36, 0xBD, 0xB4, +0xA4, 0xB0, 0xA4, 0xD1, 0xBD, 0x73, 0xD6, 0x35, +0xDE, 0x54, 0xD6, 0x14, 0xD5, 0xF3, 0xD6, 0x14, +0xCD, 0xF4, 0xCE, 0x14, 0xAD, 0x32, 0xAD, 0x33, +0xCE, 0x15, 0xD6, 0x35, 0xBD, 0x72, 0xAC, 0xF0, +0xBD, 0x72, 0xB5, 0x10, 0xB5, 0x72, 0x94, 0x2E, +0xAD, 0x12, 0xA4, 0xF2, 0x9C, 0xD1, 0x94, 0x70, +0x8C, 0x0E, 0xB5, 0x32, 0x8C, 0x0D, 0xB5, 0x32, +0xB5, 0x31, 0xC5, 0x93, 0xBD, 0x93, 0xC5, 0xD4, +0xC5, 0xB3, 0xA4, 0xD0, 0x94, 0x2D, 0x94, 0x2D, +0x94, 0x4E, 0x9C, 0x8F, 0xA4, 0xB0, 0x8C, 0x0D, +0x8C, 0x0D, 0x8B, 0xED, 0x9C, 0x6F, 0xA4, 0xF0, +0xAD, 0x10, 0xBD, 0xB3, 0xC5, 0xD3, 0xC5, 0xB3, +0xAD, 0x11, 0xAC, 0xF2, 0xA4, 0xF1, 0xCE, 0x15, +0xDE, 0x97, 0xDE, 0x77, 0xD6, 0x56, 0xC5, 0xF5, +0xC5, 0xF5, 0xC5, 0xD5, 0xCE, 0x16, 0xD6, 0x56, +0xDE, 0x97, 0xD6, 0x56, 0xCE, 0x35, 0xD6, 0x36, +0xCE, 0x15, 0xBD, 0x94, 0xCE, 0x15, 0xDE, 0x76, +0xDE, 0x97, 0xE6, 0xD7, 0xEE, 0xF7, 0xF6, 0xF7, +0xF7, 0x38, 0xBD, 0xB3, 0x6B, 0x4B, 0x41, 0xE6, +0x31, 0x85, 0x31, 0xA5, 0x39, 0xC6, 0x42, 0x27, +0x4A, 0x28, 0x31, 0xA6, 0x4A, 0x48, 0x6B, 0xAA, +0x7C, 0xAB, 0x7C, 0xCB, 0x5B, 0x67, 0x3A, 0x04, +0x84, 0x4C, 0xA5, 0x0F, 0x8C, 0x0E, 0xA4, 0xB1, +0xA4, 0xB1, 0xAD, 0x12, 0xBD, 0x74, 0xAD, 0x12, +0xBD, 0xB4, 0xBD, 0xB4, 0xB5, 0x33, 0xBD, 0xB4, +0xBD, 0x93, 0xBD, 0xB4, 0xB5, 0x52, 0xB5, 0x53, +0xC5, 0xB4, 0xBD, 0x53, 0xBD, 0x74, 0xB5, 0x53, +0xB5, 0x32, 0xC5, 0x94, 0xBD, 0x53, 0xBD, 0x32, +0xBD, 0x73, 0xBD, 0x53, 0xB5, 0x53, 0xB5, 0x32, +0xAD, 0x32, 0xAC, 0xF1, 0xAD, 0x12, 0xAC, 0xF2, +0xA4, 0xF2, 0xA4, 0xF2, 0xA4, 0xB1, 0x9C, 0x90, +0x7B, 0xCC, 0x9C, 0xD0, 0xA4, 0xAF, 0x9C, 0x6E, +0x7B, 0xAB, 0x7B, 0x8B, 0x83, 0xEC, 0x8C, 0x2E, +0x94, 0x4E, 0xAC, 0xF0, 0xA4, 0xAE, 0x8C, 0x0C, +0x83, 0xAB, 0x83, 0xCB, 0x8C, 0x0C, 0xB5, 0x31, +0xDE, 0x76, 0xDE, 0x56, 0xE6, 0xB7, 0xEE, 0xB7, +0xB4, 0xCF, 0xDE, 0x34, 0xD6, 0x14, 0xCD, 0xB2, +0xCD, 0xD3, 0xD5, 0xF3, 0xD6, 0x14, 0xDE, 0x76, +0xD5, 0xF4, 0xDE, 0x56, 0xDE, 0x76, 0xDE, 0x75, +0xDE, 0x55, 0xDE, 0x34, 0xC5, 0x71, 0xCD, 0x92, +0xCD, 0x72, 0xC5, 0x51, 0xCD, 0xB2, 0xCD, 0xD3, +0xD5, 0xD3, 0xC5, 0x51, 0xBC, 0xEF, 0xB4, 0x8E, +0x9C, 0x4D, 0xAD, 0x11, 0xC5, 0xB3, 0xC5, 0xB3, +0xC5, 0xB3, 0xCD, 0xD3, 0xCD, 0xD3, 0xCD, 0xB3, +0xD5, 0xF3, 0xCD, 0xD3, 0xCD, 0xD2, 0xD6, 0x14, +0xCD, 0xF4, 0x9C, 0x6E, 0x6B, 0x2A, 0x41, 0xE6, +0x39, 0xE6, 0x52, 0xA9, 0x52, 0x8A, 0x52, 0x8A, +0x63, 0x4C, 0x7B, 0xCF, 0x7B, 0xEF, 0x8C, 0x51, +0x8C, 0x51, 0xAD, 0x76, 0xC6, 0x18, 0xE7, 0x3C, +0xC6, 0x18, 0xA4, 0xF3, 0x9C, 0x70, 0x7B, 0x8C, +0x83, 0xEC, 0xBD, 0xB3, 0xBD, 0xB4, 0xAD, 0x32, +0x94, 0x4E, 0x94, 0x4E, 0x8B, 0xED, 0x9C, 0x8F, +0x9C, 0x8F, 0xA4, 0xAF, 0xA4, 0xD0, 0x9C, 0x6E, +0x8B, 0xED, 0x94, 0x0D, 0xA4, 0x6E, 0xB4, 0xEF, +0xB4, 0xCE, 0xCD, 0x91, 0xDE, 0x14, 0xAC, 0xB0, +0x84, 0x10, 0xC6, 0x38, 0xB5, 0x76, 0xAD, 0x55, +0xF7, 0x7D, 0xDE, 0xBA, 0xB5, 0x54, 0x8C, 0x50, +0x7B, 0xCD, 0x8C, 0x4F, 0x84, 0x0E, 0x84, 0x0E, +0xB5, 0x93, 0x9C, 0x8F, 0xA4, 0xAE, 0xA4, 0xAF, +0x94, 0x2E, 0x5A, 0x89, 0x5A, 0xEB, 0x5A, 0xAA, +0x5A, 0xCA, 0x4A, 0x28, 0x52, 0x8A, 0x52, 0x48, +0x52, 0x28, 0x41, 0xE7, 0x62, 0xEA, 0x52, 0x89, +0x52, 0x69, 0x7B, 0x6D, 0x73, 0x6D, 0x9C, 0x72, +0xBD, 0x96, 0xA4, 0xF3, 0xAD, 0x35, 0xA5, 0x14, +0xC6, 0x38, 0xE6, 0xFC, 0xC5, 0xD7, 0xC5, 0xF8, +0xD6, 0x79, 0xDE, 0xBA, 0x9C, 0xB2, 0x7B, 0x4D, +0xB5, 0x13, 0xAC, 0xD1, 0xAC, 0xF0, 0xB5, 0x31, +0xB5, 0x31, 0xAD, 0x11, 0x8B, 0xEE, 0x62, 0xCA, +0x4A, 0x48, 0x63, 0x0B, 0x4A, 0x68, 0x42, 0x48, +0x42, 0x07, 0x42, 0x48, 0x42, 0x28, 0x52, 0x89, +0x52, 0x8A, 0x52, 0xAA, 0x52, 0x8A, 0x63, 0x0C, +0x5A, 0xCB, 0x52, 0x8A, 0x42, 0x08, 0x31, 0x86, +0x29, 0x65, 0x39, 0xC6, 0x39, 0xE7, 0x83, 0xEF, +0x9C, 0x90, 0xAC, 0xF1, 0xCE, 0x16, 0xD6, 0x56, +0xCE, 0x15, 0xAC, 0xF0, 0xC5, 0xB4, 0xD6, 0x35, +0xCD, 0xF4, 0xC5, 0xF4, 0xC5, 0xB4, 0xCD, 0xF5, +0xBD, 0xB3, 0xBD, 0x72, 0xC5, 0xD4, 0xC5, 0xB3, +0xCE, 0x15, 0xD6, 0x56, 0xCE, 0x35, 0xC5, 0xD4, +0xBD, 0xB3, 0xBD, 0x93, 0xC5, 0xB3, 0xBD, 0x93, +0xC5, 0xB4, 0xC5, 0xD4, 0xC5, 0xF4, 0xBD, 0xB4, +0xA4, 0xD0, 0xAD, 0x32, 0xC5, 0xF4, 0xDE, 0x55, +0xDE, 0x75, 0xDE, 0x14, 0xDE, 0x14, 0xD6, 0x14, +0xCD, 0xD3, 0xCD, 0xF4, 0xB5, 0x52, 0xB5, 0x73, +0xD6, 0x36, 0xD6, 0x35, 0xAC, 0xD0, 0xAC, 0xCF, +0xAC, 0xF0, 0xA4, 0xCF, 0xB5, 0x51, 0x8C, 0x0E, +0x94, 0x4F, 0x94, 0x6F, 0x8C, 0x4F, 0x8C, 0x2E, +0x94, 0x70, 0xB5, 0x53, 0x8B, 0xED, 0xBD, 0x93, +0xBD, 0x93, 0xBD, 0xB3, 0xBD, 0x93, 0xBD, 0x93, +0xC5, 0xB3, 0x9C, 0x8F, 0xBD, 0x72, 0xA4, 0xF0, +0xA4, 0xAF, 0x8C, 0x0D, 0x94, 0x4E, 0xA4, 0xB0, +0xAD, 0x11, 0x8C, 0x0D, 0x9C, 0x8F, 0x9C, 0xAF, +0x94, 0x4E, 0x94, 0x4E, 0x94, 0x6E, 0xA4, 0xCF, +0xA4, 0xD0, 0xAD, 0x33, 0xB5, 0x73, 0xD6, 0x56, +0xDE, 0x96, 0xDE, 0xB7, 0xDE, 0x97, 0xD6, 0x77, +0xD6, 0x77, 0xD6, 0x77, 0xDE, 0x77, 0xE6, 0xB7, +0xDE, 0xB7, 0xDE, 0x97, 0xDE, 0x96, 0xDE, 0x96, +0xDE, 0x96, 0xD6, 0x56, 0xD6, 0x56, 0xE6, 0xB7, +0xE6, 0xD7, 0xE6, 0xD6, 0xE6, 0xB6, 0xEE, 0xD6, +0xEE, 0xF7, 0xCE, 0x14, 0xAD, 0x52, 0x84, 0x0E, +0x31, 0xA5, 0x31, 0xA6, 0x39, 0xE6, 0x31, 0xA5, +0x39, 0xC6, 0x42, 0x28, 0x4A, 0x48, 0x63, 0x4A, +0x53, 0x27, 0x74, 0x8A, 0x6C, 0x49, 0x5B, 0x48, +0x4A, 0x86, 0x8C, 0x6C, 0x73, 0x4A, 0x6B, 0x0B, +0xA4, 0xD2, 0xA4, 0xB1, 0xB5, 0x53, 0xA4, 0xD1, +0xBD, 0x93, 0xDE, 0xB7, 0xA5, 0x31, 0xA5, 0x50, +0x8C, 0xCD, 0x94, 0xED, 0xA5, 0x4F, 0xB5, 0x70, +0xCE, 0x14, 0xC5, 0xB3, 0xBD, 0x73, 0xBD, 0x52, +0xB5, 0x32, 0xB5, 0x32, 0xAD, 0x11, 0xB5, 0x12, +0xB5, 0x12, 0xA4, 0xB0, 0x94, 0x2E, 0xAC, 0xF1, +0xB5, 0x12, 0xAC, 0xB0, 0xAC, 0xF1, 0xB5, 0x12, +0xAC, 0xF2, 0xAC, 0xF2, 0xAC, 0xF2, 0xB5, 0x33, +0x8C, 0xB1, 0x94, 0xD1, 0x8C, 0x4E, 0x8C, 0x0C, +0x8B, 0xEC, 0x8B, 0xEC, 0x8B, 0xEC, 0x83, 0xCB, +0x83, 0xAB, 0x83, 0xAB, 0x83, 0xAB, 0x83, 0x8B, +0x7B, 0x6A, 0x7B, 0x6A, 0x83, 0xAB, 0x8B, 0xEB, +0x9C, 0x4D, 0x9C, 0x6E, 0xA4, 0xAF, 0xA4, 0x8E, +0x9C, 0x4D, 0xC5, 0x71, 0xBD, 0x30, 0xB5, 0x10, +0xAC, 0xEF, 0xAC, 0xEF, 0xAC, 0xAE, 0xBD, 0x31, +0xC5, 0x92, 0xBD, 0x51, 0xBD, 0x30, 0xC5, 0x72, +0xD5, 0xD3, 0xDE, 0x35, 0xDE, 0x14, 0xD5, 0xD3, +0xE6, 0x55, 0xE6, 0x75, 0xEE, 0x76, 0xE6, 0x75, +0xE6, 0x55, 0xD5, 0xB3, 0xE6, 0x14, 0xC5, 0x51, +0xA4, 0x8E, 0xC5, 0xD3, 0xC5, 0xD3, 0xC5, 0x93, +0xC5, 0xB3, 0xC5, 0xB3, 0xB5, 0x10, 0xBD, 0x30, +0xCD, 0xB2, 0xCD, 0xB2, 0xD5, 0xF3, 0xDE, 0x14, +0xE6, 0x55, 0xD6, 0x14, 0xD5, 0xF4, 0xAC, 0xF0, +0x6B, 0x09, 0x52, 0x89, 0x39, 0xE7, 0x39, 0xE7, +0x42, 0x27, 0x52, 0xAA, 0x63, 0x2C, 0x6B, 0x6D, +0x7B, 0xAF, 0xAD, 0x55, 0xBD, 0xF8, 0xCE, 0x7A, +0xD6, 0xBA, 0xDE, 0xDB, 0xB5, 0x75, 0x7B, 0xAD, +0x7B, 0x8C, 0xAD, 0x32, 0xBD, 0xB4, 0xAC, 0xF1, +0x8B, 0xED, 0x83, 0xCC, 0x8C, 0x0D, 0x9C, 0x8F, +0xA4, 0xAF, 0x9C, 0x8F, 0xA4, 0xD0, 0xB5, 0x12, +0xB5, 0x32, 0xB5, 0x11, 0xA4, 0x8E, 0xB4, 0xEF, +0xBD, 0x0F, 0xD5, 0xF3, 0xD5, 0xF3, 0xCD, 0xB3, +0x73, 0x4C, 0x8C, 0x51, 0x83, 0xF0, 0x9C, 0xB3, +0xDE, 0xBB, 0xD6, 0xBA, 0xA5, 0x13, 0xA5, 0x13, +0x8C, 0x70, 0x84, 0x2E, 0x94, 0x90, 0xAD, 0x53, +0xBD, 0xD4, 0xAD, 0x10, 0xAC, 0xCF, 0xB5, 0x52, +0xB5, 0x52, 0x9C, 0x90, 0x42, 0x07, 0x5A, 0xAA, +0x5A, 0xAA, 0x39, 0xC6, 0x52, 0x69, 0x7B, 0x8D, +0x83, 0xAE, 0x39, 0xA6, 0x29, 0x65, 0x31, 0x85, +0x62, 0xEB, 0x83, 0xEF, 0x94, 0x30, 0x94, 0x51, +0x8C, 0x0F, 0x73, 0x6E, 0x9C, 0xB3, 0xC6, 0x17, +0xC5, 0xF8, 0xB5, 0x96, 0xC5, 0xD7, 0xE6, 0xFC, +0xEF, 0x3C, 0xFF, 0xBE, 0xF7, 0x5C, 0xAC, 0xD3, +0x94, 0x0F, 0x83, 0xAD, 0x94, 0x2E, 0x94, 0x4E, +0x9C, 0x6F, 0x94, 0x4E, 0xA4, 0xAF, 0xB5, 0x52, +0x5A, 0xAA, 0x7B, 0xEE, 0x52, 0xAA, 0x4A, 0x68, +0x42, 0x27, 0x4A, 0x89, 0x4A, 0x89, 0x42, 0x48, +0x42, 0x28, 0x4A, 0x48, 0x42, 0x28, 0x4A, 0x49, +0x4A, 0x69, 0x52, 0x8A, 0x42, 0x29, 0x42, 0x08, +0x42, 0x08, 0x31, 0x86, 0x63, 0x0C, 0x9C, 0x91, +0x9C, 0x6F, 0x9C, 0x6F, 0x94, 0x2E, 0x8C, 0x0E, +0x9C, 0x4F, 0xA4, 0xD0, 0xA4, 0xB0, 0x9C, 0x8F, +0x9C, 0x4E, 0x94, 0x4E, 0x8B, 0xED, 0x8C, 0x0E, +0x94, 0x2E, 0x8C, 0x0E, 0x94, 0x4E, 0xA4, 0xD1, +0xB5, 0x32, 0xB5, 0x52, 0xBD, 0x93, 0xBD, 0x93, +0xBD, 0x73, 0xC5, 0xD4, 0xCE, 0x15, 0xCE, 0x15, +0xD6, 0x15, 0xCD, 0xF5, 0xC5, 0xD4, 0xC5, 0xD4, +0x9C, 0xB0, 0xA4, 0xD0, 0xB5, 0x52, 0xC5, 0xD3, +0xD6, 0x34, 0xDE, 0x54, 0xDE, 0x55, 0xDE, 0x54, +0xDE, 0x14, 0xCD, 0xD3, 0xAD, 0x11, 0xAD, 0x32, +0xD6, 0x35, 0xD6, 0x14, 0xB5, 0x10, 0xB5, 0x31, +0xB5, 0x31, 0xB5, 0x10, 0xAD, 0x11, 0x8C, 0x0D, +0x83, 0xEE, 0x83, 0xEE, 0x83, 0xEE, 0x7B, 0xAD, +0xA4, 0xF1, 0xB5, 0x32, 0x8C, 0x0D, 0xB5, 0x52, +0xB5, 0x72, 0xBD, 0xB3, 0xBD, 0x93, 0xBD, 0x93, +0xCD, 0xF4, 0xBD, 0x93, 0xAD, 0x11, 0xC5, 0xD4, +0xBD, 0x93, 0xA4, 0xD0, 0xA4, 0xF1, 0xBD, 0xB3, +0xBD, 0x93, 0xB5, 0x52, 0xAD, 0x32, 0x9C, 0x8F, +0x94, 0x4E, 0x8C, 0x2E, 0x8C, 0x2D, 0x94, 0x2E, +0x9C, 0xB0, 0xB5, 0x53, 0xB5, 0x33, 0xCE, 0x15, +0xDE, 0x76, 0xDE, 0x96, 0xDE, 0x97, 0xDE, 0x97, +0xDE, 0x97, 0xDE, 0x97, 0xE6, 0xB7, 0xDE, 0x76, +0xE6, 0xD7, 0xDE, 0xB6, 0xDE, 0x96, 0xDE, 0x96, +0xDE, 0x76, 0xDE, 0xB6, 0xDE, 0xB7, 0xDE, 0xB6, +0xDE, 0x96, 0xE6, 0xB6, 0xE6, 0x96, 0xE6, 0x95, +0xE6, 0xB6, 0xC5, 0xD4, 0xAD, 0x12, 0xC5, 0xD4, +0xA4, 0xF1, 0x39, 0xA5, 0x39, 0xA6, 0x39, 0xC6, +0x39, 0xC6, 0x31, 0x85, 0x31, 0xA5, 0x52, 0x88, +0x4A, 0x86, 0x8D, 0x0E, 0x7C, 0xCB, 0x74, 0x8B, +0x7C, 0x8C, 0x7C, 0x6C, 0x84, 0x4C, 0x5A, 0xE9, +0x52, 0x89, 0x8C, 0x0E, 0xAC, 0xF2, 0xB5, 0x53, +0xE6, 0xF8, 0xE6, 0xD7, 0xA5, 0x90, 0x8D, 0x4D, +0x7C, 0xAA, 0x6C, 0x48, 0x74, 0x68, 0x95, 0x0B, +0xAD, 0xAE, 0xAD, 0x30, 0xB5, 0x72, 0xC5, 0xB3, +0xBD, 0x52, 0xA4, 0xB0, 0xBD, 0x52, 0xC5, 0x93, +0xBD, 0x52, 0xA4, 0xB0, 0x9C, 0x6F, 0xA4, 0x8F, +0x94, 0x0D, 0x8B, 0xAC, 0x83, 0x8B, 0xB4, 0xF1, +0xC5, 0x73, 0xC5, 0x73, 0xC5, 0xB4, 0xAC, 0xF2, +0x8C, 0xB1, 0x73, 0xCE, 0x5B, 0x09, 0x83, 0xEC, +0x94, 0x4E, 0x94, 0x2D, 0x94, 0x2D, 0x9C, 0x6E, +0x9C, 0x6E, 0x9C, 0x4E, 0x9C, 0x8F, 0xA4, 0xAF, +0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0x8E, 0xA4, 0x8E, +0xA4, 0xAE, 0xAC, 0xCF, 0xA4, 0x8E, 0xAC, 0xAF, +0xAC, 0xAE, 0xAC, 0xAE, 0xA4, 0x8E, 0xA4, 0x8E, +0xA4, 0x8E, 0xA4, 0x6E, 0x9C, 0x6D, 0x9C, 0x4D, +0x9C, 0x6D, 0xA4, 0x6E, 0xA4, 0x8E, 0xA4, 0x8E, +0x9C, 0x2D, 0x9C, 0x4D, 0xAC, 0x8E, 0xAC, 0x8E, +0xA4, 0x4D, 0xA4, 0x6E, 0xBD, 0x10, 0xC5, 0x51, +0xCD, 0x92, 0xD5, 0xB3, 0xDD, 0xF4, 0xBD, 0x10, +0xA4, 0x8D, 0xC5, 0x92, 0xC5, 0x92, 0xCD, 0xD3, +0xCD, 0xF4, 0xCD, 0xB3, 0xAC, 0xAE, 0xBD, 0x50, +0xD5, 0xF3, 0xD5, 0xD3, 0xDE, 0x14, 0xDE, 0x14, +0xDE, 0x13, 0xD5, 0xF3, 0xD6, 0x13, 0xDE, 0x34, +0xD5, 0xF3, 0x9C, 0x6E, 0x4A, 0x27, 0x31, 0xA5, +0x39, 0xC6, 0x42, 0x28, 0x4A, 0x48, 0x52, 0x8A, +0x63, 0x0C, 0x84, 0x30, 0x9C, 0xF4, 0xAD, 0x76, +0xC6, 0x19, 0xD6, 0x9B, 0xE7, 0x1C, 0xDE, 0xDB, +0xC6, 0x18, 0xAD, 0x13, 0xB5, 0x73, 0x9C, 0xB0, +0x7B, 0x8C, 0x7B, 0x8C, 0x8C, 0x0E, 0x9C, 0x4E, +0xA4, 0xAF, 0x9C, 0x6E, 0x9C, 0x8F, 0xBD, 0x73, +0xC5, 0x93, 0xC5, 0xB3, 0xB4, 0xF0, 0xAC, 0xCE, +0xAC, 0xCE, 0xD5, 0xF3, 0xDD, 0xF3, 0xE6, 0x55, +0xA4, 0x90, 0x5A, 0x8A, 0x9C, 0xD3, 0xCE, 0x59, +0xEF, 0x3D, 0xE7, 0x3D, 0xCE, 0x59, 0xB5, 0x95, +0xB5, 0x74, 0x9C, 0xF2, 0x94, 0xB1, 0xAD, 0x33, +0xAD, 0x52, 0xA4, 0x8E, 0xAC, 0xCF, 0xBD, 0x72, +0xB5, 0x31, 0xBD, 0x72, 0x8C, 0x0E, 0x4A, 0x28, +0x4A, 0x28, 0x29, 0x44, 0x31, 0x65, 0x52, 0x69, +0x83, 0xAD, 0x52, 0x69, 0x52, 0x69, 0x31, 0x65, +0x39, 0xC6, 0x4A, 0x28, 0x73, 0x6C, 0x73, 0x6D, +0x52, 0x69, 0x73, 0x6E, 0x84, 0x30, 0x9C, 0xB2, +0xB5, 0x76, 0xCE, 0x59, 0xE6, 0xDB, 0xE6, 0xDB, +0xE6, 0xFB, 0xEF, 0x3C, 0xE6, 0xFB, 0xD6, 0x18, +0xA4, 0xB3, 0xCE, 0x17, 0xB5, 0x54, 0x94, 0x50, +0xAD, 0x12, 0xA4, 0xF1, 0xA4, 0xD0, 0xB5, 0x53, +0x5A, 0xAA, 0x8C, 0x50, 0x63, 0x0B, 0x4A, 0x69, +0x42, 0x07, 0x42, 0x07, 0x42, 0x27, 0x39, 0xE6, +0x42, 0x07, 0x4A, 0x48, 0x39, 0xE7, 0x39, 0xC7, +0x42, 0x28, 0x42, 0x28, 0x42, 0x08, 0x39, 0xC7, +0x39, 0xC7, 0x73, 0x6E, 0xBD, 0xB6, 0xAD, 0x33, +0xB5, 0x54, 0xBD, 0x94, 0xB5, 0x73, 0xAD, 0x12, +0xAD, 0x12, 0xB5, 0x52, 0xA4, 0xD0, 0x9C, 0x8F, +0x94, 0x2E, 0x9C, 0x90, 0xA4, 0xB0, 0xA4, 0xB0, +0xA4, 0xB0, 0xA4, 0xB0, 0x9C, 0x8F, 0x9C, 0x6F, +0x9C, 0x6F, 0x9C, 0x6F, 0x9C, 0x8F, 0x9C, 0x8F, +0xA4, 0xAF, 0xA4, 0xAF, 0x9C, 0x8F, 0x9C, 0x8F, +0xA4, 0x90, 0x9C, 0x4F, 0x8C, 0x0E, 0x9C, 0x8F, +0xA4, 0xAF, 0xA4, 0xD0, 0x9C, 0x6F, 0x8C, 0x0D, +0x8C, 0x0D, 0x9C, 0x4E, 0x9C, 0x4D, 0x9C, 0x4D, +0xAC, 0xAF, 0xAC, 0xCF, 0xA4, 0xD0, 0xAC, 0xF1, +0xB5, 0x11, 0xB5, 0x31, 0xA4, 0x8E, 0x9C, 0x6E, +0xAC, 0xCF, 0xA4, 0x8E, 0x8B, 0xEC, 0x7B, 0x6B, +0x83, 0xCD, 0x7B, 0x8C, 0x6B, 0x4B, 0x6B, 0x2B, +0xAC, 0xF1, 0xB5, 0x32, 0x83, 0xED, 0x8C, 0x0E, +0x94, 0x4E, 0xAD, 0x11, 0x9C, 0xB0, 0x9C, 0xAF, +0xAD, 0x11, 0x83, 0xCC, 0x9C, 0x6F, 0xAC, 0xF1, +0xAD, 0x31, 0xA4, 0xB0, 0xB5, 0x52, 0xC5, 0xD4, +0xB5, 0x73, 0xB5, 0x73, 0xC5, 0xB4, 0x9C, 0xB0, +0x8C, 0x2E, 0x94, 0x6F, 0x83, 0xED, 0x83, 0xED, +0xA4, 0xD1, 0xAD, 0x32, 0xAD, 0x12, 0xBD, 0x72, +0xDE, 0x55, 0xD6, 0x55, 0xDE, 0x76, 0xDE, 0x96, +0xDE, 0x96, 0xDE, 0x97, 0xE6, 0x97, 0xE6, 0xB6, +0xE6, 0xD7, 0xE6, 0xB6, 0xE6, 0xB6, 0xDE, 0x75, +0xD6, 0x34, 0xDE, 0x76, 0xDE, 0xB6, 0xD6, 0x75, +0xD6, 0x35, 0xDE, 0x96, 0xE6, 0x96, 0xE6, 0x95, +0xE6, 0x96, 0xC5, 0xD4, 0xAC, 0xF1, 0xD6, 0x36, +0xDE, 0xB7, 0xAD, 0x32, 0x4A, 0x27, 0x39, 0xA6, +0x31, 0x85, 0x31, 0x65, 0x29, 0x44, 0x31, 0xA5, +0x73, 0xEC, 0xA5, 0xB1, 0x85, 0x2D, 0x84, 0xED, +0x85, 0x0D, 0x84, 0xED, 0x6C, 0x29, 0x94, 0xEE, +0x6B, 0x6B, 0x6A, 0xEA, 0x8B, 0xEE, 0xAC, 0xF1, +0xCE, 0x34, 0xD6, 0x95, 0x84, 0xAC, 0x8D, 0x2D, +0x95, 0x6D, 0x6C, 0x27, 0x6C, 0x47, 0x7C, 0xC9, +0x8D, 0x2B, 0x84, 0xAC, 0x9D, 0x0F, 0xC5, 0xD3, +0xCD, 0xB3, 0xC5, 0x73, 0xC5, 0x93, 0xB5, 0x11, +0x94, 0x0E, 0xA4, 0x6F, 0xA4, 0x6F, 0x9C, 0x2E, +0x8B, 0xAC, 0x83, 0x8C, 0x94, 0x0E, 0xBD, 0x32, +0xD5, 0xF5, 0xD5, 0xD4, 0x9C, 0x4F, 0x94, 0x50, +0x7B, 0xEF, 0x39, 0xE7, 0x42, 0x28, 0x4A, 0x68, +0x62, 0xEA, 0x6B, 0x2A, 0x83, 0xED, 0x94, 0x4E, +0x9C, 0x8F, 0x94, 0x4E, 0xA4, 0xD0, 0x94, 0x4E, +0x8C, 0x0D, 0x94, 0x2D, 0x9C, 0x6E, 0xA4, 0xAE, +0xD6, 0x14, 0xC5, 0xB2, 0x94, 0x2D, 0x9C, 0x6E, +0x8B, 0xEC, 0xAC, 0xCF, 0xAC, 0xEF, 0xAC, 0xCF, +0xAC, 0xAF, 0xAC, 0xCF, 0xB4, 0xF0, 0xB5, 0x10, +0xA4, 0xAE, 0xAC, 0xCF, 0xAC, 0xCF, 0xB4, 0xEF, +0xB4, 0xEF, 0xB4, 0xEF, 0xA4, 0x8E, 0xA4, 0x8E, +0xA4, 0x8E, 0xAC, 0xCF, 0xAC, 0xCF, 0xAC, 0xAE, +0xAC, 0xAE, 0xAC, 0xAE, 0xB4, 0xCE, 0xB4, 0xEF, +0xB4, 0xEF, 0xAC, 0xCE, 0xAC, 0x8D, 0xA4, 0x8D, +0xA4, 0x6D, 0xA4, 0x6D, 0xA4, 0x4C, 0xA4, 0x6D, +0xAC, 0x8E, 0xAC, 0x8E, 0xAC, 0xCE, 0xB4, 0xEF, +0xB4, 0xEF, 0xBD, 0x30, 0xC5, 0x50, 0xCD, 0x71, +0xCD, 0x92, 0xCD, 0x92, 0xB4, 0xF0, 0x7B, 0x8B, +0x41, 0xE6, 0x39, 0xC6, 0x42, 0x28, 0x42, 0x07, +0x4A, 0x48, 0x63, 0x2C, 0x7B, 0xF0, 0x94, 0xB3, +0xAD, 0x56, 0xBD, 0xD8, 0xC6, 0x39, 0xDE, 0xDC, +0xF7, 0x7E, 0xEF, 0x3C, 0xBD, 0xB6, 0xA4, 0xB1, +0x73, 0x2B, 0x73, 0x4B, 0x8B, 0xED, 0x94, 0x2E, +0xA4, 0xD0, 0x9C, 0x8F, 0xA4, 0xB0, 0xC5, 0xD4, +0xD6, 0x14, 0xD6, 0x14, 0xC5, 0x71, 0xB4, 0xCF, +0xAC, 0xAE, 0xD5, 0xD2, 0xE6, 0x34, 0xDD, 0xF3, +0xCD, 0xB3, 0x5A, 0xCA, 0xA5, 0x14, 0xDE, 0xBB, +0xE6, 0xFC, 0xBD, 0xD8, 0xDE, 0xBB, 0xCE, 0x59, +0xB5, 0x75, 0xAD, 0x53, 0xA5, 0x33, 0xB5, 0x73, +0xB5, 0x73, 0xA4, 0x8E, 0xAC, 0xCF, 0xC5, 0xB3, +0xB5, 0x31, 0xBD, 0x52, 0xBD, 0x93, 0x7B, 0xAD, +0x31, 0x64, 0x21, 0x03, 0x18, 0xC3, 0x39, 0xA6, +0x62, 0xEA, 0x52, 0x69, 0x62, 0xEB, 0x6B, 0x2B, +0x73, 0x2B, 0x5A, 0x89, 0x4A, 0x68, 0x73, 0x6C, +0x83, 0xEF, 0x83, 0xEF, 0x73, 0x6D, 0x7B, 0xCF, +0x94, 0x72, 0x94, 0xB3, 0xBD, 0xD7, 0xD6, 0x7A, +0xDE, 0xBB, 0xCE, 0x39, 0xDE, 0x9A, 0xEE, 0xFC, +0xDE, 0x9A, 0xD6, 0x59, 0xEE, 0xFB, 0xE6, 0xDA, +0xAD, 0x13, 0xA4, 0xB1, 0x9C, 0x70, 0x9C, 0xB0, +0x5A, 0x89, 0x6B, 0x2C, 0x73, 0xAD, 0x52, 0x89, +0x4A, 0x48, 0x39, 0xE7, 0x39, 0xE6, 0x42, 0x28, +0x39, 0xE7, 0x42, 0x28, 0x42, 0x08, 0x42, 0x08, +0x39, 0xE7, 0x39, 0xE7, 0x39, 0xE8, 0x42, 0x07, +0x63, 0x2C, 0xA5, 0x34, 0xBD, 0xD7, 0xA4, 0xF2, +0xB5, 0x33, 0xBD, 0xB4, 0xC5, 0xF5, 0xC5, 0xB4, +0x9C, 0x6F, 0x73, 0x4B, 0x83, 0xAC, 0x8C, 0x0E, +0x8B, 0xED, 0x8B, 0xED, 0x94, 0x4F, 0x8C, 0x2E, +0xA4, 0xB0, 0xA4, 0xD1, 0x94, 0x6F, 0x8C, 0x2E, +0x8C, 0x0E, 0x94, 0x4F, 0xA4, 0xD0, 0xA4, 0xF1, +0xAD, 0x32, 0xBD, 0x93, 0xB5, 0x52, 0xA4, 0xF1, +0xAC, 0xF1, 0xA4, 0xD0, 0xAC, 0xF1, 0xA4, 0xD0, +0xA4, 0xB0, 0xAD, 0x11, 0xA4, 0xB0, 0xA4, 0xB0, +0xA4, 0xB0, 0xB5, 0x11, 0xB5, 0x32, 0xBD, 0x52, +0xB5, 0x11, 0xB5, 0x11, 0xA4, 0x90, 0xB4, 0xF1, +0xAC, 0xD0, 0xAC, 0xB0, 0xAC, 0xD0, 0xA4, 0x8F, +0xA4, 0x6E, 0xA4, 0x8E, 0xA4, 0x8F, 0x9C, 0x8F, +0xA4, 0x90, 0x94, 0x0E, 0x8C, 0x0E, 0x7B, 0xAC, +0x9C, 0x6F, 0xA4, 0xD0, 0x94, 0x4F, 0x8C, 0x0E, +0x8B, 0xED, 0x8B, 0xED, 0x8C, 0x0D, 0x83, 0xCD, +0x83, 0xCD, 0x7B, 0x6B, 0x83, 0xAC, 0x83, 0xCC, +0x83, 0xCC, 0x83, 0xCC, 0x8C, 0x0E, 0x94, 0x4E, +0x8C, 0x2E, 0x8C, 0x2E, 0x9C, 0x8F, 0x8C, 0x0E, +0x83, 0xCC, 0x83, 0xED, 0x83, 0xCD, 0x8C, 0x2E, +0xB5, 0x32, 0xB5, 0x73, 0xBD, 0x93, 0xD6, 0x56, +0xDE, 0x96, 0xE6, 0xD7, 0xE6, 0xD7, 0xE6, 0xD7, +0xE6, 0xB7, 0xE6, 0xB7, 0xE6, 0xB7, 0xE6, 0xB6, +0xE6, 0xD7, 0xE6, 0xD6, 0xE6, 0xD6, 0xE6, 0xD7, +0xE6, 0xB6, 0xE6, 0xD7, 0xDE, 0x96, 0xDE, 0x76, +0xDE, 0x75, 0xDE, 0x75, 0xE6, 0xB6, 0xE6, 0xB6, +0xE6, 0xB6, 0xC5, 0xF4, 0xB5, 0x32, 0xDE, 0x76, +0xDE, 0x75, 0xE6, 0xB7, 0xC5, 0xB4, 0x73, 0x4B, +0x39, 0xC6, 0x31, 0x85, 0x31, 0x85, 0x29, 0x64, +0x3A, 0x25, 0x5B, 0xA9, 0x7C, 0xCC, 0x8D, 0x2E, +0x8D, 0x6F, 0x7C, 0xCC, 0x6C, 0x6A, 0x74, 0x2A, +0x94, 0xAE, 0x7B, 0x8B, 0x62, 0xA8, 0x9C, 0xB0, +0x9C, 0xAF, 0xB5, 0x71, 0x9D, 0x0E, 0x84, 0xAA, +0x95, 0x8C, 0x74, 0x89, 0x64, 0x06, 0x6C, 0x68, +0x7C, 0xEA, 0x8D, 0x6E, 0x95, 0x4F, 0xC6, 0x13, +0xDE, 0x35, 0xD5, 0xD4, 0xCD, 0x93, 0xC5, 0x93, +0xC5, 0xB4, 0xCD, 0xB4, 0xD5, 0xD3, 0xDE, 0x15, +0xDE, 0x35, 0xDE, 0x16, 0xE6, 0x56, 0xDE, 0x15, +0xCD, 0x93, 0xDE, 0x57, 0xCD, 0xF7, 0xBD, 0x96, +0x5A, 0xCA, 0x42, 0x07, 0x4A, 0x69, 0x52, 0xA9, +0x6B, 0x2B, 0x73, 0x8C, 0xA4, 0xF0, 0xBD, 0x93, +0xBD, 0x93, 0xBD, 0xB3, 0xBD, 0x93, 0x8C, 0x2D, +0x8C, 0x2D, 0xA4, 0xF1, 0xAC, 0xF0, 0xA4, 0x8E, +0xDE, 0x55, 0xB5, 0x31, 0x8C, 0x0C, 0x94, 0x4E, +0x8C, 0x0E, 0xC5, 0xB4, 0xC5, 0xB3, 0xBD, 0x52, +0xB5, 0x10, 0x94, 0x0C, 0x9C, 0x4D, 0xC5, 0x92, +0xC5, 0xB3, 0xBD, 0x72, 0xBD, 0x72, 0xAC, 0xD0, +0x8C, 0x0C, 0x9C, 0x8E, 0xAC, 0xF0, 0xAD, 0x10, +0xAC, 0xEF, 0xA4, 0xAE, 0xAC, 0xCE, 0xA4, 0x8D, +0xB5, 0x10, 0xAC, 0xCE, 0xAC, 0xAE, 0xA4, 0x8D, +0xA4, 0x6D, 0xAC, 0xAE, 0xBD, 0x30, 0xB5, 0x0F, +0xAC, 0xCE, 0xAC, 0xCE, 0xAC, 0xCE, 0xAC, 0xAE, +0xB4, 0xEF, 0xB4, 0xEF, 0xB4, 0xEE, 0xB4, 0xCE, +0xB4, 0xEF, 0xBD, 0x0F, 0xBD, 0x0F, 0xBC, 0xEF, +0xB4, 0xEE, 0xAC, 0xAE, 0xA4, 0x8D, 0xAC, 0xAE, +0x9C, 0x4D, 0x6A, 0xE9, 0x39, 0xC6, 0x39, 0xA6, +0x39, 0xE7, 0x42, 0x28, 0x52, 0xCB, 0x73, 0xAF, +0x84, 0x11, 0x9C, 0xD4, 0xB5, 0xD8, 0xCE, 0x7A, +0xD6, 0xBB, 0xDE, 0xDB, 0xE6, 0xDC, 0xD6, 0x59, +0xA4, 0xD2, 0x83, 0xAD, 0x83, 0xAC, 0x8B, 0xED, +0x8B, 0xED, 0x94, 0x2E, 0xA4, 0x8F, 0xCD, 0xF4, +0xC5, 0x93, 0xC5, 0x92, 0xBD, 0x31, 0xB4, 0xEF, +0xAC, 0xCE, 0xE6, 0x54, 0xEE, 0x55, 0xE6, 0x14, +0xBD, 0x11, 0x73, 0x4B, 0x8C, 0x71, 0xC6, 0x18, +0xAD, 0x76, 0xC6, 0x39, 0xEF, 0x5E, 0xDE, 0xFC, +0xBD, 0xF7, 0xBD, 0xB5, 0xC5, 0xD5, 0xCE, 0x56, +0xD6, 0x56, 0xBD, 0x51, 0xAC, 0xF0, 0xCD, 0xD3, +0xC5, 0xB3, 0xC5, 0xB3, 0xCD, 0xB3, 0xBD, 0x72, +0x8C, 0x2E, 0x5A, 0xA9, 0x63, 0x0A, 0x6B, 0x2B, +0x31, 0x65, 0x39, 0xA6, 0x52, 0x69, 0x5A, 0xCA, +0x6B, 0x2B, 0x62, 0xCA, 0x31, 0x65, 0x4A, 0x07, +0x7B, 0xAD, 0xA4, 0xD2, 0x8C, 0x30, 0x73, 0x8E, +0x84, 0x10, 0x9C, 0xB3, 0xB5, 0x96, 0xAD, 0x55, +0xDE, 0xBB, 0xE6, 0xDB, 0xD6, 0x59, 0xCE, 0x18, +0xF7, 0x5D, 0xEE, 0xFB, 0xD6, 0x58, 0xDE, 0x79, +0xF7, 0x3B, 0xC5, 0xB6, 0x73, 0x4D, 0x8C, 0x2F, +0x6B, 0x0B, 0x42, 0x08, 0x73, 0x8C, 0x52, 0xA9, +0x4A, 0x48, 0x42, 0x07, 0x3A, 0x07, 0x4A, 0x69, +0x42, 0x48, 0x31, 0xA6, 0x31, 0xA6, 0x4A, 0x49, +0x5A, 0xCB, 0x52, 0x69, 0x52, 0x6A, 0x63, 0x2C, +0x7B, 0xCF, 0x9C, 0xD3, 0xA5, 0x14, 0xA5, 0x34, +0x8C, 0x50, 0x9C, 0xB1, 0xBD, 0xD4, 0xCE, 0x16, +0xB5, 0x73, 0xA4, 0xD1, 0xAD, 0x32, 0xAD, 0x32, +0xAD, 0x32, 0xA4, 0xF1, 0xC5, 0xF5, 0xBD, 0xB4, +0xA4, 0xD1, 0x94, 0x4F, 0x94, 0x4F, 0x94, 0x90, +0x9C, 0x90, 0x9C, 0xB0, 0x9C, 0xB0, 0xAD, 0x33, +0xBD, 0x94, 0xCE, 0x36, 0xCE, 0x15, 0xC5, 0xF4, +0xC5, 0xF4, 0xB5, 0x73, 0xB5, 0x53, 0xAD, 0x32, +0xAC, 0xF1, 0xAD, 0x11, 0x9C, 0xB0, 0x94, 0x4E, +0x8C, 0x2E, 0x9C, 0x8F, 0x9C, 0x2E, 0x8B, 0xCD, +0x83, 0x8C, 0x94, 0x2E, 0xAC, 0xD0, 0xCD, 0xD4, +0xCD, 0xD4, 0xC5, 0x93, 0xCD, 0xF4, 0xCD, 0xD4, +0xCD, 0xB3, 0xBD, 0x72, 0xB5, 0x10, 0xBD, 0x52, +0xC5, 0x72, 0xBD, 0x52, 0xBD, 0x52, 0xB5, 0x11, +0xAC, 0xF1, 0xAC, 0xF1, 0xA4, 0xD0, 0xB5, 0x11, +0xB5, 0x11, 0xB5, 0x12, 0xB5, 0x32, 0xB5, 0x12, +0xB5, 0x11, 0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x11, +0xAC, 0xF1, 0xAC, 0xF1, 0xA4, 0xB0, 0x9C, 0x90, +0xA4, 0xB0, 0xAC, 0xF1, 0xA4, 0xD1, 0x9C, 0x6F, +0x8C, 0x0E, 0x83, 0xCD, 0x83, 0xED, 0x94, 0x2E, +0x94, 0x4F, 0xA4, 0xD1, 0x9C, 0x90, 0xBD, 0x93, +0xCE, 0x14, 0xDE, 0x76, 0xDE, 0x76, 0xD6, 0x56, +0xD6, 0x56, 0xDE, 0x76, 0xDE, 0x96, 0xDE, 0x96, +0xDE, 0x96, 0xE6, 0xB6, 0xE6, 0xB6, 0xEE, 0xD6, +0xEE, 0xD7, 0xEE, 0xF8, 0xE6, 0xD7, 0xE6, 0xD7, +0xE6, 0xF7, 0xEE, 0xF7, 0xEE, 0xF7, 0xEE, 0xF7, +0xF7, 0x18, 0xCE, 0x14, 0xC5, 0xB4, 0xEF, 0x18, +0xE6, 0x96, 0xE6, 0xB6, 0xEE, 0xD7, 0xEE, 0xF8, +0xAD, 0x11, 0x39, 0xC6, 0x31, 0x85, 0x31, 0x85, +0x29, 0x64, 0x32, 0x25, 0x4B, 0x27, 0x74, 0x8B, +0x85, 0x0C, 0x74, 0x8A, 0x6C, 0x6A, 0x21, 0xA2, +0x5A, 0xE9, 0x9C, 0xEF, 0xA5, 0x0F, 0x73, 0x8A, +0x62, 0xE9, 0x73, 0x6B, 0x8C, 0x6E, 0x7C, 0x4B, +0x84, 0xCA, 0x74, 0xA9, 0x63, 0xE8, 0x53, 0x67, +0x7C, 0xAB, 0x7C, 0xCC, 0x8D, 0x0E, 0xCE, 0x33, +0xD6, 0x14, 0xCD, 0xB3, 0xCD, 0xB4, 0xCD, 0xD4, +0xD5, 0xF5, 0xCD, 0x93, 0xCD, 0xB3, 0xE6, 0x56, +0xE6, 0x56, 0xD5, 0xF5, 0xAC, 0xF2, 0x9C, 0x50, +0xB5, 0x13, 0xBD, 0x54, 0xB5, 0x34, 0xA4, 0xB2, +0x39, 0xE7, 0x4A, 0x49, 0x52, 0x89, 0x5A, 0xAA, +0x5A, 0xCA, 0x6B, 0x4B, 0x9C, 0xB0, 0xAD, 0x32, +0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x31, 0x94, 0x2E, +0x83, 0xCD, 0xAD, 0x32, 0xB5, 0x11, 0xA4, 0x8D, +0xD6, 0x34, 0xB5, 0x11, 0x8B, 0xEC, 0x8C, 0x2E, +0x94, 0x4F, 0xD6, 0x56, 0xBD, 0x52, 0xB5, 0x10, +0xA4, 0xAE, 0x83, 0xAA, 0x8C, 0x0C, 0xA4, 0xAF, +0xAD, 0x10, 0xBD, 0x92, 0xD6, 0x56, 0xC5, 0xB3, +0x7B, 0xAB, 0xAD, 0x11, 0xC5, 0xD4, 0xBD, 0xD3, +0xC5, 0xF4, 0xB5, 0x31, 0xA4, 0x8D, 0x9C, 0x4D, +0xC5, 0x92, 0xBD, 0x71, 0xAC, 0xEF, 0x9C, 0x4D, +0x94, 0x2C, 0x83, 0xCC, 0x7B, 0x6A, 0x83, 0xEB, +0x83, 0xCB, 0x83, 0xAB, 0x94, 0x0C, 0x73, 0x49, +0x83, 0xCB, 0x83, 0xCA, 0x94, 0x2C, 0x9C, 0x6D, +0x9C, 0x6D, 0x94, 0x2C, 0x94, 0x0C, 0xA4, 0x8E, +0xB4, 0xEF, 0xBD, 0x30, 0xB5, 0x10, 0xBD, 0x30, +0xC5, 0x92, 0xAC, 0xCF, 0x8B, 0xEC, 0x4A, 0x27, +0x31, 0xA6, 0x31, 0xA6, 0x3A, 0x07, 0x52, 0x8A, +0x5A, 0xCC, 0x84, 0x31, 0xA5, 0x15, 0xA5, 0x35, +0xA5, 0x35, 0xB5, 0x97, 0xE7, 0x1D, 0xEF, 0x5D, +0xE6, 0xFC, 0xAC, 0xF3, 0x94, 0x4F, 0x9C, 0x4E, +0x94, 0x0D, 0x8B, 0xCC, 0x8B, 0xAB, 0x8B, 0xAB, +0x83, 0x8B, 0x83, 0x8B, 0x8B, 0xCB, 0x9C, 0x2C, +0x8B, 0xAA, 0x8B, 0xAB, 0x9C, 0x2C, 0xAC, 0x8E, +0x9C, 0x2D, 0x9C, 0x8F, 0x8C, 0x2E, 0x8C, 0x70, +0xA5, 0x14, 0xDE, 0xBB, 0xE7, 0x3D, 0xDE, 0xDC, +0xE7, 0x3D, 0xB5, 0x95, 0xC5, 0xD5, 0xCE, 0x36, +0xC5, 0xF4, 0xA4, 0x8F, 0x9C, 0x4D, 0xAD, 0x10, +0xD6, 0x15, 0xD6, 0x15, 0xD5, 0xF4, 0xC5, 0xB3, +0xC5, 0x72, 0xC5, 0xB4, 0xD6, 0x35, 0xAD, 0x31, +0x41, 0xC6, 0x39, 0xA6, 0x29, 0x44, 0x39, 0xE7, +0x4A, 0x28, 0x5A, 0x89, 0x62, 0xEB, 0x52, 0x89, +0x42, 0x07, 0x62, 0xCA, 0x9C, 0x71, 0x94, 0x71, +0x6B, 0x4D, 0x8C, 0x51, 0xB5, 0x75, 0xB5, 0x76, +0xAD, 0x35, 0xC5, 0xF8, 0xBD, 0x96, 0xDE, 0xDB, +0xF7, 0x7D, 0xF7, 0x5D, 0xCD, 0xF7, 0xC5, 0xB6, +0xE6, 0xBA, 0xEE, 0x9A, 0xDE, 0x59, 0xBD, 0x75, +0xB5, 0x55, 0x39, 0xE7, 0x42, 0x07, 0x5A, 0xEA, +0x52, 0xA9, 0x4A, 0x48, 0x4A, 0x68, 0x42, 0x07, +0x39, 0xC6, 0x31, 0x85, 0x39, 0xE7, 0x42, 0x28, +0x4A, 0x89, 0x4A, 0x69, 0x52, 0xAA, 0x63, 0x2C, +0x6B, 0x8E, 0x73, 0xAF, 0x9C, 0xD3, 0xBD, 0xF7, +0xB5, 0x96, 0x8C, 0x50, 0xAD, 0x32, 0xBD, 0xB4, +0xB5, 0x52, 0xAD, 0x12, 0xB5, 0x33, 0xB5, 0x32, +0xAD, 0x12, 0xB5, 0x32, 0xBD, 0x94, 0xC5, 0xF5, +0x94, 0x6F, 0x9C, 0xB1, 0xBD, 0xD5, 0xB5, 0x94, +0xBD, 0xD5, 0xBD, 0x94, 0x9C, 0x90, 0xAD, 0x12, +0xBD, 0xD4, 0xD6, 0x55, 0xCE, 0x34, 0xD6, 0x75, +0xD6, 0x55, 0xB5, 0x73, 0x8C, 0x4F, 0x9C, 0xD0, +0xAD, 0x32, 0xAD, 0x12, 0xAD, 0x52, 0xA4, 0xF1, +0x9C, 0xB0, 0xAC, 0xF1, 0x83, 0x8C, 0x73, 0x2A, +0x83, 0xAC, 0x9C, 0x6F, 0xB5, 0x11, 0xA4, 0x6E, +0xBD, 0x52, 0xAC, 0xF0, 0xA4, 0xAF, 0xAC, 0xF0, +0xB5, 0x30, 0xBD, 0x51, 0xC5, 0x51, 0xC5, 0x92, +0xCD, 0xD3, 0xCD, 0xD3, 0xCD, 0xB2, 0xCD, 0xD3, +0xBD, 0x72, 0xAC, 0xD0, 0x94, 0x2D, 0x8B, 0xED, +0x8B, 0xAC, 0x9C, 0x6F, 0x8C, 0x0E, 0x8C, 0x0D, +0x94, 0x2E, 0x94, 0x4E, 0x94, 0x4E, 0x94, 0x4E, +0x9C, 0x6F, 0xAC, 0xF1, 0xA4, 0x8F, 0x9C, 0x8F, +0xA4, 0xB0, 0xA4, 0xB0, 0xA4, 0xB0, 0xAD, 0x11, +0xAD, 0x12, 0xAC, 0xF1, 0xAC, 0xF1, 0xAC, 0xF1, +0x9C, 0x6F, 0x94, 0x2E, 0x94, 0x4F, 0x9C, 0x6F, +0xAD, 0x12, 0xA4, 0xD1, 0x9C, 0xB1, 0xAC, 0xF2, +0xAD, 0x32, 0xB5, 0x32, 0xAD, 0x32, 0xAD, 0x11, +0xAD, 0x32, 0xB5, 0x32, 0xB5, 0x52, 0xBD, 0x72, +0xBD, 0x93, 0xC5, 0xB3, 0xC5, 0xD4, 0xC5, 0xD4, +0xC5, 0xD4, 0xC5, 0xD4, 0xC5, 0xB3, 0xBD, 0x93, +0xBD, 0x73, 0xAC, 0xF1, 0xB5, 0x52, 0xDE, 0x96, +0xDE, 0x55, 0xD6, 0x35, 0xD6, 0x35, 0xDE, 0x96, +0xDE, 0x76, 0x7B, 0xCD, 0x31, 0xA5, 0x31, 0x85, +0x4A, 0x67, 0x6C, 0x0B, 0x7C, 0xAC, 0x85, 0x0D, +0x6C, 0x6A, 0x6C, 0x49, 0x5B, 0x88, 0x19, 0x22, +0x31, 0xC5, 0x63, 0x49, 0xB5, 0xB0, 0x62, 0xE8, +0x29, 0x24, 0x41, 0xE6, 0x5A, 0x88, 0x5A, 0xE8, +0x74, 0x09, 0x7C, 0x8A, 0x6C, 0x0A, 0x42, 0x67, +0xAD, 0x91, 0xCE, 0x53, 0x9D, 0x2F, 0xD6, 0x75, +0xD5, 0xF4, 0xCD, 0xB3, 0xD5, 0xF5, 0xDE, 0x36, +0xDE, 0x36, 0xC5, 0x73, 0xD5, 0xD5, 0xCD, 0xB4, +0xCD, 0x94, 0xC5, 0x95, 0xCD, 0xF7, 0xCE, 0x18, +0xB5, 0x55, 0xAC, 0xF3, 0xB5, 0x34, 0xAD, 0x14, +0x31, 0xA7, 0x42, 0x28, 0x4A, 0x48, 0x52, 0xAA, +0x5A, 0xAA, 0x63, 0x0A, 0x8C, 0x6F, 0xA4, 0xF1, +0xA4, 0xD0, 0x9C, 0xB0, 0xA4, 0xF0, 0x8C, 0x2E, +0x7B, 0xAC, 0xAD, 0x32, 0xA4, 0xCF, 0x9C, 0x8E, +0xD6, 0x35, 0xBD, 0x71, 0x94, 0x4E, 0x8C, 0x2E, +0x94, 0x6F, 0xCD, 0xF5, 0xA4, 0xAF, 0x83, 0xAB, +0xA4, 0xAF, 0x9C, 0x6E, 0x94, 0x4E, 0x8C, 0x2E, +0xA4, 0xD0, 0xCE, 0x15, 0xD6, 0x76, 0xBD, 0xB4, +0x94, 0x4E, 0xB5, 0x93, 0xCE, 0x15, 0xBD, 0xB4, +0xCE, 0x15, 0xB5, 0x51, 0x9C, 0x6D, 0x9C, 0x8E, +0xB5, 0x71, 0xBD, 0x92, 0xC5, 0xD3, 0xC5, 0xD4, +0xC5, 0xD3, 0xBD, 0xB3, 0xB5, 0x93, 0x9C, 0xAF, +0x7B, 0xAB, 0x9C, 0xAF, 0xA4, 0xAF, 0xA4, 0xF0, +0xB5, 0x52, 0xAD, 0x31, 0xAD, 0x10, 0xB5, 0x31, +0x9C, 0x8F, 0x7B, 0x8B, 0x7B, 0xAB, 0x9C, 0x6E, +0xC5, 0x72, 0xB4, 0xEF, 0x9C, 0x6C, 0xBD, 0x51, +0xC5, 0x71, 0xAC, 0xAF, 0x9C, 0x4D, 0xA4, 0x8F, +0x52, 0x47, 0x31, 0xA5, 0x31, 0xA5, 0x42, 0x28, +0x4A, 0x69, 0x63, 0x0C, 0x7B, 0xCF, 0x6B, 0x4D, +0x73, 0x8E, 0xB5, 0xB7, 0xCE, 0x7A, 0xCE, 0x5A, +0xE6, 0xFC, 0xD6, 0x7A, 0xCE, 0x18, 0xBD, 0x74, +0xC5, 0x93, 0xB5, 0x31, 0xA4, 0x8E, 0xA4, 0x8E, +0xAC, 0xCF, 0xB4, 0xF0, 0xAC, 0xAE, 0xAC, 0xAE, +0xAC, 0xCF, 0x9C, 0x4D, 0x9C, 0x2D, 0xA4, 0x4D, +0x9C, 0x4D, 0x9C, 0x4E, 0x9C, 0x8F, 0x6B, 0x4C, +0x9C, 0xD3, 0xA5, 0x14, 0xD6, 0x9A, 0xC6, 0x19, +0xE7, 0x1C, 0xCE, 0x59, 0x83, 0xCE, 0x8B, 0xED, +0x94, 0x0D, 0x9C, 0x4D, 0xA4, 0x6E, 0x94, 0x0D, +0x83, 0xAB, 0x83, 0x8B, 0x83, 0xAB, 0x8B, 0xEC, +0x9C, 0x2D, 0xA4, 0x6E, 0xA4, 0xAF, 0x94, 0x2D, +0x8B, 0xED, 0x6A, 0xE9, 0x31, 0xA5, 0x39, 0xC5, +0x42, 0x06, 0x52, 0x68, 0x6B, 0x2B, 0x6B, 0x2C, +0x9C, 0xB2, 0x94, 0x50, 0x62, 0xCA, 0x83, 0xEF, +0x9C, 0xD2, 0x63, 0x0C, 0x73, 0xAF, 0x94, 0xB2, +0x9C, 0xB2, 0x94, 0x92, 0xAD, 0x55, 0xCE, 0x39, +0xEF, 0x5D, 0xD6, 0x79, 0xC5, 0xF7, 0xCE, 0x18, +0xBD, 0xB6, 0xD6, 0x39, 0xE6, 0x9A, 0xFF, 0x5D, +0xC5, 0xD7, 0x6A, 0xEC, 0x4A, 0x08, 0x5A, 0xCA, +0x52, 0x89, 0x42, 0x28, 0x42, 0x27, 0x39, 0xE7, +0x39, 0xC6, 0x31, 0x85, 0x31, 0xA6, 0x39, 0xC6, +0x4A, 0x69, 0x5A, 0xEB, 0x5A, 0xCA, 0x5A, 0xCA, +0x6B, 0x6D, 0x84, 0x30, 0xAD, 0x55, 0xB5, 0x96, +0xBD, 0xD7, 0xB5, 0x74, 0xB5, 0x74, 0xBD, 0xB4, +0xB5, 0x52, 0xA4, 0xF1, 0xAD, 0x12, 0xAD, 0x32, +0xB5, 0x53, 0xB5, 0x73, 0xBD, 0x93, 0xC5, 0xF5, +0xAD, 0x32, 0xA5, 0x12, 0xBD, 0xB4, 0xC5, 0xF5, +0xC5, 0xF5, 0xBD, 0xB4, 0xA4, 0xD1, 0xAD, 0x53, +0xBD, 0x93, 0xCE, 0x14, 0xCE, 0x34, 0xD6, 0x55, +0xCE, 0x35, 0xA4, 0xF1, 0xB5, 0x74, 0xB5, 0x94, +0xAD, 0x32, 0xB5, 0x94, 0xBD, 0x94, 0xA5, 0x11, +0x9C, 0x8F, 0xAC, 0xF1, 0x94, 0x0D, 0x83, 0x8C, +0x94, 0x2D, 0xBD, 0x32, 0xB4, 0xF0, 0xAC, 0xAF, +0xBD, 0x32, 0x9C, 0x8F, 0xA4, 0xB0, 0xB5, 0x31, +0xCD, 0xB3, 0xD5, 0xD3, 0xCD, 0xB2, 0xCD, 0xB3, +0xCD, 0xD3, 0xCD, 0xB2, 0xC5, 0x51, 0xA4, 0x8F, +0x8B, 0xCC, 0x8B, 0xED, 0x94, 0x2D, 0x94, 0x2D, +0x8B, 0xCC, 0xA4, 0x90, 0x9C, 0x8F, 0xAC, 0xF0, +0xBD, 0x72, 0xBD, 0x93, 0xB5, 0x52, 0xA4, 0xD0, +0xA4, 0xB0, 0xA4, 0xF0, 0xA4, 0xAF, 0xA4, 0xB0, +0xAC, 0xF1, 0xA4, 0xD0, 0x9C, 0x6F, 0x9C, 0x6F, +0xB5, 0x12, 0xAD, 0x11, 0xA4, 0xB0, 0x9C, 0x6F, +0x83, 0xCD, 0x7B, 0x8B, 0xB5, 0x32, 0xCD, 0xF4, +0xBD, 0x93, 0x94, 0x6F, 0xA4, 0xD0, 0xC5, 0xD5, +0xBD, 0x73, 0xB5, 0x32, 0xCD, 0xD4, 0xD6, 0x35, +0xD6, 0x36, 0xB5, 0x52, 0xB5, 0x32, 0xB5, 0x32, +0xB5, 0x32, 0xC5, 0xB4, 0xBD, 0x94, 0xBD, 0x73, +0xB5, 0x52, 0xB5, 0x52, 0xBD, 0x73, 0xBD, 0x73, +0xBD, 0x73, 0xB5, 0x53, 0xB5, 0x53, 0xB5, 0x32, +0xB5, 0x32, 0xAC, 0xF1, 0xA4, 0xD1, 0x9C, 0xB0, +0x9C, 0x90, 0x9C, 0xD0, 0x8C, 0x2E, 0x4A, 0x68, +0x5B, 0x08, 0x6C, 0x2A, 0x6C, 0x4A, 0x53, 0xA8, +0x3A, 0xA5, 0x32, 0x44, 0x29, 0xC3, 0x21, 0x83, +0x4A, 0xE7, 0x4A, 0xE7, 0x7B, 0xEB, 0x8C, 0x6E, +0x42, 0x07, 0x29, 0x44, 0x39, 0xA6, 0x52, 0x67, +0x5B, 0x28, 0x53, 0x08, 0x42, 0xA7, 0x3A, 0x07, +0x73, 0x8B, 0xCE, 0x14, 0xBD, 0x92, 0xCD, 0xF3, +0xCD, 0xF4, 0xBD, 0xB3, 0xE6, 0xD8, 0xEE, 0xD9, +0xDE, 0x57, 0xE6, 0xB9, 0xE6, 0xD9, 0xD6, 0x77, +0xD6, 0x78, 0xD6, 0x17, 0xAD, 0x13, 0xBD, 0x75, +0xC5, 0xB6, 0xBD, 0x96, 0xC5, 0xB6, 0xBD, 0x96, +0x31, 0x86, 0x39, 0xE7, 0x42, 0x28, 0x4A, 0x28, +0x52, 0x69, 0x5A, 0xEA, 0x7B, 0xCD, 0x94, 0x90, +0x94, 0x90, 0x94, 0x70, 0x94, 0x70, 0x83, 0xEE, +0x83, 0xEE, 0xBD, 0xB4, 0xAC, 0xD0, 0xA4, 0x8E, +0xD6, 0x14, 0xCD, 0xD3, 0xA4, 0xB0, 0x94, 0x6F, +0x94, 0x6F, 0xBD, 0x93, 0xBD, 0x72, 0xB5, 0x52, +0xCE, 0x15, 0xBD, 0x93, 0xC5, 0xD4, 0x9C, 0x90, +0xB5, 0x53, 0xCE, 0x15, 0xC5, 0xF4, 0xB5, 0x52, +0xA4, 0xD0, 0xC5, 0xF5, 0xCE, 0x35, 0xCE, 0x56, +0xC5, 0xD4, 0xB5, 0x31, 0xAC, 0xCF, 0xA4, 0xAE, +0xBD, 0x72, 0xBD, 0x93, 0xC5, 0xD4, 0xC5, 0xD4, +0xC5, 0xB3, 0xCE, 0x35, 0xCE, 0x35, 0xAD, 0x11, +0x63, 0x09, 0xBD, 0xD4, 0xD6, 0x76, 0xCE, 0x55, +0xD6, 0x55, 0xD6, 0x76, 0xD6, 0x76, 0xCE, 0x35, +0xBD, 0x93, 0xC5, 0xD4, 0xD6, 0x56, 0xCE, 0x14, +0xDE, 0x55, 0xB5, 0x10, 0xAC, 0xAE, 0xEE, 0xB6, +0xEE, 0xD7, 0xEE, 0xB6, 0xE6, 0x76, 0xE6, 0x55, +0xCD, 0x93, 0x72, 0xE9, 0x31, 0x84, 0x39, 0xC6, +0x42, 0x07, 0x4A, 0x48, 0x5A, 0xAB, 0x5A, 0xCB, +0x73, 0xAF, 0xAD, 0x76, 0xB5, 0xD8, 0xC6, 0x19, +0xD6, 0x9B, 0xE7, 0x1D, 0xEF, 0x5D, 0xCE, 0x59, +0x9C, 0x91, 0x94, 0x0D, 0xA4, 0xAE, 0xAC, 0xCF, +0xC5, 0xB2, 0xC5, 0x71, 0xBD, 0x71, 0xC5, 0x92, +0x9C, 0x2D, 0x83, 0x49, 0x9C, 0x2D, 0xB5, 0x11, +0xAC, 0xAF, 0x94, 0x0D, 0x9C, 0x6E, 0x6B, 0x2B, +0x8C, 0x71, 0x9C, 0xD3, 0xD6, 0xBA, 0xCE, 0x59, +0xBD, 0xD7, 0xEF, 0x3D, 0xC6, 0x17, 0x94, 0x2F, +0x9C, 0x4E, 0xAC, 0xCF, 0xB5, 0x10, 0xAC, 0xCF, +0xAC, 0xF0, 0xB4, 0xF0, 0xB4, 0xF0, 0xB4, 0xF0, +0xB5, 0x10, 0xB5, 0x10, 0xBD, 0x31, 0xBD, 0x31, +0xBD, 0x51, 0x83, 0xAC, 0x29, 0x23, 0x6B, 0x2A, +0x8C, 0x4E, 0x63, 0x09, 0x52, 0x89, 0x42, 0x07, +0x5A, 0xCA, 0x8B, 0xEE, 0x6B, 0x0B, 0x31, 0x85, +0x6B, 0x2C, 0x6B, 0x2C, 0x62, 0xEC, 0x5A, 0xAB, +0x7B, 0xEF, 0x94, 0xB2, 0x9C, 0xB3, 0xA5, 0x35, +0xA5, 0x14, 0xC5, 0xF8, 0xEF, 0x5D, 0xE6, 0xFB, +0xDE, 0x9A, 0xCE, 0x18, 0xDE, 0x9A, 0xF7, 0x3C, +0xF7, 0x3D, 0xD6, 0x18, 0xA4, 0xD3, 0xA4, 0xB2, +0x62, 0xCA, 0x42, 0x07, 0x42, 0x07, 0x42, 0x07, +0x42, 0x27, 0x39, 0xE7, 0x39, 0xE7, 0x42, 0x07, +0x4A, 0x28, 0x52, 0x89, 0x52, 0xAA, 0x5A, 0xEB, +0x6B, 0x6D, 0x84, 0x10, 0xA5, 0x14, 0xB5, 0x96, +0xA5, 0x14, 0xB5, 0xB5, 0xAD, 0x53, 0xC5, 0xD4, +0xC5, 0xB4, 0xB5, 0x52, 0xBD, 0x73, 0xBD, 0x73, +0xBD, 0x73, 0xB5, 0x73, 0xB5, 0x73, 0xC5, 0xB4, +0xAD, 0x32, 0xAD, 0x33, 0xA4, 0xF2, 0xAD, 0x32, +0xAD, 0x12, 0xAD, 0x53, 0xA4, 0xD1, 0xAD, 0x53, +0xBD, 0x93, 0xBD, 0x93, 0xC5, 0xF3, 0xD6, 0x55, +0xCE, 0x14, 0x9C, 0xB0, 0xAD, 0x33, 0xC5, 0xF5, +0xB5, 0x73, 0xAD, 0x32, 0xAD, 0x12, 0xA4, 0xD1, +0x9C, 0x8F, 0xA4, 0xB0, 0x9C, 0x4E, 0xA4, 0x6F, +0xB4, 0xF0, 0xC5, 0x52, 0xAC, 0x8F, 0xB4, 0xF1, +0xC5, 0x93, 0xA4, 0x8F, 0xA4, 0xD0, 0xAC, 0xF0, +0xCD, 0xB2, 0xD5, 0xD3, 0xCD, 0xB3, 0xCD, 0xB2, +0xD5, 0xD3, 0xCD, 0x92, 0xBD, 0x31, 0x8B, 0xEC, +0x7B, 0x8C, 0x7B, 0xAC, 0x83, 0xCD, 0x83, 0xAB, +0x8B, 0xCC, 0xA4, 0xD0, 0xAD, 0x31, 0xB5, 0x72, +0xB5, 0x72, 0xB5, 0x72, 0xB5, 0x52, 0xB5, 0x52, +0xAD, 0x11, 0xA4, 0xF0, 0xA4, 0xD0, 0xB5, 0x32, +0xBD, 0x73, 0xB5, 0x72, 0xB5, 0x52, 0xA4, 0xF0, +0xBD, 0x72, 0xBD, 0x92, 0xC5, 0xB3, 0xA4, 0xF0, +0x83, 0xCD, 0xBD, 0xB3, 0xB5, 0x31, 0xDE, 0x75, +0xCE, 0x14, 0x8C, 0x2E, 0xB5, 0x31, 0xC5, 0x93, +0x94, 0x4F, 0x73, 0x4B, 0xBD, 0x73, 0xD6, 0x14, +0xAD, 0x11, 0x94, 0x4F, 0x94, 0x4E, 0x94, 0x2E, +0x9C, 0x6F, 0xBD, 0x72, 0x83, 0xCC, 0x94, 0x4E, +0x94, 0x6F, 0xBD, 0x73, 0xBD, 0x73, 0xA4, 0xB0, +0xAD, 0x11, 0xB5, 0x11, 0xBD, 0x73, 0xC5, 0xB4, +0xDE, 0x77, 0xC5, 0xD4, 0x94, 0x2F, 0xD6, 0x77, +0xE6, 0xD7, 0xEE, 0xF8, 0xDE, 0xB7, 0xBD, 0xF4, +0x84, 0x6E, 0x74, 0x6C, 0x6C, 0x4A, 0x4B, 0x47, +0x32, 0x85, 0x3A, 0x65, 0x53, 0x28, 0x7C, 0xAD, +0x53, 0x66, 0x5B, 0xE9, 0x42, 0xA6, 0x9D, 0x10, +0x73, 0xAC, 0x52, 0x68, 0x39, 0xA6, 0x52, 0x68, +0x52, 0x87, 0x29, 0x84, 0x3A, 0x06, 0x4A, 0x48, +0x42, 0x07, 0x8C, 0x0E, 0xA4, 0xD0, 0xD6, 0x56, +0xA5, 0x11, 0xA5, 0x72, 0x95, 0x0F, 0xAD, 0x72, +0xEF, 0x3A, 0xC5, 0xF5, 0x94, 0xF0, 0x8C, 0xEF, +0x9D, 0x31, 0xAD, 0x93, 0x8C, 0x0F, 0xBD, 0x96, +0xBD, 0xB6, 0xB5, 0x34, 0xAD, 0x34, 0xA4, 0xD2, +0x29, 0x45, 0x29, 0x86, 0x39, 0xC7, 0x39, 0xE7, +0x39, 0xE7, 0x42, 0x28, 0x52, 0xA9, 0x63, 0x0B, +0x6B, 0x2B, 0x6B, 0x2B, 0x6B, 0x2B, 0x6B, 0x4B, +0x83, 0xCD, 0xB5, 0x73, 0xB5, 0x10, 0x9C, 0x6D, +0xD6, 0x14, 0xC5, 0x92, 0xA4, 0xAF, 0x94, 0x6F, +0x9C, 0x90, 0xCE, 0x35, 0xCD, 0xF4, 0xCE, 0x15, +0xD6, 0x56, 0xBD, 0xD3, 0xCE, 0x15, 0xA4, 0xD1, +0xCE, 0x16, 0xB5, 0x73, 0xA4, 0xF1, 0xAD, 0x32, +0x94, 0x6F, 0xB5, 0x73, 0xCE, 0x15, 0xCE, 0x35, +0xBD, 0x93, 0xB5, 0x31, 0xAC, 0xCF, 0x9C, 0x4D, +0xBD, 0x93, 0xBD, 0x92, 0xBD, 0x92, 0xBD, 0x72, +0xB5, 0x51, 0xB5, 0x72, 0xBD, 0xB3, 0x94, 0x8F, +0x73, 0x8C, 0xB5, 0xB4, 0xCE, 0x35, 0xCE, 0x35, +0xCE, 0x14, 0xCE, 0x34, 0xCE, 0x35, 0xCE, 0x35, +0xCE, 0x35, 0xD6, 0x76, 0xDE, 0x96, 0xD6, 0x76, +0xCD, 0xF3, 0xBD, 0x72, 0xB4, 0xCF, 0xE6, 0xB6, +0xE6, 0xB6, 0xEE, 0xB6, 0xEE, 0x96, 0xD5, 0xD3, +0xD5, 0x72, 0xE6, 0x35, 0xB5, 0x11, 0x52, 0x47, +0x39, 0xC6, 0x39, 0xE6, 0x4A, 0x69, 0x4A, 0x28, +0x5A, 0xCB, 0x8C, 0x51, 0x9C, 0xF4, 0xB5, 0xD8, +0xB5, 0x97, 0xDE, 0xDC, 0xE6, 0xFC, 0xE7, 0x1D, +0xC5, 0xF8, 0xA4, 0xF2, 0xA4, 0x8F, 0xBD, 0x51, +0xE6, 0x75, 0xE6, 0x55, 0xDE, 0x55, 0xCD, 0xD3, +0xA4, 0x6E, 0xAC, 0x8F, 0xCD, 0x93, 0xD5, 0xF4, +0xBD, 0x72, 0xCD, 0xD3, 0xCD, 0xD4, 0xA4, 0xD0, +0x8C, 0x2F, 0x7B, 0xEF, 0xC6, 0x39, 0xCE, 0x59, +0xCE, 0x59, 0xE6, 0xFC, 0xEF, 0x5D, 0xA4, 0xD3, +0x7B, 0x8C, 0x73, 0x6B, 0x73, 0x6B, 0x6B, 0x2A, +0x73, 0x2A, 0x73, 0x4B, 0x7B, 0x8B, 0x83, 0xCC, +0x8C, 0x0D, 0x94, 0x4E, 0x94, 0x4E, 0x94, 0x2D, +0x9C, 0x6E, 0x5A, 0x88, 0x29, 0x24, 0x8C, 0x0E, +0xA4, 0xF0, 0xAD, 0x31, 0x94, 0x4F, 0x41, 0xE6, +0x39, 0xC6, 0x31, 0xA5, 0x21, 0x24, 0x39, 0xE7, +0x31, 0x65, 0x4A, 0x48, 0x63, 0x0B, 0x62, 0xEB, +0x7B, 0xCF, 0x7B, 0xAE, 0x8C, 0x31, 0x84, 0x10, +0x94, 0xB3, 0x94, 0x72, 0xB5, 0x76, 0xDE, 0xBB, +0xF7, 0x7E, 0xEF, 0x3C, 0xC5, 0xD8, 0xBD, 0xB6, +0xDE, 0x79, 0xEF, 0x1B, 0xF7, 0x5C, 0xCD, 0xF6, +0x9C, 0x91, 0x52, 0x48, 0x39, 0xE7, 0x39, 0xE6, +0x39, 0xE7, 0x42, 0x07, 0x42, 0x07, 0x4A, 0x48, +0x4A, 0x69, 0x4A, 0x69, 0x52, 0xAA, 0x63, 0x0C, +0x6B, 0x4D, 0x84, 0x10, 0x83, 0xF0, 0x8C, 0x51, +0x9C, 0xD3, 0xBD, 0xF7, 0xAD, 0x12, 0xC5, 0xB4, +0xC5, 0xB4, 0xC5, 0x93, 0xCD, 0xF4, 0xCD, 0xF5, +0xC5, 0xB4, 0xAD, 0x32, 0xBD, 0x93, 0xB5, 0x53, +0xB5, 0x73, 0xAD, 0x12, 0xA4, 0xF1, 0xA5, 0x11, +0x9C, 0xD1, 0x9C, 0xD1, 0x9C, 0xB0, 0xA4, 0xF1, +0xB5, 0x73, 0xC5, 0xB3, 0xCD, 0xF4, 0xCE, 0x35, +0xC5, 0xF4, 0x94, 0x6F, 0x94, 0x90, 0xB5, 0x74, +0xB5, 0x94, 0xAD, 0x12, 0xAD, 0x53, 0x9C, 0xD0, +0x94, 0x4E, 0xA4, 0xD0, 0x9C, 0x4E, 0xA4, 0x8F, +0xBD, 0x11, 0xBD, 0x31, 0xA4, 0x8F, 0xB5, 0x11, +0xB5, 0x32, 0x9C, 0x90, 0xA4, 0xD0, 0xAC, 0xF0, +0xCD, 0x92, 0xCD, 0x92, 0xCD, 0x92, 0xCD, 0xB2, +0xD5, 0xD3, 0xCD, 0xB2, 0xB5, 0x10, 0x7B, 0xAC, +0x73, 0x6C, 0x7B, 0x8C, 0x7B, 0xAC, 0x7B, 0x8C, +0x83, 0xAC, 0xAC, 0xF1, 0xA4, 0xF0, 0xBD, 0x92, +0xBD, 0x72, 0xAD, 0x31, 0xAD, 0x11, 0xA4, 0xF0, +0x9C, 0x8F, 0xA4, 0xD0, 0xAC, 0xF1, 0xB5, 0x52, +0xB5, 0x52, 0xBD, 0xB3, 0xC5, 0xD3, 0xB5, 0x51, +0xC5, 0xB3, 0xC5, 0x92, 0xC5, 0x93, 0xB5, 0x31, +0xC5, 0x93, 0xDE, 0x55, 0x93, 0xEC, 0xCD, 0xD4, +0xCD, 0xF4, 0x9C, 0x8F, 0xCE, 0x15, 0xD6, 0x36, +0xC5, 0xB4, 0xCD, 0xF6, 0xCE, 0x15, 0xDE, 0x56, +0xCE, 0x15, 0xBD, 0x53, 0x9C, 0x90, 0x8C, 0x0E, +0x9C, 0x90, 0xAD, 0x12, 0xB5, 0x32, 0xBD, 0x73, +0xC5, 0x94, 0xD6, 0x36, 0xD6, 0x35, 0xD6, 0x35, +0xDE, 0x76, 0xE6, 0x76, 0xE6, 0x76, 0xDE, 0x56, +0xDE, 0x76, 0xD6, 0x36, 0xB5, 0x12, 0xCE, 0x16, +0xB5, 0x32, 0x9C, 0x90, 0xA4, 0xF1, 0xA5, 0x11, +0x95, 0x30, 0x8D, 0x2E, 0x8D, 0x2E, 0x74, 0x6B, +0x53, 0x88, 0x5B, 0xE9, 0x85, 0x0E, 0x85, 0x0D, +0x5B, 0xE8, 0x74, 0x8B, 0x6B, 0xCA, 0x84, 0x6C, +0xBD, 0xF2, 0x73, 0xAB, 0x42, 0x27, 0x52, 0xA7, +0x52, 0xC8, 0x31, 0xC5, 0x29, 0x44, 0x42, 0x68, +0x5A, 0xEA, 0x73, 0x8C, 0xBD, 0xF4, 0xEF, 0x7A, +0xD6, 0xF8, 0x84, 0xCF, 0x42, 0xE5, 0x53, 0x87, +0x84, 0xED, 0x74, 0x6B, 0x8D, 0x4F, 0xAE, 0x12, +0xAE, 0x33, 0xBE, 0x75, 0xBD, 0xF5, 0x94, 0x50, +0x8C, 0x10, 0x83, 0xCE, 0x7B, 0xAD, 0x73, 0x4C, +0x31, 0xA6, 0x39, 0xE7, 0x4A, 0x48, 0x52, 0x69, +0x5A, 0xA9, 0x5A, 0xAA, 0x5A, 0xA9, 0x5A, 0xA9, +0x62, 0xEA, 0x63, 0x0A, 0x63, 0x0A, 0x62, 0xEA, +0x73, 0x4B, 0xA4, 0xD0, 0xA4, 0xAF, 0x9C, 0x4D, +0xBD, 0x71, 0xB5, 0x10, 0xB5, 0x11, 0xAC, 0xD1, +0xAC, 0xF1, 0xD6, 0x36, 0xCE, 0x15, 0xC5, 0xD4, +0xC5, 0xD4, 0x94, 0x6E, 0xAD, 0x11, 0x9C, 0xB0, +0xBD, 0xD4, 0xDE, 0xD8, 0xBD, 0x93, 0xC5, 0xD4, +0xC6, 0x15, 0xCE, 0x35, 0xAD, 0x52, 0xCE, 0x15, +0xBD, 0xB3, 0xAD, 0x10, 0xA4, 0x8E, 0x9C, 0x4D, +0xBD, 0x92, 0xBD, 0x93, 0xBD, 0x93, 0xBD, 0x93, +0xC5, 0xD4, 0xBD, 0x93, 0xC5, 0xD4, 0xB5, 0x73, +0xA4, 0xF1, 0xB5, 0x73, 0xBD, 0xB3, 0xBD, 0x92, +0xBD, 0x92, 0xC5, 0xF4, 0xC5, 0xD3, 0xBD, 0x93, +0xBD, 0x93, 0xC5, 0xB3, 0xCE, 0x34, 0xCE, 0x14, +0xD6, 0x14, 0xBD, 0x51, 0xB4, 0xEF, 0xEE, 0xB6, +0xE6, 0x75, 0xE6, 0x75, 0xEE, 0x95, 0xDD, 0xD3, +0xDD, 0xB3, 0xE6, 0x14, 0xF6, 0xD7, 0xDE, 0x55, +0x7B, 0x8C, 0x39, 0xA6, 0x39, 0xC6, 0x39, 0xC6, +0x4A, 0x48, 0x5A, 0xCB, 0x73, 0xAF, 0x94, 0xB3, +0xA5, 0x56, 0xB5, 0xD8, 0xBD, 0xF9, 0xCE, 0x7A, +0xDE, 0xBB, 0xEF, 0x5C, 0xB5, 0x54, 0xCD, 0xD4, +0xD5, 0xF4, 0xE6, 0x55, 0xDE, 0x34, 0xBD, 0x72, +0xBD, 0x52, 0xDE, 0x55, 0xE6, 0x96, 0xE6, 0x96, +0xDE, 0x35, 0xD6, 0x14, 0xDE, 0x14, 0xE6, 0x96, +0xDE, 0x55, 0x9C, 0x6F, 0x94, 0x50, 0xB5, 0x96, +0xB5, 0x76, 0xCE, 0x39, 0xDE, 0xDB, 0xDE, 0x9A, +0xAD, 0x33, 0xAD, 0x53, 0xAD, 0x12, 0x9C, 0xB1, +0x8C, 0x0E, 0x7B, 0xAD, 0x73, 0x4B, 0x6B, 0x4B, +0x6B, 0x4B, 0x6B, 0x2B, 0x5A, 0xA9, 0x52, 0x89, +0x7B, 0xAD, 0x31, 0x64, 0x41, 0xE7, 0x52, 0x68, +0x52, 0x88, 0x73, 0x6B, 0x9C, 0x90, 0x73, 0x4C, +0x41, 0xE6, 0x31, 0x85, 0x4A, 0x28, 0x5A, 0xCA, +0x5A, 0xCA, 0x42, 0x27, 0x42, 0x07, 0x5A, 0xCA, +0x6B, 0x4C, 0x5A, 0xCA, 0x6B, 0x4C, 0x73, 0x8E, +0x8C, 0x31, 0x9C, 0xD3, 0x73, 0x8F, 0x9C, 0xF4, +0xC6, 0x18, 0xDE, 0xBA, 0xD6, 0x7A, 0xBD, 0x96, +0xD6, 0x59, 0xDE, 0x79, 0xFF, 0xDE, 0xEF, 0x3C, +0xCD, 0xF7, 0xA4, 0xD3, 0x4A, 0x28, 0x42, 0x28, +0x39, 0xC6, 0x39, 0xC6, 0x31, 0xA6, 0x42, 0x48, +0x52, 0x89, 0x52, 0xAA, 0x5A, 0xEB, 0x52, 0xCA, +0x63, 0x0C, 0x6B, 0x4D, 0x73, 0x6E, 0x94, 0xB3, +0xB5, 0x96, 0xC6, 0x18, 0xB5, 0x75, 0x9C, 0x91, +0x9C, 0x8F, 0x9C, 0x8F, 0x9C, 0x8F, 0xA4, 0xB0, +0x9C, 0x6F, 0x9C, 0x8F, 0xA4, 0xD0, 0x9C, 0x90, +0xAD, 0x12, 0xBD, 0x73, 0xBD, 0xB4, 0xAD, 0x32, +0xA4, 0xF1, 0x9C, 0xB0, 0xA4, 0xF1, 0xB5, 0x73, +0xD6, 0x56, 0xD6, 0x76, 0xD6, 0x55, 0xD6, 0x55, +0xC5, 0xF4, 0x9C, 0x90, 0x94, 0x70, 0x9C, 0xD1, +0xA4, 0xF1, 0xA4, 0xF1, 0xAD, 0x12, 0x9C, 0xB0, +0x8C, 0x0D, 0xAC, 0xF1, 0x9C, 0x4E, 0xAC, 0xD0, +0xBD, 0x32, 0xC5, 0x73, 0xAC, 0xB0, 0xA4, 0x6F, +0x94, 0x4F, 0x8C, 0x2E, 0x9C, 0x6F, 0xAC, 0xF1, +0xC5, 0x92, 0xCD, 0x92, 0xCD, 0x92, 0xCD, 0x92, +0xC5, 0x71, 0xBD, 0x30, 0xAC, 0xCF, 0x73, 0x8B, +0x73, 0x4B, 0x73, 0x4B, 0x73, 0x4B, 0x7B, 0x6C, +0x8B, 0xED, 0xAC, 0xF1, 0x9C, 0xB0, 0xB5, 0x31, +0xA4, 0xF0, 0xA4, 0xD0, 0xA4, 0xD0, 0xA4, 0xD0, +0xA4, 0xD0, 0xAD, 0x32, 0xB5, 0x72, 0xBD, 0x93, +0xBD, 0x73, 0xB5, 0x52, 0xBD, 0x92, 0xA4, 0xF0, +0xAC, 0xF0, 0xB5, 0x51, 0xBD, 0x72, 0xB5, 0x51, +0xC5, 0x71, 0xD5, 0xF3, 0xBD, 0x31, 0xB5, 0x31, +0xC5, 0x93, 0x9C, 0x90, 0xD6, 0x36, 0xDE, 0x77, +0xD6, 0x56, 0xDE, 0x77, 0xDE, 0x97, 0xE6, 0xB8, +0xDE, 0x77, 0xE6, 0x98, 0xC5, 0xB4, 0xB5, 0x53, +0xDE, 0x98, 0xE6, 0xB8, 0xD6, 0x56, 0xE6, 0x97, +0xEE, 0xD9, 0xE6, 0xB7, 0xEE, 0xF7, 0xE6, 0xB7, +0xE6, 0x76, 0xE6, 0x75, 0xDE, 0x75, 0xDE, 0x55, +0xDE, 0x55, 0xD6, 0x15, 0x9C, 0xB0, 0xAD, 0x33, +0xC5, 0xF6, 0xC5, 0xF6, 0xCE, 0x37, 0xBD, 0xD3, +0x8C, 0xEF, 0x8D, 0x2F, 0x7C, 0xCC, 0x6C, 0x4A, +0x74, 0x6B, 0x7C, 0xED, 0x95, 0x6F, 0x64, 0x29, +0x64, 0x49, 0x5B, 0xC8, 0x32, 0x04, 0x52, 0xE7, +0x84, 0x4B, 0x9D, 0x50, 0x53, 0x07, 0x3A, 0x85, +0x42, 0xC5, 0x53, 0x07, 0x4A, 0xC8, 0x63, 0x6A, +0x7C, 0x8E, 0x74, 0x0C, 0xB5, 0xF4, 0xD7, 0x18, +0x9D, 0x71, 0x4B, 0x27, 0x43, 0x05, 0x3A, 0xE4, +0x42, 0xE5, 0x4B, 0x46, 0x6C, 0x2A, 0x9D, 0xD1, +0xB6, 0x75, 0xB6, 0x95, 0xA5, 0x92, 0x63, 0x0A, +0x62, 0xCA, 0x83, 0xCE, 0x8C, 0x0F, 0x8C, 0x0F, +0x5A, 0xCA, 0x6B, 0x0B, 0x6B, 0x4B, 0x7B, 0x8C, +0x83, 0xCD, 0x83, 0xED, 0x8C, 0x0D, 0x8C, 0x0D, +0x8B, 0xED, 0x8B, 0xEC, 0x8C, 0x0D, 0x94, 0x2D, +0x94, 0x4E, 0x94, 0x4D, 0x94, 0x2C, 0x94, 0x2C, +0x94, 0x0C, 0x94, 0x2C, 0x94, 0x2D, 0x9C, 0x4E, +0x8C, 0x0C, 0x94, 0x2D, 0x94, 0x0C, 0x94, 0x0C, +0x94, 0x2D, 0x94, 0x4D, 0x9C, 0x6E, 0x94, 0x2D, +0x94, 0x4E, 0xAD, 0x31, 0xB5, 0x73, 0xB5, 0x52, +0xAD, 0x11, 0xA5, 0x11, 0xAC, 0xF0, 0xB5, 0x51, +0x9C, 0x6E, 0x94, 0x0C, 0xA4, 0x8E, 0xAC, 0xCF, +0xB5, 0x72, 0xC5, 0xD3, 0xBD, 0xD3, 0xBD, 0xB3, +0xCE, 0x35, 0xC5, 0xD4, 0xBD, 0x93, 0xBD, 0x93, +0xAD, 0x31, 0xB5, 0x72, 0xB5, 0x72, 0xBD, 0x92, +0xBD, 0x92, 0xB5, 0x92, 0xAD, 0x11, 0xA4, 0xF0, +0xA4, 0xD0, 0xB5, 0x72, 0xC5, 0xD3, 0xC5, 0xD3, +0xC5, 0xB2, 0xBD, 0x30, 0xBD, 0x30, 0xEE, 0xD7, +0xE6, 0x95, 0xE6, 0x75, 0xE6, 0x55, 0xE6, 0x14, +0xE5, 0xF3, 0xEE, 0x55, 0xEE, 0x95, 0xEE, 0xB6, +0xE6, 0x96, 0xAC, 0xD0, 0x4A, 0x27, 0x31, 0xA6, +0x39, 0xE7, 0x39, 0xE7, 0x4A, 0x69, 0x6B, 0x4D, +0x84, 0x51, 0x8C, 0x93, 0xB5, 0x97, 0xC6, 0x19, +0xDE, 0xFC, 0xEF, 0x3D, 0xB5, 0x96, 0xD6, 0x79, +0xC5, 0xD6, 0xCD, 0xF4, 0xD6, 0x14, 0xC5, 0x93, +0xD6, 0x15, 0xD6, 0x35, 0xDE, 0x35, 0xDE, 0x34, +0xDE, 0x34, 0xDE, 0x34, 0xD5, 0xF3, 0xD5, 0xB2, +0xD5, 0xF3, 0xD5, 0xF3, 0xB5, 0x31, 0x73, 0x6C, +0xAD, 0x55, 0xDE, 0xDB, 0xE6, 0xFC, 0xEF, 0x5D, +0xD6, 0x79, 0xB5, 0x33, 0xB5, 0x93, 0xB5, 0x73, +0xAD, 0x32, 0xAD, 0x12, 0x9C, 0xB1, 0x9C, 0x90, +0x9C, 0xB0, 0x94, 0x8F, 0x8C, 0x2E, 0x8C, 0x2F, +0x4A, 0x27, 0x4A, 0x48, 0x8C, 0x2F, 0x8C, 0x4F, +0x9C, 0xD1, 0xAD, 0x12, 0xAD, 0x32, 0x9C, 0xAF, +0xA4, 0xD0, 0x73, 0x6B, 0x63, 0x0A, 0x52, 0x68, +0x5A, 0xAA, 0x5A, 0xA9, 0x31, 0xA5, 0x39, 0xA6, +0x42, 0x07, 0x4A, 0x48, 0x6B, 0x4C, 0x73, 0x6D, +0x6B, 0x2C, 0x83, 0xF0, 0x83, 0xF0, 0x7B, 0xF0, +0x7B, 0xCF, 0x8C, 0x51, 0x94, 0xB3, 0xAD, 0x35, +0xE6, 0xDB, 0xDE, 0x9A, 0xEF, 0x1B, 0xEF, 0x5C, +0xC5, 0xD7, 0xDE, 0xBA, 0xAD, 0x34, 0x42, 0x08, +0x31, 0xA6, 0x39, 0xC6, 0x39, 0xE6, 0x39, 0xC6, +0x3A, 0x07, 0x4A, 0x48, 0x42, 0x48, 0x52, 0x8A, +0x5B, 0x0B, 0x6B, 0x6E, 0x7B, 0xD0, 0x9C, 0xB3, +0xAD, 0x76, 0xBD, 0xD7, 0xAD, 0x55, 0xC5, 0xD6, +0xCE, 0x17, 0xC5, 0x94, 0xBD, 0x94, 0xC5, 0xB4, +0xC5, 0x94, 0xBD, 0x93, 0xBD, 0x73, 0xB5, 0x32, +0xAC, 0xF1, 0xAC, 0xF1, 0xAC, 0xD1, 0xA4, 0xD0, +0xA4, 0xD0, 0xA4, 0xD1, 0xA4, 0xD1, 0xAD, 0x11, +0xB5, 0x52, 0xBD, 0x52, 0xB5, 0x52, 0xB5, 0x11, +0xBD, 0x72, 0xA4, 0xF1, 0xAD, 0x12, 0xAC, 0xF2, +0xA4, 0xD1, 0x9C, 0xD1, 0x94, 0x4F, 0x8C, 0x0D, +0x94, 0x4F, 0xA4, 0xD0, 0x94, 0x0E, 0x93, 0xED, +0x94, 0x0D, 0xB5, 0x11, 0xBD, 0x52, 0xBD, 0x52, +0xB5, 0x32, 0xAD, 0x31, 0xB5, 0x52, 0xBD, 0x52, +0xC5, 0x72, 0xD5, 0xD3, 0xD5, 0xD2, 0xCD, 0xB2, +0xCD, 0x92, 0xC5, 0x72, 0x94, 0x4E, 0x6B, 0x2B, +0x62, 0xEA, 0x63, 0x0A, 0x63, 0x0A, 0x73, 0x4B, +0x94, 0x0D, 0xAD, 0x11, 0xA4, 0xD0, 0xBD, 0x72, +0xAD, 0x10, 0xAD, 0x11, 0xAD, 0x31, 0xB5, 0x72, +0xB5, 0x52, 0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x52, +0xB5, 0x52, 0xB5, 0x52, 0xBD, 0x92, 0xB5, 0x51, +0x9C, 0x8E, 0xB5, 0x31, 0xC5, 0xB3, 0xBD, 0x92, +0xBD, 0x71, 0xBD, 0x51, 0xCD, 0xB3, 0xB5, 0x31, +0xB5, 0x52, 0x9C, 0x90, 0xD6, 0x56, 0xDE, 0x76, +0xE6, 0x97, 0xE6, 0xD8, 0xBD, 0xB4, 0x94, 0x50, +0x9C, 0x91, 0xB5, 0x54, 0xBD, 0x95, 0xC5, 0xD6, +0xC5, 0xF5, 0xD6, 0x16, 0xDE, 0x56, 0xCE, 0x15, +0xBD, 0x94, 0xC5, 0xD5, 0xE6, 0x96, 0xDE, 0x35, +0xE6, 0x96, 0xE6, 0x96, 0xDE, 0x75, 0xDE, 0x34, +0xD6, 0x14, 0xB5, 0x32, 0xB5, 0x74, 0xCE, 0x58, +0xC5, 0xF7, 0x9C, 0xB2, 0xE6, 0xD8, 0xE6, 0xD7, +0xB5, 0xD2, 0x8D, 0x2E, 0x7C, 0xCD, 0x85, 0x0D, +0x8D, 0x2E, 0x8D, 0x4F, 0x95, 0x70, 0x64, 0x09, +0x4B, 0x67, 0x21, 0xA3, 0x19, 0x03, 0x29, 0x64, +0x21, 0x63, 0x63, 0x8A, 0x7C, 0xAC, 0x5B, 0xC9, +0x32, 0x84, 0x42, 0xA6, 0x7C, 0x6C, 0x74, 0x4C, +0x9D, 0xB1, 0xA5, 0xD2, 0x8C, 0xEE, 0x6C, 0x2B, +0x2A, 0x24, 0x53, 0x88, 0x53, 0xA7, 0x4B, 0x66, +0x53, 0x87, 0x63, 0xA8, 0x8C, 0xEE, 0x74, 0x4C, +0x7C, 0x8D, 0x85, 0x2F, 0x84, 0xEE, 0x9C, 0xF0, +0xC5, 0xB5, 0xAC, 0xF2, 0x83, 0x8D, 0x7B, 0x4C, +0x63, 0x0A, 0x7B, 0x8C, 0x83, 0xCD, 0x83, 0xCD, +0x94, 0x6F, 0xB5, 0x52, 0xBD, 0xD3, 0xC5, 0xF4, +0xBD, 0x92, 0xA4, 0x8E, 0x94, 0x0C, 0xA4, 0xCF, +0xB5, 0x31, 0xC5, 0x93, 0xB5, 0x10, 0xAC, 0xCF, +0xB4, 0xEF, 0xAC, 0xAF, 0xB4, 0xEF, 0xAC, 0xCF, +0x9C, 0x6E, 0x9C, 0x4D, 0xA4, 0xAE, 0xB5, 0x0F, +0xAC, 0xEF, 0xB5, 0x10, 0xAC, 0xEF, 0xAC, 0xCF, +0xAC, 0xCF, 0xA4, 0x8E, 0x9C, 0x6D, 0x9C, 0x4D, +0x94, 0x2D, 0x94, 0x2C, 0x8B, 0xEC, 0x8B, 0xCB, +0x94, 0x0C, 0x94, 0x2D, 0x9C, 0x2D, 0x8B, 0xEB, +0x8B, 0xCB, 0x83, 0xAB, 0x83, 0xAB, 0x83, 0xAB, +0x83, 0xCC, 0x83, 0xCB, 0x83, 0xCC, 0x94, 0x0D, +0x9C, 0x8E, 0x94, 0x2D, 0x8C, 0x0C, 0x9C, 0x6E, +0x94, 0x2D, 0x83, 0xCB, 0x7B, 0x8B, 0x83, 0xED, +0x94, 0x6E, 0xBD, 0x93, 0xCE, 0x14, 0xD6, 0x35, +0xD6, 0x55, 0xBD, 0x51, 0xC5, 0x70, 0xF6, 0xF7, +0xEE, 0xB6, 0xE6, 0x75, 0xDD, 0xF4, 0xDD, 0x93, +0xDD, 0xB3, 0xEE, 0x55, 0xE6, 0x75, 0xE6, 0x75, +0xE6, 0x75, 0xEE, 0x96, 0xD5, 0xF4, 0x73, 0x2A, +0x41, 0xE6, 0x39, 0xC6, 0x39, 0xE7, 0x4A, 0x28, +0x5A, 0xCB, 0x73, 0xAF, 0x9C, 0xF4, 0xAD, 0x97, +0xC6, 0x5A, 0xD6, 0x7B, 0xB5, 0x97, 0xC6, 0x39, +0xE7, 0x3C, 0xEF, 0x3B, 0xDE, 0xB8, 0xCD, 0xD4, +0xCD, 0xD3, 0xCD, 0xD3, 0xD5, 0xF4, 0xDE, 0x55, +0xE6, 0x75, 0xE6, 0x54, 0xE6, 0x34, 0xE6, 0x14, +0xE6, 0x34, 0xE6, 0x34, 0xE6, 0x35, 0x8B, 0xED, +0x9C, 0xF3, 0xC6, 0x18, 0xD6, 0x9A, 0xE6, 0xFC, +0xEF, 0x5D, 0xBD, 0xD6, 0xB5, 0x73, 0xB5, 0x52, +0xAD, 0x12, 0xA4, 0xF1, 0xA4, 0xF1, 0xA4, 0xF1, +0xAD, 0x12, 0xAD, 0x32, 0xAD, 0x53, 0x84, 0x0F, +0x31, 0x85, 0x9C, 0xD1, 0xB5, 0x53, 0xAD, 0x32, +0xA4, 0xF2, 0x9C, 0xD1, 0xB5, 0x73, 0xBD, 0x72, +0xB5, 0x10, 0x83, 0xAC, 0x73, 0x8C, 0x84, 0x0E, +0x52, 0x68, 0x5A, 0xA9, 0x42, 0x27, 0x39, 0xC6, +0x39, 0xA6, 0x42, 0x07, 0x4A, 0x48, 0x6B, 0x2C, +0x6B, 0x4D, 0x5A, 0xCB, 0x5A, 0xEB, 0x73, 0x6E, +0x7B, 0xAF, 0x6B, 0x4E, 0x9C, 0x92, 0xAD, 0x34, +0x9C, 0xB3, 0x9C, 0xB2, 0x9C, 0xB2, 0xBD, 0x75, +0x8C, 0x10, 0xAD, 0x34, 0xD6, 0xBA, 0x5A, 0xCB, +0x42, 0x07, 0x31, 0xC6, 0x39, 0xC6, 0x39, 0xE7, +0x42, 0x28, 0x42, 0x27, 0x4A, 0x48, 0x5A, 0xEB, +0x63, 0x4D, 0x7B, 0xCF, 0x8C, 0x51, 0x94, 0x72, +0x9C, 0xD3, 0xA5, 0x35, 0xBD, 0xF8, 0xCE, 0x39, +0xC5, 0xF7, 0xAD, 0x12, 0xB5, 0x12, 0xAC, 0xF1, +0xB5, 0x32, 0xB5, 0x53, 0xB5, 0x53, 0xB5, 0x53, +0xBD, 0x73, 0xC5, 0xD4, 0xCD, 0xF5, 0xC5, 0xD4, +0xC5, 0xB4, 0xC5, 0xD4, 0xC5, 0xB4, 0xBD, 0x73, +0xB5, 0x52, 0xB5, 0x11, 0xC5, 0x93, 0xBD, 0x53, +0xB5, 0x52, 0xBD, 0x93, 0xBD, 0x93, 0xC5, 0xD4, +0xC5, 0xD4, 0xC5, 0xD5, 0xC5, 0xB4, 0xB5, 0x53, +0xB5, 0x53, 0xAC, 0xF1, 0x9C, 0x6F, 0x9C, 0x70, +0x9C, 0x6F, 0xA4, 0xB0, 0xA4, 0xAF, 0xB5, 0x11, +0xB5, 0x11, 0xAC, 0xCF, 0xB5, 0x10, 0xAC, 0xCF, +0xAC, 0xCF, 0xBD, 0x31, 0xBD, 0x30, 0xBD, 0x10, +0xBD, 0x30, 0xB5, 0x10, 0x8B, 0xED, 0x73, 0x4B, +0x73, 0x6C, 0x73, 0x4B, 0x73, 0x2B, 0x7B, 0x6B, +0x94, 0x2D, 0xAD, 0x11, 0x9C, 0x8F, 0xC5, 0xD4, +0xC5, 0xD4, 0xBD, 0x93, 0xBD, 0x73, 0xBD, 0x93, +0xBD, 0x93, 0xBD, 0x92, 0xBD, 0x93, 0xB5, 0x52, +0xB5, 0x72, 0xBD, 0x93, 0xBD, 0x93, 0xBD, 0x92, +0x94, 0x6D, 0xBD, 0x92, 0xD6, 0x14, 0xCD, 0xF4, +0xCD, 0xD3, 0xCD, 0xD4, 0xDE, 0x55, 0xB5, 0x51, +0xA4, 0xD0, 0x9C, 0x90, 0xD6, 0x36, 0xEE, 0xD7, +0xE6, 0xB7, 0xEE, 0xF8, 0x8C, 0x2F, 0x5A, 0xCB, +0x6B, 0x4C, 0x94, 0xB2, 0x9C, 0xB2, 0xC5, 0xD6, +0xE6, 0xB9, 0xDE, 0x99, 0xE6, 0xB9, 0xC5, 0xF6, +0x8C, 0x10, 0x9C, 0xD2, 0xBD, 0x73, 0xB5, 0x31, +0xAC, 0xF1, 0xB5, 0x11, 0xD6, 0x15, 0xDE, 0x55, +0xCD, 0xB3, 0xCE, 0x16, 0xC5, 0xF7, 0x9C, 0xF3, +0xAD, 0x13, 0xE6, 0xD9, 0xE6, 0xB7, 0xE6, 0xB6, +0xE7, 0x17, 0xCE, 0x95, 0x8D, 0x0E, 0x85, 0x0E, +0x85, 0x2E, 0x8D, 0x6F, 0x85, 0x0E, 0x74, 0x8B, +0x32, 0x65, 0x29, 0x84, 0x21, 0x44, 0x29, 0x85, +0x29, 0xA5, 0x29, 0xA4, 0x5B, 0xA9, 0x6C, 0x8B, +0x5B, 0xE9, 0x32, 0x84, 0x63, 0xCA, 0x42, 0xC6, +0x32, 0x65, 0x5B, 0xAA, 0x74, 0x6C, 0x6C, 0x4B, +0x43, 0x07, 0x5B, 0xE9, 0x5C, 0x09, 0x5B, 0xE8, +0x63, 0xE9, 0x5B, 0x89, 0x5B, 0x29, 0x5B, 0x29, +0x52, 0xC8, 0x7C, 0x4E, 0xA5, 0x91, 0xAD, 0x92, +0xA5, 0x11, 0x8C, 0x0E, 0x7B, 0x4C, 0x73, 0x0A, +0x6B, 0x0B, 0x6B, 0x2B, 0x6B, 0x6B, 0x83, 0xED, +0x8C, 0x2E, 0x94, 0x8E, 0xA5, 0x10, 0xB5, 0x51, +0xB5, 0x51, 0xB5, 0x31, 0xC5, 0xB3, 0xDE, 0x96, +0xC5, 0xF4, 0xBD, 0xB3, 0xC5, 0xB3, 0xBD, 0x91, +0xDE, 0x75, 0xD6, 0x34, 0xD6, 0x14, 0xCD, 0xF3, +0xD6, 0x14, 0xAC, 0xAF, 0xBD, 0x71, 0xEE, 0xB6, +0xD5, 0xF3, 0xCD, 0xD2, 0xC5, 0x91, 0xCD, 0xD2, +0xDE, 0x54, 0xDE, 0x34, 0xD5, 0xF3, 0xD6, 0x34, +0xCD, 0xB2, 0xB5, 0x10, 0xC5, 0x71, 0xC5, 0x71, +0xB5, 0x10, 0xD5, 0xF3, 0xCD, 0xD2, 0xC5, 0x92, +0xBD, 0x30, 0xBD, 0x51, 0xC5, 0x71, 0xBD, 0x30, +0xB5, 0x10, 0xB5, 0x10, 0xAC, 0xCF, 0xAC, 0xAF, +0xAC, 0xAE, 0xAC, 0xAE, 0xAC, 0xCF, 0xAC, 0xAE, +0xA4, 0x8E, 0xA4, 0x8E, 0xA4, 0x6E, 0x9C, 0x6E, +0x94, 0x4D, 0x94, 0x0C, 0x94, 0x2D, 0x9C, 0x6E, +0xA4, 0xAE, 0xA4, 0x6D, 0xA4, 0x4C, 0xBD, 0x30, +0xBD, 0x51, 0xBD, 0x31, 0xB4, 0xAF, 0xA4, 0x2D, +0xAC, 0x8E, 0xBD, 0x10, 0xBD, 0x10, 0xBD, 0x10, +0xD5, 0xF4, 0xDE, 0x14, 0xDE, 0x34, 0xB5, 0x10, +0x83, 0xAB, 0x4A, 0x06, 0x42, 0x07, 0x42, 0x07, +0x42, 0x28, 0x5A, 0xCB, 0x73, 0xAE, 0x94, 0xB3, +0xAD, 0x96, 0x9C, 0xF4, 0xB5, 0xB7, 0xE7, 0x1C, +0xD6, 0x9A, 0xBD, 0xF7, 0xC6, 0x38, 0xCE, 0x17, +0xCD, 0xF5, 0xDE, 0x35, 0xE6, 0x96, 0xEE, 0x96, +0xEE, 0x75, 0xEE, 0x75, 0xE6, 0x54, 0xE6, 0x34, +0xDE, 0x13, 0xDD, 0xF3, 0xE6, 0x55, 0xB4, 0xF0, +0x7B, 0xAD, 0xA5, 0x14, 0xCE, 0x5A, 0xD6, 0x9A, +0xDE, 0xBB, 0xCE, 0x58, 0x9C, 0xD1, 0xAD, 0x12, +0xA4, 0xF1, 0xA4, 0xD1, 0xA4, 0xF1, 0x9C, 0xD1, +0x9C, 0xD1, 0xA4, 0xD1, 0xA4, 0xF1, 0x52, 0x68, +0x6B, 0x2C, 0xB5, 0x74, 0xAD, 0x32, 0xA5, 0x12, +0xA4, 0xF1, 0x9C, 0xB0, 0xAD, 0x52, 0xBD, 0x72, +0xB5, 0x10, 0x8C, 0x0D, 0x83, 0xCC, 0xAD, 0x31, +0x9C, 0x8F, 0x73, 0x6B, 0x4A, 0x27, 0x31, 0x85, +0x39, 0xE6, 0x42, 0x07, 0x52, 0x69, 0x4A, 0x48, +0x5A, 0xAA, 0x5A, 0xAA, 0x5A, 0xAB, 0x5A, 0xCB, +0x7B, 0xCF, 0x84, 0x10, 0xBD, 0x96, 0xC5, 0xD7, +0xB5, 0x34, 0xAD, 0x14, 0x94, 0x71, 0xAD, 0x13, +0x94, 0x51, 0x52, 0x8A, 0xAD, 0x35, 0xAD, 0x55, +0x42, 0x07, 0x31, 0xA6, 0x31, 0xC6, 0x39, 0xE7, +0x42, 0x27, 0x4A, 0x48, 0x52, 0x89, 0x63, 0x0C, +0x73, 0x8E, 0x73, 0x8E, 0x7B, 0xEF, 0x73, 0x8E, +0x7B, 0xF0, 0x94, 0x92, 0xB5, 0x76, 0xAD, 0x55, +0xAD, 0x55, 0x94, 0x2F, 0xAC, 0xF1, 0x83, 0xEE, +0x83, 0xEE, 0x6B, 0x4C, 0x63, 0x0A, 0x63, 0x0A, +0x6B, 0x4B, 0x6B, 0x2B, 0x6B, 0x2B, 0x6B, 0x2B, +0x73, 0x6C, 0x7B, 0xAD, 0x8C, 0x0E, 0x94, 0x4F, +0x9C, 0x6F, 0xA4, 0xD0, 0xC5, 0xD4, 0xDE, 0x97, +0xD6, 0x56, 0xAC, 0xF1, 0xA4, 0xD0, 0xA4, 0xAF, +0x9C, 0x8F, 0xAC, 0xF0, 0xB5, 0x32, 0xB5, 0x52, +0xAD, 0x11, 0xA4, 0xB0, 0xB4, 0xF0, 0xB5, 0x10, +0xAC, 0xF0, 0xAC, 0xF1, 0xAC, 0xD0, 0xB5, 0x11, +0xB5, 0x32, 0xB5, 0x11, 0xAC, 0xF0, 0xA4, 0xAF, +0xAC, 0xCF, 0xA4, 0xAF, 0xAC, 0xD0, 0xAC, 0xD0, +0xAC, 0xF0, 0xAC, 0xF1, 0xB4, 0xF1, 0xAC, 0xF1, +0xA4, 0xB0, 0x9C, 0x6F, 0x8B, 0xEE, 0x8C, 0x0D, +0xA4, 0xB0, 0xAD, 0x12, 0xA4, 0xB0, 0x94, 0x4E, +0x8B, 0xED, 0x8B, 0xED, 0x8C, 0x0D, 0x8B, 0xED, +0x8C, 0x0D, 0x8C, 0x0D, 0x94, 0x2E, 0x94, 0x2E, +0x8C, 0x0D, 0x83, 0xED, 0x83, 0xEC, 0x94, 0x2D, +0x9C, 0xAF, 0xA4, 0xD0, 0xB5, 0x11, 0xBD, 0x72, +0xB5, 0x11, 0xA4, 0xAF, 0xBD, 0x92, 0xC5, 0xD3, +0x9C, 0x8F, 0x9C, 0x90, 0xC5, 0xD4, 0xF7, 0x18, +0xE6, 0xB7, 0xE6, 0x96, 0x9C, 0x70, 0x62, 0xCA, +0x5A, 0x89, 0x6B, 0x4C, 0x7B, 0xAE, 0xBD, 0x75, +0xCE, 0x17, 0xAD, 0x14, 0x8C, 0x51, 0x83, 0xEF, +0xBD, 0x96, 0xDE, 0xBA, 0xE6, 0xBA, 0xCD, 0xD6, +0xB5, 0x54, 0xA4, 0xB1, 0x8C, 0x0F, 0xAD, 0x13, +0xCE, 0x17, 0xA5, 0x14, 0x73, 0xAF, 0xD6, 0x78, +0xEF, 0x19, 0xEE, 0xD7, 0xE6, 0xB6, 0xE6, 0xB6, +0xE6, 0xD6, 0xE6, 0xF7, 0xCE, 0x95, 0x95, 0x2F, +0x85, 0x0E, 0x8D, 0x6F, 0x74, 0xCC, 0x74, 0x8B, +0x32, 0x04, 0x3A, 0x27, 0x3A, 0x07, 0x31, 0xC6, +0x31, 0xA5, 0x31, 0xE6, 0x32, 0x24, 0x5B, 0xE8, +0x64, 0x2A, 0x4B, 0x47, 0x32, 0x24, 0x42, 0x85, +0x29, 0xE3, 0x19, 0xA2, 0x3A, 0x85, 0x74, 0xAC, +0x53, 0x88, 0x53, 0xA8, 0x5B, 0xC8, 0x43, 0x05, +0x3A, 0xA4, 0x3A, 0x85, 0x5B, 0x28, 0x7C, 0x4D, +0x7C, 0x4D, 0xA5, 0x72, 0x9C, 0xF0, 0x94, 0x6F, +0x8C, 0x0E, 0x6B, 0x0A, 0x5A, 0x48, 0x6A, 0xA9, +0x62, 0xEA, 0x73, 0x8C, 0x7B, 0xAC, 0x94, 0x8F, +0x9C, 0xD0, 0x9C, 0xCF, 0x9C, 0xCF, 0xAD, 0x10, +0xA4, 0xF0, 0xA4, 0xF0, 0x94, 0x6E, 0xC5, 0xD4, +0xAD, 0x32, 0xB5, 0x52, 0xAD, 0x10, 0xAD, 0x10, +0xD6, 0x14, 0xCD, 0xF3, 0xCD, 0xF3, 0xBD, 0x91, +0xDE, 0x96, 0xAC, 0xAE, 0xC5, 0x71, 0xE6, 0x95, +0xE6, 0x74, 0xE6, 0x74, 0xE6, 0x95, 0xE6, 0x95, +0xE6, 0x95, 0xE6, 0x75, 0xDE, 0x34, 0xE6, 0x95, +0xDE, 0x75, 0xD6, 0x13, 0xE6, 0x54, 0xE6, 0x74, +0xD6, 0x13, 0xEE, 0xB5, 0xE6, 0x74, 0xE6, 0x95, +0xE6, 0x54, 0xD5, 0xF2, 0xE6, 0x95, 0xC5, 0x70, +0xCD, 0xB1, 0xB5, 0x0F, 0xB4, 0xEF, 0xDE, 0x34, +0xCD, 0x92, 0xBD, 0x30, 0xB5, 0x30, 0xB5, 0x0F, +0xBD, 0x50, 0xBD, 0x30, 0xB5, 0x0F, 0xBD, 0x30, +0xBD, 0x10, 0xBD, 0x30, 0xBD, 0x30, 0xB5, 0x10, +0xB4, 0xEF, 0xBD, 0x30, 0xBD, 0x30, 0xB4, 0xCF, +0xAC, 0xAE, 0xAC, 0x8E, 0x9C, 0x4D, 0x9C, 0x4D, +0x9C, 0x4D, 0x9C, 0x4D, 0x9C, 0x4D, 0x9C, 0x2D, +0x93, 0xEB, 0x8B, 0xCB, 0x8B, 0xCB, 0x8B, 0xAA, +0x8B, 0xAA, 0x7B, 0x4A, 0x52, 0x47, 0x39, 0xC6, +0x39, 0xE7, 0x42, 0x28, 0x52, 0xAA, 0x6B, 0x8E, +0x84, 0x31, 0x94, 0xB3, 0xBD, 0xD7, 0xC6, 0x18, +0x84, 0x10, 0x8C, 0x51, 0x8C, 0x51, 0x73, 0x8E, +0xAC, 0xF2, 0xC5, 0x93, 0xCD, 0xB3, 0xDE, 0x34, +0xE6, 0x34, 0xE6, 0x54, 0xEE, 0x95, 0xEE, 0xB5, +0xEE, 0x95, 0xEE, 0x75, 0xE6, 0x34, 0xB4, 0xCF, +0xA4, 0xB0, 0x84, 0x10, 0xBD, 0xF7, 0xC6, 0x38, +0x94, 0x92, 0xB5, 0x96, 0xC5, 0xF8, 0xB5, 0x55, +0xAD, 0x33, 0xB5, 0x73, 0xAD, 0x32, 0xA4, 0xD1, +0xA4, 0xD1, 0x9C, 0xB0, 0x7B, 0xCD, 0x29, 0x44, +0x9C, 0xB1, 0xAD, 0x12, 0xAD, 0x12, 0xAD, 0x32, +0x9C, 0xD1, 0x9C, 0xD0, 0x9C, 0xB0, 0xAC, 0xF0, +0xAC, 0xCF, 0xAC, 0xF0, 0xAC, 0xF0, 0xB5, 0x52, +0xBD, 0x72, 0xB5, 0x31, 0x83, 0xCD, 0x4A, 0x27, +0x42, 0x07, 0x4A, 0x28, 0x52, 0x69, 0x5A, 0xAA, +0x73, 0x8D, 0x5A, 0xCA, 0x5A, 0xCA, 0x52, 0x89, +0x6B, 0x4D, 0xA4, 0xD3, 0xAD, 0x14, 0xB5, 0x34, +0xD6, 0x18, 0xD6, 0x18, 0xC5, 0x96, 0x94, 0x71, +0x9C, 0xB3, 0x73, 0x8E, 0xB5, 0xB6, 0xBD, 0xD6, +0x52, 0xAA, 0x39, 0xC6, 0x31, 0xA6, 0x39, 0xC6, +0x42, 0x07, 0x42, 0x28, 0x5A, 0xCA, 0x73, 0xAE, +0x6B, 0x2C, 0x52, 0xAA, 0x52, 0xAA, 0x63, 0x0C, +0x6B, 0x6D, 0x8C, 0x51, 0x84, 0x31, 0xA5, 0x14, +0xB5, 0x96, 0xA4, 0xF3, 0xAD, 0x33, 0x9C, 0x90, +0xBD, 0x94, 0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x73, +0xB5, 0x73, 0xAD, 0x32, 0x9C, 0xB1, 0x8C, 0x4F, +0x8C, 0x2E, 0x8C, 0x2E, 0x8C, 0x2F, 0x9C, 0x90, +0x8C, 0x2F, 0xA4, 0xF1, 0xBD, 0x94, 0xBD, 0xD4, +0xD6, 0x77, 0xA4, 0xF1, 0x9C, 0xAF, 0xA4, 0xD0, +0xA4, 0xD0, 0x8C, 0x0D, 0x8C, 0x0D, 0x94, 0x6E, +0xB5, 0x31, 0x94, 0x2D, 0xBD, 0x30, 0xCD, 0xD2, +0xCD, 0xB2, 0xAC, 0xB0, 0xB5, 0x32, 0x9C, 0x8F, +0x94, 0x0D, 0xA4, 0xCF, 0xAD, 0x11, 0xAC, 0xF0, +0xAC, 0xF1, 0x9C, 0x4E, 0x9C, 0x6F, 0xB5, 0x32, +0xC5, 0xD4, 0xBD, 0x72, 0xC5, 0xB4, 0xC5, 0xD4, +0xCD, 0xF5, 0xCE, 0x15, 0xCD, 0xD4, 0xBD, 0x93, +0x9C, 0x8F, 0xAD, 0x11, 0xBD, 0x52, 0xBD, 0x52, +0xB5, 0x32, 0xB5, 0x32, 0xB5, 0x53, 0xAD, 0x32, +0xAD, 0x11, 0xA4, 0xF1, 0xA4, 0xF1, 0xAD, 0x12, +0xAD, 0x12, 0xA4, 0xD1, 0xA4, 0xB0, 0xA4, 0x90, +0x9C, 0x8F, 0x9C, 0x6F, 0x94, 0x4F, 0x8C, 0x0E, +0x94, 0x0E, 0x94, 0x0E, 0x94, 0x2E, 0x94, 0x0D, +0x83, 0xCD, 0x8C, 0x0E, 0x94, 0x2F, 0xAD, 0x11, +0xB5, 0x12, 0xB5, 0x31, 0xB5, 0x32, 0xAC, 0xF2, +0x8C, 0x2F, 0x5A, 0xCA, 0x5A, 0xAA, 0x9C, 0x92, +0x94, 0x51, 0x9C, 0xB2, 0x7B, 0xCE, 0x5A, 0xCB, +0xC5, 0xF7, 0xCE, 0x38, 0xD6, 0x59, 0xD6, 0x79, +0xEF, 0x3C, 0xDE, 0xBA, 0xD6, 0xBA, 0xE6, 0xFC, +0xC6, 0x18, 0x9C, 0xD3, 0xAD, 0x54, 0xDE, 0x97, +0xEE, 0xD7, 0xEE, 0xF7, 0xEE, 0xF7, 0xEE, 0xF7, +0xEE, 0xF7, 0xEE, 0xF7, 0xF7, 0x17, 0xCE, 0x75, +0x84, 0xEE, 0x95, 0x6F, 0x7C, 0xCD, 0x5B, 0xA9, +0x31, 0xC5, 0x42, 0x07, 0x42, 0x28, 0x52, 0x89, +0x52, 0xAA, 0x42, 0x47, 0x29, 0xE5, 0x4B, 0x47, +0x6C, 0x8B, 0x63, 0xEA, 0x52, 0xC6, 0x7C, 0x09, +0x53, 0x46, 0x2A, 0x44, 0x19, 0xA2, 0x4B, 0x27, +0x64, 0x09, 0x32, 0xA3, 0x32, 0xC4, 0x3A, 0xC3, +0x3A, 0xC4, 0x4B, 0x46, 0x74, 0x8B, 0x8D, 0x2D, +0x84, 0xCC, 0x6C, 0x09, 0x6B, 0xA9, 0x6B, 0x49, +0x62, 0xA9, 0x49, 0xC6, 0x52, 0x27, 0x7B, 0x4B, +0x6B, 0x4B, 0x7B, 0xAC, 0x83, 0xED, 0x9C, 0xD0, +0xAD, 0x32, 0xAD, 0x31, 0xA5, 0x10, 0xAD, 0x31, +0x9C, 0xAF, 0x94, 0x6E, 0x84, 0x0D, 0xAD, 0x32, +0xB5, 0x53, 0xA5, 0x11, 0xA5, 0x10, 0xB5, 0x71, +0xCD, 0xF3, 0xCD, 0xF3, 0xC5, 0x92, 0xAC, 0xEF, +0xCE, 0x14, 0xA4, 0x8E, 0xBD, 0x50, 0xE6, 0x75, +0xE6, 0x74, 0xEE, 0xB5, 0xE6, 0x74, 0xE6, 0x74, +0xE6, 0x74, 0xE6, 0xB6, 0xE6, 0x95, 0xE6, 0x95, +0xE6, 0x95, 0xDE, 0x54, 0xE6, 0x74, 0xDE, 0x54, +0xDE, 0x13, 0xDE, 0x33, 0xD5, 0xF2, 0xDE, 0x33, +0xDE, 0x13, 0xD5, 0xD2, 0xE6, 0x74, 0xE6, 0x53, +0xE6, 0x95, 0xAC, 0xCE, 0xCD, 0x92, 0xCD, 0x72, +0xB4, 0xEF, 0xAC, 0xCF, 0xB5, 0x30, 0xC5, 0x72, +0xD5, 0xD3, 0xC5, 0x71, 0xB4, 0xEF, 0xC5, 0x71, +0xC5, 0x71, 0xC5, 0x71, 0xC5, 0x71, 0xC5, 0x71, +0xC5, 0x91, 0xCD, 0x92, 0xCD, 0x91, 0xC5, 0x51, +0xCD, 0xB2, 0xD6, 0x14, 0xBD, 0x51, 0xBD, 0x31, +0xDE, 0x14, 0xAC, 0xAE, 0xCD, 0xB2, 0xEE, 0x95, +0xDE, 0x34, 0xDE, 0x34, 0xCD, 0xD3, 0xBD, 0x51, +0xCD, 0xB3, 0xD5, 0xF4, 0xCD, 0xD4, 0x94, 0x2D, +0x41, 0xE6, 0x42, 0x28, 0x52, 0x89, 0x63, 0x0C, +0x63, 0x2C, 0x73, 0xAF, 0x94, 0xB3, 0x73, 0x6E, +0x7B, 0xCF, 0x6B, 0x4D, 0x7B, 0xAE, 0x73, 0xAE, +0x9C, 0xB2, 0xEF, 0x1B, 0xBD, 0x54, 0x94, 0x0D, +0x9C, 0x0C, 0xA4, 0x4D, 0xA4, 0x4D, 0xA4, 0x6D, +0xAC, 0x8E, 0xAC, 0xAE, 0xB4, 0xCF, 0xB4, 0xEF, +0xB5, 0x31, 0x8C, 0x0E, 0x8C, 0x51, 0xA5, 0x14, +0xBD, 0xD7, 0xDE, 0xFC, 0xE7, 0x1C, 0xC6, 0x18, +0xBD, 0xB5, 0xBD, 0x74, 0xBD, 0x72, 0xB5, 0x72, +0xC5, 0xD4, 0xB5, 0x53, 0x6B, 0x4B, 0x4A, 0x48, +0xBD, 0xD4, 0xD6, 0x56, 0xCD, 0xF4, 0xB5, 0x32, +0x94, 0x4E, 0x8C, 0x2E, 0x8C, 0x2E, 0xB5, 0x31, +0xAC, 0xEF, 0xC5, 0xB3, 0xB5, 0x51, 0xB5, 0x51, +0xBD, 0x72, 0xC5, 0xD4, 0xBD, 0x93, 0xAD, 0x32, +0x63, 0x0A, 0x52, 0x88, 0x4A, 0x68, 0x52, 0x69, +0x63, 0x0B, 0x6B, 0x2B, 0x63, 0x0B, 0x42, 0x07, +0x52, 0x68, 0x83, 0xAE, 0xAD, 0x14, 0x9C, 0x72, +0xDE, 0x59, 0xEE, 0xDB, 0xA4, 0x92, 0x8B, 0xEF, +0x9C, 0xB2, 0xAD, 0x55, 0xAD, 0x54, 0xC5, 0xF7, +0xC5, 0xF7, 0x5A, 0xCB, 0x39, 0xE7, 0x39, 0xE7, +0x41, 0xE7, 0x4A, 0x48, 0x63, 0x2C, 0x5A, 0xCA, +0x4A, 0x69, 0x52, 0x89, 0x52, 0xCA, 0x63, 0x2C, +0x73, 0x6E, 0x73, 0xAF, 0x8C, 0x72, 0xAD, 0x55, +0xBD, 0xD7, 0xCE, 0x38, 0x94, 0x70, 0x9C, 0xB1, +0xCE, 0x36, 0xCE, 0x15, 0xC5, 0xF5, 0xC5, 0xF5, +0xCE, 0x15, 0xCE, 0x15, 0xCD, 0xF5, 0xC5, 0xD4, +0xC5, 0xD4, 0xC5, 0xD4, 0xC5, 0xD4, 0xBD, 0x93, +0xAD, 0x32, 0xC5, 0xD4, 0xC5, 0xF5, 0xC5, 0xD4, +0xCE, 0x15, 0xA4, 0xD0, 0xAD, 0x11, 0xBD, 0xB3, +0xB5, 0x72, 0x9C, 0xAF, 0x9C, 0x8F, 0x94, 0x6E, +0xA4, 0xCF, 0xAC, 0xCF, 0xAC, 0xEF, 0xC5, 0x70, +0xC5, 0x91, 0xAC, 0xF0, 0xB5, 0x52, 0x9C, 0xAF, +0x9C, 0xAF, 0xAD, 0x11, 0xAC, 0xF0, 0xAD, 0x11, +0xAD, 0x11, 0xAC, 0xF1, 0x9C, 0xAF, 0x9C, 0xAF, +0xA4, 0xF0, 0x9C, 0xAF, 0xA4, 0xB0, 0xA4, 0xB0, +0xA4, 0xD0, 0xB5, 0x52, 0xBD, 0x73, 0xB5, 0x31, +0xAD, 0x10, 0xB5, 0x31, 0xAC, 0xF0, 0xC5, 0x92, +0xD6, 0x14, 0x9C, 0x8F, 0xA4, 0xB0, 0xAD, 0x11, +0xB5, 0x52, 0xB5, 0x32, 0xA4, 0xB0, 0xAD, 0x11, +0xBD, 0x93, 0xAD, 0x12, 0xBD, 0x93, 0xC5, 0xB4, +0xB5, 0x52, 0xAC, 0xF1, 0xA4, 0xF1, 0x8C, 0x0E, +0x9C, 0x90, 0xAC, 0xF1, 0xAC, 0xD1, 0xAC, 0xF1, +0xAD, 0x11, 0xAD, 0x32, 0xAD, 0x12, 0xAD, 0x12, +0xAD, 0x12, 0xAD, 0x12, 0xB5, 0x33, 0xB5, 0x33, +0xAD, 0x32, 0xA4, 0xD2, 0x9C, 0xD2, 0xB5, 0x54, +0x41, 0xC7, 0x52, 0x69, 0x52, 0x89, 0x52, 0x69, +0x73, 0x8D, 0x73, 0x8E, 0x84, 0x10, 0xAD, 0x34, +0xA5, 0x14, 0xB5, 0x76, 0xDE, 0xDB, 0xE7, 0x3C, +0xE7, 0x1C, 0xE6, 0xFC, 0xC5, 0xD6, 0xB5, 0x53, +0xCD, 0xF5, 0xBD, 0x93, 0xBD, 0x73, 0xBD, 0x52, +0xBD, 0x52, 0xC5, 0x93, 0xCD, 0xF4, 0xCE, 0x35, +0x9D, 0x0F, 0x8D, 0x50, 0x9D, 0x91, 0x73, 0xEC, +0x39, 0xE6, 0x42, 0x48, 0x52, 0xCA, 0x42, 0x07, +0x52, 0xCA, 0x4A, 0xA9, 0x42, 0x88, 0x53, 0x88, +0x85, 0x0D, 0x4B, 0x27, 0x29, 0x82, 0x4A, 0xC5, +0x6C, 0x49, 0x4B, 0x67, 0x4B, 0x47, 0x32, 0xA4, +0x32, 0xA4, 0x2A, 0x42, 0x2A, 0x62, 0x3A, 0xE4, +0x43, 0x45, 0x6C, 0x6A, 0x74, 0xCB, 0x6C, 0x49, +0x4B, 0x65, 0x3A, 0xE3, 0x4B, 0x05, 0x63, 0x88, +0x6B, 0x09, 0x7B, 0x2B, 0x7B, 0x4C, 0x73, 0x0C, +0x6B, 0x4B, 0x7B, 0xCD, 0x7B, 0xED, 0xA4, 0xF1, +0xAD, 0x52, 0xAD, 0x32, 0xAD, 0x51, 0xB5, 0x72, +0xAD, 0x11, 0xAD, 0x52, 0xAD, 0x73, 0xAD, 0x52, +0xAD, 0x32, 0xBD, 0xD4, 0xAD, 0x31, 0xAD, 0x31, +0xCD, 0xF3, 0xCD, 0xD3, 0xBD, 0x72, 0xAD, 0x11, +0xCE, 0x14, 0xA4, 0x8E, 0xBD, 0x50, 0xE6, 0x74, +0xDE, 0x13, 0xE6, 0x74, 0xDE, 0x54, 0xE6, 0x54, +0xDE, 0x54, 0xE6, 0x75, 0xD6, 0x13, 0xE6, 0x75, +0xE6, 0xB6, 0xE6, 0x75, 0xDE, 0x33, 0xDE, 0x33, +0xDE, 0x33, 0xCD, 0xB1, 0xD5, 0xD1, 0xE6, 0x74, +0xEE, 0x95, 0xE6, 0x74, 0xDE, 0x13, 0xD5, 0xF2, +0xDE, 0x13, 0xB4, 0xCE, 0xBD, 0x30, 0xE6, 0x55, +0xCD, 0xB3, 0xC5, 0x52, 0xC5, 0x71, 0xBD, 0x51, +0xBD, 0x31, 0xB4, 0xEF, 0xBD, 0x10, 0xBD, 0x10, +0xBD, 0x30, 0xC5, 0x71, 0xC5, 0x71, 0xBD, 0x30, +0xBD, 0x10, 0xC5, 0x71, 0xBD, 0x30, 0xAC, 0xCF, +0xB4, 0xEF, 0xC5, 0x71, 0xE6, 0x95, 0xE6, 0x55, +0xE6, 0x75, 0xB4, 0xCF, 0xB4, 0xEF, 0xCD, 0xB2, +0xEE, 0x95, 0xCD, 0xB2, 0xBD, 0x51, 0xCD, 0xB3, +0xD5, 0xF4, 0xD5, 0xF4, 0xD6, 0x14, 0xDE, 0x34, +0xB5, 0x10, 0x5A, 0xA8, 0x4A, 0x48, 0x4A, 0x48, +0x42, 0x28, 0x4A, 0x69, 0x52, 0x8A, 0x42, 0x07, +0x4A, 0x69, 0x39, 0xC7, 0x52, 0x8A, 0x73, 0x8E, +0xAD, 0x55, 0xDE, 0xBA, 0xE6, 0xFB, 0xD6, 0x78, +0xBD, 0x74, 0xA4, 0x8F, 0xA4, 0x6E, 0x93, 0xEC, +0x9C, 0x4D, 0xA4, 0x6E, 0xA4, 0x8E, 0xA4, 0xAF, +0xB4, 0xF0, 0xAC, 0xF1, 0x83, 0xCE, 0x94, 0xB3, +0xCE, 0x59, 0xC6, 0x38, 0xE7, 0x1D, 0xE7, 0x3D, +0xC5, 0xD7, 0x8C, 0x0E, 0x94, 0x2D, 0x9C, 0x4D, +0x9C, 0x6E, 0xA5, 0x11, 0x52, 0x68, 0x73, 0x4B, +0xAC, 0xF0, 0xA4, 0x8E, 0xA4, 0xAF, 0xA4, 0xAF, +0x9C, 0x6F, 0x94, 0x4E, 0x83, 0xCB, 0xA4, 0x8E, +0xA4, 0x6D, 0x94, 0x2D, 0x9C, 0x4E, 0x9C, 0x6E, +0xAC, 0xF0, 0xBD, 0x93, 0xAD, 0x11, 0xA4, 0xCF, +0x8C, 0x2D, 0x8C, 0x2E, 0x52, 0x88, 0x4A, 0x27, +0x52, 0x69, 0x63, 0x0A, 0x73, 0x6C, 0x62, 0xCA, +0x4A, 0x07, 0x5A, 0x69, 0x83, 0x8E, 0x8C, 0x10, +0xA4, 0xF3, 0xA4, 0xD2, 0x83, 0xAF, 0x9C, 0x92, +0xAC, 0xF3, 0x83, 0xCF, 0x9C, 0xD3, 0xF7, 0x7D, +0xEF, 0x1B, 0x9C, 0xB3, 0x41, 0xE7, 0x42, 0x07, +0x39, 0xE7, 0x52, 0x89, 0x42, 0x27, 0x39, 0xA6, +0x39, 0xC6, 0x4A, 0x69, 0x5A, 0xCA, 0x62, 0xEB, +0x6B, 0x4D, 0x6B, 0x6D, 0x8C, 0x72, 0xA5, 0x35, +0xB5, 0x96, 0xCE, 0x79, 0xC5, 0xF6, 0xA4, 0xD1, +0xD6, 0x36, 0xCD, 0xF5, 0xC5, 0xD4, 0xCE, 0x14, +0xCE, 0x35, 0xCE, 0x15, 0xCE, 0x15, 0xCD, 0xF4, +0xC5, 0xD4, 0xC5, 0xD4, 0xBD, 0xB3, 0xBD, 0x73, +0xC5, 0xF5, 0xC5, 0xD4, 0xCD, 0xF4, 0xC5, 0xF4, +0xCE, 0x36, 0xA4, 0xF1, 0xB5, 0x73, 0xC5, 0xD3, +0xB5, 0x72, 0xBD, 0xB3, 0xAD, 0x11, 0xAD, 0x51, +0xAD, 0x31, 0xB5, 0x30, 0xB5, 0x50, 0xBD, 0x50, +0xCD, 0xB2, 0xA4, 0xAF, 0xAD, 0x11, 0x9C, 0xAF, +0x9C, 0xAF, 0xA4, 0xCF, 0xA4, 0xD0, 0xAD, 0x11, +0xB5, 0x72, 0xB5, 0x52, 0xAD, 0x11, 0xAD, 0x11, +0xB5, 0x73, 0xB5, 0x32, 0xB5, 0x32, 0xAD, 0x11, +0xA4, 0xD0, 0x9C, 0x8F, 0x8B, 0xED, 0xA4, 0xAF, +0xB5, 0x52, 0xB5, 0x31, 0xB5, 0x30, 0xCD, 0xB2, +0xCD, 0xD3, 0xB5, 0x12, 0xAD, 0x12, 0xC5, 0xD4, +0xCE, 0x15, 0xBD, 0xB4, 0xAD, 0x52, 0xBD, 0x93, +0xE6, 0xB7, 0xE6, 0xD7, 0xCE, 0x14, 0xE6, 0xB7, +0xE6, 0xB7, 0xD6, 0x56, 0xB5, 0x72, 0x8B, 0xED, +0xA4, 0x90, 0xBD, 0x93, 0xBD, 0x93, 0xC5, 0xF5, +0xBD, 0xB3, 0xBD, 0x93, 0xB5, 0x72, 0xBD, 0x93, +0xB5, 0x52, 0x8C, 0x0E, 0x9C, 0x70, 0xCE, 0x36, +0xC5, 0xF5, 0xC5, 0xD5, 0xB5, 0x94, 0x8C, 0x30, +0x84, 0x10, 0x9C, 0xD2, 0xA4, 0xD2, 0x9C, 0xB1, +0xB5, 0x53, 0x52, 0xA9, 0x4A, 0x28, 0x73, 0x8E, +0x5A, 0xCB, 0x73, 0xAF, 0x8C, 0x72, 0x8C, 0x52, +0x94, 0x93, 0xD6, 0xBB, 0xE6, 0xFB, 0xB5, 0x75, +0xB5, 0x75, 0xA4, 0xD2, 0xB5, 0x53, 0xAC, 0xF2, +0xA4, 0xB1, 0x9C, 0x70, 0x9C, 0x70, 0x9C, 0x90, +0xA5, 0x31, 0x9D, 0x92, 0x8C, 0xD0, 0x7B, 0xEE, +0x63, 0x2C, 0x5B, 0x0B, 0x52, 0xA9, 0x39, 0xE6, +0x31, 0x85, 0x31, 0xA5, 0x31, 0xC5, 0x53, 0x48, +0x85, 0x0D, 0x32, 0x44, 0x3A, 0x65, 0x63, 0xC9, +0x6C, 0x6A, 0x6C, 0x69, 0x64, 0x29, 0x5B, 0xE8, +0x43, 0x05, 0x4B, 0x67, 0x2A, 0x83, 0x43, 0x25, +0x53, 0xE7, 0x5C, 0x08, 0x4B, 0x65, 0x32, 0xC3, +0x32, 0xA2, 0x3A, 0xA3, 0x3A, 0xC4, 0x53, 0x66, +0x8C, 0x8D, 0x94, 0x6F, 0xAD, 0x34, 0xCE, 0x18, +0x83, 0xEE, 0x84, 0x0E, 0x84, 0x0E, 0x9C, 0xB0, +0xAD, 0x52, 0xAD, 0x52, 0xAD, 0x51, 0xAD, 0x52, +0xAD, 0x31, 0xAD, 0x52, 0xB5, 0x93, 0xAD, 0x52, +0xAD, 0x52, 0xC5, 0xF5, 0xA5, 0x11, 0xB5, 0x72, +0xC5, 0xD4, 0xCE, 0x14, 0xC5, 0xD3, 0xB5, 0x51, +0xBD, 0x92, 0xA4, 0x8D, 0xBD, 0x50, 0xE6, 0x95, +0xBD, 0x2F, 0xC5, 0x71, 0xDE, 0x34, 0xDE, 0x33, +0xD6, 0x33, 0xE6, 0x75, 0xE6, 0x95, 0xE6, 0x95, +0xE6, 0x95, 0xDE, 0x54, 0xDE, 0x13, 0xDE, 0x33, +0xDE, 0x53, 0xE6, 0x74, 0xC5, 0x91, 0xE6, 0x54, +0xE6, 0x95, 0xDE, 0x53, 0xD6, 0x12, 0xDE, 0x33, +0xE6, 0x74, 0xB4, 0xEE, 0xD6, 0x14, 0xD5, 0xF4, +0xCD, 0x92, 0xC5, 0x92, 0xC5, 0x51, 0xBD, 0x31, +0xB5, 0x10, 0x9C, 0x4D, 0xBD, 0x51, 0xBD, 0x31, +0xBD, 0x31, 0xBD, 0x10, 0xB5, 0x10, 0xAC, 0xCF, +0xAC, 0xCF, 0xB4, 0xF0, 0xB4, 0xEF, 0xB4, 0xCF, +0xBD, 0x30, 0xCD, 0xD3, 0xDE, 0x55, 0xE6, 0x75, +0xE6, 0x75, 0xAC, 0xCE, 0xBD, 0x30, 0xD5, 0xF3, +0xEE, 0xF7, 0xDE, 0x34, 0xCD, 0xB2, 0xCD, 0xD3, +0xD5, 0xF3, 0xD6, 0x14, 0xDE, 0x34, 0xDE, 0x34, +0xEE, 0xB6, 0xCD, 0xF4, 0x62, 0xE9, 0x31, 0x85, +0x31, 0x86, 0x39, 0xC7, 0x42, 0x07, 0x42, 0x28, +0x52, 0x69, 0x63, 0x2C, 0x73, 0xAE, 0x94, 0x71, +0x9C, 0xB3, 0xCE, 0x39, 0xCE, 0x59, 0xDE, 0xFB, +0xEF, 0x3C, 0xD6, 0x58, 0x94, 0x70, 0x8C, 0x30, +0x8C, 0x2F, 0x7B, 0x8C, 0x5A, 0xC9, 0x5A, 0xA8, +0x6B, 0x0A, 0x73, 0x4B, 0x5A, 0xA9, 0x84, 0x30, +0xCE, 0x7A, 0xD6, 0x7A, 0xD6, 0x9B, 0xDE, 0xFC, +0xE6, 0xFC, 0x7B, 0xAE, 0x7B, 0x8C, 0x94, 0x0D, +0x94, 0x2E, 0x8C, 0x4F, 0x39, 0xA5, 0x73, 0x8C, +0x94, 0x4D, 0x9C, 0x4D, 0xA4, 0x8E, 0xAC, 0xCF, +0xB4, 0xF0, 0xB4, 0xF0, 0xB4, 0xF0, 0xAC, 0xEF, +0xAC, 0xCF, 0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0xAF, +0x9C, 0x8E, 0x94, 0x4D, 0x9C, 0x4E, 0xA4, 0xAF, +0xA4, 0xCF, 0xA4, 0x8F, 0x94, 0x2D, 0x6B, 0x0A, +0x4A, 0x06, 0x62, 0xEA, 0x5A, 0xCA, 0x63, 0x0B, +0x4A, 0x28, 0x39, 0x85, 0x5A, 0xAA, 0x83, 0xEF, +0x94, 0x71, 0x73, 0x4D, 0x6B, 0x0C, 0x8C, 0x10, +0x8C, 0x10, 0x8B, 0xF0, 0x7B, 0xAE, 0x94, 0x92, +0xE6, 0xFB, 0xE7, 0x1B, 0x7B, 0xCF, 0x31, 0xA6, +0x39, 0xE7, 0x42, 0x28, 0x39, 0xE7, 0x42, 0x07, +0x41, 0xE7, 0x42, 0x28, 0x52, 0xAA, 0x5A, 0xCA, +0x6B, 0x4D, 0x84, 0x10, 0x84, 0x31, 0x9C, 0xD3, +0xAD, 0x56, 0xBD, 0xF8, 0xC5, 0xF7, 0xA4, 0xF2, +0xB5, 0x73, 0xC5, 0xB4, 0xB5, 0x72, 0xBD, 0x93, +0xBD, 0xB3, 0xBD, 0x93, 0xB5, 0x73, 0xBD, 0x93, +0xB5, 0x52, 0xB5, 0x73, 0xBD, 0x93, 0xB5, 0x73, +0xBD, 0xB3, 0xC5, 0xD4, 0xCE, 0x35, 0xC6, 0x14, +0xC5, 0xF5, 0xA4, 0xD1, 0xBD, 0x93, 0xCE, 0x15, +0xB5, 0x51, 0x9C, 0xAF, 0x7B, 0xAB, 0xAD, 0x31, +0xBD, 0x92, 0xC5, 0xD3, 0xCD, 0xF3, 0xD6, 0x12, +0xDE, 0x54, 0x9C, 0x8F, 0xA4, 0xD0, 0x9C, 0xB0, +0xAD, 0x11, 0xAD, 0x31, 0xA4, 0xF0, 0xAD, 0x11, +0xB5, 0x52, 0xB5, 0x73, 0xB5, 0x73, 0xBD, 0x73, +0xB5, 0x52, 0xBD, 0x73, 0xBD, 0x93, 0xB5, 0x52, +0xAD, 0x52, 0xB5, 0x52, 0x94, 0x6F, 0xA4, 0xB0, +0xB5, 0x32, 0xBD, 0x72, 0xBD, 0x71, 0xBD, 0x71, +0xCD, 0xB2, 0xB5, 0x32, 0xB5, 0x53, 0xD6, 0x76, +0xD6, 0x55, 0xC5, 0xF4, 0xBD, 0x93, 0xC5, 0xF5, +0xDE, 0x96, 0xCE, 0x14, 0xB5, 0x31, 0xC5, 0x92, +0xD5, 0xF3, 0xD6, 0x35, 0xA4, 0xD0, 0x9C, 0xB0, +0x9C, 0x90, 0xCE, 0x36, 0xD6, 0x76, 0xCE, 0x35, +0xCE, 0x14, 0xCD, 0xF3, 0xCE, 0x14, 0xCE, 0x14, +0xD6, 0x35, 0x94, 0x6F, 0xB5, 0x73, 0xB5, 0x74, +0xAD, 0x53, 0xBD, 0xB4, 0xCE, 0x57, 0xC6, 0x15, +0xB5, 0x94, 0x94, 0x90, 0x8C, 0x2F, 0x9C, 0x90, +0xBD, 0xB4, 0xB5, 0x94, 0xBD, 0xB4, 0xBD, 0xB5, +0xAD, 0x54, 0x8C, 0x50, 0x52, 0xAA, 0x42, 0x09, +0x4A, 0x4B, 0xAD, 0x56, 0xDE, 0xBB, 0xCE, 0x18, +0xBD, 0x96, 0xC5, 0xD6, 0xB5, 0x54, 0xA4, 0xD1, +0xAD, 0x12, 0xA5, 0x12, 0xAD, 0x12, 0xAD, 0x12, +0x9C, 0xD1, 0x84, 0x2E, 0x6B, 0x6C, 0x4A, 0x89, +0x41, 0xE7, 0x31, 0x85, 0x29, 0x85, 0x21, 0x24, +0x21, 0x44, 0x21, 0x44, 0x32, 0x06, 0x5B, 0x89, +0x64, 0x2A, 0x64, 0x2A, 0x95, 0x6F, 0x7C, 0xCC, +0x4B, 0x67, 0x6C, 0x6A, 0x7C, 0xCB, 0x6C, 0x6A, +0x4B, 0x87, 0x64, 0x2A, 0x3A, 0xC5, 0x32, 0x84, +0x3A, 0xE5, 0x43, 0x25, 0x4B, 0x86, 0x3A, 0xE4, +0x43, 0x25, 0x63, 0xA8, 0x53, 0x27, 0x42, 0xA4, +0x5B, 0x88, 0x6B, 0x4A, 0x9C, 0xD2, 0x8C, 0x71, +0x7B, 0xAD, 0x7B, 0xAD, 0x6B, 0x2B, 0x63, 0x2A, +0x94, 0x6E, 0x9C, 0xD0, 0x8C, 0x4E, 0x94, 0x8F, +0xA4, 0xD0, 0xAD, 0x32, 0xB5, 0x73, 0xB5, 0x73, +0xB5, 0x73, 0xBD, 0xB4, 0xAD, 0x32, 0xBD, 0xD4, +0xC5, 0xD3, 0xC5, 0xD3, 0xAD, 0x30, 0x9C, 0x8E, +0x9C, 0x6E, 0xA4, 0xAE, 0xBD, 0x50, 0xEE, 0xB5, +0xE6, 0x95, 0xE6, 0x95, 0xE6, 0x75, 0xD5, 0xF2, +0xDE, 0x54, 0xDE, 0x74, 0xE6, 0x75, 0xE6, 0xB6, +0xE6, 0x95, 0xDE, 0x54, 0xDE, 0x33, 0xD5, 0xD2, +0xCD, 0x91, 0xCD, 0xB1, 0xC5, 0x70, 0xD5, 0xD2, +0xDE, 0x33, 0xDE, 0x13, 0xCD, 0xB1, 0xD5, 0xD2, +0xB4, 0xCE, 0xA4, 0x4C, 0xDE, 0x14, 0xD5, 0xD3, +0xCD, 0x92, 0xD5, 0xF4, 0xD5, 0xF4, 0xCD, 0xB3, +0xD5, 0xF4, 0xC5, 0x93, 0xCD, 0xB3, 0xD5, 0xF4, +0xCD, 0xD3, 0xC5, 0x92, 0xC5, 0x52, 0xC5, 0x72, +0xC5, 0x52, 0xBD, 0x51, 0xC5, 0x72, 0xCD, 0x93, +0xC5, 0x72, 0xC5, 0x72, 0xCD, 0xD3, 0xE6, 0x96, +0xDE, 0x14, 0xA4, 0x8D, 0xDE, 0x13, 0xE6, 0x54, +0xEE, 0xB6, 0xEE, 0xB6, 0xEE, 0xB6, 0xEE, 0x96, +0xE6, 0x95, 0xEE, 0x95, 0xEE, 0x95, 0xDE, 0x54, +0xE6, 0x75, 0xF6, 0xD7, 0xEE, 0xB7, 0xB5, 0x31, +0x5A, 0x88, 0x39, 0xC6, 0x39, 0xC6, 0x31, 0xA6, +0x39, 0xE7, 0x52, 0xAA, 0x5A, 0xEB, 0x7B, 0xCF, +0x8C, 0x72, 0x9C, 0xD3, 0xA5, 0x14, 0xC6, 0x39, +0xAD, 0x55, 0xD6, 0x9A, 0xE7, 0x3C, 0xD6, 0x9A, +0xC6, 0x17, 0xB5, 0x74, 0x94, 0xB1, 0x84, 0x0F, +0x84, 0x0E, 0x84, 0x2F, 0x73, 0x8D, 0x73, 0xAE, +0xA5, 0x35, 0xCE, 0x7A, 0xD6, 0xBB, 0xE7, 0x1D, +0xDE, 0xFC, 0xB5, 0x76, 0x83, 0xEF, 0x73, 0x8D, +0x94, 0x70, 0x73, 0x6C, 0x39, 0xC6, 0x8C, 0x2F, +0x8C, 0x2E, 0x83, 0xEE, 0x8C, 0x0E, 0x83, 0xCC, +0x83, 0xAC, 0x83, 0xAB, 0x7B, 0x8B, 0x7B, 0x8B, +0x7B, 0x8B, 0x83, 0xCC, 0x94, 0x2E, 0xA4, 0xCF, +0x8C, 0x0C, 0xA4, 0x6E, 0xA4, 0x8E, 0xA4, 0xAF, +0xA4, 0xAF, 0xAC, 0xAF, 0xAC, 0xEF, 0xB5, 0x10, +0x94, 0x2E, 0x5A, 0xA8, 0x52, 0x68, 0x52, 0x69, +0x42, 0x07, 0x4A, 0x48, 0x6B, 0x2C, 0x5A, 0xAA, +0x52, 0x49, 0x52, 0x69, 0x62, 0xCB, 0x83, 0xAE, +0xA4, 0xD2, 0x9C, 0x92, 0x9C, 0xB2, 0x83, 0xCF, +0x94, 0x92, 0xCE, 0x57, 0x83, 0xEF, 0x5A, 0xCA, +0x39, 0xE7, 0x31, 0xA6, 0x31, 0xA6, 0x39, 0xE6, +0x39, 0xE7, 0x42, 0x27, 0x52, 0x89, 0x63, 0x0B, +0x63, 0x0C, 0x6B, 0x6D, 0x73, 0xAF, 0x8C, 0x92, +0xA5, 0x35, 0xAD, 0x56, 0xA5, 0x14, 0xB5, 0x75, +0xB5, 0x94, 0xA4, 0xD1, 0xAD, 0x32, 0xB5, 0x53, +0x9C, 0x90, 0xB5, 0x73, 0xAD, 0x11, 0xA4, 0xF1, +0x9C, 0x90, 0x9C, 0xB0, 0xA4, 0xF1, 0xAD, 0x11, +0xB5, 0x52, 0xBD, 0x93, 0xC5, 0xF4, 0xCE, 0x35, +0xC5, 0xB4, 0xAC, 0xF1, 0xBD, 0xB3, 0xC5, 0xF3, +0xB5, 0x92, 0x94, 0x4E, 0x94, 0x6E, 0xAD, 0x31, +0xB5, 0x92, 0xBD, 0xB2, 0xBD, 0x71, 0xBD, 0x70, +0xD6, 0x13, 0xA4, 0xD0, 0xAD, 0x11, 0xA4, 0xF0, +0xAD, 0x32, 0xA4, 0xF1, 0xB5, 0x72, 0xBD, 0xB4, +0xBD, 0xB3, 0xC5, 0xD4, 0xC5, 0xD4, 0xC5, 0xD4, +0xBD, 0xB3, 0xBD, 0x93, 0xBD, 0x93, 0xBD, 0xB3, +0xC5, 0xD4, 0xC5, 0xD4, 0xBD, 0x93, 0xC5, 0xF5, +0xBD, 0x93, 0xB5, 0x52, 0xB5, 0x51, 0xBD, 0x51, +0xC5, 0x92, 0xB5, 0x31, 0xBD, 0x93, 0xC5, 0xF4, +0xCE, 0x14, 0xC5, 0xD4, 0xB5, 0x93, 0xCE, 0x15, +0xC5, 0xD4, 0xB5, 0x31, 0xDE, 0x35, 0xC5, 0x71, +0xCD, 0x92, 0xCD, 0xD3, 0xB5, 0x52, 0xB5, 0x53, +0xBD, 0xB4, 0xC5, 0xF4, 0xC5, 0xD3, 0xBD, 0xB3, +0xCD, 0xF4, 0xCD, 0xF3, 0xD6, 0x14, 0xD6, 0x14, +0xCD, 0xF4, 0x9C, 0xB0, 0xA5, 0x12, 0xA4, 0xF1, +0xB5, 0x53, 0xBD, 0xB4, 0xC6, 0x15, 0xC5, 0xD4, +0xC5, 0xF5, 0xAD, 0x53, 0xA4, 0xD1, 0xB5, 0x74, +0xBD, 0xD5, 0xBD, 0xF5, 0xCE, 0x56, 0xCE, 0x36, +0xBD, 0xD5, 0x94, 0x70, 0x6B, 0x4C, 0x39, 0xC7, +0x4A, 0x4A, 0xB5, 0x76, 0xAD, 0x55, 0xBD, 0x96, +0xC6, 0x18, 0xAD, 0x54, 0xB5, 0x54, 0xBD, 0xB5, +0xC5, 0xF6, 0xAD, 0x53, 0x8C, 0x50, 0x6B, 0x4C, +0x63, 0x0B, 0x7B, 0xAD, 0x73, 0x6D, 0x42, 0x08, +0x42, 0x28, 0x39, 0xC6, 0x39, 0xE7, 0x29, 0x64, +0x21, 0x44, 0x21, 0x44, 0x53, 0x49, 0x6C, 0x6B, +0x74, 0xCB, 0x85, 0x2E, 0x95, 0xB0, 0x6C, 0x6B, +0x21, 0xE3, 0x21, 0xC3, 0x4B, 0x47, 0x53, 0x87, +0x43, 0x26, 0x43, 0x26, 0x3A, 0xE6, 0x19, 0xC3, +0x21, 0xE3, 0x3A, 0xE5, 0x64, 0x2A, 0x53, 0xE8, +0x5C, 0x09, 0x6C, 0x2A, 0x5B, 0x68, 0x42, 0x85, +0x53, 0x06, 0x5B, 0xA8, 0x5B, 0x88, 0x4B, 0x08, +0x7B, 0xCD, 0x8C, 0x0E, 0x8C, 0x2F, 0x8C, 0x0E, +0x8C, 0x0D, 0x8C, 0x0E, 0x94, 0x2E, 0x94, 0x4E, +0x94, 0x4E, 0x94, 0x4E, 0x8C, 0x2D, 0x84, 0x0D, +0x83, 0xED, 0x84, 0x0D, 0x8C, 0x2E, 0x9C, 0x8F, +0x94, 0x6E, 0x94, 0x2D, 0x8C, 0x0C, 0x8B, 0xEC, +0x9C, 0x6E, 0xA4, 0x8E, 0xA4, 0x8D, 0xDE, 0x33, +0xE6, 0x95, 0xE6, 0x95, 0xE6, 0x75, 0xE6, 0x75, +0xEE, 0xB6, 0xE6, 0xB5, 0xE6, 0xB6, 0xE6, 0xB6, +0xEE, 0xD6, 0xEE, 0xB6, 0xE6, 0x95, 0xE6, 0x74, +0xD6, 0x13, 0xC5, 0x91, 0xCD, 0xD2, 0xD6, 0x13, +0xEE, 0xB6, 0xD5, 0xF3, 0xC5, 0x71, 0xC5, 0x71, +0xBD, 0x0F, 0xA4, 0x6D, 0xCD, 0xB2, 0xCD, 0xB2, +0xCD, 0xB2, 0xDE, 0x14, 0xD5, 0xF4, 0xD6, 0x14, +0xC5, 0x92, 0xC5, 0x93, 0xAC, 0xD0, 0xD5, 0xF4, +0xCD, 0xD4, 0xCD, 0xD3, 0xCD, 0xB3, 0xCD, 0xB3, +0xCD, 0xB3, 0xCD, 0x93, 0xC5, 0x92, 0xCD, 0xB3, +0xCD, 0xB3, 0xD5, 0xD3, 0xCD, 0xB2, 0xDE, 0x14, +0xD5, 0xF3, 0xA4, 0x8D, 0xDE, 0x34, 0xE6, 0x75, +0xEE, 0xB6, 0xEE, 0x96, 0xEE, 0x95, 0xE6, 0x75, +0xE6, 0x75, 0xE6, 0x75, 0xE6, 0x75, 0xE6, 0x95, +0xE6, 0x75, 0xE6, 0x95, 0xEE, 0xD6, 0xEE, 0xD6, +0xE6, 0x75, 0x9C, 0x6E, 0x4A, 0x07, 0x39, 0xA6, +0x39, 0xE7, 0x42, 0x07, 0x42, 0x07, 0x5A, 0xCB, +0x63, 0x2D, 0x7B, 0xF0, 0x8C, 0x72, 0xAD, 0x55, +0xC6, 0x19, 0xAD, 0x56, 0xCE, 0x7A, 0xE7, 0x1C, +0xEF, 0x3C, 0xCE, 0x38, 0x9C, 0xD2, 0x8C, 0x50, +0x9C, 0xD1, 0xA5, 0x12, 0xA5, 0x12, 0x9C, 0xD1, +0x73, 0xAE, 0xAD, 0x76, 0xC6, 0x3A, 0xEF, 0x5E, +0xF7, 0x9E, 0xE7, 0x3D, 0xB5, 0x75, 0xAD, 0x33, +0xA4, 0xF2, 0x4A, 0x48, 0x73, 0x8D, 0xBD, 0xD5, +0xBD, 0xB4, 0xB5, 0x74, 0xAD, 0x53, 0xA4, 0xF1, +0xAD, 0x32, 0xB5, 0x53, 0xAD, 0x32, 0xA4, 0xF1, +0xB5, 0x53, 0xBD, 0xB4, 0xB5, 0x53, 0xAD, 0x31, +0x9C, 0x8F, 0x9C, 0x6E, 0x8C, 0x0C, 0x94, 0x4E, +0x94, 0x2E, 0x9C, 0x8F, 0xA4, 0xD0, 0xA4, 0xCF, +0xC5, 0xD4, 0xBD, 0x92, 0x63, 0x0A, 0x4A, 0x27, +0x4A, 0x27, 0x5A, 0xAA, 0x63, 0x0B, 0x5A, 0xCA, +0x52, 0x89, 0x52, 0x49, 0x6B, 0x2C, 0x7B, 0x8E, +0x83, 0xCF, 0x73, 0x4D, 0x94, 0x51, 0xBD, 0x95, +0x94, 0x71, 0x62, 0xEB, 0xB5, 0x96, 0x9C, 0xB2, +0x4A, 0x28, 0x42, 0x28, 0x3A, 0x07, 0x31, 0xA5, +0x39, 0xC6, 0x39, 0xE7, 0x42, 0x28, 0x4A, 0x49, +0x4A, 0x49, 0x63, 0x0C, 0x73, 0xAF, 0x84, 0x51, +0x9D, 0x15, 0xB5, 0x96, 0xAD, 0x76, 0xC5, 0xF7, +0xCE, 0x78, 0xAD, 0x55, 0x73, 0x8D, 0x9C, 0x91, +0x52, 0x68, 0x94, 0x70, 0x9C, 0x90, 0x9C, 0xB0, +0x9C, 0x90, 0x9C, 0x6F, 0xA4, 0xB1, 0xA4, 0xD1, +0xA4, 0xB0, 0xBD, 0xB4, 0xC5, 0xF4, 0xC5, 0xD4, +0xC5, 0xD4, 0xA4, 0xB0, 0xAD, 0x11, 0xC6, 0x14, +0xCE, 0x55, 0xC5, 0xF4, 0xCE, 0x35, 0xD6, 0x55, +0xD6, 0x55, 0xD6, 0x54, 0xD6, 0x13, 0xD6, 0x13, +0xDE, 0x74, 0xA4, 0xAF, 0xA4, 0xF1, 0xA4, 0xF0, +0xAD, 0x31, 0xB5, 0x52, 0xBD, 0x93, 0xB5, 0x72, +0xBD, 0xB3, 0xBD, 0xD4, 0xC5, 0xD4, 0xBD, 0xB4, +0xC5, 0xF5, 0xC5, 0xF4, 0xC5, 0xD4, 0xC5, 0xF5, +0xBD, 0x93, 0xB5, 0x32, 0xAD, 0x11, 0xC5, 0xF4, +0xB5, 0x52, 0xBD, 0x73, 0xBD, 0x72, 0xC5, 0x92, +0xC5, 0x92, 0xB5, 0x11, 0xB5, 0x52, 0xC5, 0xF4, +0xC5, 0xF4, 0xBD, 0x93, 0xB5, 0x73, 0xBD, 0x93, +0xB5, 0x72, 0xA4, 0xAF, 0xD6, 0x14, 0xD5, 0xB2, +0xCD, 0x72, 0xCD, 0xF3, 0xC5, 0xD4, 0xC5, 0xD4, +0xCE, 0x15, 0xC5, 0xD4, 0xC5, 0xB3, 0xCE, 0x14, +0xCE, 0x14, 0xCD, 0xF3, 0xD6, 0x34, 0xD6, 0x55, +0xC5, 0xB3, 0x9C, 0xB1, 0x9C, 0xD1, 0x94, 0x90, +0xA4, 0xF2, 0xB5, 0x53, 0xB5, 0x93, 0xB5, 0x93, +0xB5, 0x73, 0xB5, 0x73, 0xA5, 0x12, 0xC6, 0x15, +0xC5, 0xF5, 0xCE, 0x36, 0xDE, 0x97, 0xC5, 0xF5, +0x9C, 0xD1, 0x83, 0xEE, 0xC5, 0xD5, 0x7B, 0xCE, +0x42, 0x08, 0x9C, 0xB3, 0x9C, 0xD3, 0xBD, 0xD7, +0xB5, 0x75, 0xBD, 0x96, 0xA4, 0xF3, 0x7B, 0xEF, +0x63, 0x0C, 0x5A, 0xCB, 0x9C, 0xD1, 0xC5, 0xF5, +0xE6, 0xB8, 0xD6, 0x16, 0xAC, 0xF2, 0x94, 0x92, +0x73, 0xAE, 0x39, 0xE7, 0x42, 0x48, 0x42, 0x07, +0x31, 0xC6, 0x31, 0xA5, 0x74, 0x4C, 0x85, 0x0D, +0x95, 0xB0, 0xA6, 0x11, 0x9D, 0xD0, 0x5B, 0xC8, +0x32, 0x65, 0x2A, 0x04, 0x3A, 0xC5, 0x5B, 0xC8, +0x5B, 0xC8, 0x4B, 0x47, 0x4B, 0x67, 0x32, 0x85, +0x2A, 0x44, 0x32, 0x84, 0x5B, 0xE9, 0x5C, 0x09, +0x5C, 0x29, 0x64, 0x08, 0x64, 0x08, 0x7C, 0x6B, +0xC6, 0x33, 0x95, 0x0E, 0x5B, 0xA7, 0x5B, 0xC7, +0x73, 0x6B, 0x8C, 0x2E, 0x9C, 0x6F, 0x9C, 0x6F, +0xAD, 0x12, 0x9C, 0x6F, 0x94, 0x4E, 0x9C, 0x8F, +0x9C, 0x8F, 0xA4, 0xF1, 0xB5, 0x52, 0xBD, 0x73, +0xAC, 0xF1, 0xA4, 0xB0, 0xA4, 0xD0, 0xA4, 0xAF, +0xA4, 0xAF, 0xA4, 0xAE, 0xAC, 0xCF, 0xA4, 0xAE, +0xA4, 0x8E, 0xA4, 0x8E, 0xA4, 0x6D, 0x9C, 0x4C, +0x9C, 0x6D, 0xA4, 0xAE, 0xAC, 0xCE, 0xAC, 0xCF, +0xB4, 0xEF, 0xB5, 0x30, 0xBD, 0x50, 0xBD, 0x71, +0xC5, 0xB2, 0xCD, 0xD2, 0xD5, 0xF3, 0xD5, 0xF3, +0xD6, 0x14, 0xD6, 0x34, 0xD6, 0x34, 0xDE, 0x55, +0xE6, 0x96, 0xEE, 0xB6, 0xE6, 0x95, 0xC5, 0x51, +0xCD, 0xD2, 0xAC, 0xAE, 0xE6, 0x96, 0xCD, 0xD3, +0xDE, 0x35, 0xD5, 0xF4, 0xDE, 0x35, 0xD6, 0x14, +0x9C, 0x4D, 0xC5, 0x93, 0xCD, 0xD4, 0xD5, 0xF4, +0xCD, 0xD4, 0xD5, 0xF4, 0xD5, 0xD4, 0xD5, 0xD4, +0xD5, 0xD4, 0xD5, 0xD4, 0xD5, 0xF4, 0xD5, 0xF4, +0xD5, 0xF4, 0xDE, 0x14, 0xD5, 0xF4, 0xD5, 0xF3, +0xDE, 0x34, 0xA4, 0x6D, 0xDE, 0x54, 0xE6, 0x95, +0xEE, 0x95, 0xEE, 0x95, 0xEE, 0x95, 0xE6, 0x95, +0xDE, 0x13, 0xEE, 0x95, 0xE6, 0x95, 0xE6, 0x75, +0xE6, 0x75, 0xE6, 0x75, 0xEE, 0xB6, 0xDE, 0x33, +0xE6, 0x95, 0xF6, 0xD7, 0xCD, 0xD3, 0x7B, 0x6B, +0x41, 0xE6, 0x31, 0x85, 0x31, 0xA6, 0x42, 0x08, +0x5A, 0xCB, 0x5B, 0x0C, 0x73, 0x8E, 0x7B, 0xF0, +0x94, 0xB3, 0xB5, 0xB7, 0xCE, 0x5A, 0xCE, 0x7A, +0xDE, 0xDC, 0xEF, 0x5D, 0xE7, 0x1C, 0xAD, 0x75, +0x94, 0x91, 0x9C, 0xF2, 0xB5, 0x53, 0xB5, 0x74, +0x7B, 0xEE, 0x84, 0x51, 0xC6, 0x39, 0xDE, 0xDC, +0xBE, 0x18, 0xC6, 0x19, 0xCE, 0x59, 0xAD, 0x54, +0x94, 0x70, 0x39, 0xC6, 0x94, 0x90, 0xA5, 0x12, +0xAD, 0x52, 0xB5, 0x73, 0xB5, 0x73, 0xAD, 0x52, +0xA5, 0x11, 0xB5, 0x73, 0xBD, 0xB4, 0xBD, 0x93, +0xB5, 0x94, 0xAD, 0x73, 0xAD, 0x32, 0xA4, 0xF1, +0xAD, 0x32, 0xA4, 0xAF, 0x7B, 0x6B, 0x6B, 0x6C, +0x73, 0x6C, 0x73, 0x8D, 0x83, 0xEE, 0x7B, 0xEE, +0x9C, 0xB0, 0xAD, 0x32, 0x9C, 0xB0, 0x6B, 0x4B, +0x52, 0x68, 0x4A, 0x68, 0x4A, 0x48, 0x52, 0x89, +0x7B, 0x8D, 0x6B, 0x2C, 0x5A, 0x8A, 0x83, 0xEF, +0x83, 0xCE, 0x83, 0xAE, 0x9C, 0x71, 0xBD, 0x75, +0xCD, 0xD7, 0xA4, 0xB2, 0xA4, 0xB2, 0x73, 0x6D, +0x5A, 0xEA, 0x42, 0x07, 0x3A, 0x07, 0x31, 0xA6, +0x39, 0xE7, 0x42, 0x28, 0x52, 0xAA, 0x4A, 0x69, +0x52, 0xAA, 0x63, 0x2C, 0x73, 0xAF, 0x84, 0x11, +0x94, 0xB3, 0xA5, 0x15, 0x8C, 0x72, 0xB5, 0x96, +0xC6, 0x17, 0xC5, 0xF7, 0x84, 0x10, 0x73, 0x6D, +0x4A, 0x48, 0xAD, 0x33, 0xCD, 0xF6, 0xAD, 0x32, +0xAC, 0xF1, 0xA4, 0xD1, 0xA4, 0xB0, 0xA4, 0xB0, +0x9C, 0x90, 0x9C, 0x90, 0x9C, 0x90, 0x94, 0x6F, +0x9C, 0x8F, 0xA4, 0xB0, 0x9C, 0x6F, 0x94, 0x2E, +0x8C, 0x2E, 0x94, 0x4E, 0x94, 0x4E, 0x94, 0x4E, +0x9C, 0x6E, 0x9C, 0x8E, 0x9C, 0x8F, 0xA4, 0xCF, +0x9C, 0xAF, 0x94, 0x2E, 0x8C, 0x2E, 0x8C, 0x0D, +0x8C, 0x0D, 0x8C, 0x2E, 0x8C, 0x0D, 0x83, 0xCC, +0x8C, 0x2E, 0x94, 0x6F, 0x9C, 0xB0, 0xA4, 0xF1, +0xA4, 0xF1, 0x9C, 0xB0, 0xA4, 0xD0, 0xAD, 0x32, +0xB5, 0x72, 0xBD, 0x93, 0xAD, 0x31, 0xA4, 0xD0, +0xC5, 0xB4, 0xC5, 0xB4, 0xCD, 0xF3, 0xC5, 0x92, +0xCD, 0xB3, 0xAD, 0x11, 0x9C, 0xAF, 0xCE, 0x35, +0xCE, 0x15, 0xC5, 0xD4, 0xC5, 0xF5, 0xC5, 0xF5, +0xBD, 0xB4, 0xBD, 0x92, 0xCD, 0xB3, 0xD5, 0xD3, +0xBD, 0x51, 0xCE, 0x15, 0xC5, 0xD4, 0xC5, 0xD4, +0xCE, 0x14, 0xCD, 0xF4, 0xC5, 0xF4, 0xCE, 0x14, +0xC5, 0xB3, 0xD6, 0x55, 0xD6, 0x55, 0xDE, 0x75, +0xC5, 0xD3, 0xA4, 0xF2, 0xA4, 0xF2, 0x94, 0x70, +0x9C, 0xD1, 0xAD, 0x53, 0xB5, 0x53, 0xB5, 0x73, +0xB5, 0x74, 0xAD, 0x33, 0xA4, 0xF2, 0xAD, 0x32, +0xB5, 0x93, 0xC5, 0xF5, 0xD6, 0x76, 0xCE, 0x56, +0xD6, 0x57, 0xD6, 0x77, 0xEF, 0x1A, 0xC5, 0xF6, +0xAD, 0x75, 0xD6, 0x79, 0xB5, 0x96, 0xA5, 0x14, +0x83, 0xF0, 0x63, 0x0C, 0x5A, 0xCB, 0x5A, 0xEC, +0x8C, 0x72, 0xC6, 0x17, 0xDE, 0xB8, 0xDE, 0x97, +0xE6, 0xB8, 0xB5, 0x12, 0xD6, 0x38, 0xDE, 0xDB, +0xA5, 0x34, 0x42, 0x07, 0x42, 0x07, 0x3A, 0x07, +0x21, 0x64, 0x21, 0x64, 0x7C, 0x8D, 0x74, 0xAC, +0x6C, 0x6B, 0x7C, 0xED, 0x8D, 0x4E, 0x4B, 0x67, +0x3A, 0x85, 0x21, 0xC3, 0x43, 0x06, 0x63, 0xE9, +0x2A, 0x44, 0x2A, 0x44, 0x5B, 0xC9, 0x5B, 0xA9, +0x32, 0x65, 0x2A, 0x04, 0x3A, 0xC5, 0x4B, 0x67, +0x53, 0xA8, 0x53, 0xA7, 0x53, 0xA6, 0x84, 0x8C, +0xEF, 0x38, 0xE7, 0x17, 0x7C, 0x4B, 0x53, 0x86, +0x62, 0xEA, 0x5A, 0x89, 0x83, 0xCD, 0x94, 0x2E, +0x94, 0x4F, 0x52, 0x68, 0x5A, 0x88, 0x7B, 0x8C, +0x83, 0xAC, 0x73, 0x4B, 0x94, 0x6F, 0xDE, 0x77, +0xCE, 0x15, 0x9C, 0x4E, 0xAC, 0xD0, 0xA4, 0x6E, +0xA4, 0x6E, 0xA4, 0xAF, 0xC5, 0xB2, 0xC5, 0xB2, +0xC5, 0x92, 0xCD, 0xF3, 0xCD, 0xB3, 0xCD, 0xD3, +0xCD, 0xD3, 0xC5, 0xB2, 0xC5, 0xB2, 0xC5, 0xB2, +0xC5, 0x91, 0xB5, 0x30, 0xB5, 0x10, 0xBD, 0x71, +0xB4, 0xF0, 0xAC, 0xCF, 0xB4, 0xEF, 0xAC, 0xCF, +0xA4, 0x8E, 0xA4, 0x6D, 0xA4, 0x6E, 0xA4, 0x6E, +0xA4, 0x6D, 0xA4, 0x6D, 0xA4, 0x6D, 0xAC, 0x8E, +0xA4, 0x8D, 0xA4, 0x8E, 0xB5, 0x0F, 0xAC, 0xAE, +0xA4, 0x8E, 0x9C, 0x2C, 0x94, 0x2C, 0x9C, 0x2D, +0x9C, 0x4D, 0x8B, 0xCB, 0x94, 0x0C, 0x9C, 0x2D, +0x9C, 0x2D, 0xA4, 0x6E, 0xAC, 0xAF, 0xB4, 0xCF, +0xBD, 0x31, 0xC5, 0x72, 0xBD, 0x51, 0xCD, 0xD4, +0xCD, 0xB3, 0xCD, 0xD3, 0xCD, 0xF3, 0xD5, 0xF4, +0xE6, 0x95, 0xAC, 0x8E, 0xE6, 0x95, 0xF6, 0xF6, +0xEE, 0xD6, 0xEE, 0xD6, 0xEE, 0xD6, 0xEE, 0xB6, +0xEE, 0xB6, 0xEE, 0xD6, 0xDE, 0x34, 0xE6, 0x75, +0xEE, 0x95, 0xEE, 0x95, 0xE6, 0x75, 0xE6, 0x54, +0xE6, 0x74, 0xE6, 0x74, 0xEE, 0x95, 0xEE, 0x96, +0xB5, 0x10, 0x62, 0xA9, 0x39, 0xA5, 0x31, 0xA6, +0x31, 0xC6, 0x3A, 0x07, 0x4A, 0x69, 0x52, 0xAB, +0x6B, 0x4D, 0x84, 0x51, 0xAD, 0x96, 0xC6, 0x3A, +0xCE, 0x7A, 0xDE, 0xDB, 0xAD, 0x55, 0xBD, 0xB7, +0xE7, 0x3C, 0xCE, 0x59, 0xBD, 0x95, 0xB5, 0x75, +0x8C, 0x50, 0x8C, 0x30, 0x9C, 0xB3, 0xA5, 0x35, +0xD6, 0x9A, 0xD6, 0xBB, 0xEF, 0x3D, 0xD6, 0x79, +0x73, 0x6D, 0x5A, 0xA9, 0xBD, 0xB4, 0xC5, 0xF4, +0xC5, 0xD4, 0xCD, 0xF4, 0xC5, 0xB4, 0xBD, 0xB3, +0xBD, 0x93, 0x94, 0x6F, 0x94, 0x8F, 0x9C, 0xB0, +0xAD, 0x32, 0xBD, 0x73, 0xC5, 0xD4, 0xC5, 0xB3, +0xB5, 0x52, 0xA4, 0x8F, 0x73, 0x2A, 0x6B, 0x4C, +0x5A, 0xEB, 0x63, 0x0B, 0x63, 0x2C, 0x6B, 0x6C, +0x7B, 0xEE, 0x8C, 0x4F, 0x8C, 0x4F, 0x8C, 0x2F, +0x83, 0xEE, 0x52, 0x48, 0x4A, 0x68, 0x62, 0xEA, +0x63, 0x0B, 0x62, 0xEB, 0x4A, 0x28, 0x52, 0x89, +0x7B, 0x8E, 0x6A, 0xEB, 0x8C, 0x10, 0xAC, 0xF3, +0xCE, 0x17, 0xB5, 0x54, 0xBD, 0x95, 0x9C, 0x72, +0x94, 0x71, 0x4A, 0x89, 0x39, 0xE6, 0x39, 0xE7, +0x31, 0xA5, 0x31, 0xA5, 0x42, 0x28, 0x42, 0x28, +0x5A, 0xEB, 0x6B, 0x6D, 0x6B, 0x6E, 0x7B, 0xF0, +0x7C, 0x10, 0x7B, 0xF0, 0xA5, 0x14, 0xAD, 0x76, +0xC6, 0x18, 0xC6, 0x18, 0xA5, 0x14, 0x63, 0x0C, +0x4A, 0x48, 0x8C, 0x0F, 0xCE, 0x16, 0xC5, 0xF6, +0xB5, 0x53, 0xBD, 0xB4, 0xBD, 0x73, 0xBD, 0xB4, +0xAD, 0x12, 0x8C, 0x0E, 0x94, 0x4F, 0xA4, 0xAF, +0xAC, 0xF1, 0xC5, 0x93, 0xBD, 0x53, 0xBD, 0x53, +0xB5, 0x52, 0xA4, 0xD0, 0xA4, 0xB0, 0x9C, 0x8F, +0x9C, 0x70, 0x9C, 0x90, 0x9C, 0x90, 0x9C, 0x90, +0x9C, 0xB0, 0xAD, 0x11, 0xB5, 0x32, 0xAD, 0x11, +0xAC, 0xF1, 0xAC, 0xF1, 0xAD, 0x12, 0xAD, 0x11, +0xAC, 0xF1, 0xAC, 0xD1, 0xA4, 0xB0, 0xA4, 0x90, +0x9C, 0x6F, 0x9C, 0x4F, 0x9C, 0x4F, 0x9C, 0x4F, +0x8B, 0xED, 0x8C, 0x0E, 0x8C, 0x0E, 0x8C, 0x0D, +0x94, 0x4E, 0x94, 0x2E, 0x94, 0x2E, 0x94, 0x2D, +0x94, 0x0D, 0x94, 0x4F, 0x8C, 0x0E, 0x94, 0x6F, +0xAC, 0xF1, 0xB5, 0x52, 0xAD, 0x12, 0xBD, 0x93, +0xC5, 0xB4, 0xC5, 0xD4, 0xDE, 0x55, 0xE6, 0x96, +0xD6, 0x35, 0xD6, 0x56, 0xC5, 0xD3, 0xCE, 0x15, +0xD6, 0x56, 0xC5, 0xD4, 0xCE, 0x15, 0xCE, 0x35, +0xCD, 0xF4, 0xCE, 0x14, 0xDE, 0x55, 0xD6, 0x55, +0xCD, 0xD4, 0xAD, 0x12, 0x9C, 0xF1, 0x8C, 0x4F, +0xA5, 0x12, 0xB5, 0x73, 0xB5, 0x74, 0xBD, 0x94, +0xB5, 0x73, 0xAD, 0x33, 0xAD, 0x53, 0xAD, 0x53, +0xB5, 0x73, 0xBD, 0xB4, 0xCE, 0x36, 0xCE, 0x56, +0xD6, 0x77, 0xD6, 0x98, 0xCE, 0x37, 0xB5, 0x74, +0x9C, 0xD2, 0x7B, 0xCF, 0x7B, 0xCE, 0x83, 0xEE, +0x73, 0x6D, 0x7B, 0xAE, 0x73, 0x4D, 0x6B, 0x2C, +0x73, 0x8E, 0xB5, 0x75, 0xAD, 0x53, 0xDE, 0xB9, +0xD6, 0x78, 0x84, 0x10, 0x94, 0x92, 0x94, 0x92, +0x84, 0x10, 0x42, 0x28, 0x31, 0xA5, 0x39, 0xC6, +0x31, 0xC6, 0x21, 0x64, 0x53, 0x29, 0x6C, 0x8B, +0x53, 0xC8, 0x53, 0xC8, 0x4B, 0x67, 0x2A, 0x03, +0x19, 0x41, 0x19, 0x62, 0x4B, 0x06, 0x4B, 0x66, +0x5B, 0xC9, 0x19, 0x82, 0x53, 0x49, 0x7C, 0xCD, +0x5B, 0xA9, 0x63, 0xEA, 0x63, 0xE9, 0x5B, 0xE9, +0x6C, 0x6A, 0x4B, 0x86, 0x43, 0x04, 0x8C, 0xCC, +0xDE, 0xF5, 0xAD, 0xD0, 0x7C, 0xAA, 0x4B, 0x24, +0x52, 0x89, 0x39, 0xC6, 0x52, 0xA9, 0x5A, 0xA9, +0x5A, 0xA9, 0x52, 0x48, 0x7B, 0xCD, 0xC5, 0xF4, +0xD6, 0x56, 0xB5, 0x32, 0x83, 0xED, 0xA4, 0xD0, +0xC5, 0xB4, 0x9C, 0x2E, 0xA4, 0x6E, 0xB4, 0xD0, +0x8B, 0xCC, 0x73, 0x2A, 0x7B, 0x6B, 0x83, 0xAC, +0x9C, 0x6E, 0xD6, 0x14, 0xCD, 0xB3, 0xCD, 0xB2, +0xBD, 0x72, 0xAC, 0xF0, 0xE6, 0x96, 0xDE, 0x54, +0xE6, 0x75, 0xC5, 0x92, 0x94, 0x0C, 0xBD, 0x51, +0xBD, 0x51, 0xA4, 0x6E, 0xAC, 0xAF, 0xBD, 0x51, +0xB4, 0xEF, 0xAC, 0xAE, 0xC5, 0x71, 0xE6, 0x96, +0xCD, 0xD3, 0xC5, 0x72, 0xC5, 0x92, 0xD6, 0x14, +0xD5, 0xF3, 0xC5, 0x71, 0xC5, 0x71, 0xC5, 0x91, +0xC5, 0x91, 0xBD, 0x51, 0xBD, 0x51, 0xAC, 0xEF, +0xAC, 0xEF, 0xB5, 0x10, 0xB5, 0x10, 0xB5, 0x30, +0xBD, 0x30, 0xB4, 0xEF, 0xAC, 0xAE, 0xAC, 0xCF, +0xA4, 0x8E, 0xA4, 0x6E, 0xA4, 0x6E, 0xAC, 0xCF, +0x9C, 0x2D, 0x8B, 0xEB, 0x8B, 0xCB, 0xB5, 0x10, +0xCD, 0xB2, 0xAC, 0x8D, 0xBD, 0x30, 0xC5, 0x71, +0xCD, 0x91, 0xCD, 0xB2, 0xCD, 0x71, 0xCD, 0xB2, +0xD5, 0xF3, 0xD5, 0xD2, 0xC5, 0x30, 0xCD, 0x92, +0xD5, 0xD2, 0xDE, 0x34, 0xDE, 0x34, 0xDE, 0x33, +0xDE, 0x33, 0xE6, 0x54, 0xE6, 0x53, 0xEE, 0x95, +0xF6, 0xB6, 0xE6, 0x55, 0x8B, 0xED, 0x39, 0xC6, +0x31, 0xA5, 0x31, 0xC6, 0x39, 0xE7, 0x42, 0x08, +0x52, 0xAA, 0x6B, 0x6D, 0x84, 0x30, 0x9D, 0x14, +0xAD, 0x55, 0xAD, 0x55, 0x6B, 0x4D, 0xB5, 0xB7, +0xDE, 0xDB, 0xEF, 0x5D, 0xEF, 0x7D, 0xDE, 0xBA, +0xBD, 0x95, 0xA4, 0xD3, 0x84, 0x10, 0x94, 0xB3, +0xEF, 0x5D, 0xDE, 0xDB, 0xD6, 0x7A, 0xEF, 0x3D, +0x73, 0x8E, 0x94, 0x6F, 0xCE, 0x35, 0xDE, 0x75, +0xD6, 0x34, 0xCD, 0xF4, 0xD6, 0x14, 0xCD, 0xF4, +0xCD, 0xF4, 0xC5, 0xD4, 0xC5, 0xD4, 0xCE, 0x15, +0xCE, 0x15, 0xCE, 0x14, 0xCD, 0xF4, 0xD6, 0x14, +0xB5, 0x30, 0xA4, 0x8E, 0x8B, 0xCD, 0x63, 0x2C, +0x5A, 0xEB, 0x63, 0x0B, 0x63, 0x4C, 0x73, 0x8D, +0x73, 0xAE, 0x7B, 0xEF, 0x84, 0x0F, 0x84, 0x2F, +0x84, 0x2F, 0x7B, 0xCE, 0x62, 0xEA, 0x52, 0x69, +0x52, 0x69, 0x52, 0x68, 0x62, 0xEB, 0x62, 0xCA, +0x7B, 0x8D, 0x7B, 0x8E, 0x73, 0x4C, 0x8C, 0x0F, +0xA4, 0xD2, 0x8C, 0x10, 0xA4, 0xD3, 0xB5, 0x76, +0xCE, 0x38, 0x8C, 0x51, 0x39, 0xE7, 0x3A, 0x07, +0x29, 0x65, 0x39, 0xC6, 0x42, 0x07, 0x39, 0xE7, +0x52, 0xCA, 0x63, 0x2C, 0x63, 0x0C, 0x73, 0xAF, +0x7B, 0xF0, 0x94, 0x93, 0xA5, 0x35, 0xA5, 0x15, +0xBD, 0xF8, 0xB5, 0xB6, 0xB5, 0x96, 0x5A, 0xCB, +0x39, 0xA6, 0x5A, 0xCA, 0x5A, 0xAA, 0x84, 0x0F, +0xB5, 0x74, 0xC6, 0x16, 0xA5, 0x12, 0xA4, 0xD2, +0xDE, 0x98, 0xC5, 0xB5, 0xB4, 0xF1, 0xAC, 0xD0, +0xB4, 0xD0, 0xCD, 0x92, 0xCD, 0x72, 0xCD, 0xB3, +0xC5, 0x93, 0x9C, 0x6F, 0xA4, 0xD1, 0xA4, 0xF2, +0x9C, 0x90, 0x94, 0x2F, 0x83, 0xED, 0x83, 0xED, +0x83, 0xCD, 0xA4, 0xB0, 0xAD, 0x11, 0xB5, 0x11, +0xB5, 0x31, 0xB5, 0x11, 0xB5, 0x31, 0xBD, 0x72, +0xCD, 0xD4, 0xC5, 0xB3, 0xCD, 0xB3, 0xCD, 0xB4, +0xCD, 0xD4, 0xC5, 0x73, 0xC5, 0x93, 0xC5, 0xB4, +0xC5, 0x93, 0xBD, 0x73, 0xBD, 0x73, 0xBD, 0x73, +0xBD, 0x73, 0xB5, 0x33, 0xAC, 0xF1, 0xAD, 0x11, +0xB5, 0x32, 0xB5, 0x53, 0xAD, 0x33, 0xAD, 0x12, +0xAC, 0xF1, 0xA4, 0xD0, 0x9C, 0x90, 0x9C, 0x90, +0x9C, 0x6F, 0x9C, 0x6F, 0x9C, 0x8F, 0x9C, 0x6F, +0x9C, 0x6F, 0x94, 0x2E, 0x8C, 0x2E, 0x94, 0x6F, +0xA4, 0xF1, 0xA4, 0xB0, 0xB5, 0x52, 0xBD, 0xB3, +0xBD, 0x73, 0xC5, 0xB3, 0xCD, 0xF4, 0xC5, 0xD3, +0xAC, 0xF0, 0xA4, 0xF1, 0x94, 0x90, 0x8C, 0x4F, +0xA4, 0xF2, 0xAD, 0x33, 0xA5, 0x32, 0xA4, 0xF2, +0xA4, 0xF2, 0xA4, 0xF2, 0xB5, 0x94, 0xC5, 0xD5, +0xCE, 0x57, 0xD6, 0x98, 0xD6, 0x57, 0xC5, 0xF6, +0xAD, 0x54, 0x94, 0x91, 0x7B, 0xEF, 0x8C, 0x50, +0xA4, 0xF2, 0x9C, 0xD2, 0x8C, 0x4F, 0x9C, 0xB1, +0x8B, 0xEE, 0x5A, 0x68, 0x5A, 0x68, 0x6B, 0x0B, +0x62, 0xCA, 0x7B, 0xAE, 0x73, 0x8D, 0xA5, 0x12, +0x94, 0x91, 0x52, 0x69, 0x39, 0xE7, 0x31, 0x86, +0x42, 0x28, 0x31, 0xC6, 0x31, 0xA5, 0x21, 0x44, +0x19, 0x23, 0x21, 0x44, 0x21, 0xA4, 0x5B, 0xC9, +0x5B, 0xE9, 0x3A, 0xE5, 0x4B, 0x27, 0x6B, 0xEB, +0x63, 0xCA, 0x74, 0x6C, 0x5C, 0x08, 0x5C, 0x28, +0x7C, 0xEC, 0x32, 0x65, 0x19, 0x83, 0x53, 0x49, +0x63, 0xEB, 0x84, 0xCD, 0x95, 0x4F, 0x7C, 0xAC, +0x6C, 0x2A, 0x43, 0x26, 0x4B, 0x65, 0x6C, 0x28, +0x85, 0x0A, 0x6C, 0x86, 0x4B, 0xA3, 0x43, 0x23, +0x52, 0x89, 0x42, 0x08, 0x42, 0x48, 0x52, 0x89, +0x5A, 0xCA, 0x62, 0xEB, 0xAD, 0x11, 0xD6, 0x35, +0xDE, 0x35, 0xDE, 0x55, 0xD6, 0x15, 0xCD, 0xF4, +0xCD, 0xF5, 0x9C, 0x4E, 0x9C, 0x2D, 0xCD, 0x72, +0xCD, 0xD4, 0xC5, 0xB3, 0xCD, 0xF4, 0xD6, 0x35, +0xD6, 0x14, 0xE6, 0x96, 0xDE, 0x76, 0xDE, 0x55, +0xDE, 0x76, 0xD6, 0x35, 0xDE, 0x55, 0xDE, 0x34, +0xD6, 0x13, 0xCD, 0xF4, 0xC5, 0xD4, 0xAD, 0x11, +0xBD, 0x72, 0xC5, 0xD4, 0xD6, 0x35, 0xEE, 0x97, +0xBD, 0x51, 0xA4, 0x6D, 0x94, 0x0C, 0xAC, 0xD0, +0x9C, 0x4D, 0x83, 0x8A, 0x8B, 0xCB, 0xAC, 0x8F, +0xA4, 0x4E, 0x93, 0xCB, 0x93, 0xEC, 0x93, 0xEC, +0x8B, 0xCB, 0x7B, 0x6A, 0x83, 0xAB, 0x94, 0x0C, +0x94, 0x2D, 0x8B, 0xEC, 0x7B, 0x4A, 0x83, 0xAB, +0x94, 0x0D, 0x94, 0x0C, 0xA4, 0x8E, 0xB5, 0x10, +0xB4, 0xEF, 0xBD, 0x30, 0xA4, 0x6D, 0xA4, 0x6D, +0xAC, 0xAE, 0xB4, 0xEF, 0xB5, 0x10, 0xB4, 0xEF, +0xB4, 0xEF, 0xB4, 0xCE, 0xAC, 0xCE, 0xAC, 0xEF, +0xAC, 0xCE, 0xAC, 0xCE, 0xB4, 0xEF, 0xB4, 0xEF, +0xB4, 0xEF, 0xB4, 0xCE, 0xB4, 0xEF, 0xB4, 0xEF, +0xAC, 0xAE, 0xAC, 0xCE, 0xAC, 0xAE, 0xA4, 0x8D, +0xAC, 0xAE, 0xBD, 0x0F, 0xBD, 0x0F, 0xB4, 0xEE, +0xB4, 0xCE, 0xB4, 0xEF, 0xBD, 0x10, 0x9C, 0x2E, +0x5A, 0x88, 0x39, 0xE6, 0x31, 0xA6, 0x31, 0xA6, +0x31, 0xC6, 0x4A, 0x48, 0x5B, 0x0B, 0x73, 0xAF, +0x73, 0x8E, 0x63, 0x0C, 0x9C, 0xF3, 0xA5, 0x35, +0xC6, 0x39, 0xCE, 0x7A, 0xD6, 0xBB, 0xEF, 0x5D, +0xD6, 0x9A, 0xCE, 0x38, 0xC6, 0x18, 0x94, 0x92, +0xBD, 0xD7, 0x84, 0x10, 0x9C, 0xD4, 0xD6, 0x9A, +0xAD, 0x75, 0xB5, 0x52, 0xD6, 0x14, 0xE6, 0x96, +0xEE, 0xD6, 0xEE, 0xD7, 0xE6, 0x96, 0xE6, 0x96, +0xDE, 0x35, 0xDE, 0x55, 0xDE, 0x75, 0xDE, 0x55, +0xD6, 0x14, 0xD6, 0x14, 0xDE, 0x76, 0xCD, 0xD3, +0x9C, 0x6E, 0xA4, 0xAF, 0x8B, 0xED, 0x6B, 0x2C, +0x6B, 0x6D, 0x6B, 0x4C, 0x6B, 0x4C, 0x73, 0xAE, +0x73, 0xAD, 0x84, 0x0F, 0x8C, 0x30, 0x8C, 0x30, +0x84, 0x0F, 0x83, 0xEF, 0x8C, 0x30, 0x73, 0x8D, +0x4A, 0x48, 0x39, 0xC6, 0x5A, 0xCA, 0x6B, 0x4C, +0x83, 0xCE, 0x41, 0xE7, 0x5A, 0xAA, 0x6B, 0x0B, +0x83, 0xCF, 0xBD, 0xB6, 0xBD, 0xD7, 0x94, 0x72, +0xBD, 0xF7, 0xAD, 0x34, 0x5A, 0xCA, 0x42, 0x07, +0x31, 0xA6, 0x31, 0xA6, 0x39, 0xE7, 0x31, 0xC6, +0x31, 0xA6, 0x42, 0x28, 0x52, 0xAA, 0x63, 0x2C, +0x6B, 0x4D, 0x73, 0xAF, 0x84, 0x31, 0x8C, 0x52, +0xB5, 0xB7, 0xC6, 0x19, 0xCE, 0x7A, 0x9C, 0xD3, +0x42, 0x29, 0x4A, 0x49, 0x5A, 0xAB, 0x5A, 0xCB, +0x5A, 0xCB, 0x73, 0x8D, 0x83, 0xEF, 0x8C, 0x50, +0xD6, 0x58, 0xBD, 0x54, 0xBD, 0x32, 0xAC, 0x8E, +0xC5, 0x10, 0xDD, 0xB2, 0xDD, 0xB2, 0xD5, 0xD3, +0xC5, 0x93, 0xA4, 0xD1, 0xBD, 0x94, 0xC5, 0xD5, +0xBD, 0xB4, 0xBD, 0xB4, 0xBD, 0xB4, 0xBD, 0x94, +0xBD, 0x94, 0xC5, 0x93, 0xC5, 0xB3, 0xC5, 0xB3, +0xCD, 0xD4, 0xCD, 0xD3, 0xCD, 0xB3, 0xBD, 0x51, +0xBD, 0x31, 0xA4, 0x8E, 0xA4, 0x8E, 0xC5, 0x51, +0xCD, 0xB3, 0xD5, 0xD4, 0xCD, 0xD3, 0xD5, 0xD4, +0xEE, 0x97, 0xB5, 0x32, 0xB5, 0x32, 0xC5, 0x94, +0xB5, 0x53, 0xA4, 0xB1, 0xA4, 0xD1, 0xB5, 0x52, +0xBD, 0x73, 0xBD, 0x73, 0xBD, 0x94, 0xC5, 0xD4, +0xBD, 0x93, 0xC5, 0x94, 0xBD, 0x93, 0xC5, 0x94, +0xC5, 0xB4, 0xC5, 0x94, 0xBD, 0x93, 0xBD, 0x73, +0xB5, 0x53, 0xBD, 0x53, 0xB5, 0x32, 0xA4, 0xB0, +0x9C, 0x90, 0x9C, 0x90, 0x9C, 0x70, 0x94, 0x4F, +0x8C, 0x0F, 0x73, 0x6C, 0x83, 0xED, 0x8C, 0x2E, +0x94, 0x70, 0x9C, 0xB0, 0xA4, 0xF2, 0xA5, 0x12, +0x9C, 0xD1, 0x9C, 0x91, 0x9C, 0xB2, 0xA5, 0x13, +0xB5, 0x54, 0xBD, 0xB5, 0xCE, 0x37, 0xC5, 0xD6, +0xAD, 0x54, 0x94, 0x51, 0x73, 0x8D, 0x6B, 0x4D, +0x6B, 0x4D, 0x83, 0xEF, 0xAD, 0x13, 0xB5, 0x73, +0xA5, 0x11, 0x83, 0xEE, 0x7B, 0x8C, 0x7B, 0xAD, +0x83, 0xCD, 0x83, 0xEE, 0x83, 0xAD, 0x6B, 0x0B, +0x4A, 0x08, 0x41, 0xE7, 0x31, 0x65, 0x42, 0x27, +0x42, 0x07, 0x41, 0xE7, 0x31, 0x86, 0x31, 0xA6, +0x4A, 0x69, 0x52, 0x89, 0x5B, 0x0A, 0x42, 0xA7, +0x42, 0xC7, 0x53, 0x28, 0x42, 0xC6, 0x53, 0x88, +0x6C, 0x4B, 0x4B, 0x07, 0x95, 0x6F, 0x9D, 0xD0, +0x95, 0x90, 0x95, 0xB0, 0x7C, 0xEC, 0x74, 0xCA, +0x74, 0xAA, 0x21, 0xC3, 0x19, 0x43, 0x32, 0x05, +0x11, 0x02, 0x63, 0xAB, 0x95, 0x70, 0x8D, 0x2F, +0x43, 0x06, 0x19, 0xA1, 0x32, 0x83, 0x4B, 0x85, +0x5C, 0x46, 0x54, 0x04, 0x4B, 0xA4, 0x4B, 0x85, +0x7B, 0xEF, 0x73, 0x8D, 0x73, 0x8D, 0x7B, 0xEE, +0x84, 0x0F, 0x8C, 0x4F, 0xC5, 0xF5, 0xD6, 0x35, +0xD6, 0x14, 0xD6, 0x34, 0xDE, 0x55, 0xDE, 0x76, +0xCE, 0x15, 0x9C, 0x4E, 0x93, 0xCC, 0x93, 0xCC, +0xA4, 0x6E, 0xDE, 0x55, 0xE6, 0x76, 0xDE, 0x76, +0xD6, 0x14, 0xDE, 0x55, 0xDE, 0x55, 0xDE, 0x55, +0xDE, 0x75, 0xDE, 0x75, 0xE6, 0xB6, 0xDE, 0x55, +0xDE, 0x55, 0xD6, 0x14, 0xDE, 0x76, 0xDE, 0x76, +0xE6, 0x96, 0xE6, 0xB7, 0xE6, 0xB7, 0xE6, 0x76, +0xBD, 0x31, 0xC5, 0x71, 0xD5, 0xB3, 0xD5, 0xD3, +0xD5, 0xD4, 0xC5, 0x72, 0xC5, 0x51, 0xD5, 0x72, +0xDD, 0xB2, 0xD5, 0x92, 0xD5, 0x92, 0xC5, 0x51, +0xB4, 0xF0, 0x9C, 0x8F, 0xB5, 0x52, 0xC5, 0xB3, +0xB5, 0x31, 0xA4, 0xAF, 0x94, 0x6F, 0x94, 0x4E, +0x8B, 0xEC, 0x83, 0xAB, 0x83, 0xAB, 0xA4, 0x8E, +0xB5, 0x10, 0xDE, 0x75, 0xAC, 0xEF, 0xAD, 0x0F, +0xCD, 0xF3, 0xC5, 0xD2, 0xBD, 0x91, 0xB5, 0x0F, +0xCD, 0xD2, 0xBD, 0x51, 0xAD, 0x0F, 0xC5, 0xB2, +0xBD, 0x30, 0xAC, 0xEF, 0xAC, 0xAE, 0xA4, 0x6D, +0xA4, 0x6D, 0xA4, 0x8E, 0xAC, 0xCF, 0xA4, 0xAE, +0xA4, 0x8D, 0xB4, 0xCF, 0xB4, 0xEF, 0xB4, 0xCE, +0xEE, 0x95, 0xE6, 0x54, 0xC5, 0x70, 0xBD, 0x2F, +0xCD, 0x91, 0xCD, 0x91, 0xC5, 0x51, 0xD5, 0xF4, +0xD5, 0xF4, 0xB4, 0xEF, 0x73, 0x29, 0x39, 0xC5, +0x31, 0xA5, 0x31, 0xA6, 0x42, 0x28, 0x63, 0x2C, +0x4A, 0x49, 0x5A, 0xAA, 0x8C, 0x51, 0x84, 0x31, +0xB5, 0xD7, 0xCE, 0x9B, 0xCE, 0x7B, 0xCE, 0x7A, +0xBD, 0xD8, 0xDE, 0xFC, 0xF7, 0x9E, 0xB5, 0x96, +0x7B, 0xD0, 0x5A, 0xCB, 0xA4, 0xF4, 0xBD, 0xB7, +0xA4, 0xF4, 0x9C, 0x91, 0xAD, 0x11, 0xB5, 0x10, +0xAC, 0xAE, 0xAC, 0xCF, 0xB5, 0x10, 0xBD, 0x72, +0xC5, 0xB3, 0xD5, 0xF4, 0xDE, 0x75, 0xE6, 0x96, +0xEE, 0xD6, 0xEE, 0xD7, 0xE6, 0x96, 0xC5, 0xB3, +0x9C, 0x6E, 0xAC, 0xCF, 0x7B, 0x8C, 0x52, 0x89, +0x6B, 0x8D, 0x73, 0x8D, 0x63, 0x4C, 0x7C, 0x0F, +0x7B, 0xEE, 0x84, 0x0F, 0x7B, 0xCE, 0x83, 0xEF, +0x8C, 0x30, 0x84, 0x0F, 0x84, 0x0F, 0x94, 0x91, +0x83, 0xEE, 0x5A, 0xA9, 0x42, 0x27, 0x52, 0x89, +0x83, 0xEF, 0x6B, 0x2C, 0x39, 0xA6, 0x52, 0x48, +0x8C, 0x30, 0xCE, 0x59, 0xCE, 0x59, 0x9C, 0xF4, +0x9C, 0xF3, 0xAD, 0x54, 0x8C, 0x30, 0x52, 0x89, +0x39, 0xC6, 0x31, 0xA6, 0x39, 0xE6, 0x42, 0x07, +0x39, 0xE6, 0x42, 0x27, 0x4A, 0x89, 0x4A, 0x69, +0x52, 0xAB, 0x6B, 0x8E, 0x84, 0x31, 0x94, 0xD4, +0xB5, 0x97, 0xB5, 0xB7, 0xC6, 0x39, 0xC6, 0x39, +0x63, 0x0D, 0x5A, 0xAB, 0x73, 0x8E, 0x63, 0x2C, +0x94, 0x72, 0x94, 0x92, 0x94, 0x92, 0x7B, 0xEF, +0xA4, 0xF3, 0xBD, 0xD6, 0xD6, 0x36, 0xCD, 0x52, +0xDD, 0x92, 0xD5, 0x71, 0xDD, 0xB2, 0xD5, 0xD3, +0xBD, 0x72, 0xAC, 0xF1, 0xBD, 0x74, 0xB5, 0x73, +0xBD, 0x93, 0xBD, 0x93, 0xBD, 0x73, 0xC5, 0xD4, +0xCE, 0x15, 0xCD, 0xF4, 0xCD, 0xF4, 0xD6, 0x14, +0xD5, 0xF4, 0xD5, 0xF4, 0xD5, 0xD3, 0xD6, 0x14, +0xCD, 0xD3, 0xB4, 0xF0, 0xC5, 0x72, 0xCD, 0xB3, +0xCD, 0xB3, 0xAC, 0xCF, 0xB5, 0x10, 0xC5, 0x31, +0xC5, 0x52, 0x9C, 0x6F, 0xCE, 0x15, 0xCE, 0x56, +0xBD, 0xD4, 0xB5, 0x94, 0xAD, 0x32, 0xAD, 0x32, +0xBD, 0xB4, 0xCE, 0x15, 0xD6, 0x35, 0xCD, 0xF4, +0xBD, 0x72, 0xB5, 0x11, 0xB5, 0x52, 0xAC, 0xF1, +0xB5, 0x32, 0xBD, 0x53, 0xBD, 0x53, 0xBD, 0x73, +0xB5, 0x32, 0xBD, 0x73, 0xC5, 0xB4, 0xC5, 0xD5, +0xAD, 0x32, 0xA4, 0xD1, 0xA4, 0xF1, 0xCD, 0xB4, +0xC5, 0x93, 0xDE, 0x56, 0xD6, 0x57, 0xD6, 0x57, +0xD6, 0x37, 0xCE, 0x16, 0xCE, 0x37, 0xCE, 0x58, +0xCE, 0x58, 0xCE, 0x59, 0xC6, 0x38, 0xBD, 0xD7, +0xAD, 0x55, 0xA5, 0x14, 0x8C, 0x30, 0x7B, 0xAE, +0x8C, 0x10, 0x9C, 0xB2, 0xAD, 0x33, 0xB5, 0x74, +0xB5, 0x53, 0xB5, 0x53, 0xAD, 0x53, 0xAD, 0x32, +0xA5, 0x12, 0xB5, 0x53, 0xAD, 0x53, 0xAD, 0x53, +0xB5, 0x74, 0xB5, 0x53, 0xAD, 0x33, 0xAD, 0x12, +0xA4, 0xD2, 0x94, 0x70, 0x83, 0xEF, 0x4A, 0x08, +0x94, 0x30, 0x9C, 0xB1, 0x83, 0xEF, 0x84, 0x10, +0x94, 0x71, 0x7C, 0x0E, 0x73, 0xEC, 0x5B, 0xEA, +0x6C, 0x6B, 0x53, 0xA8, 0x32, 0x44, 0x43, 0x06, +0x42, 0xC6, 0x42, 0xE6, 0x6C, 0x6A, 0x85, 0x2D, +0x8D, 0x8F, 0x95, 0xAF, 0x85, 0x2D, 0x85, 0x2C, +0x85, 0x4D, 0x3A, 0xA5, 0x42, 0x66, 0x31, 0xE5, +0x10, 0xC2, 0x19, 0x43, 0x5B, 0x8A, 0x9D, 0x70, +0x5B, 0x89, 0x32, 0x44, 0x22, 0x02, 0x32, 0xC3, +0x53, 0xC5, 0x95, 0xCC, 0x74, 0xC9, 0x3B, 0x04, +0xAD, 0x53, 0xAD, 0x53, 0xAD, 0x53, 0xAD, 0x53, +0xB5, 0x73, 0xBD, 0xB3, 0xCE, 0x15, 0xD6, 0x35, +0xD6, 0x14, 0xD6, 0x14, 0xD6, 0x55, 0xE6, 0xB7, +0xCD, 0xF5, 0x9C, 0x2E, 0xA4, 0x0D, 0xB4, 0xAF, +0xD5, 0xF4, 0xDE, 0x76, 0xDE, 0x34, 0xDE, 0x55, +0xDE, 0x55, 0xDE, 0x55, 0xE6, 0x75, 0xE6, 0x76, +0xD6, 0x14, 0xD6, 0x14, 0xE6, 0x96, 0xDE, 0x75, +0xD6, 0x34, 0xCD, 0xF3, 0xDE, 0x55, 0xE6, 0x75, +0xE6, 0x75, 0xE6, 0x75, 0xE6, 0x75, 0xE6, 0x55, +0xBD, 0x10, 0xAC, 0xAE, 0xC5, 0x10, 0xDD, 0xF4, +0xD5, 0xD3, 0xD5, 0xB3, 0xCD, 0x92, 0xD5, 0x71, +0xD5, 0x71, 0xCD, 0x51, 0xCD, 0x51, 0xCD, 0x51, +0xCD, 0x92, 0xC5, 0x92, 0xDE, 0x56, 0xCD, 0xD4, +0xB5, 0x31, 0xA4, 0xAF, 0x8B, 0xED, 0x8C, 0x0D, +0x83, 0xCC, 0x83, 0xCC, 0x8B, 0xEC, 0xA4, 0x8E, +0xB5, 0x10, 0xD6, 0x55, 0xB5, 0x71, 0xBD, 0x91, +0xC6, 0x12, 0xC6, 0x32, 0xCE, 0x74, 0xAD, 0x50, +0xD6, 0x95, 0xD6, 0x94, 0xD6, 0xD5, 0xDE, 0xB5, +0xB5, 0x30, 0xB5, 0x30, 0xB5, 0x31, 0xA4, 0xEF, +0x9C, 0xAE, 0xB5, 0x51, 0xC5, 0xB2, 0xA4, 0xCF, +0xB5, 0x10, 0xBD, 0x50, 0xAC, 0xCE, 0xAC, 0xAD, +0xE6, 0x75, 0xDE, 0x33, 0xCD, 0xD2, 0xB5, 0x0F, +0xA4, 0x8E, 0xAC, 0xCE, 0x9C, 0x6D, 0xA4, 0x6E, +0xD5, 0xF3, 0xDE, 0x13, 0xDE, 0x13, 0xAC, 0xCF, +0x5A, 0x88, 0x31, 0x85, 0x39, 0xE7, 0x52, 0x8A, +0x42, 0x07, 0x42, 0x28, 0x63, 0x0C, 0x7B, 0xEF, +0x8C, 0x92, 0xA5, 0x35, 0xBD, 0xF8, 0xCE, 0x9B, +0xCE, 0x5A, 0xBD, 0xF8, 0xBD, 0xF8, 0x94, 0x93, +0xC5, 0xF8, 0x8C, 0x72, 0xA5, 0x35, 0xEF, 0x3D, +0xD6, 0x9A, 0x9C, 0xB3, 0x8C, 0x0F, 0xB5, 0x32, +0xC5, 0x72, 0xBD, 0x51, 0xAC, 0xAF, 0xA4, 0x8F, +0x94, 0x2D, 0x8B, 0xEC, 0x8B, 0xEB, 0x8B, 0xCB, +0x8B, 0xCC, 0x94, 0x0C, 0x9C, 0x4D, 0x94, 0x2D, +0x9C, 0x4D, 0xAC, 0xAF, 0xAC, 0xAF, 0x7B, 0xAC, +0x7B, 0x8D, 0x6B, 0x0B, 0x63, 0x0B, 0x73, 0xAE, +0x6B, 0x6D, 0x6B, 0x4C, 0x6B, 0x2C, 0x73, 0xAD, +0x7B, 0xEE, 0x7B, 0xCE, 0x84, 0x0F, 0x94, 0xB1, +0xA4, 0xF2, 0x94, 0xB1, 0x6B, 0x4C, 0x4A, 0x28, +0x4A, 0x48, 0x5A, 0xAA, 0x4A, 0x28, 0x62, 0xEB, +0x73, 0x8E, 0xAD, 0x75, 0xC5, 0xF8, 0xBD, 0xB7, +0x9C, 0xD3, 0x7B, 0xCF, 0x73, 0x6D, 0x6B, 0x6C, +0x4A, 0x48, 0x31, 0xC6, 0x39, 0xE7, 0x42, 0x07, +0x42, 0x27, 0x39, 0xE7, 0x4A, 0x69, 0x52, 0xCB, +0x63, 0x2C, 0x6B, 0x6E, 0x7B, 0xD0, 0x9C, 0xD4, +0x9D, 0x15, 0xA5, 0x36, 0xB5, 0xB8, 0xC6, 0x19, +0x9C, 0xD4, 0x73, 0x8F, 0x7B, 0xAE, 0x9C, 0xD2, +0xA4, 0xF3, 0xAD, 0x55, 0x9C, 0xD3, 0x9C, 0xB3, +0xA5, 0x14, 0x7B, 0xAE, 0x73, 0x6D, 0x8B, 0xEE, +0xBD, 0x11, 0xAC, 0x8E, 0xCD, 0x51, 0xCD, 0x92, +0xBD, 0x51, 0xAC, 0xF1, 0xB5, 0x32, 0xBD, 0xB4, +0xC5, 0xD5, 0xC5, 0xB4, 0xC5, 0xB4, 0xB5, 0x72, +0xBD, 0x93, 0xC5, 0xB3, 0xC5, 0xB3, 0xD6, 0x14, +0xBD, 0x72, 0x83, 0x8B, 0xBD, 0x51, 0xCD, 0xB2, +0xDE, 0x35, 0xC5, 0x93, 0xDE, 0x35, 0xD6, 0x14, +0xDE, 0x35, 0xC5, 0x51, 0xBD, 0x30, 0xC5, 0x72, +0xD6, 0x14, 0xA4, 0xB0, 0xD6, 0x56, 0xCE, 0x16, +0xBD, 0xD4, 0xC6, 0x36, 0xCE, 0x57, 0xC5, 0xD4, +0xBD, 0xB4, 0xBD, 0xB4, 0xD6, 0x56, 0xDE, 0xB7, +0xD6, 0x56, 0xCE, 0x15, 0xBD, 0x93, 0xB5, 0x52, +0xB5, 0x72, 0xB5, 0x73, 0xD6, 0x56, 0xCE, 0x15, +0xBD, 0x93, 0xBD, 0xB3, 0xBD, 0x93, 0xC5, 0xF4, +0xD6, 0x56, 0x9C, 0x90, 0xAD, 0x12, 0xDE, 0x15, +0xD5, 0x52, 0xE6, 0x35, 0xD6, 0x16, 0xBD, 0x94, +0xB5, 0x54, 0xB5, 0x95, 0xAD, 0x54, 0x94, 0x71, +0x73, 0xAE, 0x7B, 0x8E, 0x94, 0x51, 0x9C, 0xB2, +0x9C, 0xD2, 0x9C, 0x91, 0xBD, 0x74, 0xD6, 0x36, +0xE6, 0x57, 0xE6, 0x77, 0xE6, 0x97, 0xE6, 0xB7, +0xE6, 0xD8, 0xEE, 0xF8, 0xAD, 0x32, 0xAD, 0x32, +0xBD, 0x94, 0xBD, 0xB3, 0xC5, 0xB4, 0xC5, 0xD4, +0xC5, 0xD4, 0xBD, 0x94, 0xB5, 0x53, 0xB5, 0x73, +0xB5, 0x54, 0xDE, 0x99, 0xC5, 0xD6, 0x7B, 0x6D, +0xC5, 0x95, 0x9C, 0x91, 0x62, 0xEB, 0x84, 0x10, +0x9C, 0xB2, 0x7B, 0xCD, 0x7C, 0x8E, 0x74, 0xAC, +0x6C, 0x6B, 0x32, 0x85, 0x21, 0x82, 0x3A, 0x86, +0x11, 0x21, 0x4B, 0x27, 0x6C, 0x8A, 0x85, 0x4D, +0x95, 0xB0, 0x8D, 0x6F, 0x85, 0x2D, 0x85, 0x2D, +0x7C, 0xEC, 0x21, 0xE3, 0x53, 0x29, 0x29, 0xA3, +0x10, 0xE2, 0x19, 0x23, 0x3A, 0x26, 0x63, 0xAB, +0x4A, 0xE8, 0x32, 0x25, 0x42, 0xC6, 0x43, 0x06, +0x53, 0xC7, 0x74, 0xCA, 0x53, 0xC6, 0x3B, 0x25, +0xB5, 0x73, 0xC5, 0xF5, 0xCE, 0x16, 0xCE, 0x36, +0xD6, 0x56, 0xD6, 0x56, 0xDE, 0x55, 0xDE, 0x55, +0xDE, 0x55, 0xDE, 0x55, 0xDE, 0x76, 0xD6, 0x35, +0xB5, 0x31, 0xAC, 0x8F, 0xCD, 0x11, 0xDD, 0x93, +0xDD, 0xF4, 0xE6, 0x76, 0xDE, 0x34, 0xDE, 0x35, +0xDE, 0x55, 0xDE, 0x35, 0xDE, 0x55, 0xDE, 0x55, +0xDE, 0x35, 0xDE, 0x34, 0xE6, 0x96, 0xE6, 0x75, +0xDE, 0x55, 0xDE, 0x34, 0xDE, 0x55, 0xDE, 0x55, +0xE6, 0x75, 0xE6, 0x75, 0xE6, 0x75, 0xE6, 0x55, +0xAC, 0x8E, 0xA4, 0x2C, 0xA4, 0x4D, 0xCD, 0x92, +0xDD, 0xF4, 0xD5, 0xD3, 0xCD, 0x51, 0xCD, 0x51, +0xC5, 0x0F, 0xBC, 0xCF, 0xBC, 0xCF, 0xB4, 0xAF, +0xBD, 0x30, 0xC5, 0x92, 0xCD, 0xF4, 0xCD, 0xD3, +0xAC, 0xF0, 0xA4, 0xCF, 0x8C, 0x2E, 0x8C, 0x0D, +0x8C, 0x0D, 0x83, 0xCC, 0x94, 0x4E, 0xAC, 0xF0, +0xB5, 0x30, 0xCE, 0x14, 0xB5, 0x30, 0xBD, 0xB2, +0xBE, 0x32, 0xBE, 0x32, 0xC6, 0x53, 0xBE, 0x33, +0xCE, 0xB4, 0xD6, 0xF5, 0xDF, 0x36, 0xC6, 0x33, +0xC5, 0xD3, 0xBD, 0xB3, 0xC5, 0xD3, 0xBD, 0xB3, +0xBD, 0xB3, 0xC5, 0xF4, 0xCD, 0xF4, 0xAC, 0xEF, +0xBD, 0x51, 0xAC, 0xCF, 0xAC, 0xAE, 0xAC, 0xCE, +0xEE, 0xB5, 0xE6, 0x75, 0xE6, 0x95, 0xEE, 0xD6, +0xD6, 0x14, 0xB5, 0x30, 0xA4, 0xAF, 0xAC, 0xD0, +0xD5, 0xF3, 0xDE, 0x12, 0xD5, 0xF3, 0xD5, 0xF2, +0xCD, 0xD2, 0x9C, 0x8E, 0x52, 0x67, 0x31, 0x85, +0x21, 0x24, 0x31, 0x85, 0x3A, 0x07, 0x4A, 0x69, +0x5A, 0xEB, 0x73, 0xAE, 0x84, 0x31, 0x84, 0x31, +0xAD, 0x76, 0xC6, 0x39, 0xC6, 0x39, 0x94, 0x93, +0xAD, 0x56, 0x83, 0xF0, 0xBD, 0xF8, 0xEF, 0x5D, +0xD6, 0x9A, 0xE7, 0x1C, 0xBD, 0xD7, 0x73, 0x6D, +0x94, 0x4F, 0xAC, 0xF1, 0x9C, 0x4E, 0x94, 0x2D, +0xA4, 0x8F, 0xAC, 0xCF, 0xB5, 0x30, 0xBD, 0x31, +0xB5, 0x10, 0xB4, 0xEF, 0xAC, 0xAF, 0xAC, 0xCF, +0xB4, 0xF0, 0xAC, 0xCF, 0xB4, 0xF0, 0xB5, 0x10, +0xAC, 0xAF, 0xA4, 0x6F, 0x9C, 0x6F, 0x9C, 0x6F, +0x94, 0x2E, 0x94, 0x2E, 0x8B, 0xED, 0x8B, 0xED, +0x83, 0xED, 0x83, 0xEE, 0x83, 0xCD, 0x7B, 0xAD, +0x83, 0xCD, 0x7B, 0xCD, 0x83, 0xEE, 0x63, 0x0A, +0x41, 0xE7, 0x52, 0x69, 0x4A, 0x28, 0x52, 0x89, +0x62, 0xEB, 0x84, 0x30, 0xAD, 0x76, 0xB5, 0x76, +0x8C, 0x31, 0x73, 0x8E, 0x73, 0x6D, 0x6B, 0x4D, +0x63, 0x0B, 0x39, 0xC6, 0x42, 0x07, 0x39, 0xC6, +0x31, 0xA6, 0x3A, 0x07, 0x4A, 0x48, 0x4A, 0x48, +0x5A, 0xCB, 0x52, 0x8A, 0x5A, 0xEC, 0x84, 0x52, +0x94, 0xD4, 0x9C, 0xF5, 0xAD, 0x97, 0xCE, 0x5A, +0xD6, 0x7A, 0x9C, 0xB3, 0x73, 0x8E, 0x73, 0x8E, +0xB5, 0x96, 0xBD, 0xB7, 0xC5, 0xF8, 0xBD, 0xD7, +0xC5, 0xF8, 0xAD, 0x55, 0xA5, 0x14, 0xBD, 0xB6, +0xC5, 0xD6, 0xA4, 0x90, 0xC5, 0x32, 0xC5, 0x51, +0xBD, 0x52, 0xAD, 0x12, 0xB5, 0x53, 0xC5, 0xD4, +0xC5, 0x93, 0xB5, 0x11, 0xC5, 0x93, 0xC5, 0xB3, +0xBD, 0x52, 0xC5, 0x93, 0xC5, 0xB3, 0xD6, 0x35, +0xB5, 0x11, 0xAC, 0xD0, 0xC5, 0x72, 0xC5, 0x92, +0xCD, 0xB2, 0xDE, 0x35, 0xD6, 0x14, 0xD5, 0xF4, +0xD6, 0x14, 0xC5, 0x52, 0xC5, 0x71, 0xC5, 0x51, +0xAC, 0xAF, 0xAC, 0xD0, 0xD6, 0x56, 0xC5, 0xF4, +0xBD, 0xD4, 0xC5, 0xF5, 0xC6, 0x15, 0xBD, 0xD4, +0xC6, 0x15, 0xC5, 0xF4, 0xC5, 0xD4, 0xD6, 0x76, +0xDE, 0x96, 0xDE, 0xB7, 0xDE, 0xB7, 0xCE, 0x56, +0xDE, 0x97, 0xDE, 0x97, 0xCE, 0x36, 0xC5, 0xF5, +0xCE, 0x15, 0xCE, 0x15, 0xCE, 0x35, 0xD6, 0x56, +0xD6, 0x76, 0xA4, 0xD1, 0xB5, 0x32, 0xDD, 0xD4, +0xDD, 0x72, 0xDD, 0xD4, 0x8B, 0xAE, 0x73, 0x4D, +0x62, 0xCA, 0x73, 0x4B, 0x83, 0x8C, 0x9C, 0x2F, +0xD6, 0x57, 0xE6, 0xF9, 0xE6, 0xD9, 0xDE, 0x97, +0xE6, 0xB8, 0xE6, 0x97, 0xDE, 0x36, 0xE6, 0x35, +0xDD, 0xF4, 0xDD, 0xD4, 0xDD, 0xD4, 0xDE, 0x15, +0xDE, 0x56, 0xEF, 0x19, 0x9C, 0x90, 0xAD, 0x33, +0xCE, 0x15, 0xC5, 0xD4, 0xC5, 0xD4, 0xCD, 0xF4, +0xD6, 0x15, 0xD6, 0x15, 0xD6, 0x36, 0xD6, 0x37, +0xBD, 0x95, 0xEF, 0x3B, 0xB5, 0x75, 0x9C, 0x91, +0xCD, 0xD5, 0xA4, 0x91, 0x52, 0x49, 0x73, 0x4D, +0x8C, 0x2F, 0x84, 0x2E, 0x74, 0x4C, 0x64, 0x2A, +0x4B, 0x47, 0x19, 0x42, 0x19, 0x63, 0x32, 0x25, +0x19, 0x42, 0x53, 0x69, 0x85, 0x4E, 0x9D, 0xD0, +0x95, 0xD0, 0x8D, 0x4E, 0x85, 0x2C, 0x74, 0xCB, +0x43, 0x05, 0x2A, 0x04, 0x5B, 0x69, 0x29, 0xE4, +0x31, 0xE5, 0x42, 0x67, 0x4A, 0xE8, 0x6B, 0xEB, +0x5B, 0x69, 0x3A, 0x66, 0x4A, 0xE7, 0x5B, 0xA9, +0x85, 0x0E, 0x7D, 0x0C, 0x6C, 0x69, 0x4B, 0xA6, +0x73, 0x6B, 0x83, 0xED, 0x9C, 0x6F, 0xA4, 0xD1, +0xAC, 0xF1, 0xB5, 0x32, 0xBD, 0x72, 0xC5, 0xB3, +0xC5, 0xB3, 0xBD, 0x72, 0xC5, 0xB3, 0x9C, 0x6E, +0x9C, 0x4E, 0xA4, 0x4E, 0xD5, 0x31, 0xE5, 0xD4, +0xDD, 0xF4, 0xDE, 0x14, 0xDE, 0x34, 0xE6, 0x55, +0xE6, 0x96, 0xE6, 0x75, 0xE6, 0x96, 0xDE, 0x34, +0xDE, 0x14, 0xDE, 0x14, 0xDE, 0x55, 0xDE, 0x55, +0xE6, 0x55, 0xC5, 0x71, 0xDE, 0x14, 0xE6, 0x55, +0xE6, 0x55, 0xE6, 0x75, 0xE6, 0x75, 0xE6, 0x55, +0xAC, 0xAE, 0x9C, 0x2C, 0x8B, 0xAB, 0xAC, 0xAE, +0xA4, 0x6E, 0xB4, 0xAF, 0xB4, 0xCF, 0xBC, 0xCF, +0xC5, 0x0F, 0xC5, 0x0F, 0xBC, 0xCF, 0xB4, 0xCF, +0xB5, 0x10, 0xCD, 0xD3, 0xD6, 0x35, 0xBD, 0x72, +0xAC, 0xF0, 0xA4, 0xD0, 0xA4, 0xB0, 0x9C, 0x8F, +0x94, 0x4E, 0x83, 0xCD, 0xA4, 0xD0, 0xBD, 0x72, +0xBD, 0x71, 0xCE, 0x14, 0xAC, 0xEF, 0xBD, 0x92, +0xC6, 0x54, 0xC6, 0x73, 0xC6, 0x93, 0xC6, 0x73, +0xBE, 0x53, 0xDF, 0x36, 0xD6, 0xD5, 0xAD, 0x71, +0xC5, 0xD3, 0xCE, 0x35, 0xCE, 0x35, 0xBD, 0xB3, +0xCE, 0x14, 0xCE, 0x35, 0xD6, 0x76, 0xB5, 0x51, +0xC5, 0xB2, 0xAC, 0xEF, 0xA4, 0xAE, 0xB4, 0xEF, +0xEE, 0xD6, 0xDE, 0x74, 0xDE, 0x74, 0xDE, 0x74, +0xDE, 0x55, 0xBD, 0x51, 0xC5, 0xB2, 0xCE, 0x14, +0xD6, 0x33, 0xDE, 0x74, 0xDE, 0x74, 0xDE, 0x74, +0xD6, 0x54, 0xDE, 0x74, 0xC5, 0xF3, 0x8C, 0x0C, +0x41, 0xE6, 0x29, 0x64, 0x29, 0x44, 0x31, 0x85, +0x39, 0xC6, 0x42, 0x28, 0x4A, 0x69, 0x5A, 0xEB, +0x7B, 0xF0, 0x94, 0xB3, 0xAD, 0x55, 0x94, 0xB3, +0x5A, 0xCB, 0x8C, 0x31, 0xC6, 0x18, 0xC6, 0x39, +0x84, 0x10, 0xDE, 0xDB, 0xE7, 0x1C, 0xD6, 0x7A, +0xB5, 0xB6, 0xCE, 0x79, 0x8C, 0x0F, 0x5A, 0xA9, +0x62, 0xE9, 0x8B, 0xEC, 0xB4, 0xEF, 0xC5, 0x92, +0xC5, 0x72, 0xB5, 0x31, 0xA4, 0xAF, 0xBD, 0x71, +0xCD, 0xD3, 0xBD, 0x51, 0xB5, 0x10, 0xBD, 0x51, +0xBD, 0x51, 0xBD, 0x51, 0xBD, 0x30, 0xBD, 0x30, +0xB5, 0x10, 0xB5, 0x10, 0xB4, 0xF0, 0xB4, 0xF0, +0xAC, 0xD0, 0xB4, 0xF0, 0xB5, 0x10, 0xB5, 0x10, +0xAC, 0xAF, 0xA4, 0x8F, 0xAC, 0xF0, 0xA4, 0xD0, +0x8B, 0xED, 0x42, 0x06, 0x39, 0xC6, 0x42, 0x07, +0x52, 0x68, 0x5A, 0xEB, 0x7B, 0xCF, 0x94, 0x92, +0x6B, 0x6D, 0x7B, 0xCF, 0x8C, 0x71, 0x84, 0x0F, +0x9C, 0x91, 0x52, 0x89, 0x39, 0xE7, 0x39, 0xE6, +0x31, 0xA5, 0x3A, 0x07, 0x42, 0x07, 0x42, 0x28, +0x52, 0xAA, 0x52, 0x8A, 0x63, 0x0C, 0x73, 0xD0, +0x84, 0x32, 0x94, 0xB4, 0x9C, 0xD4, 0xBD, 0xF8, +0xAD, 0x76, 0xB5, 0xB7, 0x94, 0x92, 0xAD, 0x55, +0xC5, 0xF8, 0xC6, 0x18, 0xBD, 0xB7, 0xB5, 0x56, +0xB5, 0x97, 0xBD, 0xB7, 0xA4, 0xF4, 0xCE, 0x39, +0xEE, 0xFB, 0xDE, 0x79, 0xCD, 0xD5, 0xC5, 0x73, +0xB5, 0x31, 0xAC, 0xD1, 0x94, 0x4F, 0xBD, 0x93, +0xC5, 0x93, 0xCD, 0xD3, 0xD5, 0xF4, 0xD6, 0x14, +0xCD, 0xB3, 0xCD, 0xB3, 0xD5, 0xF4, 0xDE, 0x55, +0xC5, 0xB3, 0xBD, 0x51, 0xBD, 0x31, 0xC5, 0x51, +0xCD, 0xB3, 0xDE, 0x55, 0xDE, 0x35, 0xDE, 0x34, +0xDE, 0x55, 0xCD, 0x92, 0xCD, 0x92, 0xBD, 0x30, +0xB4, 0xF0, 0xAC, 0xD0, 0xD6, 0x56, 0xC6, 0x15, +0xC5, 0xF5, 0xC6, 0x36, 0xC6, 0x15, 0xBD, 0xD4, +0xCE, 0x36, 0xCE, 0x35, 0xC5, 0xD4, 0xCE, 0x35, +0xD6, 0x96, 0xDE, 0x96, 0xDE, 0x96, 0xD6, 0x76, +0xCE, 0x35, 0xCE, 0x14, 0xC6, 0x14, 0xCE, 0x56, +0xCE, 0x56, 0xCE, 0x15, 0xCE, 0x35, 0xCE, 0x56, +0xCE, 0x35, 0xA4, 0xB0, 0xAC, 0xD1, 0xE5, 0xF4, +0xED, 0xD3, 0xE5, 0xF4, 0xCD, 0x52, 0xC5, 0x32, +0xDD, 0x93, 0xDD, 0xB2, 0xDD, 0x51, 0xE6, 0x14, +0xF6, 0xF9, 0xE6, 0xD8, 0xE6, 0xF9, 0xE6, 0xB8, +0xE6, 0xB7, 0xE6, 0xB7, 0xE6, 0x76, 0xE6, 0x14, +0xE5, 0xB3, 0xE5, 0xB2, 0xE5, 0xB3, 0xDD, 0xB3, +0xE6, 0x55, 0xEF, 0x19, 0x94, 0x90, 0xBD, 0x94, +0xCE, 0x15, 0xBD, 0x93, 0xB5, 0x73, 0xC5, 0xD4, +0xD6, 0x35, 0xDE, 0x97, 0xE6, 0xD9, 0xBD, 0x75, +0x94, 0x51, 0x9C, 0x91, 0xAD, 0x34, 0xD5, 0xF7, +0xB5, 0x13, 0x7B, 0x4C, 0x52, 0x49, 0x5A, 0xAA, +0x73, 0x8C, 0x84, 0x6E, 0x6C, 0x2B, 0x42, 0xE6, +0x19, 0x62, 0x10, 0xE2, 0x19, 0x23, 0x21, 0x84, +0x19, 0x42, 0x4B, 0x48, 0x7C, 0xED, 0x9D, 0xF1, +0x8D, 0x90, 0x95, 0x8F, 0x85, 0x4D, 0x53, 0xC8, +0x22, 0x03, 0x4B, 0x07, 0x63, 0xEA, 0x19, 0x62, +0x19, 0x42, 0x3A, 0x65, 0x42, 0xC6, 0x63, 0xC9, +0x95, 0x70, 0x53, 0x68, 0x63, 0xEA, 0x84, 0xED, +0x95, 0x90, 0x7C, 0xEC, 0x7D, 0x0C, 0x95, 0xAF, +0x7B, 0x6C, 0x73, 0x4B, 0x73, 0x6B, 0x7B, 0x8C, +0x83, 0xAC, 0x83, 0xCD, 0x83, 0xCD, 0x8B, 0xED, +0x8B, 0xED, 0x94, 0x0D, 0x94, 0x2E, 0x9C, 0x6E, +0xA4, 0x6F, 0xA4, 0x8F, 0xA4, 0x2D, 0xA4, 0x2E, +0xA4, 0x6E, 0xA4, 0x6E, 0xA4, 0x6E, 0xA4, 0x6E, +0xA4, 0x6E, 0xA4, 0x8E, 0xAC, 0xAF, 0xA4, 0x8E, +0xAC, 0xCF, 0xAC, 0xAE, 0xBD, 0x30, 0xCD, 0x92, +0xCD, 0xB2, 0xBD, 0x30, 0xD5, 0xF3, 0xDE, 0x34, +0xDE, 0x54, 0xE6, 0x55, 0xEE, 0x76, 0xEE, 0x75, +0xB4, 0xEF, 0xA4, 0x4D, 0x9C, 0x2C, 0xBD, 0x31, +0xA4, 0x4E, 0xB5, 0x10, 0xCD, 0xB3, 0xC5, 0x30, +0xCD, 0x51, 0xB4, 0xCF, 0xAC, 0x8F, 0xA4, 0x6E, +0x94, 0x0D, 0xAC, 0xF0, 0xB5, 0x31, 0xA4, 0xCF, +0x94, 0x6E, 0x83, 0xED, 0x8C, 0x2E, 0x8C, 0x0D, +0x8B, 0xED, 0x73, 0x6B, 0xA4, 0xD0, 0x9C, 0x8E, +0xB5, 0x51, 0xD6, 0x75, 0xB5, 0x71, 0xBD, 0xB3, +0xCE, 0x75, 0xC6, 0x74, 0xC6, 0x74, 0xC6, 0x54, +0xC6, 0x54, 0xD6, 0xD6, 0xC6, 0x34, 0xBD, 0xD3, +0xBD, 0xB3, 0xC5, 0xF4, 0xC5, 0xD4, 0xC5, 0xF4, +0xC5, 0xF4, 0xC6, 0x14, 0xCE, 0x35, 0xB5, 0x51, +0xBD, 0xB2, 0xAC, 0xEF, 0xB4, 0xEF, 0xAC, 0xCE, +0xE6, 0x95, 0xDE, 0x54, 0xDE, 0x54, 0xDE, 0x54, +0xDE, 0x54, 0xCD, 0xB3, 0xCD, 0xD3, 0xD6, 0x34, +0xDE, 0x34, 0xDE, 0x54, 0xDE, 0x74, 0xE6, 0xB5, +0xDE, 0x94, 0xD6, 0x94, 0xCE, 0x33, 0xCD, 0xF3, +0xC5, 0xD3, 0x94, 0xCF, 0x52, 0xA8, 0x29, 0x64, +0x29, 0x65, 0x31, 0xA6, 0x31, 0xA6, 0x39, 0xE7, +0x52, 0xAA, 0x63, 0x4D, 0x73, 0x8E, 0x73, 0xAE, +0x6B, 0x4D, 0x8C, 0x52, 0x73, 0xAF, 0xAD, 0x76, +0x9C, 0xF4, 0xC6, 0x39, 0xEF, 0x3D, 0xCE, 0x59, +0xC6, 0x18, 0xD6, 0xBA, 0x94, 0x51, 0x94, 0x90, +0x7B, 0xAC, 0x8C, 0x0D, 0xB5, 0x0F, 0xA4, 0xAE, +0x94, 0x2D, 0x94, 0x2E, 0x94, 0x6E, 0xB5, 0x31, +0xBD, 0x92, 0xBD, 0x72, 0xBD, 0x72, 0xC5, 0x93, +0xC5, 0x93, 0xCD, 0xD3, 0xC5, 0xB3, 0xC5, 0xD3, +0xC5, 0xB3, 0xCD, 0xD3, 0xC5, 0xD3, 0xC5, 0xB3, +0xC5, 0x72, 0xB5, 0x11, 0x94, 0x4E, 0x7B, 0x6B, +0x8B, 0xED, 0x83, 0xAC, 0xA4, 0xB0, 0xBD, 0x52, +0xA4, 0xB0, 0x73, 0x6B, 0x7B, 0xAD, 0x6B, 0x4B, +0x41, 0xE6, 0x4A, 0x48, 0x42, 0x28, 0x5A, 0xEB, +0x62, 0xEB, 0x52, 0xAA, 0x63, 0x2C, 0x6B, 0x4D, +0x8C, 0x30, 0x94, 0x91, 0x4A, 0x48, 0x39, 0xC6, +0x31, 0xA6, 0x39, 0xE7, 0x4A, 0x48, 0x4A, 0x68, +0x42, 0x07, 0x5A, 0xCB, 0x5A, 0xCB, 0x6B, 0x6E, +0x7B, 0xF0, 0x84, 0x32, 0x94, 0x93, 0xA4, 0xF5, +0x9C, 0xD4, 0xB5, 0x96, 0xC5, 0xF8, 0xA4, 0xF4, +0xB5, 0x76, 0xC5, 0xF8, 0xBD, 0xD7, 0xE6, 0xFB, +0xD6, 0x7A, 0xE6, 0xFC, 0xB5, 0x97, 0xAD, 0x35, +0xC5, 0xD7, 0xD6, 0x79, 0xDE, 0xBA, 0xD6, 0x38, +0xA4, 0xD2, 0xC5, 0xD5, 0xB5, 0x32, 0xCD, 0xF5, +0xE6, 0xB7, 0xE6, 0x76, 0xDE, 0x55, 0xE6, 0x96, +0xDE, 0x55, 0xDE, 0x55, 0xE6, 0x76, 0xE6, 0x96, +0xDE, 0x55, 0xD5, 0xD3, 0xDE, 0x14, 0xDE, 0x14, +0xDE, 0x55, 0xEE, 0xB6, 0xDE, 0x75, 0xDE, 0x55, +0xEE, 0x96, 0xD5, 0xF3, 0xD5, 0xB2, 0xAC, 0x8E, +0xAC, 0x8E, 0xAC, 0xF0, 0xD6, 0x56, 0xCE, 0x35, +0xC6, 0x15, 0xCE, 0x36, 0xCE, 0x36, 0xCE, 0x36, +0xCE, 0x56, 0xD6, 0x76, 0xBD, 0xD4, 0xCE, 0x15, +0xD6, 0x55, 0xD6, 0x55, 0xD6, 0x56, 0xD6, 0x55, +0xCE, 0x14, 0xCE, 0x15, 0xCE, 0x15, 0xD6, 0x56, +0xD6, 0x76, 0xD6, 0x56, 0xCE, 0x56, 0xCE, 0x35, +0xCE, 0x35, 0xA4, 0xD1, 0xA4, 0xB0, 0xEE, 0x35, +0xED, 0xD3, 0xF6, 0x35, 0xEE, 0x35, 0xEE, 0x15, +0xEE, 0x14, 0xED, 0xF4, 0xED, 0xD3, 0xEE, 0x76, +0xEE, 0xD8, 0xE6, 0xD8, 0xDE, 0xB7, 0xE6, 0xB8, +0xE6, 0xB7, 0xE6, 0x97, 0xE6, 0x56, 0xE5, 0xD3, +0xDD, 0x51, 0xDD, 0x71, 0xE5, 0x92, 0xE5, 0x92, +0xE6, 0x35, 0xEE, 0xF9, 0x9C, 0xB1, 0xC5, 0xD5, +0xC5, 0xF5, 0xC5, 0xB4, 0xCE, 0x36, 0xE6, 0xD8, +0xC5, 0xD5, 0xB5, 0x74, 0xBD, 0x96, 0xB5, 0x55, +0x8B, 0xF0, 0xBD, 0x75, 0xCD, 0xF7, 0xDE, 0x58, +0x9C, 0x0F, 0x83, 0x2C, 0x5A, 0x49, 0x52, 0x48, +0x52, 0x88, 0x6C, 0x0B, 0x4B, 0x27, 0x5B, 0x4A, +0x32, 0x06, 0x10, 0xE2, 0x11, 0x02, 0x19, 0x02, +0x19, 0x43, 0x5B, 0xCA, 0x74, 0x8C, 0x6C, 0x8B, +0x6C, 0xAC, 0x8D, 0x6E, 0x8D, 0x8F, 0x53, 0x87, +0x53, 0x89, 0x8D, 0x2F, 0x53, 0x88, 0x32, 0x65, +0x3A, 0xA5, 0x5B, 0xC8, 0x64, 0x09, 0x7D, 0x0D, +0xB6, 0x93, 0x74, 0x8B, 0x64, 0x09, 0x74, 0x8C, +0x9D, 0xB0, 0x95, 0x4F, 0x64, 0x2A, 0xAE, 0x93, +0x73, 0x2B, 0x7B, 0x8C, 0x7B, 0x6C, 0x83, 0xAC, +0x8C, 0x2E, 0x94, 0x4F, 0x8C, 0x0E, 0x9C, 0x8F, +0x9C, 0x6F, 0x9C, 0x6F, 0x8C, 0x2D, 0x94, 0x2E, +0xA4, 0xD0, 0xB5, 0x11, 0xA4, 0x8F, 0xAC, 0xF0, +0xA4, 0xAF, 0xA4, 0x6E, 0xA4, 0x6E, 0xA4, 0x8E, +0x94, 0x0C, 0x8B, 0xCB, 0x8B, 0xAB, 0x83, 0x8A, +0x8B, 0xAB, 0x8B, 0xCB, 0x9C, 0x0C, 0x9C, 0x2C, +0x94, 0x0C, 0x94, 0x0C, 0x94, 0x0C, 0x9C, 0x2C, +0xA4, 0x6D, 0xA4, 0x8E, 0xAC, 0xAE, 0xB4, 0xCF, +0xAC, 0xCE, 0xAC, 0x8E, 0xA4, 0x6D, 0xB4, 0xCF, +0xAC, 0xD0, 0xB4, 0xF0, 0xB5, 0x10, 0xAC, 0xCF, +0xAC, 0xAE, 0x9C, 0x2D, 0x94, 0x0D, 0x83, 0xAB, +0x83, 0xAB, 0xA4, 0xD0, 0xA4, 0xCF, 0x94, 0x2D, +0x7B, 0x8B, 0x6B, 0x2A, 0x6B, 0x2B, 0x6B, 0x4A, +0x73, 0x4B, 0x73, 0x4A, 0xA4, 0xB0, 0xAC, 0xF0, +0xB5, 0x30, 0xD6, 0x55, 0xBD, 0x92, 0xC6, 0x35, +0xD6, 0x96, 0xCE, 0x75, 0xCE, 0x95, 0xC6, 0x75, +0xC6, 0x54, 0xCE, 0x75, 0xC6, 0x14, 0xB5, 0x72, +0xC5, 0xF4, 0xC6, 0x14, 0xC5, 0xD4, 0xCE, 0x14, +0xCE, 0x14, 0xCE, 0x14, 0xCE, 0x55, 0xB5, 0x72, +0x9C, 0x6E, 0x9C, 0x4D, 0xB4, 0xEF, 0xB5, 0x30, +0xE6, 0x95, 0xDE, 0x53, 0xE6, 0x74, 0xE6, 0xB5, +0xE6, 0x95, 0xCD, 0xF3, 0xCD, 0xF4, 0xD6, 0x34, +0xDE, 0x54, 0xDE, 0x54, 0xC5, 0xF1, 0xBD, 0xD1, +0xC6, 0x12, 0xD6, 0xB4, 0xD6, 0xB4, 0xC6, 0x33, +0xBD, 0xF2, 0xD6, 0xB5, 0xBD, 0xD2, 0x8C, 0x4D, +0x4A, 0x67, 0x31, 0x85, 0x31, 0xA5, 0x42, 0x28, +0x39, 0xE7, 0x42, 0x28, 0x52, 0x89, 0x52, 0xAA, +0x63, 0x2C, 0x6B, 0x4D, 0x6B, 0x4D, 0x8C, 0x52, +0xA5, 0x35, 0xB5, 0xB7, 0xD6, 0x9B, 0xB5, 0x96, +0xB5, 0xB6, 0x83, 0xF0, 0x8C, 0x51, 0xBD, 0xD7, +0x8C, 0x50, 0x94, 0x4F, 0xA4, 0x8F, 0x8C, 0x0D, +0x8C, 0x2E, 0x94, 0x90, 0xAD, 0x32, 0xB5, 0x72, +0xAD, 0x52, 0xBD, 0x93, 0xAD, 0x32, 0xB5, 0x73, +0xBD, 0xB3, 0xC5, 0xD4, 0xCE, 0x15, 0xCE, 0x15, +0xCE, 0x15, 0xCE, 0x15, 0xCE, 0x15, 0xC5, 0xD4, +0xCD, 0xF5, 0xC5, 0xD4, 0xBD, 0xB5, 0x9C, 0xF2, +0xA4, 0xF2, 0xAD, 0x53, 0x94, 0x4F, 0xB5, 0x32, +0xAD, 0x32, 0xB5, 0x73, 0xBD, 0x93, 0xB5, 0x73, +0x8C, 0x2E, 0x52, 0x68, 0x4A, 0x48, 0x8C, 0x51, +0x94, 0x91, 0x5A, 0xEB, 0x5A, 0xAA, 0x8C, 0x51, +0x73, 0x6D, 0x62, 0xEA, 0x52, 0x89, 0x4A, 0x28, +0x42, 0x07, 0x39, 0xE7, 0x3A, 0x07, 0x4A, 0x48, +0x42, 0x07, 0x4A, 0x49, 0x4A, 0x49, 0x52, 0xAB, +0x63, 0x0C, 0x7B, 0xF0, 0x9C, 0xF4, 0x7B, 0xD0, +0x9C, 0xD3, 0xB5, 0x96, 0xB5, 0xB7, 0xA4, 0xF4, +0xAD, 0x56, 0xB5, 0x76, 0xC6, 0x18, 0xA5, 0x15, +0x84, 0x11, 0xB5, 0x76, 0xAD, 0x76, 0x9C, 0xD4, +0x5A, 0xCB, 0x63, 0x0C, 0x94, 0x92, 0x83, 0xEF, +0x42, 0x08, 0x9C, 0xD3, 0x94, 0x50, 0xB5, 0x12, +0xC5, 0x93, 0xC5, 0x72, 0xC5, 0x72, 0xBD, 0x31, +0xA4, 0xAF, 0x9C, 0x8F, 0xA4, 0xB0, 0xAC, 0xB0, +0xAC, 0xD0, 0xA4, 0xB0, 0xAC, 0xD0, 0xC5, 0x72, +0xD5, 0xF3, 0xDE, 0x14, 0xDE, 0x55, 0xDE, 0x34, +0xDE, 0x14, 0xE6, 0x75, 0xC5, 0x71, 0xAC, 0xAE, +0xB5, 0x10, 0xA4, 0xD0, 0xD6, 0x36, 0xD6, 0x76, +0xCE, 0x56, 0xCE, 0x56, 0xCE, 0x56, 0xCE, 0x56, +0xCE, 0x56, 0xCE, 0x56, 0xC5, 0xF5, 0xD6, 0x56, +0xD6, 0x55, 0xD6, 0x55, 0xD6, 0x55, 0xD6, 0x56, +0xCE, 0x14, 0xC5, 0xF4, 0xD6, 0x56, 0xD6, 0x97, +0xD6, 0x97, 0xD6, 0x76, 0xD6, 0x97, 0xD6, 0x76, +0xCE, 0x15, 0xA4, 0xB0, 0xA4, 0x90, 0xE5, 0xF4, +0xED, 0xF4, 0xEE, 0x15, 0xED, 0xF4, 0xED, 0xF4, +0xE5, 0xF4, 0xEE, 0x14, 0xEE, 0x35, 0xEE, 0x97, +0xE6, 0xD8, 0xE6, 0xB8, 0xDE, 0x98, 0xE6, 0xB8, +0xE6, 0xB8, 0xE6, 0x97, 0xE6, 0x35, 0xE5, 0xB3, +0xE5, 0x71, 0xE5, 0x71, 0xE5, 0x92, 0xE5, 0xB2, +0xE6, 0x55, 0xEF, 0x19, 0xA4, 0xD1, 0xC5, 0xF5, +0xD6, 0x77, 0xE6, 0xD9, 0xD6, 0x78, 0xB5, 0x95, +0x94, 0x71, 0xBD, 0xB6, 0xBD, 0x96, 0xCD, 0xF7, +0x9C, 0x71, 0xB5, 0x13, 0xBD, 0x54, 0xAC, 0xB1, +0x82, 0xEB, 0x62, 0x48, 0x49, 0xC6, 0x4A, 0x48, +0x3A, 0x07, 0x6B, 0xEB, 0x52, 0xE8, 0x9C, 0xF2, +0x31, 0xE6, 0x10, 0xE2, 0x19, 0x02, 0x42, 0x25, +0x7C, 0x4A, 0x85, 0x0C, 0x74, 0xAC, 0x74, 0xED, +0x5C, 0x0A, 0x43, 0x47, 0x74, 0xAC, 0x6C, 0x8C, +0x74, 0xAD, 0x85, 0x0F, 0x3A, 0xE6, 0x2A, 0x43, +0x53, 0x88, 0x7D, 0x0D, 0x85, 0x2D, 0x95, 0x90, +0xB6, 0x73, 0x85, 0x2E, 0x7C, 0xCC, 0x7D, 0x0C, +0x95, 0x8F, 0xA5, 0xF2, 0x6C, 0x4B, 0x4B, 0x67, +0x8C, 0x50, 0x73, 0x6C, 0x7B, 0xAD, 0x83, 0xAD, +0x8C, 0x2E, 0x8C, 0x2E, 0x8C, 0x4E, 0x9C, 0xD0, +0xA4, 0xD0, 0x9C, 0xB0, 0x94, 0x6F, 0xA4, 0xD0, +0x94, 0x0D, 0xAC, 0xF0, 0xA4, 0xCF, 0xB5, 0x72, +0xBD, 0x92, 0xBD, 0x92, 0xC5, 0xB2, 0xB5, 0x31, +0xAC, 0xAF, 0xB4, 0xF0, 0xAC, 0xF0, 0xAC, 0xEF, +0xAC, 0xCF, 0xA4, 0xAF, 0xAC, 0xCF, 0xC5, 0xB2, +0xB5, 0x10, 0xA4, 0x8E, 0xA4, 0x8E, 0x9C, 0x6D, +0xAC, 0xEF, 0xA4, 0x6D, 0x9C, 0x4D, 0x9C, 0x6D, +0xA4, 0x8D, 0xA4, 0x6D, 0xA4, 0x6D, 0xA4, 0x8E, +0xAC, 0x8E, 0xAC, 0x8E, 0xAC, 0xAE, 0xAC, 0xAE, +0xAC, 0xAF, 0xAC, 0xAE, 0xAC, 0xAF, 0xAC, 0xAF, +0xAC, 0xCF, 0xA4, 0xAF, 0xA4, 0xAF, 0x9C, 0x6E, +0x94, 0x2D, 0x8B, 0xEC, 0x83, 0xCC, 0x83, 0xAB, +0x7B, 0x6B, 0x73, 0x4A, 0x94, 0x0D, 0x94, 0x0C, +0x8B, 0xEC, 0x9C, 0xAE, 0xA4, 0xCF, 0xBD, 0xB3, +0xC6, 0x14, 0xC6, 0x14, 0xC6, 0x35, 0xCE, 0x76, +0xC6, 0x35, 0xCE, 0x75, 0xC6, 0x34, 0xA4, 0xF0, +0xC5, 0xF4, 0xDE, 0xB7, 0xD6, 0x96, 0xD6, 0x76, +0xD6, 0x76, 0xD6, 0x76, 0xCE, 0x35, 0xCE, 0x55, +0xCE, 0x15, 0xC5, 0x92, 0xB4, 0xEF, 0xB5, 0x0F, +0xDE, 0x54, 0xEE, 0xB5, 0xE6, 0x95, 0xE6, 0x95, +0xDE, 0x75, 0xD6, 0x14, 0xC5, 0xB3, 0xCD, 0xD3, +0xDE, 0x55, 0xE6, 0xD6, 0xE6, 0xF6, 0xDE, 0xD5, +0xC6, 0x32, 0xAD, 0xAF, 0xB5, 0xD0, 0xCE, 0x94, +0xC6, 0x33, 0xC6, 0x33, 0xA5, 0x2F, 0xB5, 0x70, +0xA4, 0xEF, 0x6B, 0x6A, 0x42, 0x27, 0x31, 0xA6, +0x21, 0x24, 0x31, 0x85, 0x39, 0xE7, 0x42, 0x28, +0x52, 0x8A, 0x52, 0x8A, 0x4A, 0x69, 0x73, 0xAF, +0x9C, 0xF4, 0x7B, 0xD0, 0xBD, 0xB8, 0xA4, 0xF4, +0xB5, 0xB7, 0xAD, 0x56, 0xBD, 0xD8, 0xAD, 0x35, +0xE7, 0x1C, 0xD6, 0x79, 0xAC, 0xF2, 0x83, 0xEE, +0x73, 0x8D, 0x7B, 0xEE, 0x84, 0x0F, 0x8C, 0x50, +0x9C, 0xD1, 0xA4, 0xF1, 0x9C, 0xB0, 0x9C, 0xB1, +0xAD, 0x33, 0xB5, 0x94, 0xC5, 0xD5, 0xC5, 0xF5, +0xB5, 0x73, 0xBD, 0x94, 0xC5, 0xD5, 0xBD, 0xB4, +0xBD, 0xD4, 0xBD, 0xB4, 0xAD, 0x33, 0x94, 0xB1, +0x9C, 0xD1, 0x9C, 0xD1, 0x9C, 0x90, 0xB5, 0x52, +0xBD, 0x94, 0xBD, 0x73, 0xA4, 0xF1, 0x94, 0x8F, +0xBD, 0xD4, 0xCE, 0x16, 0x9C, 0xB1, 0x8C, 0x71, +0x94, 0x92, 0x7B, 0xEF, 0x63, 0x0B, 0x62, 0xEB, +0x5A, 0xAA, 0x31, 0xA5, 0x42, 0x28, 0x52, 0x89, +0x4A, 0x68, 0x39, 0xE7, 0x39, 0xC6, 0x42, 0x27, +0x39, 0xC6, 0x4A, 0x48, 0x52, 0xAA, 0x5A, 0xCB, +0x63, 0x2D, 0x84, 0x10, 0x7B, 0xF0, 0x73, 0x6E, +0xAD, 0x35, 0xC6, 0x39, 0xB5, 0x97, 0xC6, 0x18, +0xBD, 0xB7, 0x8C, 0x51, 0x6B, 0x4D, 0x5A, 0xAB, +0x9C, 0xB4, 0xB5, 0xB6, 0xBD, 0xD7, 0x9C, 0xB3, +0xAD, 0x55, 0x94, 0x92, 0x73, 0x6E, 0x6B, 0x4D, +0x73, 0x6E, 0xBD, 0xB6, 0xC5, 0xF6, 0xC5, 0xB5, +0xD5, 0xF4, 0xCD, 0xB3, 0xD5, 0xF4, 0xD6, 0x15, +0xCD, 0xD4, 0xBD, 0x73, 0xA4, 0xB0, 0x94, 0x4F, +0x9C, 0x6F, 0x9C, 0x90, 0xA4, 0xB0, 0xA4, 0xB0, +0xAC, 0xD0, 0xAC, 0xD0, 0xAC, 0xD0, 0xAC, 0xD0, +0xAC, 0xD0, 0xA4, 0xAF, 0xA4, 0xAF, 0xBD, 0x11, +0xBD, 0x52, 0xBD, 0x93, 0xBD, 0x93, 0xB5, 0x52, +0xB5, 0x32, 0xAD, 0x12, 0xA4, 0xF1, 0xA4, 0xF1, +0x9C, 0xD1, 0x9C, 0xB0, 0x9C, 0x90, 0xA4, 0xF1, +0xB5, 0x72, 0xB5, 0x72, 0xAD, 0x32, 0xB5, 0x73, +0xAD, 0x32, 0xAD, 0x32, 0xD6, 0x76, 0xC6, 0x15, +0xC5, 0xF4, 0xD6, 0x56, 0xC5, 0xD4, 0xC5, 0xF5, +0xB5, 0x73, 0xAC, 0xF2, 0xAC, 0xF1, 0xDD, 0xF4, +0xF6, 0x35, 0xEE, 0x14, 0xEE, 0x15, 0xEE, 0x35, +0xEE, 0x35, 0xEE, 0x56, 0xEE, 0x97, 0xEE, 0xF9, +0xEE, 0xF9, 0xEE, 0xF9, 0xEE, 0xF9, 0xEE, 0xF9, +0xEE, 0xF9, 0xEE, 0xD7, 0xEE, 0x97, 0xEE, 0x14, +0xE5, 0xB2, 0xED, 0xB3, 0xED, 0xB2, 0xED, 0xD3, +0xEE, 0x56, 0xEE, 0xF9, 0xC5, 0xF6, 0xE6, 0xB9, +0xB5, 0x74, 0x83, 0xEF, 0x9C, 0xB3, 0xC5, 0xD6, +0xB5, 0x55, 0xB5, 0x75, 0xB5, 0x35, 0xBD, 0x75, +0x9C, 0x71, 0x93, 0xEF, 0x83, 0x4C, 0x72, 0xA9, +0x62, 0x27, 0x49, 0xC6, 0x29, 0x24, 0x31, 0xA6, +0x4A, 0x68, 0x63, 0x6B, 0x9C, 0xF2, 0x94, 0xB1, +0x3A, 0x07, 0x42, 0x27, 0x7B, 0xCE, 0xA5, 0x11, +0xDE, 0xD4, 0xCE, 0x92, 0x74, 0x8C, 0x85, 0x0E, +0x53, 0xC9, 0x4B, 0x89, 0x5C, 0x0B, 0x64, 0x4B, +0x74, 0xCE, 0x74, 0x8D, 0x32, 0xA5, 0x32, 0x84, +0x53, 0xA8, 0x8D, 0x8F, 0x8D, 0x8F, 0x95, 0xB0, +0xAE, 0x33, 0x8D, 0x4E, 0x7D, 0x0D, 0x7D, 0x0C, +0x64, 0x6A, 0x6C, 0x6B, 0x9D, 0xD0, 0x7C, 0xEC, +0xC5, 0xF8, 0x7B, 0x8D, 0x7B, 0x8C, 0x7B, 0xAD, +0x94, 0x6F, 0x94, 0x6F, 0x8C, 0x4E, 0x8C, 0x4E, +0x94, 0x6E, 0x94, 0x6F, 0xA4, 0xF1, 0xAD, 0x32, +0x83, 0xCC, 0x9C, 0x8E, 0xA4, 0xF0, 0xAD, 0x31, +0xAD, 0x31, 0xA4, 0xF0, 0xA4, 0xCF, 0x9C, 0xAF, +0x8B, 0xEC, 0xA4, 0xAE, 0xAC, 0xCF, 0xAC, 0xEF, +0xAD, 0x10, 0xAC, 0xCF, 0xA4, 0xAE, 0xCE, 0x14, +0xD6, 0x35, 0xCD, 0xF4, 0xCE, 0x14, 0xC5, 0xD3, +0xD6, 0x14, 0xAC, 0xF0, 0x9C, 0x8E, 0x94, 0x2C, +0x8B, 0xEC, 0x83, 0xCB, 0x94, 0x2C, 0x8B, 0xEC, +0x94, 0x2D, 0x9C, 0x6D, 0xA4, 0xAF, 0xB5, 0x10, +0xBD, 0x72, 0xBD, 0x31, 0xB5, 0x10, 0xB5, 0x31, +0xA4, 0xAE, 0xA4, 0xAE, 0xAC, 0xCF, 0xAC, 0xCF, +0xB4, 0xF0, 0xB4, 0xF0, 0xB4, 0xF0, 0xAC, 0xF0, +0xAC, 0xF0, 0xA4, 0xCF, 0xA4, 0x8E, 0xAC, 0xCF, +0xA4, 0x8E, 0x9C, 0x8D, 0x94, 0x2D, 0x94, 0x0C, +0x8C, 0x0C, 0x94, 0x0D, 0x8C, 0x2D, 0xB5, 0x72, +0xAD, 0x51, 0xBD, 0xD3, 0xCE, 0x53, 0xDE, 0xF6, +0xD6, 0x95, 0xAD, 0x71, 0x94, 0x6E, 0x94, 0x4E, +0x9C, 0x8E, 0x9C, 0x6E, 0x9C, 0x6E, 0xA4, 0xAF, +0xB5, 0x31, 0xB5, 0x10, 0xA4, 0xAE, 0xAC, 0xCE, +0xA4, 0x8D, 0x9C, 0x6D, 0x9C, 0x2C, 0x94, 0x2C, +0x94, 0x2C, 0x9C, 0x6D, 0x9C, 0x8E, 0xA4, 0xAE, +0xAC, 0xEF, 0xB5, 0x30, 0xB5, 0x30, 0xC5, 0xB2, +0xD6, 0x33, 0xCE, 0x53, 0xB5, 0x70, 0xBD, 0xD2, +0xCE, 0x75, 0xBD, 0xD2, 0xAD, 0x30, 0xA4, 0xCE, +0xA4, 0xCE, 0x83, 0xEC, 0x7B, 0xCC, 0x5A, 0xA8, +0x42, 0x06, 0x31, 0xA6, 0x31, 0xA5, 0x31, 0xA5, +0x42, 0x27, 0x31, 0xA6, 0x31, 0xA6, 0x52, 0xAA, +0x6B, 0x8D, 0x7B, 0xF0, 0xA4, 0xF4, 0xB5, 0xB7, +0xBD, 0xD7, 0xAD, 0x35, 0xBD, 0xF8, 0xD6, 0x9A, +0xE7, 0x1C, 0xD6, 0xBA, 0xB5, 0x96, 0xA4, 0xF3, +0x8C, 0x30, 0x7B, 0xEF, 0x73, 0x8D, 0x73, 0xAE, +0x8C, 0x50, 0x7B, 0xAE, 0x73, 0x6D, 0x6B, 0x6D, +0x7B, 0xCE, 0x94, 0x71, 0x9C, 0xD2, 0x94, 0xB1, +0x94, 0x91, 0x9C, 0xD2, 0x94, 0xB1, 0x9C, 0xD2, +0x94, 0x91, 0x9C, 0xD2, 0x94, 0x71, 0x84, 0x2F, +0x94, 0x91, 0x8C, 0x4F, 0xA4, 0xD1, 0xBD, 0x93, +0xC5, 0xD4, 0xB5, 0x73, 0xA5, 0x12, 0xBD, 0x94, +0xD6, 0x56, 0xC5, 0xD4, 0xC5, 0xF5, 0x94, 0x91, +0x84, 0x30, 0x83, 0xEF, 0x73, 0x4D, 0x4A, 0x28, +0x39, 0xC6, 0x29, 0x44, 0x29, 0x24, 0x4A, 0x48, +0x52, 0x89, 0x39, 0xE7, 0x31, 0xA6, 0x39, 0xC6, +0x42, 0x07, 0x52, 0x89, 0x52, 0xAA, 0x63, 0x2C, +0x84, 0x10, 0x6B, 0x6D, 0x5A, 0xEB, 0x7B, 0xCF, +0x8C, 0x51, 0x9C, 0xD4, 0xBD, 0xD8, 0xC6, 0x18, +0x84, 0x10, 0x41, 0xE8, 0x41, 0xE8, 0x94, 0x92, +0x8C, 0x51, 0x7B, 0xAF, 0xB5, 0x96, 0xD6, 0x9A, +0xE6, 0xFB, 0xB5, 0x96, 0x9C, 0xB3, 0x8C, 0x31, +0x94, 0x71, 0xCE, 0x37, 0xDE, 0xB8, 0xC5, 0xF6, +0xCE, 0x16, 0xBD, 0x73, 0x9C, 0x6F, 0x8C, 0x0E, +0xA4, 0xD1, 0x9C, 0x90, 0x94, 0x6F, 0x7B, 0x8C, +0x7B, 0xAD, 0x8C, 0x0E, 0x83, 0xCD, 0x83, 0xAD, +0x94, 0x2F, 0x83, 0xCD, 0x83, 0xAD, 0x94, 0x2E, +0xA4, 0xB0, 0xB5, 0x53, 0xBD, 0x93, 0xBD, 0x73, +0xB5, 0x12, 0xB5, 0x52, 0xBD, 0x93, 0xB5, 0x52, +0xB5, 0x52, 0xBD, 0x94, 0xC5, 0xD4, 0xC5, 0xD4, +0xC5, 0xB4, 0xBD, 0x94, 0xBD, 0x94, 0xBD, 0x73, +0xAD, 0x32, 0xB5, 0x53, 0xB5, 0x32, 0xAD, 0x12, +0xAD, 0x12, 0xAC, 0xF1, 0xA4, 0xD1, 0xA4, 0xD1, +0xAD, 0x11, 0xA4, 0xF1, 0xA4, 0xD1, 0xAD, 0x11, +0xAC, 0xF1, 0xA4, 0xB0, 0x94, 0x2E, 0xBD, 0x52, +0xD5, 0x93, 0xCD, 0x72, 0xCD, 0x93, 0xDD, 0xF5, +0xDE, 0x15, 0xEE, 0x97, 0xEE, 0xD8, 0xEF, 0x19, +0xEF, 0x1A, 0xE7, 0x19, 0xEF, 0x1A, 0xEF, 0x1A, +0xEE, 0xF9, 0xEE, 0xB8, 0xEE, 0xD8, 0xF6, 0xB7, +0xF6, 0x76, 0xF6, 0x55, 0xEE, 0x55, 0xEE, 0x56, +0xEE, 0x98, 0xD6, 0x37, 0x9C, 0xB2, 0x8C, 0x10, +0xBD, 0x96, 0xB5, 0x55, 0xC5, 0xD7, 0xBD, 0x95, +0xAD, 0x34, 0x8C, 0x30, 0x9C, 0xB2, 0x8C, 0x10, +0x7B, 0xAE, 0x6B, 0x0B, 0x52, 0x07, 0x39, 0x44, +0x62, 0x69, 0x41, 0xE7, 0x21, 0x03, 0x21, 0x03, +0x21, 0x44, 0x31, 0xA6, 0x63, 0x2C, 0x6B, 0x4D, +0x63, 0x0C, 0xBD, 0xD5, 0xAD, 0x32, 0xB5, 0x52, +0xEF, 0x17, 0xEF, 0x16, 0x84, 0xCE, 0x74, 0x8C, +0x4B, 0xA9, 0x6C, 0x8D, 0x74, 0xAE, 0x74, 0xAE, +0x74, 0xCE, 0x5B, 0xEA, 0x3A, 0xE5, 0x3B, 0x06, +0x53, 0xC8, 0x8D, 0x6E, 0x95, 0x90, 0x9D, 0xD1, +0xA6, 0x32, 0x8D, 0x6F, 0x7D, 0x0D, 0x85, 0x2D, +0x74, 0xCC, 0x32, 0x84, 0x53, 0x88, 0x95, 0x6E, +0xBD, 0xF8, 0x94, 0x72, 0x7B, 0x6C, 0x84, 0x0D, +0x9C, 0xD0, 0xA4, 0xF1, 0x9C, 0xD1, 0x9C, 0x90, +0x94, 0x8F, 0x94, 0x90, 0x8C, 0x6F, 0x7B, 0xAC, +0x73, 0x8B, 0x8C, 0x2D, 0xA5, 0x10, 0xAD, 0x11, +0xAD, 0x31, 0xA4, 0xF0, 0xA4, 0xD0, 0xA4, 0xF0, +0x9C, 0xD0, 0xAC, 0xF0, 0xA4, 0xAF, 0xA4, 0x8E, +0xA4, 0x8E, 0xA4, 0x8E, 0xA4, 0xAE, 0xBD, 0xB2, +0xBD, 0xB2, 0xC5, 0xD3, 0xCD, 0xF4, 0xD6, 0x34, +0xD6, 0x75, 0xCD, 0xF4, 0xCE, 0x35, 0xCE, 0x15, +0xCE, 0x15, 0xCD, 0xF4, 0xCD, 0xF4, 0xC5, 0xD4, +0xBD, 0xB3, 0xBD, 0xB3, 0xCD, 0xF4, 0xD6, 0x56, +0xD6, 0x35, 0xCD, 0xF3, 0xCE, 0x14, 0xDE, 0x55, +0xAC, 0xCF, 0xA4, 0xAF, 0xB5, 0x30, 0xAC, 0xCF, +0xA4, 0xCF, 0x9C, 0x6E, 0x94, 0x2D, 0x94, 0x0C, +0x94, 0x0C, 0x94, 0x2D, 0x94, 0x2D, 0x9C, 0x6D, +0xA4, 0x8E, 0xAC, 0xCF, 0xA4, 0xAE, 0xAC, 0xCF, +0xA4, 0xAF, 0xA4, 0x8E, 0xA4, 0xCF, 0xBD, 0x92, +0x9C, 0xAE, 0x9C, 0xAD, 0xA4, 0xEE, 0xB5, 0xB0, +0xD6, 0xF5, 0xE7, 0x77, 0xD6, 0xB5, 0xBD, 0x92, +0xC5, 0xB3, 0xC5, 0xB3, 0xBD, 0x52, 0x94, 0x4D, +0x93, 0xEC, 0x94, 0x2C, 0xA4, 0x8D, 0xAC, 0xAE, +0x9C, 0x6D, 0x9C, 0x6E, 0xAC, 0xEF, 0xB5, 0x10, +0xA4, 0xAE, 0xA4, 0xAE, 0xA4, 0xAE, 0xA4, 0xAE, +0xAC, 0xCF, 0xAC, 0xEF, 0xAC, 0xCF, 0x9C, 0x6D, +0xA4, 0x8E, 0xA4, 0x8E, 0x9C, 0x4D, 0x8C, 0x2C, +0xBD, 0xD3, 0xB5, 0xB2, 0x9C, 0xAE, 0x9C, 0x8D, +0xA5, 0x2F, 0xB5, 0xD1, 0xB5, 0xF1, 0xB5, 0xF1, +0xA5, 0x70, 0x7C, 0x0C, 0x42, 0x26, 0x29, 0x64, +0x31, 0x86, 0x29, 0x44, 0x31, 0xA6, 0x39, 0xE7, +0x4A, 0x69, 0x73, 0x8E, 0x94, 0xB3, 0x94, 0x72, +0x8C, 0x51, 0xAD, 0x35, 0xA5, 0x15, 0x84, 0x10, +0x9C, 0xB3, 0x8C, 0x31, 0x6B, 0x4D, 0x8C, 0x51, +0x94, 0x71, 0xAD, 0x55, 0x6B, 0x6D, 0x63, 0x2C, +0x63, 0x4C, 0x63, 0x2C, 0x5A, 0xCA, 0x52, 0xAA, +0x6B, 0x4D, 0x7B, 0xCE, 0x84, 0x30, 0x8C, 0x50, +0x73, 0xAE, 0x84, 0x30, 0x84, 0x30, 0x8C, 0x50, +0x7B, 0xEF, 0x73, 0xAE, 0x84, 0x0F, 0x84, 0x0F, +0x84, 0x0E, 0x7B, 0xAD, 0x9C, 0xB1, 0xB5, 0x52, +0xBD, 0xB4, 0xAD, 0x53, 0xA5, 0x32, 0xD6, 0x77, +0xCE, 0x15, 0xBD, 0x94, 0xB5, 0x74, 0xB5, 0x74, +0x84, 0x0F, 0x94, 0x71, 0x73, 0x8D, 0x39, 0xE7, +0x31, 0x65, 0x29, 0x44, 0x29, 0x44, 0x31, 0xA5, +0x52, 0x88, 0x39, 0xE6, 0x31, 0x85, 0x31, 0xA6, +0x3A, 0x07, 0x52, 0xCA, 0x63, 0x2C, 0x5A, 0xEB, +0x52, 0xAA, 0x4A, 0x69, 0x63, 0x0C, 0x6B, 0x6E, +0x84, 0x11, 0x9C, 0xD4, 0xBD, 0xF8, 0x9C, 0xD3, +0x9C, 0xB3, 0x6B, 0x4D, 0x63, 0x0C, 0xA4, 0xD3, +0x6B, 0x4D, 0x6B, 0x2D, 0x83, 0xF0, 0xAD, 0x35, +0xC5, 0xF8, 0x8C, 0x31, 0x73, 0x6E, 0x7B, 0xAE, +0x73, 0x6D, 0x9C, 0xB2, 0x6B, 0x0C, 0x4A, 0x4A, +0xC5, 0xD6, 0xFF, 0x7B, 0xCD, 0xF6, 0x83, 0xEF, +0x73, 0x6C, 0x9C, 0x70, 0xBD, 0x94, 0xCE, 0x16, +0xC5, 0xD5, 0xC5, 0xD5, 0xAD, 0x12, 0xAC, 0xF2, +0xAD, 0x12, 0x9C, 0xB0, 0x94, 0x4F, 0xA4, 0xD0, +0xAD, 0x31, 0xBD, 0x93, 0xC5, 0xB4, 0xBD, 0x73, +0x9C, 0x90, 0x94, 0x6F, 0x83, 0xCD, 0x94, 0x2E, +0xA4, 0xF1, 0xA4, 0xB0, 0x9C, 0x8F, 0xB5, 0x32, +0xC5, 0xD5, 0x9C, 0x90, 0xAD, 0x12, 0x94, 0x6F, +0xA4, 0xF1, 0xB5, 0x53, 0xC5, 0xD5, 0xBD, 0x73, +0xBD, 0x73, 0xBD, 0x73, 0xB5, 0x53, 0xAD, 0x32, +0xAD, 0x12, 0xAD, 0x11, 0xA4, 0xD1, 0xA4, 0xD1, +0xA4, 0xF1, 0xA4, 0xD1, 0xA4, 0xB1, 0xA4, 0xD1, +0xAC, 0xF2, 0xAD, 0x12, 0xAD, 0x12, 0xAD, 0x12, +0xAC, 0xF2, 0xA4, 0xD1, 0xA4, 0xD2, 0xA4, 0xF2, +0xA4, 0xD2, 0x9C, 0xD2, 0x9C, 0xD2, 0x9C, 0xD2, +0xA4, 0xD2, 0xA4, 0xD2, 0xA4, 0xD1, 0xB5, 0x33, +0xCD, 0xB5, 0xC5, 0x74, 0xAC, 0xD2, 0xA4, 0xD2, +0xB5, 0x34, 0xBD, 0xB6, 0x94, 0x92, 0xAD, 0x34, +0xCE, 0x18, 0xBD, 0x75, 0xB5, 0x75, 0xA4, 0xF3, +0x94, 0x30, 0x6A, 0xEC, 0x73, 0x4D, 0x52, 0x69, +0x5A, 0xAA, 0x52, 0x48, 0x41, 0xA6, 0x39, 0x85, +0x7B, 0x6D, 0x31, 0x85, 0x21, 0x24, 0x21, 0x24, +0x21, 0x24, 0x31, 0x65, 0x73, 0x6C, 0xA5, 0x13, +0xA4, 0xF2, 0xBD, 0x94, 0xB5, 0x52, 0xB5, 0x32, +0xEF, 0x17, 0xEE, 0xF7, 0x84, 0xAD, 0x64, 0x2B, +0x64, 0x4C, 0x7C, 0xEF, 0x85, 0x10, 0x84, 0xEF, +0x74, 0xCE, 0x53, 0xC9, 0x43, 0x46, 0x43, 0x66, +0x4B, 0xA7, 0x85, 0x2D, 0x95, 0x8F, 0x9D, 0xD1, +0xA5, 0xF2, 0x95, 0xB0, 0x8D, 0x6F, 0x95, 0xB0, +0x85, 0x2E, 0x21, 0xE3, 0x21, 0xE3, 0x3A, 0xC5, +0x5A, 0xCB, 0xA4, 0xF3, 0x7B, 0x8C, 0x8C, 0x2E, +0x9C, 0xD0, 0xA4, 0xD1, 0xA4, 0xF1, 0xA5, 0x12, +0xA5, 0x11, 0xA4, 0xF1, 0xA4, 0xD1, 0xAD, 0x32, +0x94, 0x6F, 0xA5, 0x12, 0xB5, 0x93, 0xB5, 0x72, +0xB5, 0x73, 0xAD, 0x52, 0xAD, 0x52, 0xC6, 0x16, +0xE7, 0x1B, 0xF7, 0xBE, 0xFF, 0xFF, 0xFF, 0xDE, +0xEF, 0x3C, 0xC5, 0xF6, 0xAD, 0x11, 0xBD, 0xB2, +0xBD, 0x92, 0xBD, 0xB3, 0xBD, 0xB3, 0xBD, 0xB3, +0xC5, 0xF3, 0xBD, 0xB3, 0xC5, 0xB3, 0xBD, 0x93, +0xCE, 0x14, 0xD6, 0x35, 0xC5, 0xF4, 0xBD, 0x92, +0xBD, 0xB3, 0xBD, 0xB3, 0xBD, 0xB3, 0xC5, 0xD4, +0xC5, 0xD3, 0xBD, 0x93, 0xC5, 0xD3, 0xCD, 0xF4, +0xA4, 0xAE, 0xB5, 0x10, 0xC5, 0xD3, 0xBD, 0x93, +0xBD, 0x72, 0xB5, 0x51, 0xAD, 0x31, 0xB5, 0x31, +0xB5, 0x31, 0xB5, 0x31, 0xBD, 0x92, 0xD6, 0x78, +0xEF, 0x5C, 0xFF, 0xDF, 0xFF, 0xFF, 0xF7, 0x9E, +0xDE, 0xDA, 0xBD, 0xD4, 0xB5, 0x71, 0xB5, 0x71, +0xBD, 0xB2, 0xB5, 0x71, 0xAD, 0x4F, 0x9C, 0xCD, +0xA5, 0x0F, 0xC6, 0x53, 0xCE, 0x94, 0xAD, 0x51, +0xB5, 0x52, 0xAC, 0xF0, 0x94, 0x6E, 0x7B, 0xAC, +0x7B, 0x8B, 0xA4, 0xAF, 0xAC, 0xAF, 0x7B, 0x8A, +0x52, 0x67, 0x52, 0x68, 0x62, 0xE9, 0x94, 0x4E, +0x73, 0x2A, 0x5A, 0xA8, 0x62, 0xE9, 0x6A, 0xE9, +0x6B, 0x0A, 0x7B, 0x8B, 0x94, 0x4D, 0x9C, 0x6D, +0xA4, 0x8E, 0xA4, 0xAE, 0x8C, 0x0C, 0x73, 0x69, +0x8C, 0x4D, 0xAD, 0x71, 0xAD, 0x30, 0xBD, 0x92, +0xB5, 0xF0, 0xAD, 0xEF, 0xA5, 0xAD, 0xA5, 0xCE, +0xAE, 0x0F, 0xBE, 0x73, 0xB5, 0xD2, 0x4A, 0x67, +0x31, 0x85, 0x31, 0x85, 0x31, 0xA6, 0x31, 0xA6, +0x39, 0xC6, 0x52, 0xAA, 0x6B, 0x6D, 0x6B, 0x6D, +0x84, 0x10, 0xA5, 0x14, 0xA5, 0x14, 0x8C, 0x51, +0x7B, 0xAE, 0x7B, 0xCF, 0x8C, 0x51, 0x8C, 0x71, +0x9C, 0xD3, 0xE7, 0x1C, 0x8C, 0x51, 0x84, 0x10, +0x63, 0x2C, 0x5A, 0xCB, 0x52, 0xAA, 0x52, 0xAA, +0x63, 0x2C, 0x6B, 0x6D, 0x7B, 0xCE, 0x84, 0x0F, +0x73, 0x8D, 0x7B, 0xEF, 0x7B, 0xEF, 0x73, 0xAE, +0x84, 0x30, 0x73, 0x8D, 0x9C, 0xD1, 0x5A, 0xA9, +0x39, 0xE7, 0x4A, 0x28, 0xA4, 0xD1, 0xAD, 0x32, +0xAD, 0x32, 0xA4, 0xF2, 0x9C, 0xF1, 0xAD, 0x53, +0xBD, 0xB4, 0xA5, 0x12, 0xAD, 0x53, 0xB5, 0xB4, +0xB5, 0x94, 0xBD, 0xD5, 0x9C, 0xB2, 0x4A, 0x69, +0x42, 0x07, 0x39, 0xA6, 0x31, 0x65, 0x31, 0x85, +0x4A, 0x48, 0x4A, 0x69, 0x4A, 0x69, 0x4A, 0x68, +0x4A, 0x69, 0x52, 0xAA, 0x4A, 0x89, 0x42, 0x28, +0x39, 0xE7, 0x4A, 0x49, 0x5A, 0xCB, 0x73, 0xAF, +0x84, 0x10, 0xA5, 0x14, 0x94, 0x92, 0x9C, 0xD3, +0xE6, 0xDB, 0xAD, 0x35, 0x8C, 0x10, 0xA4, 0xF4, +0x83, 0xCF, 0x5A, 0xAA, 0x52, 0x8A, 0x6B, 0x2C, +0x7B, 0x8E, 0x52, 0x69, 0x63, 0x0C, 0x7B, 0xCF, +0xB5, 0x75, 0xB5, 0x96, 0x52, 0x8B, 0x7B, 0xCF, +0xBD, 0xB6, 0xCE, 0x17, 0xEE, 0xFB, 0xEE, 0xFB, +0xC5, 0xB6, 0xCD, 0xF7, 0xDE, 0x98, 0xCE, 0x16, +0xDE, 0x98, 0xC5, 0xD5, 0x94, 0x50, 0x9C, 0x91, +0xBD, 0x94, 0xBD, 0x94, 0xA5, 0x11, 0xAC, 0xF1, +0xB5, 0x52, 0xBD, 0x94, 0xAD, 0x53, 0xAD, 0x12, +0xBD, 0xB4, 0xAD, 0x32, 0xAC, 0xF1, 0xB5, 0x53, +0xAD, 0x32, 0xBD, 0x94, 0xA4, 0xF1, 0xB5, 0x73, +0xC5, 0xD5, 0xA4, 0xF1, 0xAD, 0x12, 0x73, 0x4B, +0x9C, 0x8F, 0xAD, 0x11, 0xBD, 0x52, 0xBD, 0x93, +0xC5, 0xB3, 0xBD, 0x73, 0xC5, 0x93, 0xC5, 0xB4, +0xB5, 0x53, 0xB5, 0x11, 0xAC, 0xF1, 0xAC, 0xF1, +0xA4, 0xB0, 0xA4, 0xD0, 0x94, 0x2E, 0x8C, 0x2E, +0x94, 0x2E, 0x9C, 0x6F, 0xA4, 0xD1, 0xAC, 0xF2, +0xAC, 0xF2, 0xAD, 0x12, 0xA4, 0xD2, 0xA4, 0xB1, +0xA4, 0xB0, 0xAD, 0x32, 0xB5, 0x53, 0xAD, 0x12, +0xBD, 0x74, 0xB5, 0x34, 0xBD, 0x95, 0xC5, 0xB6, +0x9C, 0x71, 0xA4, 0xD2, 0xB5, 0x75, 0xC5, 0xB6, +0xCD, 0xD7, 0xBD, 0x75, 0xAD, 0x34, 0xA4, 0xF4, +0xB5, 0x34, 0xAC, 0xF3, 0x94, 0x51, 0x7B, 0x8E, +0x73, 0x6D, 0x5A, 0xAA, 0x4A, 0x48, 0x4A, 0x28, +0x41, 0xE7, 0x31, 0x44, 0x39, 0x65, 0x6A, 0xEB, +0x5A, 0xAA, 0x21, 0x03, 0x18, 0xE3, 0x31, 0xA6, +0x63, 0x2B, 0x8C, 0x2F, 0x94, 0x70, 0x94, 0x6F, +0xA4, 0xD1, 0xA4, 0xD1, 0xA4, 0xD1, 0xA4, 0xB1, +0xBD, 0x94, 0xBD, 0xB3, 0x5B, 0x69, 0x53, 0xA9, +0x64, 0x0C, 0x53, 0x8A, 0x6C, 0x4C, 0x85, 0x10, +0x85, 0x0F, 0x53, 0xC9, 0x4B, 0x87, 0x4B, 0x66, +0x53, 0xE9, 0x85, 0x2E, 0x8D, 0x6F, 0x8D, 0x8F, +0x9D, 0xF2, 0x9D, 0xD1, 0x8D, 0x8F, 0x85, 0x4E, +0x3A, 0x65, 0x11, 0x02, 0x19, 0x62, 0x3A, 0x85, +0x39, 0xE8, 0x9C, 0xF3, 0x73, 0x6B, 0x94, 0x6F, +0xA4, 0xF1, 0x9C, 0xD0, 0xA5, 0x12, 0xAD, 0x53, +0xAD, 0x53, 0xAD, 0x52, 0xAD, 0x53, 0xA5, 0x12, +0xB5, 0x93, 0xB5, 0x93, 0xB5, 0x93, 0xBD, 0xB3, +0xBD, 0xD4, 0xBD, 0xD4, 0xCE, 0x56, 0xE7, 0x1B, +0xF7, 0xBE, 0xE7, 0x3C, 0xB5, 0x96, 0xCE, 0x59, +0xFF, 0xDE, 0xEF, 0x3C, 0xCE, 0x36, 0xBD, 0xB3, +0xB5, 0x72, 0xB5, 0x72, 0xBD, 0xB3, 0xBD, 0xB3, +0xBD, 0xD3, 0xBD, 0xD3, 0xC5, 0xD4, 0xBD, 0x73, +0xB5, 0x72, 0xB5, 0x72, 0xB5, 0x72, 0xB5, 0x52, +0xBD, 0x93, 0xBD, 0x93, 0xB5, 0x93, 0xBD, 0x93, +0xBD, 0xB3, 0xBD, 0x93, 0xBD, 0xB3, 0xBD, 0x72, +0xA4, 0x8E, 0xAD, 0x10, 0xBD, 0x92, 0xBD, 0x93, +0xBD, 0xD4, 0xBD, 0xB3, 0xB5, 0x92, 0xB5, 0x72, +0xBD, 0x92, 0xBD, 0x93, 0xD6, 0x78, 0xF7, 0x7D, +0xFF, 0xDE, 0xC6, 0x18, 0xAD, 0x55, 0xE7, 0x1C, +0xF7, 0xBE, 0xEF, 0x5B, 0xD6, 0xB7, 0xC6, 0x53, +0xD6, 0xB5, 0xBD, 0xD1, 0xB5, 0x70, 0xA5, 0x2E, +0xAD, 0x4F, 0xB5, 0x90, 0xB5, 0xD1, 0xC5, 0xF3, +0xCD, 0xD4, 0xC5, 0xB3, 0xB5, 0x52, 0x9C, 0xB0, +0x8C, 0x0D, 0x9C, 0xB0, 0x73, 0x4A, 0x6B, 0x0A, +0x52, 0x68, 0x52, 0x68, 0x4A, 0x47, 0x4A, 0x27, +0x41, 0xE7, 0x42, 0x07, 0x52, 0x68, 0x4A, 0x68, +0x52, 0x88, 0x7B, 0xCC, 0x94, 0xAE, 0xA5, 0x2F, +0xA5, 0x4F, 0xAD, 0x4F, 0xAD, 0x70, 0xAD, 0x51, +0x9C, 0xD0, 0xB5, 0xB2, 0x94, 0xAF, 0x5A, 0xE9, +0x52, 0xE9, 0x7C, 0x0C, 0xA5, 0x0E, 0x84, 0x8A, +0x94, 0xEA, 0x9D, 0x4D, 0xAD, 0xB1, 0x63, 0x4A, +0x42, 0x27, 0x31, 0x85, 0x29, 0x85, 0x29, 0x85, +0x31, 0xA6, 0x42, 0x07, 0x4A, 0x49, 0x63, 0x0B, +0x6B, 0x4D, 0x94, 0x92, 0x7B, 0xF0, 0x84, 0x30, +0x6B, 0x4D, 0x6B, 0x4D, 0x52, 0x8A, 0x62, 0xEC, +0xB5, 0x96, 0xE7, 0x1C, 0xD6, 0xBA, 0xCE, 0x59, +0x84, 0x31, 0x73, 0x6D, 0x83, 0xCD, 0x7B, 0xCD, +0x7B, 0xCD, 0x7B, 0xAD, 0x7B, 0x8C, 0x73, 0x8C, +0x6B, 0x4C, 0x6B, 0x4C, 0x73, 0x6C, 0x63, 0x2B, +0xB5, 0x94, 0x6B, 0x6B, 0x94, 0x4F, 0x8B, 0xED, +0x8B, 0xEE, 0x7B, 0xAD, 0xAD, 0x32, 0xA5, 0x11, +0xAD, 0x32, 0xC6, 0x16, 0xB5, 0x94, 0x9C, 0xD1, +0xAD, 0x53, 0xA5, 0x13, 0xAD, 0x54, 0xBD, 0x94, +0xC5, 0xD5, 0xC6, 0x16, 0xCE, 0x36, 0x9C, 0xB1, +0x9C, 0xB1, 0xBD, 0xB5, 0xAD, 0x33, 0x73, 0x8D, +0x31, 0xA5, 0x4A, 0x68, 0x5A, 0xCA, 0x52, 0x89, +0x39, 0xE7, 0x41, 0xE7, 0x4A, 0x28, 0x42, 0x28, +0x4A, 0x48, 0x52, 0x8A, 0x6B, 0x6D, 0x73, 0x8E, +0x6B, 0x4D, 0x94, 0x93, 0x9C, 0xB3, 0xA4, 0xD3, +0xDE, 0x9A, 0xCD, 0xF7, 0x9C, 0xB3, 0x8C, 0x10, +0x8C, 0x50, 0x7B, 0xAE, 0x8C, 0x0F, 0x94, 0x2F, +0x5A, 0xAA, 0x5A, 0xAA, 0x73, 0x6D, 0xB5, 0x95, +0xBD, 0xD7, 0xAD, 0x55, 0xAD, 0x35, 0xA5, 0x14, +0xC5, 0xF7, 0xBD, 0xB6, 0x6B, 0x4D, 0xDE, 0xBA, +0xE6, 0xDB, 0x9C, 0xB2, 0xB5, 0x54, 0xA4, 0xB2, +0xA4, 0xF2, 0x94, 0x30, 0x6B, 0x0B, 0xC5, 0xD5, +0xCD, 0xF5, 0xD6, 0x56, 0xCD, 0xF5, 0xBD, 0x93, +0xC5, 0xD5, 0xDE, 0x97, 0xDE, 0x98, 0xD6, 0x77, +0x9C, 0xB1, 0xB5, 0x74, 0xC5, 0xF6, 0xAD, 0x32, +0xA4, 0xF1, 0xBD, 0xB4, 0xC5, 0xD5, 0xC5, 0xD5, +0xBD, 0xB4, 0xA4, 0xF1, 0xA4, 0xB1, 0x8C, 0x0E, +0x94, 0x4E, 0x94, 0x2E, 0x9C, 0x6F, 0xA4, 0x8F, +0xAC, 0xF0, 0xA4, 0xD0, 0x9C, 0x6E, 0xA4, 0xD0, +0xB5, 0x31, 0xAC, 0xF1, 0xAD, 0x11, 0xB5, 0x52, +0xBD, 0x73, 0xCD, 0xD4, 0xC5, 0x93, 0xB5, 0x11, +0xA4, 0xB0, 0x94, 0x0E, 0x94, 0x2E, 0xA4, 0x90, +0xB5, 0x12, 0xAD, 0x12, 0xAD, 0x12, 0xC5, 0xB4, +0xC5, 0xB3, 0xDE, 0x76, 0xDE, 0x77, 0xDE, 0x57, +0xB5, 0x54, 0x94, 0x30, 0x9C, 0x92, 0xAD, 0x14, +0x94, 0x71, 0xBD, 0x75, 0xA4, 0xD2, 0xAD, 0x34, +0xAD, 0x13, 0xAD, 0x13, 0xA4, 0xD2, 0x8C, 0x10, +0x8C, 0x30, 0x83, 0xAE, 0x6B, 0x0C, 0x62, 0xAA, +0x62, 0xCA, 0x52, 0x69, 0x39, 0xA6, 0x29, 0x44, +0x29, 0x04, 0x39, 0xA6, 0x73, 0x6D, 0x5A, 0xAA, +0x29, 0x44, 0x29, 0x64, 0x5A, 0xCA, 0x9C, 0xB0, +0xAD, 0x53, 0xB5, 0x53, 0xBD, 0x74, 0xBD, 0x94, +0xBD, 0x94, 0xB5, 0x53, 0xB5, 0x33, 0xB5, 0x53, +0xB5, 0x53, 0x94, 0xAF, 0x4B, 0x08, 0x53, 0x89, +0x32, 0x85, 0x22, 0x24, 0x2A, 0x65, 0x53, 0xAA, +0x8D, 0x70, 0x53, 0xC9, 0x43, 0x26, 0x2A, 0x64, +0x53, 0xC9, 0x74, 0xED, 0x7C, 0xED, 0x8D, 0x6F, +0xA5, 0xF2, 0x9D, 0xD2, 0x85, 0x2E, 0x3A, 0x85, +0x19, 0x22, 0x10, 0xE2, 0x21, 0x63, 0x63, 0xE9, +0x63, 0x6E, 0x8C, 0x71, 0x73, 0x6C, 0x8C, 0x4E, +0x94, 0x6F, 0xA5, 0x11, 0xAD, 0x32, 0x9C, 0xD0, +0xB5, 0x93, 0xB5, 0x93, 0xBD, 0xB4, 0xB5, 0x73, +0xBD, 0xB4, 0xBD, 0xD4, 0xC5, 0xF4, 0xC5, 0xF4, +0xC5, 0xF4, 0xBD, 0xF4, 0xE7, 0x1B, 0xF7, 0xBE, +0xA5, 0x34, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, +0x4A, 0x49, 0xF7, 0x9E, 0xEF, 0x3C, 0xD6, 0x57, +0xB5, 0x93, 0xB5, 0x72, 0xBD, 0x93, 0xB5, 0x72, +0xC5, 0xD4, 0xBD, 0xD4, 0xC5, 0xF4, 0xBD, 0xB4, +0xB5, 0x93, 0xA4, 0xF0, 0xAD, 0x52, 0xB5, 0x72, +0xBD, 0xB4, 0xB5, 0x93, 0xB5, 0x93, 0xB5, 0x93, +0xB5, 0x93, 0xBD, 0x93, 0xB5, 0x72, 0xB5, 0x10, +0xA4, 0x8E, 0xAD, 0x10, 0xCE, 0x14, 0xBD, 0x93, +0xBD, 0xB3, 0xB5, 0x73, 0xB5, 0x72, 0xAD, 0x10, +0xAD, 0x30, 0xC6, 0x15, 0xEF, 0x5C, 0xF7, 0x9D, +0x39, 0xE7, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, +0xA5, 0x14, 0xFF, 0xDE, 0xDF, 0x1A, 0xC6, 0x52, +0xC6, 0x93, 0xBE, 0x10, 0xA5, 0x2B, 0xA5, 0x6B, +0xAD, 0x8C, 0xAD, 0x8D, 0xC6, 0x31, 0xE6, 0xD6, +0xDE, 0x96, 0xD6, 0x55, 0xD6, 0x35, 0xC5, 0xB4, +0xA4, 0xF1, 0xAD, 0x12, 0x73, 0x4B, 0x7B, 0xAD, +0x7B, 0xAD, 0x63, 0x0A, 0x4A, 0x48, 0x42, 0x07, +0x42, 0x07, 0x4A, 0x48, 0x4A, 0x48, 0x4A, 0x48, +0x4A, 0x47, 0xA5, 0x70, 0xAE, 0x10, 0xAE, 0x30, +0xAE, 0x50, 0xAE, 0x10, 0x95, 0x2E, 0x9D, 0x30, +0x9C, 0xCF, 0x9C, 0xF1, 0x6B, 0x6C, 0x4A, 0x68, +0x5A, 0xEA, 0x7B, 0xAD, 0x6B, 0x4A, 0x6B, 0x4A, +0xA4, 0xEE, 0xBD, 0xB1, 0x8C, 0x4D, 0x52, 0x88, +0x6B, 0x4B, 0x52, 0x88, 0x42, 0x27, 0x29, 0x65, +0x31, 0x85, 0x39, 0xE7, 0x42, 0x28, 0x42, 0x07, +0x63, 0x0B, 0x84, 0x0F, 0x73, 0x8E, 0x4A, 0x69, +0x5A, 0xCB, 0x4A, 0x48, 0x39, 0xC7, 0x6B, 0x2D, +0xBD, 0xF8, 0xE7, 0x1C, 0xC6, 0x38, 0xCE, 0x59, +0xDE, 0xBB, 0x83, 0xEF, 0x83, 0xCE, 0x9C, 0xB1, +0x9C, 0x8F, 0x9C, 0x6F, 0x9C, 0x8E, 0xAD, 0x0F, +0x94, 0x6D, 0x94, 0x2D, 0x9C, 0x6E, 0x94, 0x2D, +0xD6, 0x56, 0x83, 0xEC, 0x9C, 0x4E, 0xA4, 0x8F, +0xAC, 0xF0, 0xAC, 0xD0, 0xA4, 0xF0, 0x94, 0x2E, +0x8C, 0x2E, 0x94, 0x90, 0x83, 0xEE, 0x8C, 0x4F, +0x9C, 0xB1, 0x8C, 0x91, 0x94, 0xB1, 0xA4, 0xF2, +0xAD, 0x53, 0xB5, 0x94, 0xC5, 0xF6, 0xBD, 0xD5, +0xC5, 0xF6, 0xBD, 0xD5, 0xC5, 0xF5, 0xC6, 0x15, +0x94, 0x70, 0x39, 0xE6, 0x42, 0x07, 0x39, 0xC6, +0x31, 0x85, 0x39, 0xA6, 0x42, 0x07, 0x4A, 0x28, +0x52, 0x89, 0x52, 0xAA, 0x6B, 0x4D, 0x6B, 0x4D, +0x42, 0x08, 0x83, 0xEF, 0xAD, 0x34, 0xB5, 0x34, +0xBD, 0x75, 0xB5, 0x55, 0x7B, 0xAE, 0x7B, 0x8D, +0x8C, 0x0F, 0x83, 0xCE, 0xA4, 0xB1, 0xBD, 0x53, +0x62, 0xA9, 0x52, 0x69, 0x62, 0xEB, 0x73, 0x4C, +0x5A, 0xCB, 0xB5, 0x76, 0xC6, 0x18, 0xA4, 0xF4, +0xCE, 0x39, 0xB5, 0x55, 0x63, 0x2D, 0xBD, 0xD8, +0xEF, 0x1C, 0xCD, 0xF7, 0xAD, 0x13, 0xA4, 0xD2, +0x83, 0xCE, 0x73, 0x2C, 0x73, 0x6D, 0xAD, 0x32, +0xAC, 0xF1, 0xCD, 0xF5, 0xDE, 0x56, 0xB5, 0x32, +0xC5, 0xB4, 0xDE, 0x56, 0xDE, 0x56, 0xDE, 0xB7, +0xC5, 0xF6, 0xC6, 0x17, 0xD6, 0x99, 0xCE, 0x58, +0xC5, 0xF6, 0xCE, 0x15, 0xCE, 0x15, 0xC5, 0xD4, +0xC5, 0xF5, 0xAD, 0x12, 0x9C, 0x90, 0xA4, 0xB0, +0x9C, 0xB0, 0x94, 0x4F, 0x94, 0x4E, 0x94, 0x2E, +0xA4, 0xB0, 0x9C, 0x8F, 0x8B, 0xED, 0x9C, 0x4E, +0xA4, 0xAF, 0xA4, 0x8F, 0xA4, 0xD0, 0xA4, 0xD0, +0xAC, 0xF0, 0xB5, 0x11, 0xB5, 0x11, 0xB5, 0x11, +0xB5, 0x11, 0xAC, 0xF0, 0xAC, 0xD0, 0xB5, 0x11, +0xC5, 0x73, 0xAD, 0x12, 0xB5, 0x53, 0xBD, 0x94, +0x9C, 0x4F, 0xDE, 0x57, 0xD6, 0x16, 0xCD, 0xD5, +0xBD, 0x74, 0xC5, 0xB5, 0xD6, 0x38, 0xC5, 0xB6, +0xA4, 0xD3, 0x94, 0x50, 0x83, 0xEF, 0xA4, 0xD3, +0x9C, 0x71, 0x8B, 0xEF, 0x83, 0x8E, 0x73, 0x2C, +0x62, 0xEA, 0x62, 0xAA, 0x4A, 0x28, 0x52, 0x28, +0x4A, 0x08, 0x39, 0xA6, 0x29, 0x24, 0x21, 0x04, +0x5A, 0xAB, 0xC5, 0xF8, 0x94, 0x92, 0x31, 0x65, +0x6B, 0x0B, 0x8C, 0x0E, 0x8C, 0x0E, 0x94, 0x2E, +0xA4, 0xB1, 0xB5, 0x32, 0xBD, 0x94, 0xC5, 0xF5, +0xBD, 0x93, 0xB5, 0x73, 0xC5, 0xD4, 0xAD, 0x11, +0x9C, 0xD0, 0x73, 0xCC, 0x4B, 0x49, 0x5B, 0xCA, +0x19, 0xC3, 0x21, 0xE4, 0x3A, 0xA6, 0x32, 0xA5, +0x74, 0xAD, 0x43, 0x27, 0x2A, 0x23, 0x19, 0xC2, +0x2A, 0x24, 0x5B, 0xEA, 0x5C, 0x0A, 0x6C, 0xAC, +0x9D, 0xF2, 0xA6, 0x12, 0x5B, 0xEA, 0x32, 0x65, +0x31, 0xE5, 0x19, 0x23, 0x4B, 0x08, 0x8D, 0x4E, +0x7B, 0xF0, 0x7B, 0xF0, 0x7B, 0x8D, 0x83, 0xED, +0x83, 0xCC, 0x7B, 0xAC, 0x83, 0xCC, 0x83, 0xCC, +0x8C, 0x0D, 0x8C, 0x2E, 0x94, 0x6E, 0x9C, 0x8F, +0x9C, 0x8F, 0x9C, 0xB0, 0x9C, 0xB0, 0x9C, 0xAF, +0xA4, 0xD0, 0xA5, 0x11, 0xEF, 0x7D, 0xEF, 0x5D, +0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x84, 0x10, 0xFF, 0xBE, 0xE6, 0xFA, +0xBD, 0xD4, 0xB5, 0x73, 0xB5, 0x72, 0xB5, 0x73, +0xBD, 0xB4, 0xBD, 0x93, 0xB5, 0x93, 0xAD, 0x52, +0xAD, 0x52, 0xB5, 0x93, 0xBD, 0xD4, 0xBD, 0xD4, +0xCE, 0x36, 0xC5, 0xF5, 0xBD, 0xB3, 0xBD, 0xB3, +0xBD, 0x93, 0xBD, 0xB3, 0xB5, 0x72, 0xAD, 0x10, +0xA4, 0x8E, 0xBD, 0x72, 0xC6, 0x14, 0xBD, 0xB3, +0xB5, 0x73, 0xAD, 0x52, 0xBD, 0x93, 0xAD, 0x31, +0xAD, 0x31, 0xCE, 0x37, 0xF7, 0x9E, 0x7B, 0xCF, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x08, 0x41, 0xEF, 0x5D, 0xF7, 0x9D, 0xC6, 0x72, +0xC6, 0x72, 0x9D, 0x4B, 0x95, 0x49, 0x8D, 0x07, +0x84, 0xC6, 0x84, 0xE6, 0x8C, 0xE9, 0xAD, 0x8F, +0xCE, 0x34, 0xE6, 0xB7, 0xE6, 0x96, 0xD6, 0x55, +0xD6, 0x15, 0xCD, 0xF5, 0x83, 0xCD, 0xBD, 0xB4, +0xB5, 0x74, 0xA4, 0xD1, 0x73, 0x4C, 0x52, 0x89, +0x52, 0x89, 0x52, 0x89, 0x73, 0x8D, 0x52, 0xA9, +0x42, 0x07, 0x5A, 0xE8, 0x6B, 0xC9, 0x84, 0x8B, +0x95, 0x6D, 0xAE, 0x31, 0xBE, 0xB4, 0xB6, 0x74, +0xB6, 0x13, 0xA5, 0x52, 0x5A, 0xEA, 0x4A, 0x48, +0x4A, 0x68, 0x63, 0x2B, 0x63, 0x0B, 0x63, 0x0A, +0xBD, 0x93, 0xA5, 0x11, 0x62, 0xE9, 0x84, 0x0E, +0xA4, 0xF1, 0x94, 0x4E, 0x8B, 0xED, 0x4A, 0x27, +0x29, 0x65, 0x39, 0xC6, 0x52, 0x89, 0x52, 0x89, +0x4A, 0x69, 0x52, 0xAA, 0x63, 0x0B, 0x42, 0x28, +0x31, 0xA6, 0x42, 0x08, 0x5A, 0xCA, 0x73, 0xAF, +0x7B, 0xAF, 0x9C, 0xF4, 0xA5, 0x35, 0xDF, 0x1B, +0xCE, 0x9A, 0xAD, 0x76, 0xBD, 0xD8, 0xC6, 0x19, +0x84, 0x10, 0x7B, 0x8C, 0x94, 0x6D, 0xAD, 0x8F, +0xA5, 0x2F, 0x9C, 0x6D, 0x94, 0x2D, 0x8C, 0x0C, +0xCE, 0x55, 0x9C, 0x8E, 0xB5, 0x11, 0x9C, 0x8E, +0xA4, 0xCF, 0x9C, 0x8F, 0xA4, 0xF1, 0xB5, 0x52, +0xAD, 0x12, 0xA4, 0xB0, 0x9C, 0xB1, 0x9C, 0x90, +0x94, 0x70, 0x8C, 0x4F, 0x94, 0x4F, 0x94, 0x4F, +0x8C, 0x2F, 0x94, 0x4F, 0x94, 0x4F, 0x94, 0x4F, +0x9C, 0x90, 0x94, 0x90, 0x9C, 0x90, 0x9C, 0xB0, +0x6B, 0x4B, 0x5A, 0xAA, 0x73, 0x6C, 0x4A, 0x48, +0x39, 0xE6, 0x29, 0x65, 0x31, 0x85, 0x52, 0xAA, +0x5A, 0xEB, 0x52, 0xAA, 0x73, 0x6E, 0x8C, 0x51, +0x73, 0x6E, 0xAD, 0x14, 0xD6, 0x38, 0xCD, 0xF7, +0xB5, 0x34, 0x94, 0x71, 0x52, 0x6A, 0x6B, 0x4D, +0x6B, 0x4D, 0x39, 0xA6, 0x41, 0xC7, 0x6A, 0xEA, +0x62, 0xAA, 0x39, 0x86, 0x39, 0x86, 0x41, 0xE7, +0x6B, 0x2D, 0xCE, 0x39, 0xCE, 0x38, 0x9C, 0xB3, +0x8C, 0x51, 0x94, 0x92, 0xAD, 0x35, 0xCE, 0x59, +0xE6, 0xFB, 0xCE, 0x17, 0x8C, 0x30, 0xB5, 0x55, +0xAD, 0x14, 0x83, 0xEF, 0x73, 0x6D, 0x6B, 0x4C, +0x7B, 0xAD, 0xBD, 0x93, 0xD6, 0x35, 0xC5, 0x93, +0xDE, 0x56, 0xE6, 0x97, 0xDE, 0x76, 0xDE, 0x97, +0xA4, 0xD2, 0xA5, 0x14, 0xBD, 0xF7, 0xDE, 0xDB, +0xE6, 0xDA, 0xE6, 0xB8, 0xE6, 0xB8, 0xDE, 0x77, +0xD6, 0x56, 0xAD, 0x12, 0x9C, 0x6F, 0x9C, 0x90, +0xA4, 0xB0, 0x94, 0x4E, 0x9C, 0x8F, 0x9C, 0x6F, +0xA4, 0xB0, 0xA4, 0xB0, 0x9C, 0x6F, 0xA4, 0xB0, +0xA4, 0xB0, 0xA4, 0xD0, 0xA4, 0xD0, 0xA4, 0xAF, +0x9C, 0x8F, 0xA4, 0x8F, 0xA4, 0xB0, 0xA4, 0xAF, +0xB5, 0x11, 0xB5, 0x11, 0xB5, 0x11, 0xBD, 0x52, +0xC5, 0x93, 0x9C, 0x70, 0x9C, 0x91, 0xAD, 0x13, +0xCD, 0xF7, 0xCD, 0xF6, 0xA4, 0x91, 0xBD, 0x54, +0xB5, 0x13, 0xAC, 0xF3, 0xB5, 0x54, 0xA4, 0xB2, +0xA4, 0xD2, 0x7B, 0x6E, 0x62, 0xAB, 0x62, 0xEB, +0x7B, 0x6D, 0x73, 0x4C, 0x6A, 0xEB, 0x5A, 0x89, +0x4A, 0x07, 0x39, 0xA6, 0x31, 0x85, 0x29, 0x24, +0x29, 0x24, 0x21, 0x04, 0x39, 0xC7, 0xA4, 0xF3, +0xC6, 0x18, 0x9C, 0xF3, 0x7B, 0x8D, 0xB5, 0x33, +0xCD, 0xD5, 0xCD, 0xD4, 0xC5, 0xB3, 0xCD, 0xD4, +0xD6, 0x36, 0xC5, 0xB4, 0xBD, 0x93, 0xB5, 0x72, +0xBD, 0x73, 0xBD, 0x73, 0xB5, 0x73, 0xBD, 0x73, +0xA5, 0x11, 0x53, 0x28, 0x5B, 0xAA, 0x53, 0x89, +0x21, 0xE4, 0x19, 0xA3, 0x21, 0xC3, 0x32, 0x44, +0x4B, 0x27, 0x32, 0x64, 0x32, 0x64, 0x21, 0xE3, +0x11, 0x41, 0x2A, 0x44, 0x22, 0x24, 0x2A, 0x65, +0x53, 0x69, 0x7C, 0xCD, 0x2A, 0x23, 0x22, 0x03, +0x3A, 0x66, 0x19, 0x43, 0x4A, 0xC8, 0xA5, 0xF1, +0x9D, 0x14, 0x73, 0xAE, 0x73, 0x6C, 0x7B, 0xAC, +0x83, 0xCC, 0x8C, 0x0D, 0x94, 0x2E, 0x94, 0x4E, +0x9C, 0x6F, 0x94, 0x6F, 0x9C, 0x8F, 0xA4, 0xD0, +0xA4, 0xF0, 0x9C, 0xAF, 0x94, 0x6F, 0x9C, 0x6E, +0x9C, 0x8F, 0x94, 0x4E, 0xF7, 0x7D, 0xA5, 0x34, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x31, 0xA6, 0xFF, 0xDF, 0xE7, 0x1B, +0xB5, 0x52, 0x9C, 0x6E, 0x9C, 0x6E, 0x94, 0x4E, +0x94, 0x4E, 0x8C, 0x0C, 0x8C, 0x2D, 0x8B, 0xEC, +0x94, 0x4E, 0xA4, 0xF1, 0xAD, 0x11, 0xAD, 0x32, +0xBD, 0x93, 0xBD, 0xB3, 0xB5, 0x72, 0xBD, 0x92, +0xC5, 0xB3, 0xC5, 0xD3, 0xBD, 0xB2, 0xB5, 0x10, +0xA4, 0xAE, 0xBD, 0x72, 0xC5, 0xD2, 0xC5, 0xF3, +0xC5, 0xD3, 0xB5, 0x72, 0xB5, 0x51, 0xAD, 0x31, +0xBD, 0xB3, 0xCE, 0x78, 0xF7, 0xBE, 0x42, 0x08, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xBD, 0xD7, 0xFF, 0xDF, 0xBE, 0x72, +0xB6, 0x10, 0x95, 0x0A, 0xA5, 0xAB, 0x95, 0x29, +0x95, 0x4A, 0x9D, 0x4C, 0xAD, 0xCF, 0xC6, 0x11, +0xDE, 0x95, 0xE6, 0xB6, 0xE6, 0x96, 0xE6, 0x96, +0xDE, 0x56, 0xCD, 0xD4, 0x83, 0xAC, 0xD6, 0x77, +0xC5, 0xD4, 0xB5, 0x73, 0x94, 0x4F, 0x83, 0xEE, +0x73, 0x6C, 0x73, 0x8D, 0xA4, 0xF2, 0x7B, 0xCE, +0x73, 0x6C, 0x6B, 0x2B, 0x42, 0x46, 0x84, 0x6C, +0xAE, 0x31, 0xCF, 0x36, 0xC7, 0x16, 0xC7, 0x16, +0xD7, 0x57, 0xAD, 0xB2, 0x52, 0xA9, 0x4A, 0x69, +0x42, 0x28, 0x63, 0x0B, 0x5A, 0xAA, 0x84, 0x0F, +0xA4, 0xD2, 0x62, 0xEA, 0x6B, 0x6B, 0x94, 0x6F, +0xAD, 0x11, 0xA4, 0xD0, 0xA4, 0xF0, 0x83, 0xCC, +0x52, 0x68, 0x5A, 0xA9, 0x52, 0x89, 0x42, 0x07, +0x31, 0x85, 0x39, 0xC6, 0x39, 0xC6, 0x39, 0xC6, +0x29, 0x65, 0x21, 0x03, 0x39, 0xC7, 0x63, 0x2C, +0x63, 0x0C, 0x6B, 0x4D, 0xBD, 0xD7, 0xE7, 0x1C, +0xDE, 0xFC, 0xC6, 0x39, 0xEF, 0x7E, 0xEF, 0x7E, +0xE7, 0x3D, 0xC5, 0xF7, 0xA5, 0x11, 0xA5, 0x8F, +0xAD, 0xD0, 0xAD, 0x2F, 0x9C, 0xAE, 0xA4, 0xF0, +0xBD, 0xB3, 0x83, 0xCC, 0xA4, 0xAF, 0xAC, 0xF0, +0xAC, 0xD0, 0xA4, 0xB0, 0x9C, 0x8F, 0xA4, 0xD0, +0x9C, 0x4F, 0x94, 0x0E, 0x8B, 0xCD, 0x7B, 0x8C, +0x9C, 0x70, 0xA4, 0xD1, 0xA4, 0xF1, 0xBD, 0x94, +0xB5, 0x53, 0xAD, 0x12, 0xAD, 0x12, 0xB5, 0x33, +0xB5, 0x53, 0xB5, 0x53, 0xB5, 0x33, 0xB5, 0x53, +0x83, 0xEE, 0x62, 0xEB, 0x6B, 0x2B, 0x52, 0x48, +0x4A, 0x48, 0x39, 0xE7, 0x39, 0xC6, 0x42, 0x07, +0x42, 0x07, 0x52, 0x69, 0x5A, 0xAB, 0x7B, 0x8E, +0x8C, 0x31, 0xB5, 0x75, 0xCD, 0xF7, 0xCD, 0xF8, +0xBD, 0x55, 0x73, 0x6E, 0x84, 0x31, 0x6B, 0x4D, +0x39, 0xC7, 0x4A, 0x49, 0x5A, 0xAA, 0x39, 0xC6, +0x39, 0xC6, 0x29, 0x24, 0x18, 0xE3, 0x21, 0x03, +0x8C, 0x51, 0xD6, 0x9A, 0xAD, 0x55, 0xA4, 0xF4, +0xBD, 0xD7, 0xBD, 0x96, 0xBD, 0xB6, 0xE6, 0xDB, +0xC5, 0xD7, 0x7B, 0xAF, 0x94, 0x92, 0x94, 0x71, +0xBD, 0x75, 0xD6, 0x58, 0xD6, 0x38, 0xC5, 0xD7, +0xAC, 0xF2, 0xBD, 0x73, 0xD6, 0x36, 0xDE, 0x96, +0xE6, 0xB7, 0xCD, 0xF4, 0xE6, 0x97, 0xAC, 0xF1, +0x52, 0xAB, 0x73, 0x8F, 0x94, 0x93, 0xB5, 0xB7, +0xD6, 0xBA, 0xD6, 0x99, 0xC5, 0xF5, 0xE6, 0xD9, +0xD6, 0x56, 0xA4, 0xD1, 0x94, 0x4F, 0x9C, 0x6F, +0x9C, 0x8F, 0x94, 0x2E, 0x94, 0x4F, 0x94, 0x4E, +0xA4, 0xB0, 0x9C, 0xB0, 0xA4, 0xB0, 0xA4, 0xD0, +0xA4, 0xB0, 0xAC, 0xD1, 0xAD, 0x11, 0xAC, 0xD0, +0xA4, 0xB0, 0xA4, 0x6F, 0xA4, 0xB0, 0xAC, 0xD0, +0xB5, 0x11, 0xB5, 0x12, 0xBD, 0x33, 0xCD, 0xB4, +0xC5, 0xB5, 0xB5, 0x54, 0xD6, 0x59, 0xE6, 0xDB, +0xE6, 0xBA, 0xC5, 0xD6, 0x83, 0xAE, 0x83, 0xAE, +0x8C, 0x0F, 0x94, 0x51, 0x94, 0x30, 0x8C, 0x10, +0x8B, 0xEF, 0x41, 0xE7, 0x39, 0xA6, 0x41, 0xC7, +0x52, 0x69, 0x5A, 0x69, 0x4A, 0x07, 0x31, 0x65, +0x29, 0x24, 0x29, 0x04, 0x29, 0x24, 0x20, 0xE3, +0x21, 0x24, 0x4A, 0x29, 0x7B, 0xAF, 0x8C, 0x51, +0x63, 0x0B, 0xAD, 0x33, 0xCE, 0x15, 0xCD, 0xF4, +0xCD, 0xF4, 0xCD, 0xF4, 0xCD, 0xF4, 0xD6, 0x14, +0xCD, 0xF4, 0xD6, 0x35, 0xD6, 0x15, 0xC5, 0xD4, +0xC5, 0xB3, 0xCD, 0xF4, 0xD6, 0x35, 0xCE, 0x15, +0x8C, 0x6E, 0x5B, 0xAA, 0x5B, 0xCA, 0x3A, 0xE7, +0x3A, 0xA7, 0x32, 0x65, 0x2A, 0x25, 0x2A, 0x04, +0x21, 0xA3, 0x21, 0xC3, 0x2A, 0x44, 0x2A, 0x24, +0x3A, 0x86, 0x42, 0xE7, 0x2A, 0x44, 0x32, 0x45, +0x32, 0x65, 0x2A, 0x44, 0x2A, 0x44, 0x32, 0x65, +0x3A, 0xA6, 0x29, 0xC4, 0x11, 0x02, 0x74, 0x4C, +0x9C, 0xD3, 0x62, 0xEB, 0x6B, 0x4B, 0x73, 0x4B, +0x73, 0x4A, 0x83, 0xCC, 0x7B, 0x8B, 0x73, 0x4A, +0x83, 0xCC, 0x94, 0x2D, 0x83, 0xCC, 0x8C, 0x0D, +0x9C, 0xB0, 0xA4, 0xB0, 0x9C, 0xAF, 0xA4, 0xF0, +0xAD, 0x11, 0xB5, 0x51, 0xF7, 0xBE, 0x84, 0x10, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x08, 0x41, 0xFF, 0xDF, 0xE6, 0xFA, +0xB5, 0x52, 0xA4, 0x8E, 0xAC, 0xCF, 0xA4, 0xAE, +0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0xAE, 0xA4, 0x8E, +0x9C, 0x8E, 0x9C, 0x6E, 0x9C, 0x6E, 0x9C, 0x4D, +0x9C, 0x6E, 0xA4, 0x8E, 0xA4, 0xAE, 0xA4, 0xCE, +0xAC, 0xCF, 0xAC, 0xEF, 0xAC, 0xEF, 0xAC, 0xEF, +0xA4, 0xAE, 0x94, 0x0C, 0x94, 0x2C, 0x94, 0x4D, +0x9C, 0x6D, 0x9C, 0x6E, 0x9C, 0xAE, 0x9C, 0xAE, +0xAD, 0x11, 0xC6, 0x37, 0xF7, 0x9E, 0x63, 0x0C, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xDE, 0xDB, 0xF7, 0x9E, 0xB6, 0x11, +0x95, 0x0D, 0x84, 0x8B, 0xAD, 0xEF, 0xA5, 0x8D, +0xE7, 0x14, 0xEF, 0x15, 0xEE, 0xF5, 0xE6, 0xB5, +0xEF, 0x3A, 0xEF, 0x1A, 0xF7, 0x3A, 0xF7, 0x3A, +0xEF, 0x19, 0xD6, 0x15, 0xBD, 0xB5, 0xDE, 0xFA, +0xD6, 0x78, 0xC6, 0x37, 0xC5, 0xF6, 0xB5, 0x95, +0xC5, 0xF7, 0xCE, 0x58, 0xCE, 0x58, 0xC6, 0x17, +0xBD, 0xD6, 0x9C, 0xB1, 0x52, 0xA8, 0x9D, 0x30, +0xB6, 0x73, 0xA6, 0x11, 0xA6, 0x11, 0xAE, 0x53, +0xAD, 0xB2, 0x7C, 0x0D, 0x5A, 0xCA, 0x4A, 0x89, +0x42, 0x28, 0x4A, 0x69, 0x7B, 0xCE, 0xA5, 0x34, +0x5A, 0xCA, 0x73, 0x8C, 0x84, 0x0D, 0x8C, 0x0D, +0x9C, 0xB0, 0x9C, 0x8F, 0x9C, 0x6F, 0x8C, 0x0E, +0x8C, 0x0E, 0x9C, 0xB0, 0x6B, 0x2B, 0x41, 0xE7, +0x31, 0x85, 0x31, 0xA6, 0x39, 0xC6, 0x31, 0x85, +0x18, 0xE2, 0x29, 0x24, 0x39, 0xC6, 0x5A, 0xCB, +0x6B, 0x6D, 0x6B, 0x6E, 0xA5, 0x14, 0xA5, 0x15, +0xBD, 0xF8, 0xAD, 0x55, 0xD6, 0xBB, 0xDE, 0xDB, +0xEF, 0x5D, 0xC6, 0x38, 0xD6, 0xB9, 0xD6, 0xF8, +0xD6, 0xF8, 0xDF, 0x18, 0xC6, 0x14, 0xC5, 0xF4, +0xAD, 0x51, 0x94, 0x4E, 0xA4, 0xF0, 0xA4, 0xD0, +0xAC, 0xD0, 0xA4, 0xB0, 0xB5, 0x11, 0xBD, 0x52, +0xC5, 0x72, 0xB5, 0x11, 0xA4, 0x6F, 0x7B, 0x8C, +0xAD, 0x12, 0xB5, 0x53, 0xC5, 0xF5, 0xBD, 0xB4, +0xAD, 0x32, 0x7B, 0x8C, 0x62, 0xEA, 0x63, 0x2A, +0x6B, 0x4B, 0x6B, 0x4B, 0x73, 0x6B, 0x7B, 0x8D, +0x94, 0x50, 0xA4, 0xD1, 0x7B, 0x8C, 0x62, 0xEA, +0x4A, 0x48, 0x4A, 0x48, 0x42, 0x28, 0x4A, 0x28, +0x52, 0x89, 0x5A, 0xAA, 0x5A, 0xAB, 0x5A, 0xAA, +0x62, 0xEC, 0x7B, 0xCF, 0x94, 0x30, 0x94, 0x72, +0x83, 0xCF, 0x52, 0x49, 0x4A, 0x69, 0x31, 0x65, +0x31, 0xA6, 0x5A, 0xEB, 0x5A, 0xCA, 0x42, 0x28, +0x39, 0xA6, 0x21, 0x24, 0x29, 0x65, 0x31, 0xA6, +0x73, 0xAE, 0xCE, 0x38, 0xC6, 0x38, 0xDE, 0xDB, +0xCE, 0x59, 0xBD, 0xB6, 0x84, 0x10, 0xB5, 0x96, +0xD6, 0x39, 0xC5, 0xB7, 0x83, 0xCF, 0x52, 0x6A, +0x52, 0x8A, 0x73, 0x6E, 0xAD, 0x14, 0xD6, 0x59, +0xB5, 0x54, 0x83, 0xEF, 0x8B, 0xEE, 0x94, 0x4F, +0x9C, 0x6F, 0x94, 0x0E, 0x9C, 0x6F, 0x5A, 0x68, +0x39, 0xC7, 0x52, 0x8B, 0x6B, 0x6E, 0x8C, 0x93, +0xAD, 0x55, 0x83, 0xF0, 0xA5, 0x34, 0xE6, 0xFA, +0xCE, 0x16, 0x9C, 0xB1, 0x8C, 0x0E, 0x94, 0x2E, +0x9C, 0x6F, 0x83, 0xCD, 0x83, 0xCD, 0x83, 0xED, +0xA4, 0xB0, 0x9C, 0xB0, 0xAC, 0xF1, 0xAC, 0xF1, +0xAC, 0xF1, 0xB5, 0x11, 0xA4, 0xD0, 0xA4, 0xD1, +0xAC, 0xF1, 0xAC, 0xF1, 0xAC, 0xF1, 0x9C, 0x6F, +0x9C, 0x91, 0xCD, 0xD6, 0xD6, 0x17, 0xDE, 0x99, +0xDE, 0x78, 0xBD, 0x95, 0xCE, 0x18, 0xD6, 0x38, +0xBD, 0x96, 0x9C, 0x71, 0x73, 0x6D, 0x62, 0xEB, +0x83, 0xAE, 0x8B, 0xEF, 0x73, 0x6D, 0x73, 0x2C, +0x73, 0x4C, 0x52, 0x48, 0x5A, 0xAA, 0x52, 0x69, +0x31, 0x65, 0x41, 0xE7, 0x62, 0xEB, 0x41, 0xE7, +0x52, 0x69, 0x31, 0x45, 0x5A, 0xCB, 0x7B, 0xCF, +0xAD, 0x55, 0xC5, 0xF7, 0x9C, 0xF3, 0x84, 0x0F, +0xA4, 0xD1, 0xD6, 0x76, 0xD6, 0x15, 0xD6, 0x35, +0xCD, 0xF4, 0xCD, 0xF4, 0xC5, 0x93, 0xCD, 0xF4, +0xCD, 0xF4, 0xD6, 0x55, 0xDE, 0x96, 0xD6, 0x14, +0xCD, 0xF4, 0xCD, 0xF4, 0xD6, 0x14, 0xBD, 0xD3, +0x63, 0x8A, 0x6C, 0x2B, 0x64, 0x0A, 0x53, 0x89, +0x63, 0xEB, 0x53, 0x49, 0x2A, 0x24, 0x19, 0x82, +0x21, 0x83, 0x2A, 0x05, 0x21, 0xE3, 0x22, 0x03, +0x5B, 0xC9, 0x53, 0xA8, 0x43, 0x07, 0x4B, 0x48, +0x53, 0x68, 0x43, 0x27, 0x43, 0x07, 0x4B, 0x48, +0x53, 0x88, 0x3A, 0x86, 0x10, 0xE1, 0x21, 0xA3, +0x52, 0x89, 0x62, 0xEA, 0x73, 0x6B, 0x83, 0xCC, +0x83, 0xAB, 0x83, 0xCC, 0x94, 0x4D, 0x9C, 0x6E, +0xA4, 0xAF, 0x9C, 0x8E, 0x83, 0xEC, 0x83, 0xCC, +0x83, 0xED, 0xA4, 0xD0, 0xAC, 0xF1, 0xB5, 0x51, +0xBD, 0x72, 0xC5, 0xB3, 0xF7, 0xBE, 0x9C, 0xD3, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0xC3, 0xFF, 0xDF, 0xE6, 0xFA, +0xBD, 0x72, 0x8B, 0xEB, 0xA4, 0xAE, 0xA4, 0xAF, +0xA4, 0x8E, 0x94, 0x2C, 0xA4, 0x8E, 0xBD, 0x31, +0xB5, 0x10, 0xA4, 0xAE, 0x9C, 0x6D, 0xA4, 0xAF, +0xA4, 0xAE, 0xA4, 0xAE, 0xB5, 0x0F, 0xB5, 0x0F, +0xB5, 0x0F, 0xBD, 0x51, 0xB5, 0x10, 0xAC, 0xCF, +0xAC, 0xEF, 0xB5, 0x30, 0xAC, 0xEF, 0xAC, 0xEF, +0xAC, 0xEF, 0xA4, 0xAE, 0xA4, 0x8E, 0x9C, 0x4D, +0xA4, 0x8E, 0xBD, 0xB4, 0xEF, 0x5C, 0xDE, 0xBA, +0x08, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x63, 0x0C, 0xFF, 0xDE, 0xDE, 0xDA, 0xA5, 0x90, +0x6B, 0xE9, 0x95, 0x2E, 0xBE, 0x51, 0xBE, 0x6F, +0xBE, 0x4E, 0xC6, 0x4E, 0xCE, 0x50, 0xC5, 0xD1, +0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, +0xEF, 0x3B, 0xCE, 0x37, 0xE7, 0x1C, 0xF7, 0x9E, +0xF7, 0x9E, 0xF7, 0x9D, 0xE7, 0x3C, 0xCE, 0x79, +0xE7, 0x3C, 0xF7, 0x9E, 0xF7, 0x9E, 0xEF, 0x7D, +0xDE, 0xDB, 0xA4, 0xF2, 0x6B, 0x6B, 0x94, 0xCF, +0xB6, 0x53, 0xA6, 0x11, 0xAE, 0x11, 0xA5, 0xB1, +0x94, 0x8E, 0x62, 0xEA, 0x5A, 0xCA, 0x52, 0x89, +0x39, 0xC7, 0x7B, 0xEF, 0xA5, 0x34, 0x5A, 0xEA, +0x73, 0x6B, 0x9C, 0xB0, 0x83, 0xCC, 0x83, 0xED, +0x9C, 0x8F, 0x9C, 0x6F, 0x9C, 0x8F, 0x9C, 0xAF, +0x94, 0x6F, 0xA4, 0xF1, 0x6B, 0x0A, 0x62, 0xEA, +0x52, 0xA9, 0x4A, 0x48, 0x39, 0xC6, 0x31, 0xC6, +0x31, 0xA6, 0x31, 0x86, 0x39, 0xE7, 0x4A, 0x69, +0x63, 0x2D, 0x6B, 0x4D, 0x94, 0x72, 0x6B, 0x6E, +0xAD, 0x76, 0xDE, 0xDC, 0xA5, 0x35, 0xAD, 0x35, +0xEF, 0x5D, 0xE7, 0x3C, 0xF7, 0x9D, 0xF7, 0xDE, +0xF7, 0xBE, 0xF7, 0xBD, 0xD6, 0xB7, 0xD6, 0x95, +0xAD, 0x10, 0xAC, 0xF0, 0xAD, 0x10, 0xB5, 0x31, +0xB5, 0x31, 0xBD, 0x31, 0xC5, 0x92, 0xC5, 0x72, +0xC5, 0x72, 0xCD, 0x72, 0xAC, 0xCF, 0x8C, 0x0E, +0xB5, 0x53, 0xBD, 0xB4, 0xCE, 0x36, 0xBD, 0x93, +0xCE, 0x15, 0xBD, 0xB4, 0xB5, 0x53, 0xA5, 0x12, +0xA4, 0xF1, 0x9C, 0x90, 0xA4, 0xD1, 0x94, 0x50, +0x7B, 0x6D, 0x94, 0x2F, 0xBD, 0x93, 0xBD, 0xB4, +0x83, 0xEE, 0x63, 0x0B, 0x62, 0xEB, 0x63, 0x0B, +0x73, 0x6D, 0x83, 0xF0, 0x9C, 0xB2, 0x7B, 0xAE, +0x52, 0x6A, 0x4A, 0x29, 0x5A, 0xCB, 0x6B, 0x4D, +0x52, 0x8A, 0x39, 0xE7, 0x29, 0x45, 0x29, 0x24, +0x31, 0xA6, 0x42, 0x28, 0x31, 0xC6, 0x39, 0xC6, +0x29, 0x65, 0x21, 0x24, 0x31, 0x85, 0x39, 0xC6, +0x6B, 0x6D, 0xCE, 0x39, 0xEF, 0x7D, 0xF7, 0x9E, +0xF7, 0xBE, 0xEF, 0x5D, 0xB5, 0x96, 0xC5, 0xB7, +0xD6, 0x39, 0xCE, 0x18, 0xCE, 0x38, 0x94, 0x92, +0x63, 0x0D, 0xA5, 0x14, 0xBD, 0xD7, 0xD6, 0x58, +0xB5, 0x55, 0xC5, 0xB6, 0xC5, 0xD6, 0xB5, 0x33, +0xB5, 0x33, 0xB5, 0x33, 0xB5, 0x33, 0x94, 0x50, +0x42, 0x08, 0x42, 0x08, 0x4A, 0x8A, 0x63, 0x4D, +0x7B, 0xF0, 0x7C, 0x11, 0xA5, 0x55, 0xC6, 0x18, +0xDE, 0xDB, 0xC6, 0x17, 0xB5, 0x75, 0xAD, 0x13, +0x9C, 0xB1, 0x8B, 0xEE, 0x83, 0xCD, 0x83, 0xCD, +0x8B, 0xEE, 0x8C, 0x0E, 0xA4, 0xD0, 0xAC, 0xF1, +0x9C, 0x6F, 0xAC, 0xF1, 0x8C, 0x0E, 0x8C, 0x0E, +0x9C, 0x90, 0x9C, 0x91, 0xCD, 0xF6, 0x7B, 0xAE, +0xA4, 0xD3, 0xBD, 0x96, 0xC5, 0xB6, 0xDE, 0x58, +0xC5, 0xB6, 0xA4, 0xF3, 0xBD, 0x96, 0xBD, 0x96, +0xBD, 0x75, 0x8C, 0x10, 0x7B, 0x6D, 0x5A, 0x89, +0x6B, 0x2C, 0x6B, 0x0C, 0x6B, 0x0C, 0x62, 0xCB, +0x5A, 0x8A, 0x52, 0x49, 0x4A, 0x28, 0x31, 0x65, +0x52, 0x69, 0x8C, 0x10, 0xA4, 0xF3, 0xB5, 0x96, +0xBD, 0xD7, 0x83, 0xEF, 0xBD, 0xB7, 0x9C, 0xF3, +0x8C, 0x71, 0x73, 0x6E, 0x52, 0x6A, 0x83, 0xCE, +0xBD, 0xB4, 0xD6, 0x15, 0xBD, 0x72, 0xC5, 0xB3, +0xC5, 0x92, 0xBD, 0x72, 0xBD, 0x93, 0xCD, 0xF4, +0xD6, 0x35, 0xE6, 0x96, 0xEE, 0xD7, 0xE6, 0x96, +0xD6, 0x55, 0xDE, 0x55, 0xDE, 0x76, 0xAD, 0x51, +0x74, 0x6D, 0x64, 0x0B, 0x64, 0x0A, 0x3A, 0xE7, +0x3A, 0xC6, 0x4B, 0x28, 0x3A, 0x86, 0x2A, 0x05, +0x42, 0xE8, 0x32, 0x25, 0x3A, 0x87, 0x2A, 0x24, +0x53, 0xA8, 0x64, 0x4A, 0x4B, 0x88, 0x53, 0xA9, +0x64, 0x2A, 0x5B, 0xE9, 0x53, 0xC9, 0x5C, 0x0A, +0x53, 0x88, 0x22, 0x04, 0x11, 0x22, 0x10, 0xE2, +0x4A, 0x48, 0x62, 0xEA, 0x8C, 0x0D, 0x8C, 0x2D, +0x9C, 0x8E, 0xAD, 0x31, 0xB5, 0x71, 0xB5, 0x51, +0xB5, 0x30, 0xB5, 0x71, 0xB5, 0x51, 0xB5, 0x51, +0xBD, 0x93, 0xA4, 0xD0, 0xA4, 0xB0, 0xBD, 0x72, +0xAD, 0x10, 0xB5, 0x31, 0xF7, 0x9D, 0x9C, 0xD3, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0xE3, 0xFF, 0xDF, 0xEF, 0x3B, +0xD6, 0x55, 0xAD, 0x30, 0xD6, 0x76, 0xD6, 0x56, +0xCE, 0x15, 0xC5, 0xD4, 0xC5, 0xB4, 0xD6, 0x15, +0xC5, 0x92, 0x9C, 0x6D, 0xAC, 0xF0, 0xBD, 0x93, +0xC5, 0xD4, 0xBD, 0x73, 0xC5, 0xD4, 0xD6, 0x34, +0xA4, 0xAE, 0xBD, 0x51, 0xB5, 0x31, 0xC5, 0xD4, +0xDE, 0x77, 0xDE, 0x97, 0xCE, 0x15, 0xDE, 0x55, +0xD6, 0x34, 0xB5, 0x30, 0xC5, 0xB2, 0xBD, 0x31, +0xC5, 0x92, 0xCE, 0x16, 0xEF, 0x1B, 0xFF, 0xDF, +0xE7, 0x1C, 0x73, 0xAE, 0x5A, 0xEB, 0x9C, 0xF3, +0xFF, 0xDE, 0xF7, 0x7C, 0xCE, 0x56, 0x63, 0x88, +0x5B, 0xC7, 0x95, 0x4E, 0xBE, 0x71, 0xAE, 0x4D, +0xB6, 0x4C, 0xB6, 0x4C, 0xBE, 0x6D, 0xBD, 0xEF, +0xFF, 0xFF, 0xD6, 0x9A, 0x73, 0xAE, 0xE7, 0x1C, +0xEF, 0x5D, 0xD6, 0x78, 0xF7, 0x9D, 0xC6, 0x18, +0x73, 0xAE, 0xAD, 0x75, 0xF7, 0x9E, 0xDE, 0xBA, +0xF7, 0x9E, 0xCE, 0x59, 0x73, 0xAE, 0xEF, 0x3C, +0xDE, 0xFB, 0x94, 0x70, 0x83, 0xCC, 0x94, 0x8E, +0x9D, 0x2F, 0xA5, 0xF1, 0x9D, 0x6F, 0x94, 0xAD, +0x9C, 0xCF, 0x9C, 0xB0, 0x94, 0x6F, 0x8C, 0x2E, +0x94, 0x91, 0x9C, 0xD3, 0x52, 0x89, 0x6B, 0x4B, +0x9C, 0xAF, 0x9C, 0x8F, 0x7B, 0xAC, 0xAD, 0x72, +0xC6, 0x56, 0xBE, 0x14, 0xC6, 0x74, 0xC6, 0x74, +0xAD, 0x92, 0x9C, 0x8F, 0x83, 0xED, 0x52, 0x68, +0x5A, 0xCA, 0x62, 0xEA, 0x62, 0xEA, 0x4A, 0x48, +0x39, 0xC6, 0x31, 0x85, 0x39, 0xE6, 0x42, 0x07, +0x5A, 0xCB, 0x5A, 0xEB, 0x7B, 0xF0, 0x9C, 0xD3, +0xBD, 0xF8, 0xC6, 0x39, 0xCE, 0x7A, 0x7B, 0xCF, +0xAD, 0x56, 0xF7, 0x9E, 0xFF, 0xFF, 0x7B, 0xEF, +0xB5, 0x96, 0xF7, 0xBE, 0xD6, 0xB8, 0xD6, 0x75, +0xC5, 0x92, 0xBD, 0x51, 0xC5, 0x31, 0xCD, 0xB2, +0xCD, 0x92, 0xC5, 0x72, 0xCD, 0x92, 0xC5, 0x72, +0xCD, 0x92, 0xD5, 0xD3, 0xC5, 0x72, 0xA4, 0xD0, +0xB5, 0x53, 0xBD, 0x93, 0xBD, 0xB3, 0xB5, 0x52, +0xCE, 0x35, 0xC5, 0xF5, 0xC5, 0xD5, 0xBD, 0xB5, +0xBD, 0x94, 0xBD, 0x94, 0xC5, 0xD5, 0x83, 0xEE, +0x20, 0xE3, 0x94, 0x51, 0xBD, 0x94, 0xBD, 0xB4, +0xB5, 0x74, 0xAD, 0x54, 0xBD, 0xF7, 0xC6, 0x18, +0xC5, 0xF8, 0xC5, 0xF7, 0xBD, 0xB6, 0xAD, 0x55, +0x5A, 0xAB, 0x42, 0x08, 0x41, 0xE7, 0x42, 0x28, +0x42, 0x28, 0x41, 0xE7, 0x29, 0x65, 0x29, 0x45, +0x31, 0x85, 0x29, 0x65, 0x18, 0xE3, 0x29, 0x65, +0x29, 0x44, 0x21, 0x24, 0x29, 0x65, 0x39, 0xC6, +0x7B, 0xCE, 0xD6, 0xBA, 0xF7, 0x9E, 0x73, 0xAE, +0xC6, 0x18, 0xF7, 0x9E, 0xDE, 0xBA, 0xDE, 0x9A, +0xCE, 0x18, 0xC5, 0xD7, 0xBD, 0x76, 0xC5, 0xF7, +0x94, 0x92, 0x7B, 0x8E, 0x8C, 0x31, 0xAD, 0x34, +0xBD, 0xB6, 0xE7, 0x1B, 0xDE, 0xBA, 0xDE, 0x99, +0xC5, 0xB5, 0xAC, 0xF2, 0xC5, 0xD5, 0xBD, 0x94, +0x94, 0x70, 0x52, 0xA9, 0x42, 0x08, 0x4A, 0x6A, +0x52, 0xAB, 0x6B, 0x6F, 0x8C, 0x52, 0xC6, 0x18, +0xEF, 0x5D, 0xF7, 0xBE, 0xF7, 0xBE, 0xEF, 0x5C, +0xD6, 0x99, 0xB5, 0x53, 0xAC, 0xF2, 0xA4, 0xF1, +0x9C, 0x70, 0xA4, 0xF2, 0xBD, 0x94, 0xA4, 0xB1, +0xAD, 0x33, 0xB5, 0x33, 0xB5, 0x54, 0xB5, 0x54, +0xD6, 0x18, 0xE6, 0xBA, 0xF7, 0x5C, 0x94, 0x71, +0xBD, 0xB7, 0xBD, 0x96, 0xCE, 0x18, 0xC5, 0xB7, +0xB5, 0x55, 0x9C, 0x72, 0xB5, 0x34, 0xA4, 0xD3, +0x83, 0xAE, 0x62, 0xCA, 0x62, 0xCA, 0x5A, 0x69, +0x5A, 0x8A, 0x5A, 0xAA, 0x5A, 0x89, 0x52, 0x28, +0x52, 0x49, 0x5A, 0x8A, 0x39, 0xC7, 0x20, 0xE4, +0x73, 0x8E, 0xA4, 0xF3, 0xA4, 0xD3, 0x9C, 0xD3, +0x84, 0x10, 0xA4, 0xF2, 0xB5, 0x33, 0xBD, 0x94, +0xBD, 0xB4, 0x94, 0x91, 0x9C, 0xB2, 0x94, 0x70, +0xCE, 0x15, 0xD6, 0x15, 0xC5, 0x93, 0xD6, 0x35, +0xBD, 0x72, 0xC5, 0xB3, 0xDE, 0x75, 0xDE, 0x96, +0xE6, 0x96, 0xE6, 0x96, 0xDE, 0x75, 0xDE, 0x75, +0xD6, 0x55, 0xE6, 0x96, 0xE6, 0xD7, 0xAD, 0x92, +0x63, 0xCA, 0x63, 0xEA, 0x8D, 0x50, 0x5B, 0xAA, +0x43, 0x07, 0x5B, 0x8A, 0x42, 0xC6, 0x43, 0x07, +0x22, 0x04, 0x21, 0xC3, 0x53, 0x69, 0x43, 0x07, +0x4B, 0x47, 0x53, 0xC9, 0x5C, 0x09, 0x6C, 0x8B, +0x74, 0xCC, 0x6C, 0xAB, 0x53, 0xE9, 0x3A, 0xC5, +0x19, 0xE2, 0x19, 0xA2, 0x21, 0xC4, 0x21, 0x64, +0x4A, 0x48, 0x5A, 0xCA, 0x8C, 0x0D, 0x8C, 0x2D, +0x9C, 0x8E, 0xB5, 0x31, 0xB5, 0x51, 0xAD, 0x30, +0xBD, 0x71, 0xB5, 0x30, 0xB5, 0x30, 0xBD, 0x71, +0xCE, 0x14, 0xA4, 0xB0, 0x9C, 0x6F, 0xCE, 0x15, +0xAD, 0x10, 0xAD, 0x10, 0xF7, 0x9E, 0x9C, 0xD3, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0xE3, 0xFF, 0xDF, 0xEF, 0x3B, +0xDE, 0x97, 0x9C, 0xB0, 0xDE, 0xD9, 0xEF, 0x5B, +0xEF, 0x5C, 0xEF, 0x5C, 0xE7, 0x1B, 0xDE, 0x98, +0xD6, 0x35, 0xAD, 0x11, 0xD6, 0x78, 0xE7, 0x1B, +0xEF, 0x7C, 0xEF, 0x5C, 0xEF, 0x3B, 0xEE, 0xF9, +0xB5, 0x52, 0xE6, 0xB7, 0xEF, 0x1A, 0xF7, 0x7D, +0xFF, 0xBE, 0xF7, 0x9D, 0xEF, 0x3B, 0xEF, 0x19, +0xD6, 0x55, 0xAC, 0xCF, 0xCD, 0xD3, 0xA4, 0xD0, +0xC5, 0xF6, 0xE7, 0x1B, 0xFF, 0xBE, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xF7, 0x9D, +0xEF, 0x3B, 0xD6, 0x97, 0xCE, 0x35, 0x63, 0x88, +0x6C, 0x29, 0x95, 0x2E, 0xAD, 0xAF, 0xBE, 0x4F, +0xB6, 0x2F, 0xBE, 0x6E, 0xB6, 0x2D, 0xBE, 0x50, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xEF, 0x7D, 0xD6, 0x98, 0xF7, 0x9D, 0x8C, 0x71, +0x00, 0x00, 0x6B, 0x4D, 0xF7, 0xBE, 0xE6, 0xFB, +0xF7, 0xBE, 0x9C, 0xF3, 0x00, 0x00, 0xDE, 0xDB, +0xEF, 0x3C, 0xBD, 0x73, 0xB5, 0x10, 0xB5, 0x10, +0xA5, 0x0F, 0x9D, 0x2F, 0xA5, 0x2E, 0xA5, 0x0F, +0x94, 0x6E, 0xAD, 0x52, 0xA5, 0x10, 0xC5, 0xD4, +0xAD, 0x33, 0x4A, 0x68, 0x7B, 0xCD, 0x94, 0xAF, +0x8C, 0x0C, 0x73, 0x6A, 0xA5, 0x72, 0xC6, 0x76, +0xDF, 0x3A, 0xCE, 0xF6, 0xC6, 0xB4, 0xB6, 0x52, +0xBE, 0x33, 0xA4, 0xF0, 0x8C, 0x2E, 0x52, 0x48, +0x5A, 0xA9, 0x63, 0x0A, 0x6B, 0x2B, 0x7B, 0xCD, +0x73, 0x8D, 0x42, 0x07, 0x31, 0xC6, 0x39, 0xE6, +0x42, 0x07, 0x4A, 0x69, 0x63, 0x0C, 0x8C, 0x72, +0xB5, 0xB7, 0xAD, 0x76, 0x9C, 0xD3, 0x6B, 0x6E, +0xCE, 0x7A, 0xEF, 0x7E, 0xFF, 0xFF, 0x08, 0x41, +0x6B, 0x6D, 0xF7, 0x9E, 0xBD, 0xD6, 0xA4, 0xF2, +0xAD, 0x11, 0xCD, 0xB3, 0xD5, 0xB2, 0xDE, 0x14, +0xD5, 0xF3, 0xC5, 0x51, 0xC5, 0x71, 0xC5, 0x51, +0xCD, 0x92, 0xDD, 0xF3, 0xDD, 0xF4, 0x9C, 0x6F, +0xB5, 0x53, 0xB5, 0x73, 0xBD, 0xB4, 0xC5, 0xD4, +0xC5, 0xF5, 0xBD, 0xB4, 0xBD, 0xB4, 0xBD, 0x94, +0xBD, 0x94, 0xBD, 0xB5, 0xC5, 0xD5, 0x83, 0xAE, +0x52, 0x69, 0xB5, 0x34, 0xBD, 0x95, 0xCE, 0x37, +0xD6, 0x79, 0xD6, 0x79, 0xC6, 0x18, 0xCE, 0x59, +0xBD, 0xB6, 0xA5, 0x14, 0x9C, 0x92, 0x94, 0x71, +0x5A, 0xAA, 0x41, 0xE7, 0x42, 0x08, 0x42, 0x08, +0x39, 0xC7, 0x31, 0x86, 0x31, 0x86, 0x21, 0x24, +0x31, 0x85, 0x31, 0xA6, 0x31, 0x86, 0x39, 0xA6, +0x29, 0x44, 0x21, 0x03, 0x29, 0x44, 0x4A, 0x48, +0x84, 0x0F, 0xDE, 0xDB, 0xEF, 0x7D, 0x00, 0x00, +0x8C, 0x51, 0xF7, 0x9E, 0xE6, 0xDB, 0xD6, 0x59, +0xC5, 0xF7, 0xD6, 0x59, 0xAD, 0x34, 0xB5, 0x76, +0xCE, 0x59, 0xBD, 0xD7, 0x73, 0x4E, 0x7B, 0xAF, +0x94, 0x92, 0xD6, 0x79, 0xEF, 0x1C, 0xBD, 0xB6, +0xA5, 0x13, 0x94, 0x51, 0xC5, 0xB6, 0xDE, 0xB9, +0xC5, 0xB5, 0xB5, 0x74, 0x5A, 0xAA, 0x39, 0xC7, +0x42, 0x28, 0x5A, 0xCC, 0x84, 0x31, 0xC6, 0x18, +0xF7, 0x9E, 0xEF, 0x5D, 0xDE, 0xFB, 0xF7, 0xBE, +0xD6, 0x79, 0xA4, 0xD3, 0xAC, 0xF3, 0xAD, 0x34, +0x9C, 0xB2, 0x9C, 0x91, 0xB5, 0x55, 0xB5, 0x55, +0xCE, 0x38, 0xD6, 0x58, 0xEE, 0xFA, 0xEF, 0x3C, +0xEE, 0xFB, 0xF7, 0x1C, 0xD6, 0x79, 0x7B, 0xAF, +0x7B, 0xCF, 0xAD, 0x14, 0xCE, 0x18, 0xBD, 0x96, +0x8C, 0x10, 0x7B, 0x4D, 0x6B, 0x0C, 0x5A, 0x69, +0x49, 0xE7, 0x41, 0xC7, 0x49, 0xE7, 0x41, 0xC7, +0x52, 0x49, 0x5A, 0xAA, 0x63, 0x0B, 0x83, 0xEF, +0x9C, 0xD2, 0x7B, 0xAE, 0x5A, 0xAA, 0x31, 0x86, +0x62, 0xCA, 0x7B, 0x8E, 0x73, 0x4D, 0x73, 0x6D, +0x9C, 0x91, 0xC5, 0xF5, 0xD6, 0x35, 0xD6, 0x56, +0xD6, 0x56, 0xAD, 0x32, 0xB5, 0x54, 0xA4, 0xF2, +0xB5, 0x32, 0xB5, 0x11, 0xB5, 0x12, 0xBD, 0x94, +0xBD, 0x94, 0xBD, 0x93, 0xBD, 0x72, 0xC5, 0xD4, +0xCE, 0x14, 0xD6, 0x35, 0xD6, 0x35, 0xD6, 0x35, +0xDE, 0x55, 0xD6, 0x35, 0xD6, 0x35, 0x8C, 0xAF, +0x42, 0xC7, 0x64, 0x0B, 0xA6, 0x13, 0x5B, 0xCA, +0x6C, 0x2C, 0x74, 0x8D, 0x4B, 0x68, 0x32, 0xA4, +0x2A, 0x23, 0x2A, 0x65, 0x53, 0x89, 0x53, 0xA9, +0x64, 0x0A, 0x4B, 0x48, 0x32, 0xA5, 0x5B, 0xE9, +0x6C, 0x8B, 0x85, 0x2D, 0x64, 0x0A, 0x21, 0xE3, +0x19, 0xC3, 0x21, 0xE3, 0x32, 0x66, 0x21, 0x84, +0x52, 0x89, 0x63, 0x0A, 0x83, 0xCC, 0x8C, 0x0C, +0x94, 0x6D, 0xAC, 0xF0, 0xA4, 0xEF, 0xAD, 0x30, +0xB5, 0x30, 0xAD, 0x0F, 0xAC, 0xF0, 0xBD, 0x71, +0xCE, 0x34, 0xA4, 0xAF, 0xA4, 0x8F, 0xB5, 0x72, +0xB5, 0x31, 0xB5, 0x31, 0xF7, 0x9E, 0x9C, 0xD3, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0xE3, 0xFF, 0xDF, 0xE7, 0x1B, +0xDE, 0xB7, 0xD6, 0x78, 0xF7, 0x7D, 0xFF, 0xDE, +0xEF, 0x7D, 0xE7, 0x3C, 0xFF, 0xDE, 0xF7, 0x9D, +0xE7, 0x1A, 0xDE, 0xDA, 0xFF, 0xBE, 0xF7, 0x9E, +0xC6, 0x18, 0xCE, 0x59, 0xFF, 0xBE, 0xF7, 0x9D, +0xDE, 0xBA, 0xF7, 0x9D, 0xFF, 0xDE, 0xE7, 0x1C, +0xAD, 0x55, 0xC6, 0x38, 0xFF, 0xDF, 0xF7, 0x9D, +0xE6, 0xD8, 0xB5, 0x52, 0xD6, 0x55, 0xCE, 0x37, +0xF7, 0x7D, 0xF7, 0x9E, 0xB5, 0x96, 0xA5, 0x34, +0xE7, 0x1C, 0xFF, 0xFF, 0xEF, 0x7D, 0xDF, 0x19, +0xEF, 0x59, 0xD6, 0x95, 0xD6, 0x97, 0x63, 0x69, +0x7C, 0x6B, 0xB6, 0x12, 0xC6, 0x33, 0xD6, 0xB4, +0xCE, 0x74, 0xC6, 0x52, 0xBE, 0x11, 0xB5, 0xB0, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xEF, 0x7D, 0xE6, 0xFA, 0xF7, 0xBE, 0xBD, 0xD7, +0x63, 0x0C, 0xA5, 0x14, 0xF7, 0xBE, 0xE6, 0xFB, +0xF7, 0xBE, 0x9C, 0xF3, 0x00, 0x00, 0xDE, 0xDB, +0xEF, 0x5C, 0xCE, 0x36, 0xCD, 0xF4, 0xD6, 0x55, +0xCE, 0x14, 0xDE, 0x95, 0xBD, 0x71, 0xAC, 0xEF, +0x8C, 0x0D, 0xB5, 0x53, 0xCE, 0x16, 0xAD, 0x53, +0x73, 0xAD, 0x94, 0xB0, 0xA5, 0x50, 0xA5, 0x4F, +0xA5, 0x0F, 0x9C, 0xCF, 0xC6, 0x55, 0xDF, 0x19, +0xEF, 0x7C, 0xCE, 0xB7, 0xAD, 0xF2, 0x94, 0xEF, +0x94, 0x8E, 0xBD, 0xB4, 0xB5, 0x53, 0x84, 0x0F, +0xA4, 0xD2, 0x9C, 0x91, 0x9C, 0x91, 0xC6, 0x16, +0x8C, 0x6F, 0x8C, 0x70, 0x7B, 0xCD, 0x63, 0x2C, +0x6B, 0x6D, 0x73, 0xAE, 0x84, 0x0F, 0x84, 0x30, +0x94, 0x72, 0x73, 0x8E, 0x63, 0x2D, 0x84, 0x10, +0xC6, 0x18, 0xE7, 0x3D, 0xFF, 0xFF, 0x08, 0x41, +0x6B, 0x6D, 0xF7, 0x9E, 0xC6, 0x18, 0xAD, 0x74, +0xAD, 0x13, 0xD6, 0x36, 0xDE, 0x35, 0xDE, 0x34, +0xDE, 0x34, 0xBD, 0x10, 0xC5, 0x51, 0xCD, 0x92, +0xD5, 0xD2, 0xD5, 0xF3, 0xCD, 0xB3, 0xA4, 0xB0, +0xBD, 0xB4, 0xB5, 0x74, 0xC6, 0x16, 0xCE, 0x36, +0xCE, 0x16, 0xC5, 0xF5, 0xBD, 0xB4, 0xBD, 0xB4, +0xB5, 0x93, 0xB5, 0x53, 0xAD, 0x32, 0x73, 0x4C, +0xA4, 0xD3, 0xCE, 0x17, 0x9C, 0x91, 0x94, 0x71, +0xC6, 0x18, 0xBD, 0xD7, 0x9C, 0xD3, 0x94, 0x71, +0x8C, 0x51, 0x73, 0x8E, 0x63, 0x0C, 0x7B, 0x8E, +0x41, 0xE7, 0x39, 0xA6, 0x31, 0x85, 0x39, 0xC6, +0x31, 0xA6, 0x42, 0x07, 0x5A, 0xCB, 0x6B, 0x2C, +0x6B, 0x4D, 0x6B, 0x6D, 0x73, 0x8E, 0x6B, 0x4D, +0x5A, 0xCA, 0x39, 0xE7, 0x42, 0x07, 0x63, 0x0B, +0x8C, 0x30, 0xDE, 0xDB, 0xF7, 0x7D, 0x00, 0x00, +0x8C, 0x51, 0xF7, 0x9E, 0xCE, 0x59, 0xC5, 0xD7, +0xCE, 0x18, 0xCE, 0x18, 0xAD, 0x35, 0xCE, 0x59, +0xD6, 0x9A, 0xD6, 0x79, 0xA4, 0xF4, 0xC6, 0x18, +0xB5, 0x96, 0x9C, 0xB3, 0xE6, 0xDB, 0xE7, 0x1C, +0xC5, 0xF8, 0xDE, 0xBB, 0xCE, 0x18, 0xBD, 0x96, +0xC5, 0xD6, 0xC5, 0xD6, 0x94, 0x71, 0x6B, 0x4C, +0x5A, 0xCB, 0x7B, 0xF0, 0x9C, 0xF4, 0xCE, 0x59, +0xF7, 0xBE, 0x6B, 0x6D, 0x10, 0x82, 0xFF, 0xDF, +0xE7, 0x3C, 0xCE, 0x58, 0xE6, 0xDA, 0xCE, 0x38, +0xC5, 0xF7, 0xC5, 0xD7, 0xD6, 0x59, 0xDE, 0x79, +0xC5, 0xD6, 0xAD, 0x55, 0xCE, 0x38, 0xCE, 0x59, +0xCE, 0x38, 0xBD, 0xB6, 0x9C, 0x93, 0x6B, 0x0D, +0x5A, 0xAB, 0x41, 0xE8, 0x4A, 0x49, 0x4A, 0x6A, +0x4A, 0x08, 0x41, 0xC7, 0x41, 0xC6, 0x39, 0xA6, +0x31, 0x45, 0x31, 0x45, 0x39, 0xA6, 0x62, 0xEC, +0xAD, 0x55, 0xAD, 0x54, 0xAD, 0x34, 0xA4, 0xF3, +0x94, 0x92, 0x8C, 0x51, 0x84, 0x10, 0x63, 0x0C, +0x62, 0xEB, 0x73, 0x6C, 0xAD, 0x32, 0xBD, 0xB5, +0xBD, 0xD6, 0xBD, 0xD5, 0xBD, 0xB5, 0xBD, 0xB5, +0xC5, 0xD6, 0xCE, 0x17, 0xCE, 0x17, 0xCE, 0x17, +0xCE, 0x37, 0xC5, 0xF6, 0xBD, 0x95, 0xB5, 0x53, +0xB5, 0x53, 0xBD, 0x74, 0xBD, 0x95, 0xBD, 0x94, +0xB5, 0x74, 0xB5, 0x54, 0xAD, 0x33, 0xA4, 0xF2, +0xA4, 0xD1, 0xA4, 0xF2, 0xA5, 0x12, 0x8C, 0x90, +0x8C, 0x90, 0x8C, 0x90, 0x42, 0xE6, 0x2A, 0x43, +0x53, 0x68, 0x32, 0x44, 0x3A, 0xC5, 0x3A, 0xE5, +0x3A, 0xC5, 0x43, 0x07, 0x5B, 0xEA, 0x53, 0xA9, +0x64, 0x4B, 0x3A, 0xC6, 0x22, 0x03, 0x19, 0xC2, +0x43, 0x27, 0x85, 0x2E, 0x74, 0xAC, 0x22, 0x03, +0x19, 0xA3, 0x2A, 0x24, 0x2A, 0x25, 0x21, 0x84, +0x52, 0xA9, 0x63, 0x0A, 0x7B, 0xAC, 0x83, 0xCB, +0x94, 0x2D, 0x9C, 0x8E, 0x9C, 0x8E, 0xA4, 0xCF, +0x94, 0x4D, 0xAD, 0x30, 0xA4, 0xEF, 0xB5, 0x71, +0xCE, 0x34, 0xA4, 0xAF, 0xA4, 0xAF, 0xB5, 0x71, +0xB5, 0x51, 0xB5, 0x72, 0xF7, 0x9E, 0x9C, 0xD3, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0xE3, 0xFF, 0xDF, 0xE7, 0x1B, +0xDE, 0xB8, 0xEF, 0x7C, 0xEF, 0x7D, 0x52, 0xAA, +0x00, 0x00, 0x00, 0x00, 0x39, 0xE7, 0xE7, 0x1B, +0xFF, 0xDE, 0xFF, 0xBE, 0xD6, 0x9A, 0x21, 0x04, +0x00, 0x00, 0x00, 0x00, 0x31, 0x86, 0xE7, 0x1C, +0xFF, 0xBE, 0xFF, 0xFF, 0x9C, 0xF3, 0x00, 0x20, +0x00, 0x00, 0x00, 0x00, 0x42, 0x28, 0xF7, 0xBE, +0xF7, 0x7C, 0xC5, 0xD5, 0xDE, 0xB8, 0xEF, 0x5C, +0xEF, 0x3C, 0x29, 0x65, 0x00, 0x00, 0x00, 0x00, +0x08, 0x41, 0xAD, 0x55, 0xF7, 0xBE, 0xD6, 0xD8, +0xC6, 0x95, 0xE7, 0x58, 0xD6, 0xB6, 0x6B, 0x8A, +0x9D, 0x50, 0xDF, 0x17, 0xE6, 0xD7, 0xE6, 0xD6, +0xDE, 0xB6, 0xDE, 0xB6, 0xDE, 0xB5, 0xDE, 0x75, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xF7, 0x9D, 0xE7, 0x1A, 0xFF, 0xBE, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xBE, 0xE6, 0xFA, +0xF7, 0xBE, 0x9C, 0xF3, 0x00, 0x00, 0xDE, 0xDB, +0xF7, 0x9E, 0xE7, 0x1B, 0xEF, 0x3B, 0xEF, 0x5B, +0xE6, 0xFA, 0xDE, 0xB9, 0xC5, 0xF6, 0xAD, 0x32, +0xA5, 0x12, 0xDE, 0xDA, 0xD6, 0x99, 0xC6, 0x38, +0xCE, 0x58, 0xCE, 0x77, 0xAD, 0xB2, 0xA5, 0x6E, +0xB6, 0x31, 0xAD, 0xB2, 0xCE, 0xB8, 0xEF, 0x7C, +0xF7, 0xBE, 0xDF, 0x1B, 0xBE, 0x16, 0x9C, 0xD1, +0x73, 0x6C, 0x7B, 0xAD, 0xAD, 0x74, 0xCE, 0x38, +0xEF, 0x3C, 0xEF, 0x3C, 0xEF, 0x5D, 0xCE, 0x79, +0x7B, 0xEF, 0x94, 0xB1, 0xD6, 0x98, 0xCE, 0x79, +0xCE, 0x59, 0xCE, 0x79, 0xCE, 0x79, 0xC6, 0x38, +0xB5, 0x96, 0x94, 0xB2, 0x8C, 0x51, 0xAD, 0x56, +0xBD, 0xF8, 0xE7, 0x1C, 0xFF, 0xDF, 0x08, 0x41, +0x6B, 0x6D, 0xFF, 0xDF, 0xDE, 0xFB, 0xDE, 0xDB, +0xEF, 0x3C, 0xEF, 0x7D, 0xE7, 0x1A, 0xE7, 0x18, +0xDE, 0xB6, 0xC5, 0xF3, 0x9C, 0x6D, 0x94, 0x0D, +0xA4, 0x6E, 0xAC, 0xAF, 0xAC, 0xD0, 0xBD, 0xB5, +0xCE, 0x58, 0xD6, 0xBA, 0xE7, 0x1B, 0xE7, 0x3B, +0xE7, 0x3B, 0xDE, 0xFA, 0xD6, 0x98, 0xCE, 0x57, +0xAD, 0xB2, 0xA5, 0x4F, 0x9C, 0xCF, 0xAD, 0x13, +0xAC, 0xF3, 0xB5, 0x54, 0x9C, 0xD3, 0xAD, 0x75, +0xCE, 0x59, 0xD6, 0x9A, 0xD6, 0x9A, 0xCE, 0x79, +0xC6, 0x38, 0xAD, 0x75, 0x94, 0x91, 0x6B, 0x4D, +0x39, 0xE7, 0x31, 0x85, 0x31, 0x85, 0x4A, 0x69, +0x52, 0xAA, 0x84, 0x10, 0xAD, 0x55, 0xC6, 0x18, +0xCE, 0x59, 0xCE, 0x79, 0xCE, 0x79, 0xC6, 0x38, +0xB5, 0x96, 0x94, 0x92, 0x7B, 0xCE, 0x52, 0x89, +0x84, 0x0F, 0xDE, 0xDB, 0xF7, 0x7D, 0x00, 0x00, +0x8C, 0x51, 0xF7, 0x7D, 0xBD, 0xB6, 0xA4, 0xD3, +0xC5, 0xB7, 0xB5, 0x76, 0xCE, 0x59, 0xE7, 0x3C, +0xD6, 0xBA, 0xEF, 0x3D, 0xDE, 0xFB, 0xD6, 0x9A, +0xBD, 0xF7, 0xC5, 0xF8, 0xDE, 0xDB, 0xDE, 0xDB, +0xE7, 0x1C, 0xE7, 0x1C, 0xEF, 0x5D, 0xE7, 0x1C, +0xC6, 0x18, 0xBD, 0xD7, 0x9C, 0x91, 0xD6, 0x78, +0xA5, 0x14, 0xBD, 0xD7, 0xCE, 0x79, 0xDE, 0xFB, +0xF7, 0xBE, 0x6B, 0x6D, 0x10, 0x82, 0xFF, 0xFF, +0xEF, 0x7D, 0xDE, 0xDB, 0xE7, 0x1C, 0xD6, 0x9A, +0xBD, 0xB7, 0xCE, 0x38, 0xC5, 0xD7, 0xEF, 0x1C, +0xD6, 0x9A, 0xCE, 0x59, 0xD6, 0xBA, 0xD6, 0xBA, +0xDE, 0xBA, 0xCE, 0x79, 0xC5, 0xF7, 0x9C, 0xD3, +0x7B, 0xAE, 0x52, 0x6A, 0x41, 0xE8, 0x39, 0xC7, +0x29, 0x65, 0x31, 0x65, 0x42, 0x08, 0x73, 0x6D, +0x9C, 0xD3, 0xBD, 0xB6, 0xBD, 0xF7, 0xAD, 0x55, +0x94, 0xB2, 0xAD, 0x55, 0xBD, 0xF7, 0xCE, 0x59, +0xD6, 0xBA, 0xDE, 0xDA, 0xD6, 0x99, 0xC6, 0x37, +0xC5, 0xF5, 0xCE, 0x15, 0xBD, 0xB3, 0xB5, 0x74, +0xCE, 0x37, 0xDE, 0xDA, 0xEF, 0x1B, 0xE7, 0x1B, +0xDE, 0xDA, 0xDE, 0xDA, 0xE6, 0xFB, 0xE7, 0x1B, +0xE7, 0x1B, 0xDE, 0xDB, 0xC6, 0x17, 0xB5, 0x74, +0xC5, 0xD6, 0xCE, 0x58, 0xDE, 0xDA, 0xE6, 0xFB, +0xE7, 0x1B, 0xE7, 0x1B, 0xE6, 0xFB, 0xDE, 0xDA, +0xDE, 0xBA, 0xDE, 0xDA, 0xE7, 0x3C, 0xE7, 0x3C, +0xEF, 0x5C, 0xD6, 0xDA, 0x22, 0x03, 0x22, 0x23, +0x22, 0x03, 0x2A, 0x24, 0x43, 0x27, 0x53, 0xC8, +0x53, 0xA8, 0x53, 0xA8, 0x64, 0x4B, 0x5B, 0xEA, +0x43, 0x28, 0x19, 0xC3, 0x21, 0xE4, 0x19, 0xC3, +0x19, 0xC3, 0x32, 0x84, 0x3A, 0xA5, 0x32, 0x85, +0x11, 0x82, 0x22, 0x04, 0x11, 0x42, 0x10, 0xC1, +0x52, 0x89, 0x52, 0x88, 0x62, 0xE9, 0x6B, 0x09, +0x73, 0x4A, 0x7B, 0xCC, 0x8C, 0x0C, 0x9C, 0x6E, +0xA4, 0xF0, 0xAD, 0x31, 0xAD, 0x30, 0xB5, 0x30, +0xB5, 0x51, 0x9C, 0x4E, 0x9C, 0x4E, 0xA4, 0xCF, +0xA4, 0xAF, 0x9C, 0xAF, 0xF7, 0x9D, 0x9C, 0xD3, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x10, 0xA2, 0xFF, 0xDF, 0xF7, 0x7D, +0xEF, 0x5C, 0xFF, 0xDE, 0x6B, 0x4D, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x08, +0xFF, 0xFF, 0xFF, 0xFF, 0x31, 0x86, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0xAA, +0xFF, 0xFF, 0xE7, 0x3C, 0x08, 0x41, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8C, 0x50, +0xFF, 0xDE, 0xE6, 0xFB, 0xFF, 0x9D, 0xFF, 0xDF, +0x63, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x08, 0x61, 0xF7, 0x9E, 0xE7, 0x3C, +0xAD, 0xD4, 0xDF, 0x38, 0xAD, 0x71, 0x8C, 0x8D, +0xBE, 0x34, 0xCE, 0x34, 0xCE, 0x34, 0xCE, 0x14, +0xC6, 0x13, 0xC5, 0xF3, 0xCE, 0x34, 0xCE, 0x34, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xF7, 0x9D, 0xE7, 0x1A, 0xF7, 0x9D, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xBE, 0xDE, 0xDA, +0xF7, 0xBE, 0x9C, 0xF3, 0x00, 0x00, 0xDE, 0xFB, +0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, +0xFF, 0xDF, 0xFF, 0xDE, 0xF7, 0x9D, 0xEF, 0x3B, +0xDE, 0xDA, 0xDE, 0xFB, 0xF7, 0x9D, 0xFF, 0xDE, +0xF7, 0xBE, 0xEF, 0x5D, 0xC6, 0x36, 0x9D, 0x6F, +0xBE, 0x73, 0xC6, 0x96, 0xEF, 0x9D, 0xFF, 0xDF, +0xFF, 0xFF, 0xF7, 0xBE, 0xE7, 0x1B, 0x9C, 0xD2, +0x52, 0x89, 0x6B, 0x6D, 0xC6, 0x38, 0xEF, 0x7D, +0xF7, 0xBE, 0xFF, 0xDF, 0xF7, 0xBE, 0xD6, 0xBA, +0xB5, 0x96, 0xD6, 0xBA, 0xF7, 0xBE, 0xFF, 0xDE, +0xFF, 0xBE, 0xFF, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, +0xEF, 0x7D, 0xDE, 0xFB, 0xBD, 0xF7, 0xA5, 0x14, +0xB5, 0x96, 0xE7, 0x1C, 0xFF, 0xDF, 0x08, 0x41, +0x6B, 0x6D, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xDF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDE, 0xF7, 0xBE, +0xEF, 0x7C, 0xD6, 0xF8, 0xCE, 0x55, 0xBD, 0x92, +0xB5, 0x72, 0xBD, 0xB4, 0xD6, 0x99, 0xEF, 0x5C, +0xF7, 0x9E, 0xFF, 0xDE, 0xFF, 0xDF, 0xFF, 0xDF, +0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDE, 0xEF, 0x7C, +0xCE, 0xB8, 0xA5, 0x91, 0x9D, 0x6F, 0xBD, 0xF4, +0xAD, 0x33, 0xBD, 0xF7, 0xDE, 0xFB, 0xEF, 0x7D, +0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, +0xF7, 0xBE, 0xEF, 0x7D, 0xE7, 0x1C, 0xBD, 0xF7, +0x84, 0x10, 0x42, 0x28, 0x39, 0xC6, 0x63, 0x2C, +0xA5, 0x34, 0xD6, 0xBA, 0xEF, 0x7D, 0xF7, 0x9E, +0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, +0xF7, 0x9E, 0xE7, 0x1C, 0xC6, 0x18, 0x8C, 0x71, +0x84, 0x30, 0xDE, 0xDB, 0xF7, 0x9E, 0x00, 0x00, +0x8C, 0x51, 0xEF, 0x7D, 0xB5, 0x55, 0xB5, 0x55, +0xC5, 0xD7, 0xDE, 0xDB, 0xF7, 0xBE, 0xFF, 0xDF, +0xF7, 0xBE, 0xFF, 0xDF, 0xF7, 0xBE, 0xF7, 0x9E, +0xDE, 0xDB, 0xE7, 0x3C, 0xF7, 0x9E, 0xFF, 0xDF, +0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, +0xF7, 0xBE, 0xEF, 0x5D, 0xCE, 0x59, 0xB5, 0x96, +0xBD, 0xF7, 0xEF, 0x5D, 0xF7, 0xBE, 0xFF, 0xDF, +0xFF, 0xFF, 0x6B, 0x6D, 0x10, 0x82, 0xFF, 0xFF, +0xFF, 0xDF, 0xF7, 0xBE, 0xF7, 0xBE, 0xEF, 0x5D, +0xD6, 0x59, 0xC5, 0xF8, 0xE7, 0x1C, 0xEF, 0x5D, +0xF7, 0x9E, 0xF7, 0xBE, 0xFF, 0xBF, 0xFF, 0xDF, +0xF7, 0xBE, 0xF7, 0xBE, 0xEF, 0x7D, 0xE6, 0xFB, +0xBD, 0xF7, 0x73, 0xAE, 0x4A, 0x29, 0x29, 0x65, +0x21, 0x24, 0x31, 0x86, 0xB5, 0x75, 0xC6, 0x17, +0xBD, 0xD7, 0xB5, 0x95, 0x8C, 0x71, 0xB5, 0x96, +0xDE, 0xFB, 0xEF, 0x7D, 0xF7, 0xBE, 0xFF, 0xDF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFE, +0xFF, 0xDD, 0xEF, 0x5B, 0xCE, 0x56, 0xAD, 0x33, +0xE7, 0x1B, 0xFF, 0xBE, 0xFF, 0xDF, 0xFF, 0xDF, +0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xEF, 0x7D, +0xEF, 0x7D, 0xF7, 0xBE, 0xE6, 0xDA, 0xDE, 0x99, +0xEF, 0x3C, 0xF7, 0x9E, 0xFF, 0xDE, 0xFF, 0xDE, +0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xF7, 0xBE, +0xFF, 0xBE, 0xFF, 0xBE, 0xEF, 0x7D, 0xB5, 0x96, +0xD6, 0xBA, 0xEF, 0x5D, 0x32, 0xA4, 0x32, 0x84, +0x32, 0xA5, 0x63, 0xEB, 0x3A, 0xE6, 0x4B, 0x67, +0x5B, 0xE9, 0x53, 0xA8, 0x6C, 0x8C, 0x53, 0xA9, +0x19, 0xA2, 0x11, 0x82, 0x19, 0xC3, 0x19, 0xC3, +0x19, 0xA2, 0x2A, 0x24, 0x32, 0x85, 0x3A, 0xA5, +0x11, 0x41, 0x11, 0x42, 0x11, 0x22, 0x29, 0xC5, +0x5A, 0xCA, 0x5A, 0xCA, 0x5A, 0x89, 0x5A, 0xA9, +0x6B, 0x0A, 0x6B, 0x0A, 0x6B, 0x2A, 0x73, 0x2A, +0x7B, 0x6B, 0x83, 0xAB, 0x73, 0x6A, 0x73, 0x2A, +0x83, 0xCC, 0x94, 0x4E, 0x9C, 0x8F, 0x8C, 0x0D, +0x94, 0x2D, 0x94, 0x2E, 0xF7, 0x7D, 0x84, 0x30, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x08, 0x41, 0xFF, 0xFF, 0xFF, 0xBE, +0xF7, 0xBE, 0xFF, 0xFF, 0x18, 0xC3, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xEF, 0x7D, 0xEF, 0x5D, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x61, +0xFF, 0xFF, 0xA5, 0x14, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xE7, +0xFF, 0xFF, 0xF7, 0x7D, 0xFF, 0xBE, 0xFF, 0xFF, +0x21, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xBD, 0xD7, 0xEF, 0x7D, +0xAD, 0xD3, 0xD7, 0x17, 0x9D, 0x0F, 0xB5, 0xD3, +0xC6, 0x54, 0xC6, 0x34, 0xC6, 0x14, 0xC5, 0xF4, +0xCE, 0x14, 0xCE, 0x55, 0xCE, 0x34, 0xCE, 0x34, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xF7, 0x9D, 0xDE, 0xD9, 0xF7, 0x9D, 0xDE, 0xDB, +0x29, 0x65, 0xB5, 0xB6, 0xF7, 0xBE, 0xDE, 0xB9, +0xF7, 0x9E, 0x9C, 0xF3, 0x00, 0x00, 0xDE, 0xFB, +0xAD, 0x55, 0x42, 0x28, 0x18, 0xC3, 0x00, 0x00, +0x10, 0xA2, 0x39, 0xE7, 0x9C, 0xD3, 0xFF, 0xDF, +0xEF, 0x7D, 0xE7, 0x1C, 0xFF, 0xDF, 0x6B, 0x6D, +0x4A, 0x49, 0xFF, 0xDE, 0xDF, 0x1A, 0xB6, 0x32, +0xA5, 0x90, 0xCE, 0xB8, 0xF7, 0xBE, 0x63, 0x0C, +0x31, 0x86, 0x94, 0xB2, 0xF7, 0xBE, 0xCE, 0xB8, +0xA5, 0x92, 0xAD, 0x73, 0xE7, 0x1C, 0xE7, 0x1C, +0x31, 0x86, 0xA5, 0x34, 0xF7, 0xBE, 0xE7, 0x1C, +0xE7, 0x3C, 0xF7, 0xBE, 0x9C, 0xD3, 0x42, 0x08, +0x18, 0xC3, 0x00, 0x00, 0x10, 0x82, 0x29, 0x65, +0x73, 0xAE, 0xE7, 0x3C, 0xF7, 0x9E, 0xD6, 0xBA, +0xCE, 0x59, 0xE7, 0x3D, 0xFF, 0xDF, 0x08, 0x41, +0x6B, 0x6D, 0xDE, 0xFB, 0x6B, 0x4D, 0x29, 0x45, +0x08, 0x41, 0x08, 0x41, 0x21, 0x24, 0x6B, 0x6D, +0xE7, 0x1C, 0xF7, 0xBE, 0xE7, 0x1A, 0xBD, 0xB3, +0xC5, 0xF4, 0xE7, 0x1A, 0xF7, 0xBE, 0xE7, 0x1C, +0x73, 0x8E, 0x29, 0x65, 0x10, 0xA2, 0x00, 0x00, +0x08, 0x61, 0x21, 0x24, 0x63, 0x2C, 0xD6, 0x9A, +0xF7, 0x9D, 0xD6, 0xD8, 0xA5, 0xD1, 0xAD, 0xF1, +0xD6, 0xB8, 0xF7, 0xBD, 0xE7, 0x3C, 0x73, 0xAE, +0x31, 0x86, 0x10, 0x82, 0x00, 0x00, 0x08, 0x61, +0x21, 0x24, 0x63, 0x0C, 0xCE, 0x79, 0xF7, 0x9D, +0xCE, 0x59, 0x84, 0x10, 0x6B, 0x4C, 0xAD, 0x55, +0xE7, 0x1C, 0xEF, 0x5D, 0x84, 0x30, 0x39, 0xC7, +0x10, 0x82, 0x00, 0x00, 0x08, 0x41, 0x21, 0x04, +0x63, 0x0C, 0xD6, 0x9A, 0xEF, 0x7D, 0xCE, 0x79, +0xA5, 0x14, 0xDE, 0xFB, 0xF7, 0x9E, 0x00, 0x00, +0x8C, 0x51, 0xF7, 0x9E, 0xBD, 0x96, 0xBD, 0x96, +0xDE, 0xDB, 0xF7, 0xBE, 0xB5, 0xB6, 0x31, 0x86, +0x63, 0x0C, 0xF7, 0xBE, 0xEF, 0x7D, 0xE7, 0x3C, +0xEF, 0x7D, 0xFF, 0xDF, 0xBD, 0xF7, 0x5A, 0xCB, +0x18, 0xE3, 0x08, 0x41, 0x08, 0x41, 0x21, 0x04, +0x63, 0x0C, 0xCE, 0x59, 0xFF, 0xDF, 0xE7, 0x3C, +0xD6, 0xBA, 0xF7, 0x9E, 0x73, 0x8E, 0x31, 0x86, +0x31, 0x86, 0x10, 0xA2, 0x00, 0x00, 0x21, 0x04, +0x21, 0x04, 0x21, 0x04, 0x73, 0xAE, 0xF7, 0xBE, +0xDE, 0xBA, 0xEF, 0x3C, 0xF7, 0xBE, 0xD6, 0x9A, +0x63, 0x0C, 0x29, 0x45, 0x10, 0x82, 0x00, 0x00, +0x08, 0x61, 0x29, 0x65, 0x73, 0xAE, 0xDE, 0xFB, +0xEF, 0x5D, 0xBD, 0xD7, 0x6B, 0x4D, 0x31, 0x86, +0x29, 0x45, 0x29, 0x24, 0x5A, 0xCA, 0x62, 0xEB, +0x52, 0xAB, 0x73, 0xAE, 0xBD, 0xF7, 0xEF, 0x7D, +0xE7, 0x3C, 0x7B, 0xCF, 0x31, 0x86, 0x10, 0xA2, +0x00, 0x00, 0x08, 0x61, 0x21, 0x24, 0x63, 0x0C, +0xCE, 0x79, 0xFF, 0xDE, 0xE7, 0x3B, 0xCE, 0x37, +0xEF, 0x5C, 0xEF, 0x5C, 0x21, 0x24, 0xB5, 0x96, +0xB5, 0x96, 0x39, 0xC7, 0x08, 0x41, 0x00, 0x00, +0x52, 0x8A, 0xFF, 0xDF, 0xF7, 0x7C, 0xF7, 0x9D, +0xF7, 0xBE, 0x94, 0xB2, 0x42, 0x08, 0x18, 0xE3, +0x08, 0x41, 0x00, 0x20, 0x18, 0xC3, 0x31, 0xA6, +0x84, 0x10, 0xC6, 0x18, 0x10, 0x82, 0x00, 0x00, +0x9C, 0xF3, 0xEF, 0x5D, 0x3A, 0xE5, 0x3B, 0x06, +0x64, 0x0B, 0x85, 0x0F, 0x5B, 0xCA, 0x43, 0x07, +0xA5, 0xD2, 0x53, 0x88, 0x74, 0xAD, 0x43, 0x07, +0x19, 0xA3, 0x19, 0xA3, 0x21, 0xC3, 0x19, 0xA3, +0x19, 0xA3, 0x19, 0xA2, 0x32, 0x64, 0x32, 0x85, +0x19, 0xA3, 0x21, 0xC3, 0x2A, 0x25, 0x32, 0x66, +0x73, 0x4C, 0x83, 0xCD, 0x6B, 0x0A, 0x83, 0xED, +0xAC, 0xF1, 0xAC, 0xD0, 0xAC, 0xD0, 0x9C, 0x8F, +0x9C, 0x6F, 0x94, 0x4E, 0x8B, 0xED, 0x8C, 0x0D, +0xA4, 0xD0, 0xBD, 0x73, 0xB5, 0x32, 0xA4, 0xB0, +0xA4, 0xD0, 0xAC, 0xD0, 0xF7, 0x9D, 0x5A, 0xEB, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xDE, +0xF7, 0xBE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xC6, 0x38, 0xDE, 0xDB, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xF7, 0x9E, 0x84, 0x30, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x82, +0xFF, 0xDF, 0xEF, 0x7C, 0xFF, 0xBE, 0xFF, 0xFF, +0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xA5, 0x14, 0xEF, 0x7D, +0xB6, 0x14, 0xB6, 0x94, 0xBE, 0x74, 0x9D, 0x0F, +0x94, 0xAD, 0xAD, 0x70, 0xA5, 0x2E, 0x9D, 0x4D, +0xA5, 0x6E, 0xC6, 0x53, 0xD6, 0x96, 0xB5, 0x72, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xF7, 0x9D, 0xCE, 0x58, 0xF7, 0x9D, 0xD6, 0x9A, +0x00, 0x00, 0xA5, 0x34, 0xF7, 0xBE, 0xDE, 0xB9, +0xF7, 0xBE, 0x9C, 0xF3, 0x00, 0x00, 0x52, 0xAA, +0x00, 0x00, 0x52, 0x8A, 0x8C, 0x71, 0x9C, 0xD3, +0x84, 0x30, 0x39, 0xE7, 0x00, 0x00, 0x52, 0xAA, +0xFF, 0xDF, 0xF7, 0x9E, 0xFF, 0xFF, 0x84, 0x30, +0x00, 0x00, 0xE7, 0x1C, 0xE7, 0x5C, 0xAD, 0xF2, +0xAD, 0xF2, 0xDF, 0x3B, 0xF7, 0xBE, 0x08, 0x41, +0x08, 0x61, 0x39, 0xE7, 0xF7, 0xDE, 0xDF, 0x1A, +0xB6, 0x54, 0xCE, 0x97, 0xEF, 0x7D, 0xA5, 0x34, +0x00, 0x00, 0xCE, 0x59, 0xFF, 0xDF, 0xF7, 0xBE, +0xF7, 0x9E, 0x42, 0x08, 0x00, 0x00, 0x4A, 0x69, +0x8C, 0x71, 0xA5, 0x34, 0x9C, 0xD3, 0x6B, 0x6D, +0x10, 0xA2, 0x10, 0x82, 0xCE, 0x79, 0xF7, 0xBE, +0xE7, 0x3C, 0xEF, 0x7D, 0xFF, 0xFF, 0x08, 0x41, +0x42, 0x28, 0x10, 0x82, 0x21, 0x24, 0x7B, 0xCF, +0x9C, 0xD3, 0x94, 0x92, 0x63, 0x2C, 0x08, 0x61, +0x10, 0x82, 0xD6, 0xBA, 0xEF, 0x7D, 0xBD, 0xD6, +0xC6, 0x16, 0xEF, 0x7D, 0xD6, 0xBA, 0x10, 0x82, +0x08, 0x41, 0x5A, 0xCB, 0x84, 0x30, 0x9C, 0xD3, +0x8C, 0x71, 0x6B, 0x4D, 0x18, 0xC3, 0x08, 0x41, +0xBD, 0xF7, 0xEF, 0x9D, 0xC6, 0x76, 0xBE, 0x56, +0xEF, 0x7D, 0xCE, 0x59, 0x10, 0x82, 0x10, 0x82, +0x63, 0x0C, 0x94, 0x92, 0x9C, 0xD3, 0x94, 0xB2, +0x73, 0x8E, 0x18, 0xE3, 0x00, 0x00, 0xA5, 0x14, +0xEF, 0x7D, 0xBD, 0xF7, 0xA5, 0x13, 0xDE, 0xDB, +0xEF, 0x5D, 0x29, 0x65, 0x00, 0x20, 0x52, 0xAA, +0x84, 0x10, 0x9C, 0xD3, 0x94, 0x92, 0x6B, 0x4D, +0x10, 0x82, 0x00, 0x20, 0xAD, 0x75, 0xEF, 0x7D, +0xCE, 0x59, 0xEF, 0x5D, 0xF7, 0x9E, 0x00, 0x00, +0x8C, 0x51, 0xFF, 0xDF, 0xDE, 0xBA, 0xD6, 0xBA, +0xF7, 0x9E, 0xB5, 0x96, 0x00, 0x20, 0x39, 0xE7, +0xEF, 0x5D, 0xEF, 0x5D, 0xCE, 0x59, 0xE7, 0x1C, +0xFF, 0xDF, 0x7B, 0xEF, 0x00, 0x00, 0x31, 0x86, +0x84, 0x10, 0x9C, 0xF3, 0x9C, 0xF3, 0x7B, 0xEF, +0x29, 0x65, 0x00, 0x00, 0x94, 0xB2, 0xF7, 0xBE, +0xEF, 0x7D, 0xFF, 0xDF, 0x94, 0xB2, 0x63, 0x2C, +0x63, 0x2C, 0x29, 0x45, 0x08, 0x41, 0x73, 0xAE, +0x73, 0xAE, 0x73, 0xAE, 0xAD, 0x55, 0xF7, 0xBE, +0xE7, 0x1C, 0xF7, 0x9E, 0xBD, 0xF7, 0x08, 0x41, +0x10, 0xA2, 0x63, 0x2C, 0x8C, 0x71, 0x9C, 0xD3, +0x8C, 0x51, 0x5A, 0xEB, 0x08, 0x61, 0x10, 0xA2, +0xD6, 0xBA, 0xE7, 0x1C, 0x94, 0x92, 0x42, 0x07, +0x21, 0x04, 0x21, 0x04, 0x21, 0x24, 0x29, 0x65, +0x62, 0xEB, 0xBD, 0xD6, 0xF7, 0x9D, 0xCE, 0x79, +0x10, 0x82, 0x08, 0x61, 0x63, 0x0C, 0x8C, 0x71, +0x9C, 0xD3, 0x94, 0xB2, 0x73, 0x8E, 0x21, 0x04, +0x00, 0x00, 0x9C, 0xF3, 0xF7, 0xBE, 0xEF, 0x5B, +0xFF, 0xDD, 0xE7, 0x3C, 0x00, 0x00, 0x42, 0x08, +0x00, 0x20, 0x52, 0x8A, 0x94, 0x92, 0x9C, 0xD3, +0xBD, 0xD7, 0xFF, 0xFF, 0xFF, 0xDE, 0xFF, 0xDF, +0x4A, 0x49, 0x00, 0x00, 0x4A, 0x49, 0x8C, 0x71, +0x9C, 0xF3, 0x9C, 0xF3, 0x84, 0x30, 0x5A, 0xEB, +0x08, 0x41, 0x00, 0x00, 0x5A, 0xCB, 0xDE, 0xFB, +0xFF, 0xDF, 0xE7, 0x3C, 0x43, 0x26, 0x64, 0x6C, +0x85, 0x30, 0x9D, 0xB3, 0x85, 0x10, 0x7C, 0x8D, +0xA5, 0xB2, 0x2A, 0x04, 0x53, 0x69, 0x2A, 0x24, +0x11, 0x62, 0x19, 0xC4, 0x2A, 0x05, 0x21, 0xC3, +0x21, 0xC3, 0x43, 0x07, 0x19, 0xA2, 0x3A, 0x85, +0x22, 0x03, 0x3A, 0xC6, 0x42, 0xE6, 0x32, 0x24, +0x9C, 0x4F, 0x94, 0x2E, 0x6A, 0xEA, 0xA4, 0xF1, +0xC5, 0xB3, 0xC5, 0xB4, 0xBD, 0x93, 0xBD, 0x52, +0xB5, 0x32, 0x94, 0x4F, 0x8C, 0x2E, 0x8C, 0x0D, +0x83, 0xED, 0x83, 0xCD, 0x7B, 0xAC, 0x73, 0x4B, +0x73, 0x4B, 0x73, 0x6B, 0xEF, 0x7D, 0x63, 0x2C, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xF7, 0xBE, +0xF7, 0x9E, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xCE, 0x59, 0xDE, 0xFB, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xF7, 0x9E, 0xA5, 0x14, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x24, +0xFF, 0xDE, 0xE7, 0x1B, 0xEF, 0x5C, 0xFF, 0xDE, +0x18, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xAD, 0x75, 0xEF, 0x7D, +0xB6, 0x55, 0xBE, 0xB5, 0xBE, 0x94, 0xA5, 0x91, +0x8C, 0x8D, 0xAD, 0x90, 0x7C, 0x88, 0x8D, 0x09, +0x8D, 0x08, 0x8C, 0xEA, 0x94, 0xEC, 0xAD, 0x4F, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xF7, 0x9D, 0xDE, 0xD9, 0xF7, 0x9D, 0xD6, 0x9A, +0x00, 0x00, 0xA5, 0x34, 0xF7, 0xBE, 0xDE, 0xB9, +0xFF, 0xBE, 0x9C, 0xF3, 0x00, 0x00, 0x00, 0x00, +0xB5, 0x96, 0xFF, 0xDF, 0xF7, 0xBE, 0xF7, 0x9D, +0xF7, 0xBE, 0xFF, 0xDF, 0x84, 0x10, 0x00, 0x00, +0xAD, 0x55, 0xFF, 0xFF, 0xFF, 0xFF, 0xCE, 0x79, +0x00, 0x00, 0xA5, 0x14, 0xEF, 0x9D, 0xC6, 0x55, +0xCE, 0x76, 0xEF, 0x9D, 0xBD, 0xF7, 0x00, 0x00, +0x7B, 0xEF, 0x00, 0x20, 0xF7, 0x9E, 0xDF, 0x3B, +0xAE, 0x13, 0xCE, 0xD8, 0xFF, 0xDE, 0x63, 0x2C, +0x10, 0x82, 0xFF, 0xDF, 0xF7, 0xBE, 0xFF, 0xFF, +0x73, 0xAE, 0x00, 0x20, 0xBD, 0xD7, 0xF7, 0xBE, +0xEF, 0x7D, 0xEF, 0x5D, 0xEF, 0x7D, 0xF7, 0xBE, +0xE7, 0x3C, 0x21, 0x24, 0x29, 0x45, 0xF7, 0xBE, +0xE7, 0x1C, 0xE7, 0x1C, 0xFF, 0xDF, 0x08, 0x41, +0x00, 0x00, 0x4A, 0x69, 0xF7, 0xBE, 0xF7, 0x9E, +0xF7, 0x9E, 0xF7, 0xBE, 0xFF, 0xDF, 0xDE, 0xDB, +0x10, 0xA2, 0x39, 0xE7, 0xFF, 0xDF, 0xEF, 0x5D, +0xE7, 0x3C, 0xFF, 0xDE, 0x52, 0xAA, 0x08, 0x61, +0xDE, 0xDB, 0xFF, 0xDF, 0xF7, 0xBE, 0xF7, 0xBE, +0xFF, 0xDE, 0xFF, 0xDF, 0xEF, 0x7D, 0x29, 0x45, +0x31, 0x86, 0xF7, 0xDE, 0xDF, 0x1A, 0xE7, 0x3B, +0xF7, 0xDE, 0x29, 0x45, 0x29, 0x45, 0xE7, 0x3C, +0xF7, 0xBE, 0xEF, 0x9D, 0xEF, 0x7D, 0xEF, 0x7D, +0xF7, 0x9E, 0xF7, 0xBE, 0x4A, 0x49, 0x08, 0x41, +0xE7, 0x1C, 0xE7, 0x3C, 0xD6, 0x9A, 0xF7, 0x9E, +0x6B, 0x4D, 0x00, 0x00, 0xB5, 0xB6, 0xF7, 0xBE, +0xEF, 0x7D, 0xEF, 0x5D, 0xEF, 0x7D, 0xF7, 0x9E, +0xEF, 0x7D, 0x31, 0x86, 0x10, 0x82, 0xEF, 0x7D, +0xEF, 0x5D, 0xEF, 0x7D, 0xF7, 0x9E, 0x00, 0x00, +0x8C, 0x51, 0xFF, 0xFF, 0xF7, 0x9E, 0xF7, 0xBE, +0xA5, 0x14, 0x00, 0x20, 0x4A, 0x69, 0xF7, 0x9E, +0xEF, 0x3C, 0xBD, 0xF7, 0xC6, 0x18, 0xEF, 0x7D, +0xBD, 0xF7, 0x00, 0x00, 0x73, 0xAE, 0xFF, 0xDF, +0xF7, 0xBE, 0xF7, 0x9E, 0xF7, 0x9E, 0xF7, 0xBE, +0xFF, 0xDF, 0x5A, 0xCB, 0x00, 0x20, 0xD6, 0xBA, +0xFF, 0xDF, 0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, +0xFF, 0xFF, 0x6B, 0x6D, 0x10, 0x82, 0xFF, 0xFF, +0xFF, 0xDF, 0xF7, 0x9E, 0xF7, 0xBE, 0xF7, 0x9E, +0xEF, 0x5D, 0xF7, 0xBE, 0x29, 0x65, 0x18, 0xE3, +0xEF, 0x5D, 0xF7, 0xBE, 0xEF, 0x7D, 0xEF, 0x7D, +0xEF, 0x7D, 0xF7, 0xBE, 0xE7, 0x1C, 0x10, 0x82, +0x52, 0xAA, 0xEF, 0x7D, 0xAD, 0x75, 0x52, 0xCA, +0x41, 0xE7, 0x7B, 0xAD, 0xAD, 0x32, 0xCE, 0x15, +0xD6, 0x77, 0xEF, 0x5C, 0xFF, 0xDF, 0x29, 0x65, +0x21, 0x24, 0xE7, 0x3C, 0xFF, 0xDE, 0xF7, 0xDE, +0xF7, 0xBD, 0xF7, 0xBD, 0xFF, 0xDE, 0xF7, 0xBE, +0x4A, 0x69, 0x08, 0x41, 0xE7, 0x1C, 0xFF, 0xDE, +0xFF, 0xDE, 0xE7, 0x3C, 0x00, 0x00, 0x00, 0x20, +0xC6, 0x18, 0xFF, 0xDF, 0xFF, 0xBE, 0xFF, 0xBE, +0xFF, 0xBE, 0xFF, 0xBE, 0xFF, 0xFF, 0xB5, 0xB6, +0x00, 0x00, 0x9C, 0xD3, 0xFF, 0xFF, 0xF7, 0xBE, +0xF7, 0x9D, 0xF7, 0xBE, 0xF7, 0xBE, 0xFF, 0xDF, +0xDE, 0xDB, 0x08, 0x61, 0x73, 0x8E, 0xFF, 0xDF, +0xEF, 0x5C, 0xC6, 0x78, 0x6C, 0x6B, 0x8D, 0x50, +0x95, 0x72, 0xA6, 0x15, 0x95, 0x72, 0x53, 0x29, +0x53, 0x49, 0x29, 0xE4, 0x21, 0xC3, 0x19, 0xA2, +0x11, 0x42, 0x21, 0xC4, 0x32, 0x66, 0x21, 0xC4, +0x09, 0x01, 0x19, 0xA3, 0x11, 0x42, 0x21, 0xE4, +0x32, 0x85, 0x5B, 0xE9, 0x43, 0x46, 0x3A, 0xA5, +0x9C, 0x70, 0x8B, 0xED, 0x6B, 0x0A, 0xAD, 0x11, +0xBD, 0xB3, 0xCD, 0xF4, 0xCD, 0xF5, 0xCE, 0x15, +0xDE, 0x77, 0xD6, 0x36, 0xCD, 0xF5, 0xD6, 0x56, +0xD6, 0x77, 0xBD, 0xB4, 0xAD, 0x32, 0xAD, 0x11, +0xA4, 0xD0, 0x9C, 0x90, 0xF7, 0x9D, 0x6B, 0x4D, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xF7, 0x9E, +0xEF, 0x7D, 0xFF, 0xDF, 0x00, 0x20, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xCE, 0x59, 0xDE, 0xFB, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xF7, 0x9E, 0xA5, 0x14, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x65, +0xFF, 0xDE, 0xEF, 0x3B, 0xEF, 0x3B, 0xFF, 0xDE, +0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xAD, 0x75, 0xEF, 0x7D, +0x9D, 0x72, 0xA5, 0xD1, 0xBE, 0x95, 0x6B, 0xCB, +0xA5, 0x30, 0xAD, 0x90, 0x63, 0xC6, 0xA5, 0xCC, +0x84, 0xE8, 0x7C, 0xA8, 0x84, 0x89, 0x84, 0x2A, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xEF, 0x3C, 0xC5, 0xF6, 0xEF, 0x5C, 0xD6, 0x9A, +0x00, 0x00, 0xA5, 0x34, 0xF7, 0x9D, 0xDE, 0xB9, +0xF7, 0x9D, 0x9C, 0xF3, 0x00, 0x00, 0x52, 0xAA, +0xFF, 0xDF, 0xE7, 0x3B, 0xC6, 0x76, 0xBE, 0x14, +0xDE, 0xF9, 0xF7, 0x9D, 0xFF, 0xDF, 0x21, 0x04, +0x4A, 0x49, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xDF, +0x10, 0xA2, 0x63, 0x0C, 0xFF, 0xDE, 0xEF, 0x5B, +0xE7, 0x19, 0xF7, 0xBE, 0x7B, 0xCF, 0x21, 0x24, +0xE7, 0x1C, 0x00, 0x00, 0xBD, 0xD7, 0xEF, 0x9D, +0xD6, 0xB7, 0xDF, 0x1A, 0xFF, 0xDF, 0x21, 0x04, +0x52, 0xAA, 0xFF, 0xFF, 0xFF, 0xDE, 0xF7, 0xBE, +0x08, 0x61, 0x6B, 0x4D, 0xFF, 0xDF, 0xE7, 0x3C, +0xBE, 0x17, 0xBE, 0x16, 0xBE, 0x36, 0xD6, 0x99, +0xF7, 0x9E, 0xAD, 0x55, 0x00, 0x00, 0xBD, 0xF7, +0xF7, 0x9E, 0xE7, 0x3C, 0xFF, 0xDF, 0x08, 0x41, +0x00, 0x20, 0xE7, 0x1C, 0xEF, 0x5D, 0xC6, 0x18, +0xA5, 0x14, 0xAD, 0x35, 0xCE, 0x79, 0xF7, 0xBE, +0x8C, 0x71, 0x00, 0x00, 0xDE, 0xDB, 0xF7, 0xBE, +0xF7, 0x9E, 0xFF, 0xDF, 0x18, 0xE3, 0x63, 0x0C, +0xFF, 0xFF, 0xF7, 0x7D, 0xDE, 0xDB, 0xB5, 0xB6, +0xC6, 0x18, 0xD6, 0xBA, 0xF7, 0xBE, 0x7B, 0xEF, +0x00, 0x20, 0xF7, 0xDE, 0xEF, 0x7C, 0xF7, 0xBE, +0xC6, 0x18, 0x00, 0x00, 0xAD, 0x55, 0xF7, 0xDE, +0xE7, 0x7B, 0xD6, 0xF8, 0xBE, 0x55, 0xBD, 0xF5, +0xC6, 0x17, 0xEF, 0x5D, 0xD6, 0xBA, 0x00, 0x00, +0x94, 0x92, 0xFF, 0xDF, 0xEF, 0x7D, 0xF7, 0x9E, +0x08, 0x61, 0x5A, 0xCB, 0xF7, 0xBE, 0xD6, 0x9A, +0xA5, 0x34, 0x94, 0xB2, 0x9C, 0xF3, 0xC6, 0x17, +0xEF, 0x7D, 0xBD, 0xD7, 0x00, 0x00, 0xB5, 0x96, +0xF7, 0xBE, 0xF7, 0x9E, 0xF7, 0x9E, 0x00, 0x00, +0x8C, 0x51, 0xFF, 0xFF, 0xFF, 0xFF, 0x9C, 0xD3, +0x00, 0x00, 0x5A, 0xEB, 0xF7, 0xBE, 0xE7, 0x3C, +0xAD, 0x75, 0xA4, 0xF3, 0xCE, 0x79, 0xF7, 0x9E, +0x52, 0x8A, 0x21, 0x04, 0xFF, 0xDF, 0xF7, 0x9E, +0xDE, 0xDB, 0xDE, 0xFB, 0xD6, 0x9A, 0xEF, 0x5D, +0xF7, 0xBE, 0xEF, 0x5D, 0x00, 0x20, 0x7B, 0xCF, +0xFF, 0xBF, 0xDE, 0xDB, 0xCE, 0x79, 0xCE, 0x79, +0xF7, 0xBE, 0x6B, 0x6D, 0x10, 0x82, 0xFF, 0xDF, +0xE7, 0x1C, 0xB5, 0xB6, 0xAD, 0x75, 0xBD, 0xD7, +0xDE, 0xFB, 0xEF, 0x7D, 0x00, 0x00, 0x84, 0x30, +0xF7, 0xBE, 0xD6, 0x9A, 0xB5, 0x96, 0xA5, 0x34, +0xAD, 0x75, 0xD6, 0x9A, 0xF7, 0xBE, 0x52, 0xAA, +0x29, 0x45, 0xF7, 0x9E, 0xC6, 0x17, 0x9C, 0xD1, +0xCE, 0x35, 0xEF, 0x18, 0xEF, 0x18, 0xEF, 0x18, +0xDE, 0xB8, 0xF7, 0x9D, 0xCE, 0x58, 0x00, 0x00, +0xA5, 0x34, 0xFF, 0xDE, 0xDE, 0xF9, 0xDF, 0x17, +0xDF, 0x16, 0xDF, 0x36, 0xEF, 0x99, 0xF7, 0xDD, +0xDE, 0xFB, 0x00, 0x00, 0x8C, 0x71, 0xFF, 0xFF, +0xFF, 0xFE, 0xE7, 0x3C, 0x00, 0x00, 0x5A, 0xCB, +0xFF, 0xFF, 0xF7, 0x9C, 0xE6, 0xF9, 0xE6, 0xB8, +0xDE, 0x98, 0xE6, 0xFA, 0xFF, 0xDE, 0x7B, 0xEF, +0x00, 0x00, 0xEF, 0x5D, 0xF7, 0x9D, 0xD6, 0x78, +0xD6, 0x37, 0xE6, 0xB8, 0xDE, 0x98, 0xEF, 0x5C, +0xFF, 0xDF, 0x4A, 0x49, 0x39, 0xC7, 0xF7, 0xBE, +0xCE, 0xB8, 0x8D, 0x10, 0x85, 0x4F, 0x95, 0x92, +0xA5, 0xD4, 0x9D, 0xB3, 0x4B, 0x29, 0x19, 0xA3, +0x2A, 0x04, 0x21, 0xE3, 0x21, 0xE3, 0x11, 0x82, +0x11, 0x62, 0x19, 0x83, 0x32, 0x66, 0x19, 0x83, +0x19, 0x62, 0x11, 0x21, 0x19, 0xC3, 0x2A, 0x65, +0x43, 0x27, 0x4B, 0x87, 0x4B, 0xA7, 0x5B, 0xE9, +0x9C, 0x6F, 0x83, 0xAC, 0x73, 0x4B, 0xB5, 0x32, +0xB5, 0x52, 0xAD, 0x10, 0xAD, 0x31, 0xBD, 0x93, +0xCD, 0xF4, 0xD6, 0x36, 0xCD, 0xF4, 0xDE, 0x76, +0xD6, 0x56, 0xBD, 0x93, 0xB5, 0x31, 0xB5, 0x32, +0xE6, 0xD8, 0xDE, 0x77, 0xF7, 0xBE, 0x6B, 0x4D, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xF7, 0x9E, +0xEF, 0x7D, 0xFF, 0xDF, 0x00, 0x20, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xCE, 0x59, 0xDE, 0xFB, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xF7, 0x9E, 0xA5, 0x14, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x65, +0xFF, 0xDF, 0xF7, 0x9C, 0xF7, 0x9C, 0xFF, 0xDF, +0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xAD, 0x75, 0xEF, 0x7D, +0xA5, 0xB3, 0x8C, 0xEE, 0x9D, 0x51, 0x84, 0x6E, +0x94, 0xAE, 0x9D, 0x0E, 0x74, 0x27, 0x74, 0x67, +0x6C, 0x26, 0x8C, 0xCA, 0xAD, 0x4E, 0xAD, 0x0F, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xEF, 0x5C, 0xCE, 0x16, 0xEF, 0x3C, 0xD6, 0x9A, +0x00, 0x00, 0xA5, 0x34, 0xF7, 0x9D, 0xDE, 0xB9, +0xF7, 0x9D, 0x9C, 0xF3, 0x00, 0x00, 0xA5, 0x14, +0xF7, 0x9D, 0xC6, 0x36, 0xA5, 0x0F, 0x9C, 0x8E, +0xBD, 0xB4, 0xD6, 0x79, 0xF7, 0x9E, 0x63, 0x2C, +0x10, 0xA2, 0xFF, 0xFF, 0xFF, 0xDE, 0xFF, 0xDF, +0x52, 0xAA, 0x18, 0xE3, 0xFF, 0xDE, 0xE7, 0x1B, +0xDE, 0xFB, 0xF7, 0xBE, 0x39, 0xC7, 0x63, 0x2C, +0xFF, 0xFF, 0x21, 0x04, 0x7B, 0xCF, 0xF7, 0xBE, +0xDE, 0xFA, 0xEF, 0x7D, 0xDE, 0xFB, 0x00, 0x00, +0x9C, 0xD3, 0xFF, 0xFF, 0xFF, 0xFF, 0xCE, 0x59, +0x00, 0x00, 0xB5, 0xB6, 0xFF, 0xDF, 0xE7, 0x3B, +0xD6, 0xF9, 0xD6, 0xF9, 0xD6, 0xD9, 0xDF, 0x1A, +0xF7, 0xBE, 0xE7, 0x3C, 0x00, 0x00, 0x8C, 0x71, +0xFF, 0xDF, 0xEF, 0x5D, 0xFF, 0xDF, 0x08, 0x41, +0x31, 0xA6, 0xF7, 0xBE, 0xD6, 0xBA, 0xB5, 0x96, +0xAD, 0x55, 0x9C, 0xF3, 0xB5, 0x96, 0xEF, 0x5D, +0xD6, 0x9A, 0x00, 0x00, 0xA5, 0x34, 0xF7, 0xBE, +0xE7, 0x3C, 0xF7, 0xBE, 0x10, 0xA2, 0x6B, 0x4D, +0xFF, 0xDF, 0xE7, 0x1C, 0xCE, 0x59, 0xBD, 0xD6, +0xB5, 0xB6, 0xCE, 0x79, 0xF7, 0xBE, 0xEF, 0x7D, +0xE7, 0x1C, 0xF7, 0xDE, 0xEF, 0x9D, 0xFF, 0xDF, +0x94, 0x92, 0x00, 0x00, 0xEF, 0x5C, 0xEF, 0x9C, +0xCE, 0xF6, 0x95, 0x6F, 0xAD, 0xF1, 0xBE, 0x74, +0xBD, 0xD5, 0xDE, 0xFB, 0xFF, 0xDF, 0x18, 0xC3, +0x63, 0x0C, 0xFF, 0xFF, 0xFF, 0xDF, 0xCE, 0x79, +0x00, 0x00, 0xA5, 0x14, 0xEF, 0x5D, 0xA5, 0x14, +0x63, 0x0B, 0x52, 0x89, 0x52, 0x89, 0x8C, 0x51, +0xDE, 0xFB, 0xEF, 0x5D, 0x00, 0x00, 0x94, 0x92, +0xFF, 0xDF, 0xF7, 0x9E, 0xF7, 0x9E, 0x00, 0x00, +0x8C, 0x51, 0xFF, 0xFF, 0x94, 0x92, 0x00, 0x00, +0x6B, 0x6D, 0xF7, 0xBE, 0xDE, 0xFB, 0xAD, 0x55, +0x73, 0x6D, 0x83, 0xEF, 0xCE, 0x79, 0xF7, 0xBE, +0x10, 0xA2, 0x6B, 0x4D, 0xFF, 0xDF, 0xEF, 0x7D, +0xE7, 0x3C, 0xEF, 0x5D, 0xE7, 0x1C, 0xEF, 0x5D, +0xEF, 0x7E, 0xFF, 0xFF, 0x29, 0x65, 0x42, 0x28, +0xF7, 0xBE, 0xBD, 0xF8, 0x8C, 0x51, 0xBD, 0xD7, +0xF7, 0x9E, 0x6B, 0x6D, 0x10, 0x82, 0xF7, 0xBE, +0xCE, 0x79, 0x7B, 0xCF, 0x52, 0x8A, 0x7B, 0xEF, +0xD6, 0xBA, 0xEF, 0x5D, 0x00, 0x00, 0x8C, 0x71, +0xF7, 0xBE, 0xDE, 0xDB, 0xC6, 0x18, 0xB5, 0x96, +0xAD, 0x75, 0xCE, 0x79, 0xF7, 0xBE, 0xEF, 0x5D, +0xE7, 0x3C, 0xF7, 0x9E, 0xD6, 0xBA, 0xBD, 0xF4, +0xAD, 0x72, 0xAD, 0x51, 0xB5, 0x91, 0xBD, 0xB2, +0xCE, 0x36, 0xF7, 0x9D, 0x9C, 0xD3, 0x00, 0x00, +0xE7, 0x1C, 0xEF, 0x5C, 0xC6, 0x54, 0xA5, 0x6E, +0xB6, 0x0F, 0xBE, 0x4E, 0xC6, 0x91, 0xE7, 0x3A, +0xFF, 0xDF, 0x21, 0x04, 0x5A, 0xEB, 0xFF, 0xFF, +0xFF, 0xDF, 0xE7, 0x3C, 0x00, 0x00, 0x8C, 0x51, +0xFF, 0xDE, 0xEF, 0x5A, 0xCE, 0x34, 0xE6, 0xB6, +0xD6, 0x35, 0xE6, 0xB9, 0xFF, 0xBE, 0x84, 0x10, +0x00, 0x20, 0xFF, 0xFF, 0xF7, 0x7D, 0xD6, 0x58, +0xDE, 0x77, 0xE6, 0xB8, 0xE6, 0xB8, 0xF7, 0x5C, +0xFF, 0xDF, 0x42, 0x28, 0x31, 0xA6, 0xF7, 0xBE, +0xC6, 0x77, 0x74, 0x8C, 0x53, 0xE8, 0x85, 0x4F, +0x95, 0x71, 0x53, 0x8A, 0x21, 0xE3, 0x19, 0xA3, +0x22, 0x04, 0x21, 0xE3, 0x21, 0xE3, 0x19, 0xA2, +0x11, 0x62, 0x11, 0x62, 0x21, 0xC3, 0x19, 0xA3, +0x21, 0xC3, 0x11, 0x41, 0x4B, 0x28, 0x5C, 0x0A, +0x5C, 0x0A, 0x4B, 0xA8, 0x5C, 0x09, 0x6C, 0x8C, +0xA4, 0xB0, 0x83, 0xAC, 0x73, 0x6B, 0xBD, 0x93, +0xAC, 0xF0, 0xA4, 0xF0, 0xA5, 0x10, 0xAD, 0x31, +0xB5, 0x52, 0xBD, 0xB3, 0xB5, 0x72, 0xCE, 0x15, +0xC5, 0xD4, 0xC5, 0xD4, 0xB5, 0x52, 0xB5, 0x52, +0xD6, 0x76, 0xDE, 0x96, 0xFF, 0xBE, 0x6B, 0x4D, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xF7, 0xBE, +0xF7, 0x9D, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xCE, 0x59, 0xDE, 0xFB, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xF7, 0x9E, 0x9C, 0xF3, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x04, +0xFF, 0xFF, 0xF7, 0x9D, 0xF7, 0x9D, 0xFF, 0xFF, +0x10, 0xA2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xAD, 0x75, 0xEF, 0x9D, +0xBE, 0x15, 0xA5, 0x51, 0x9D, 0x10, 0x94, 0xCF, +0x73, 0xEB, 0x73, 0xE9, 0x8C, 0x8B, 0x94, 0xCC, +0x94, 0xAC, 0xA5, 0x0E, 0xC5, 0xD2, 0xCD, 0xF3, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xF7, 0x9D, 0xDE, 0x98, 0xEF, 0x7C, 0xD6, 0x9A, +0x00, 0x00, 0xA5, 0x34, 0xFF, 0xBE, 0xE6, 0xFA, +0xF7, 0xBE, 0x9C, 0xF3, 0x00, 0x00, 0xBD, 0xF7, +0xF7, 0x9D, 0xCE, 0x15, 0xC5, 0xB3, 0xD6, 0x36, +0xAD, 0x13, 0xAD, 0x54, 0xF7, 0x9D, 0x84, 0x10, +0x00, 0x00, 0xFF, 0xDF, 0xF7, 0xBE, 0xFF, 0xDF, +0x9C, 0xF3, 0x00, 0x00, 0xDE, 0xFB, 0xF7, 0xBE, +0xF7, 0x9E, 0xEF, 0x7D, 0x00, 0x20, 0xAD, 0x55, +0xFF, 0xFF, 0x63, 0x2C, 0x39, 0xC7, 0xFF, 0xDF, +0xF7, 0x7D, 0xFF, 0xDF, 0x9C, 0xF3, 0x00, 0x00, +0xDE, 0xFB, 0xFF, 0xDF, 0xFF, 0xFF, 0xB5, 0x96, +0x00, 0x00, 0xD6, 0xBA, 0xFF, 0xFF, 0xFF, 0xDF, +0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, 0xFF, 0xDE, +0xFF, 0xFF, 0xFF, 0xDF, 0x00, 0x00, 0x7B, 0xCF, +0xFF, 0xDF, 0xF7, 0x9D, 0xFF, 0xDF, 0x08, 0x41, +0x52, 0x8A, 0xF7, 0x9E, 0xBD, 0xD7, 0x84, 0x30, +0x8C, 0x51, 0x6B, 0x6D, 0x94, 0xB2, 0xE7, 0x3C, +0xEF, 0x5D, 0x00, 0x00, 0x94, 0xB2, 0xF7, 0xBE, +0xDE, 0xFB, 0xF7, 0xBE, 0x4A, 0x69, 0x18, 0xC3, +0xD6, 0x9A, 0xFF, 0xDF, 0xFF, 0xDF, 0xF7, 0xBE, +0xF7, 0xBE, 0xFF, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xEF, 0x9D, 0xE7, 0x7C, 0xFF, 0xDE, +0x84, 0x10, 0x00, 0x00, 0xFF, 0xDF, 0xE7, 0x7B, +0xA5, 0xD1, 0x74, 0x4A, 0x7C, 0x2B, 0x84, 0x6E, +0x94, 0xB1, 0xCE, 0x79, 0xFF, 0xDE, 0x29, 0x65, +0x52, 0x8A, 0xFF, 0xFF, 0xFF, 0xFF, 0xAD, 0x55, +0x00, 0x00, 0xCE, 0x59, 0xE7, 0x1C, 0x84, 0x10, +0x42, 0x27, 0x3A, 0x06, 0x42, 0x27, 0x7B, 0xCE, +0xD6, 0x99, 0xF7, 0x9E, 0xFF, 0xDF, 0xFF, 0xDF, +0xF7, 0xBE, 0xF7, 0x9E, 0xF7, 0x9E, 0x00, 0x00, +0x8C, 0x51, 0x8C, 0x51, 0x00, 0x00, 0x8C, 0x51, +0xFF, 0xFF, 0xE7, 0x5D, 0xC6, 0x18, 0x6B, 0x4D, +0x5A, 0x8A, 0x7B, 0xCF, 0xD6, 0xBA, 0xF7, 0x9E, +0x00, 0x00, 0x8C, 0x51, 0xFF, 0xFF, 0xFF, 0xDF, +0xFF, 0xDF, 0xFF, 0xDF, 0xF7, 0xBF, 0xF7, 0xBF, +0xFF, 0xDF, 0xFF, 0xFF, 0x42, 0x28, 0x31, 0x86, +0xF7, 0xBE, 0xCE, 0x59, 0xA5, 0x14, 0xB5, 0x96, +0xEF, 0x7D, 0x6B, 0x6D, 0x10, 0x82, 0xF7, 0xBE, +0xCE, 0x59, 0x6B, 0x6D, 0x31, 0x86, 0x6B, 0x4D, +0xC6, 0x38, 0xF7, 0xBE, 0x21, 0x24, 0x29, 0x65, +0xDE, 0xFB, 0xF7, 0xBE, 0xF7, 0x9E, 0xEF, 0x7D, +0xEF, 0x7D, 0xF7, 0xBE, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xDF, 0xF7, 0x9D, 0xDE, 0xD9, 0xAD, 0x73, +0xA5, 0x31, 0xAD, 0x92, 0xB5, 0x91, 0xB5, 0x92, +0xC6, 0x36, 0xF7, 0x9E, 0x84, 0x30, 0x00, 0x00, +0xF7, 0xBE, 0xEF, 0x5B, 0xBE, 0x32, 0x9D, 0x6A, +0xA5, 0xAA, 0xAE, 0x0A, 0xB6, 0x2D, 0xD6, 0xF8, +0xFF, 0xDE, 0x31, 0xA6, 0x4A, 0x49, 0xFF, 0xFF, +0xFF, 0xFF, 0xE7, 0x3C, 0x00, 0x00, 0x9C, 0xD3, +0xF7, 0xBE, 0xDE, 0xF8, 0xA4, 0xF0, 0xD6, 0x76, +0xDE, 0xB7, 0xD6, 0x78, 0xF7, 0x9E, 0xAD, 0x55, +0x00, 0x00, 0xC6, 0x38, 0xFF, 0xDF, 0xF7, 0x9D, +0xF7, 0x9D, 0xF7, 0x7D, 0xF7, 0x9D, 0xFF, 0xDF, +0xF7, 0x9E, 0x10, 0xA2, 0x63, 0x0C, 0xF7, 0x9D, +0xB5, 0xF5, 0x6C, 0x6B, 0x3B, 0x44, 0x64, 0x2A, +0x5B, 0xEA, 0x32, 0x85, 0x21, 0xE3, 0x11, 0x82, +0x22, 0x03, 0x21, 0xE3, 0x21, 0xE3, 0x19, 0xA3, +0x19, 0x83, 0x19, 0xC3, 0x2A, 0x04, 0x2A, 0x04, +0x19, 0xA3, 0x21, 0xC3, 0x64, 0x0A, 0x6C, 0x8B, +0x53, 0xC8, 0x53, 0xC8, 0x74, 0xCD, 0x7D, 0x0E, +0xAC, 0xF1, 0x83, 0xAC, 0x73, 0x4B, 0xC5, 0xD4, +0xB5, 0x52, 0xAD, 0x10, 0xA4, 0xD0, 0xAD, 0x11, +0xB5, 0x72, 0xAD, 0x31, 0xAD, 0x31, 0xC5, 0xF4, +0xBD, 0xD4, 0xBD, 0x93, 0xC6, 0x15, 0xC5, 0xF4, +0xD6, 0x76, 0xD6, 0x75, 0xFF, 0xBE, 0x63, 0x2C, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xDE, +0xFF, 0xBE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xC6, 0x38, 0xDE, 0xDB, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xF7, 0x9E, 0x7B, 0xEF, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x82, +0xFF, 0xFF, 0xFF, 0xBD, 0xFF, 0xBD, 0xFF, 0xFF, +0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x94, 0xB2, 0xFF, 0xDE, +0xCE, 0x76, 0xC6, 0x14, 0xC5, 0xF4, 0xAD, 0x72, +0x8C, 0x8E, 0xBD, 0xF3, 0xE7, 0x17, 0xD6, 0x75, +0xA4, 0xCE, 0xAC, 0xEF, 0xBD, 0xB2, 0xCD, 0xF3, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xF7, 0x9D, 0xDE, 0x98, 0xEF, 0x7D, 0xD6, 0x9A, +0x00, 0x00, 0xA5, 0x34, 0xF7, 0x9E, 0xDE, 0xB9, +0xF7, 0x9D, 0x9C, 0xF3, 0x00, 0x00, 0xD6, 0x9A, +0xEF, 0x5C, 0xCE, 0x35, 0xDE, 0x77, 0xAD, 0x12, +0x5A, 0xCA, 0xC5, 0xF6, 0xF7, 0x9D, 0x8C, 0x71, +0x00, 0x00, 0xEF, 0x7D, 0xF7, 0x9D, 0xF7, 0x9E, +0xE7, 0x1C, 0x00, 0x00, 0x9C, 0xF3, 0xFF, 0xFF, +0xFF, 0xFF, 0xB5, 0x96, 0x00, 0x00, 0xEF, 0x5D, +0xFF, 0xFF, 0xAD, 0x55, 0x00, 0x20, 0xF7, 0x9E, +0xFF, 0xFF, 0xFF, 0xFF, 0x5A, 0xEB, 0x21, 0x24, +0xFF, 0xDF, 0xF7, 0x7D, 0xFF, 0xDF, 0xA5, 0x14, +0x00, 0x00, 0x39, 0xE7, 0x42, 0x28, 0x42, 0x28, +0x42, 0x28, 0x42, 0x28, 0x42, 0x28, 0x42, 0x28, +0x42, 0x28, 0x42, 0x28, 0x00, 0x20, 0x6B, 0x4D, +0xFF, 0xFF, 0xF7, 0xBE, 0xFF, 0xDF, 0x08, 0x41, +0x63, 0x2C, 0xEF, 0x7D, 0xAD, 0x75, 0x63, 0x0C, +0x52, 0xAA, 0x63, 0x0C, 0x94, 0xB2, 0xE7, 0x1C, +0xF7, 0xBE, 0x00, 0x00, 0x84, 0x10, 0xF7, 0x9E, +0xD6, 0xDA, 0xF7, 0xBE, 0xD6, 0xBA, 0x21, 0x04, +0x00, 0x00, 0x18, 0xC3, 0x42, 0x08, 0x63, 0x2C, +0x84, 0x30, 0xA5, 0x34, 0xD6, 0x9A, 0xFF, 0xDF, +0xFF, 0xDF, 0xE7, 0x5C, 0xDF, 0x19, 0xF7, 0xBE, +0x73, 0xAE, 0x08, 0x41, 0xFF, 0xFF, 0xDF, 0x3A, +0x95, 0x0F, 0x95, 0x2E, 0xA5, 0x6F, 0x9D, 0x0F, +0x9D, 0x31, 0xCE, 0x99, 0xFF, 0xDE, 0x42, 0x08, +0x39, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0x9C, 0xF3, +0x00, 0x00, 0xDE, 0xDB, 0xDE, 0xDB, 0x7B, 0xEF, +0x39, 0xE6, 0x31, 0x85, 0x31, 0xA5, 0x6B, 0x4C, +0xBD, 0xD6, 0xDE, 0xDB, 0xE7, 0x1B, 0xE7, 0x1C, +0xE7, 0x1C, 0xEF, 0x7D, 0xF7, 0x9E, 0x00, 0x00, +0x21, 0x04, 0x00, 0x00, 0x8C, 0x51, 0xFF, 0xFF, +0xF7, 0xBE, 0xCE, 0x59, 0xCE, 0x7A, 0x7B, 0xAF, +0x73, 0xAF, 0xB5, 0xB6, 0xEF, 0x5D, 0xEF, 0x5D, +0x00, 0x00, 0x29, 0x45, 0x42, 0x28, 0x42, 0x28, +0x42, 0x28, 0x42, 0x28, 0x42, 0x28, 0x42, 0x28, +0x42, 0x28, 0x42, 0x28, 0x10, 0xA2, 0x21, 0x04, +0xF7, 0xBE, 0xC6, 0x38, 0x7B, 0xEF, 0xA5, 0x35, +0xEF, 0x7D, 0x6B, 0x6D, 0x10, 0x82, 0xF7, 0xBE, +0xCE, 0x59, 0x6B, 0x6D, 0x29, 0x65, 0x52, 0x8A, +0xA5, 0x34, 0xEF, 0x5D, 0xBD, 0xF7, 0x10, 0xA2, +0x00, 0x00, 0x21, 0x04, 0x42, 0x28, 0x6B, 0x4D, +0x8C, 0x51, 0xAD, 0x75, 0xD6, 0xBA, 0xFF, 0xFF, +0xFF, 0xDF, 0xE7, 0x1B, 0xB5, 0x94, 0x9C, 0xD0, +0xB5, 0x92, 0xBD, 0xB2, 0xAD, 0x2F, 0xC6, 0x33, +0xC6, 0x36, 0xF7, 0x9D, 0x7B, 0xCF, 0x00, 0x20, +0xFF, 0xDF, 0xEF, 0x7B, 0xC6, 0x93, 0xA5, 0xAC, +0xA5, 0xAB, 0xB6, 0x4B, 0xAE, 0x2B, 0xD6, 0xF7, +0xFF, 0xFE, 0x42, 0x28, 0x39, 0xC7, 0xFF, 0xFF, +0xFF, 0xFF, 0xE7, 0x3C, 0x00, 0x00, 0x9C, 0xD3, +0xF7, 0xBE, 0xD6, 0x98, 0xB5, 0x73, 0xA5, 0x11, +0xEF, 0x79, 0xE7, 0x3A, 0xF7, 0xBE, 0xF7, 0x9E, +0x10, 0xA2, 0x18, 0xC3, 0x84, 0x30, 0xC6, 0x18, +0xD6, 0x9A, 0xD6, 0xBA, 0xC6, 0x38, 0x9C, 0xD3, +0x29, 0x65, 0x08, 0x41, 0xCE, 0x79, 0xE7, 0x3C, +0x95, 0x11, 0x53, 0xA7, 0x3B, 0x44, 0x3B, 0x05, +0x3A, 0xC6, 0x22, 0x24, 0x19, 0xC2, 0x11, 0x61, +0x19, 0xC3, 0x22, 0x03, 0x21, 0xE3, 0x21, 0xE3, +0x21, 0xE3, 0x22, 0x04, 0x2A, 0x25, 0x21, 0xE4, +0x11, 0x42, 0x21, 0xA3, 0x53, 0x68, 0x3A, 0xC5, +0x3B, 0x06, 0x74, 0xCD, 0x85, 0x4F, 0x85, 0x0F, +0x8B, 0xEE, 0x73, 0x2A, 0x73, 0x4B, 0xA4, 0xF0, +0xAD, 0x10, 0xB5, 0x31, 0xB5, 0x31, 0xAC, 0xF0, +0xB5, 0x32, 0xAD, 0x11, 0xB5, 0x73, 0xB5, 0x72, +0xA4, 0xF0, 0x83, 0xCC, 0xBD, 0xB4, 0xE6, 0xD8, +0xDE, 0xB7, 0xDE, 0x96, 0xF7, 0xBE, 0x94, 0xB2, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x10, 0x82, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xDF, 0xFF, 0xFF, 0x10, 0x82, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xD6, 0xBA, 0xEF, 0x7D, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x61, +0xFF, 0xFF, 0xB5, 0xB6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x28, +0xFF, 0xFF, 0xF7, 0x9D, 0xFF, 0xBE, 0xFF, 0xFF, +0x39, 0xC7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xCE, 0x79, 0xF7, 0xBD, +0xD6, 0xD7, 0xD6, 0xB6, 0xBD, 0xF3, 0xA5, 0x31, +0x84, 0x4E, 0xCE, 0x55, 0xE6, 0xD7, 0xDE, 0xB6, +0xA4, 0xEF, 0xAD, 0x0F, 0xCE, 0x34, 0xD6, 0x55, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xF7, 0x9D, 0xE6, 0xF9, 0xF7, 0x9D, 0xD6, 0x9A, +0x00, 0x00, 0xA5, 0x34, 0xF7, 0xBE, 0xE6, 0xDA, +0xF7, 0xBE, 0x9C, 0xF3, 0x00, 0x00, 0xDE, 0xDB, +0xEF, 0x5C, 0xC6, 0x14, 0xA5, 0x11, 0x5A, 0xC9, +0x94, 0x6F, 0xD6, 0x77, 0xEF, 0x7D, 0x94, 0xB2, +0x00, 0x00, 0xEF, 0x5D, 0xEF, 0x5D, 0xE7, 0x3C, +0xFF, 0xDE, 0x21, 0x24, 0x5A, 0xEB, 0xFF, 0xFF, +0xFF, 0xFF, 0x73, 0x8E, 0x29, 0x65, 0xFF, 0xFF, +0xFF, 0xFF, 0xEF, 0x5D, 0x00, 0x00, 0xB5, 0xB6, +0xFF, 0xFF, 0xFF, 0xFF, 0x18, 0xC3, 0x6B, 0x4D, +0xFF, 0xDE, 0xEF, 0x3C, 0xF7, 0xBE, 0x9C, 0xD3, +0x00, 0x00, 0x5A, 0xEB, 0x63, 0x2C, 0x63, 0x2C, +0x63, 0x2C, 0x63, 0x2C, 0x63, 0x2C, 0x63, 0x2C, +0x63, 0x2C, 0x63, 0x2C, 0x63, 0x2C, 0xA5, 0x34, +0xFF, 0xFF, 0xF7, 0xBE, 0xFF, 0xFF, 0x08, 0x41, +0x73, 0x8E, 0xF7, 0x9D, 0xAD, 0x55, 0x5A, 0xCA, +0x39, 0xE7, 0x52, 0xAA, 0x8C, 0x71, 0xDE, 0xDB, +0xFF, 0xDF, 0x00, 0x00, 0x84, 0x10, 0xF7, 0x9E, +0xD6, 0xBA, 0xEF, 0x7C, 0xFF, 0xDF, 0xFF, 0xDF, +0xB5, 0x96, 0x7B, 0xEF, 0x5A, 0xCB, 0x31, 0xA6, +0x10, 0x82, 0x00, 0x00, 0x00, 0x00, 0x21, 0x04, +0xB5, 0xB6, 0xF7, 0x9E, 0xE7, 0x3C, 0xF7, 0xDE, +0x73, 0x8E, 0x10, 0x82, 0xFF, 0xDF, 0xD6, 0xD9, +0xA5, 0xB1, 0x95, 0x6B, 0xAD, 0xED, 0xA5, 0xAE, +0x95, 0x2E, 0xCE, 0x98, 0xFF, 0xDE, 0x42, 0x08, +0x39, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0x9C, 0xD3, +0x00, 0x00, 0xDE, 0xFB, 0xDE, 0xDB, 0x7B, 0xEF, +0x31, 0xA5, 0x29, 0x64, 0x29, 0x64, 0x63, 0x0B, +0xAD, 0x75, 0xD6, 0x9A, 0xDE, 0xDB, 0xDE, 0xFB, +0xE7, 0x1C, 0xEF, 0x7D, 0xF7, 0x9E, 0x00, 0x00, +0x73, 0xAE, 0x29, 0x65, 0x18, 0xE3, 0xDE, 0xDB, +0xFF, 0xDF, 0xDE, 0xDB, 0xC5, 0xF8, 0xCE, 0x59, +0xD6, 0x9A, 0xCE, 0x59, 0xEF, 0x5D, 0xDE, 0xFB, +0x00, 0x00, 0x39, 0xE7, 0x63, 0x2C, 0x63, 0x2C, +0x63, 0x2C, 0x63, 0x2C, 0x63, 0x2C, 0x63, 0x2C, +0x63, 0x2C, 0x63, 0x2C, 0x63, 0x2C, 0x7B, 0xCF, +0xF7, 0xBE, 0xC6, 0x38, 0x84, 0x30, 0xB5, 0x76, +0xEF, 0x7D, 0x6B, 0x6D, 0x10, 0x82, 0xF7, 0xBE, +0xCE, 0x59, 0x6B, 0x4D, 0x29, 0x45, 0x4A, 0x69, +0x9C, 0xD3, 0xDE, 0xDB, 0xFF, 0xDF, 0xF7, 0x9E, +0xAD, 0x55, 0x7B, 0xCF, 0x52, 0xAA, 0x31, 0x86, +0x08, 0x61, 0x00, 0x00, 0x00, 0x00, 0x31, 0x86, +0xCE, 0x79, 0xF7, 0xBE, 0xD6, 0x98, 0xB5, 0x94, +0xAD, 0x12, 0x8C, 0x2E, 0x9C, 0xAF, 0xC6, 0x13, +0xC6, 0x16, 0xF7, 0x7D, 0x73, 0xAE, 0x08, 0x41, +0xFF, 0xDF, 0xDE, 0xFA, 0xC6, 0x95, 0x95, 0x0E, +0x8C, 0xEC, 0xAE, 0x2B, 0xAE, 0x0B, 0xD7, 0x17, +0xFF, 0xFE, 0x42, 0x28, 0x39, 0xC7, 0xFF, 0xFF, +0xFF, 0xFF, 0xE7, 0x3C, 0x00, 0x00, 0x9C, 0xD3, +0xF7, 0x9E, 0xC6, 0x36, 0xBD, 0xB3, 0xDE, 0xD7, +0xEF, 0x59, 0xEF, 0x5C, 0xE7, 0x3C, 0x21, 0x04, +0x4A, 0x49, 0x5A, 0xCB, 0x08, 0x41, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x39, 0xC7, 0xC6, 0x18, 0xEF, 0x9D, 0xBE, 0x37, +0x6C, 0x0C, 0x64, 0x0A, 0x64, 0x09, 0x74, 0x8C, +0x74, 0x6D, 0x19, 0xE3, 0x11, 0x82, 0x09, 0x01, +0x19, 0xA2, 0x22, 0x03, 0x21, 0xE3, 0x19, 0xC2, +0x11, 0x82, 0x21, 0xC3, 0x19, 0xC3, 0x19, 0x83, +0x09, 0x02, 0x11, 0x42, 0x42, 0xE7, 0x21, 0xE3, +0x3A, 0xC6, 0x74, 0xAC, 0x85, 0x2F, 0x8D, 0x70, +0x5A, 0x89, 0x6B, 0x0A, 0x73, 0x4B, 0x7B, 0x8B, +0x7B, 0x8A, 0x83, 0xAB, 0x83, 0xAB, 0x83, 0xAB, +0x83, 0xCC, 0x94, 0x4E, 0x83, 0xCC, 0x83, 0xCC, +0x8B, 0xEC, 0x9C, 0x8F, 0xBD, 0x93, 0xCE, 0x15, +0xCD, 0xF4, 0xC5, 0xD3, 0xF7, 0x9D, 0xDE, 0xFB, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x52, 0x8A, 0xFF, 0xFF, 0xFF, 0xBE, +0xFF, 0xBE, 0xFF, 0xFF, 0x52, 0xAA, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x04, +0xFF, 0xFF, 0xFF, 0xFF, 0x39, 0xE7, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5A, 0xCB, +0xFF, 0xFF, 0xF7, 0x9E, 0x18, 0xC3, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0xF3, +0xFF, 0xDE, 0xF7, 0x7C, 0xEF, 0x5B, 0xF7, 0xBE, +0x94, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x29, 0x45, 0xFF, 0xDE, 0xEF, 0x7C, +0xD6, 0xF7, 0xC6, 0x34, 0x5B, 0x08, 0x84, 0x2D, +0x63, 0x49, 0xD6, 0xB6, 0xDE, 0xB6, 0xD6, 0x75, +0x94, 0x8C, 0x7C, 0x4A, 0x84, 0xAC, 0x9D, 0x2F, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xEF, 0x7D, 0xDE, 0xD9, 0xF7, 0x9D, 0xD6, 0x9A, +0x00, 0x00, 0xA5, 0x34, 0xF7, 0xBE, 0xE7, 0x3B, +0xF7, 0xBE, 0x9C, 0xF3, 0x00, 0x00, 0xD6, 0x9A, +0xE7, 0x3C, 0xBE, 0x15, 0x5A, 0xE9, 0x7C, 0x0C, +0xB5, 0x91, 0xD6, 0x57, 0xF7, 0x9D, 0x84, 0x30, +0x00, 0x00, 0xF7, 0x9E, 0xE7, 0x3C, 0xDE, 0xFA, +0xF7, 0xBE, 0x6B, 0x6D, 0x18, 0xC3, 0xFF, 0xFF, +0xFF, 0xFF, 0x29, 0x65, 0x73, 0x8E, 0xFF, 0xFF, +0xF7, 0xBE, 0xFF, 0xFF, 0x29, 0x65, 0x73, 0x8E, +0xFF, 0xFF, 0xD6, 0xBA, 0x00, 0x00, 0xAD, 0x75, +0xF7, 0x9D, 0xDE, 0xD9, 0xF7, 0x9D, 0xA5, 0x14, +0x00, 0x00, 0xDE, 0xFB, 0xFF, 0xFF, 0xF7, 0xBE, +0xF7, 0x9E, 0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, +0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xF7, 0xDE, 0xFF, 0xFF, 0x08, 0x41, +0x63, 0x2C, 0xF7, 0xBE, 0xC6, 0x17, 0x63, 0x2C, +0x39, 0xE6, 0x42, 0x07, 0x84, 0x0F, 0xDE, 0xDB, +0xEF, 0x7D, 0x00, 0x00, 0x8C, 0x51, 0xFF, 0xDF, +0xEF, 0x7D, 0xFF, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xDE, +0xFF, 0xDF, 0xEF, 0x5D, 0xB5, 0x96, 0x31, 0x86, +0x08, 0x61, 0xE7, 0x3C, 0xF7, 0xBE, 0xFF, 0xFF, +0x7B, 0xEF, 0x00, 0x00, 0xF7, 0xDE, 0xDF, 0x1A, +0xAD, 0xF0, 0x7C, 0xE7, 0x8D, 0x48, 0x85, 0x08, +0x8D, 0x4D, 0xCE, 0xB8, 0xF7, 0xDE, 0x31, 0xA6, +0x4A, 0x49, 0xFF, 0xFF, 0xFF, 0xFF, 0xA5, 0x34, +0x00, 0x00, 0xCE, 0x59, 0xE7, 0x1B, 0x7C, 0x0F, +0x39, 0xE6, 0x31, 0xA5, 0x31, 0xC5, 0x6B, 0x6D, +0xC6, 0x18, 0xEF, 0x7D, 0xF7, 0xBE, 0xF7, 0xBE, +0xF7, 0xBE, 0xF7, 0x9E, 0xF7, 0x9E, 0x00, 0x00, +0x8C, 0x51, 0xEF, 0x5D, 0x29, 0x65, 0x18, 0xC3, +0xD6, 0x9A, 0xF7, 0xBE, 0xDE, 0xFB, 0xCE, 0x59, +0xC6, 0x38, 0xB5, 0x96, 0xE7, 0x1C, 0xE7, 0x3C, +0x00, 0x00, 0x94, 0x92, 0xFF, 0xFF, 0xF7, 0xBE, +0xF7, 0x9E, 0xF7, 0x9E, 0xF7, 0x9E, 0xF7, 0x9E, +0xF7, 0xBE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xF7, 0xBE, 0xCE, 0x59, 0xA5, 0x14, 0xCE, 0x59, +0xF7, 0x9E, 0x6B, 0x6D, 0x10, 0x82, 0xF7, 0xBE, +0xCE, 0x59, 0x6B, 0x4D, 0x31, 0xA6, 0x7B, 0xEF, +0xD6, 0xBA, 0xF7, 0xBE, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xF7, 0xBE, 0xF7, 0xBE, 0xFF, 0xDE, +0xFF, 0xFF, 0xE7, 0x1C, 0xA5, 0x34, 0x18, 0xE3, +0x21, 0x04, 0xFF, 0xDE, 0xE7, 0x1B, 0xB5, 0x94, +0xAD, 0x12, 0x6B, 0x4B, 0xA4, 0xF1, 0xCE, 0x14, +0xBD, 0xB5, 0xEF, 0x7D, 0x84, 0x10, 0x00, 0x00, +0xF7, 0xBE, 0xDE, 0xDA, 0xAD, 0x93, 0x9D, 0x90, +0xA5, 0xAF, 0xAE, 0x2C, 0xA5, 0xEC, 0xD7, 0x17, +0xF7, 0xDE, 0x39, 0xC7, 0x42, 0x28, 0xFF, 0xFF, +0xFF, 0xFF, 0xE7, 0x3C, 0x00, 0x00, 0x9C, 0xD3, +0xF7, 0x9D, 0xC6, 0x36, 0xC6, 0x53, 0xCE, 0x53, +0xE7, 0x39, 0xF7, 0xBE, 0x94, 0x92, 0x08, 0x41, +0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xDF, 0xE7, 0x3C, +0xD6, 0xBA, 0xCE, 0x79, 0xDE, 0xDB, 0xF7, 0x9E, +0xFF, 0xFF, 0xFF, 0xDF, 0xD6, 0xDA, 0x8C, 0xB1, +0x6B, 0xCB, 0xAD, 0xB2, 0x74, 0x2B, 0x8D, 0x30, +0x95, 0x51, 0x19, 0xA3, 0x19, 0x82, 0x21, 0xC4, +0x2A, 0x44, 0x22, 0x23, 0x21, 0xE3, 0x19, 0xC2, +0x11, 0x62, 0x11, 0x42, 0x11, 0x42, 0x19, 0xA4, +0x09, 0x02, 0x11, 0x43, 0x19, 0xA3, 0x2A, 0x24, +0x4B, 0x68, 0x64, 0x4B, 0x43, 0x47, 0x7C, 0xEE, +0x62, 0xCA, 0x7B, 0xAC, 0x8C, 0x2E, 0x73, 0x6B, +0x7B, 0x6A, 0x83, 0x8B, 0x9C, 0x4E, 0xA4, 0xAF, +0xA4, 0xB0, 0xA4, 0xCF, 0x9C, 0x6E, 0x94, 0x2D, +0x94, 0x2D, 0x8C, 0x0C, 0x94, 0x0C, 0x8B, 0xEC, +0x8B, 0xEC, 0x8B, 0xEC, 0xDE, 0xDA, 0xFF, 0xDE, +0x52, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x20, 0xC6, 0x38, 0xF7, 0x9E, 0xD6, 0x99, +0xD6, 0x58, 0xEF, 0x7D, 0xE7, 0x1B, 0x29, 0x45, +0x00, 0x00, 0x00, 0x00, 0x10, 0xA2, 0xC6, 0x38, +0xFF, 0xFF, 0xFF, 0xDF, 0xDE, 0xFB, 0x31, 0x86, +0x00, 0x00, 0x00, 0x00, 0x42, 0x08, 0xEF, 0x5D, +0xFF, 0xFF, 0xFF, 0xFF, 0xC6, 0x38, 0x21, 0x04, +0x00, 0x00, 0x00, 0x20, 0x7B, 0xCF, 0xFF, 0xDE, +0xF7, 0x9C, 0xDE, 0xD7, 0xCE, 0x96, 0xF7, 0xBD, +0xFF, 0xFF, 0x73, 0xAE, 0x08, 0x41, 0x00, 0x00, +0x39, 0xC7, 0xD6, 0xBA, 0xEF, 0x5C, 0xAD, 0x95, +0xB6, 0x13, 0x95, 0x0E, 0x63, 0x68, 0x9D, 0x0F, +0x73, 0xAB, 0xBE, 0x13, 0x9C, 0xEE, 0x7C, 0x6B, +0x74, 0x49, 0x7C, 0xCB, 0x95, 0x4D, 0x95, 0x0C, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xF7, 0x7D, 0xD6, 0x98, 0xEF, 0x7D, 0xD6, 0x9A, +0x00, 0x00, 0xA5, 0x34, 0xF7, 0xBE, 0xE7, 0x1B, +0xF7, 0xBE, 0x9C, 0xF3, 0x00, 0x00, 0xB5, 0x96, +0xF7, 0xBE, 0xAD, 0x74, 0x5B, 0x2A, 0x7C, 0x4A, +0x8C, 0xCD, 0xCE, 0x77, 0xF7, 0xBE, 0x73, 0xAE, +0x10, 0xA2, 0xFF, 0xDF, 0xE7, 0x1B, 0xCE, 0x77, +0xF7, 0x9D, 0xB5, 0x95, 0x00, 0x00, 0xDE, 0xDB, +0xEF, 0x7D, 0x00, 0x00, 0xB5, 0x96, 0xFF, 0xBE, +0xEF, 0x5C, 0xFF, 0xDE, 0x73, 0x8E, 0x31, 0x86, +0xFF, 0xFF, 0x94, 0xB2, 0x00, 0x00, 0xEF, 0x5D, +0xE7, 0x1B, 0xC6, 0x36, 0xEF, 0x7D, 0xBD, 0xD7, +0x00, 0x00, 0xCE, 0x79, 0xF7, 0xBE, 0xD6, 0x9A, +0xE7, 0x3B, 0xE7, 0x3B, 0xC6, 0x38, 0xCE, 0x79, +0xEF, 0x7D, 0xFF, 0xFF, 0xDE, 0xFB, 0xEF, 0x7D, +0xFF, 0xFF, 0xF7, 0xBE, 0xFF, 0xFF, 0x08, 0x41, +0x42, 0x28, 0xFF, 0xFF, 0xDF, 0x1B, 0xB5, 0xF5, +0x5A, 0xEA, 0x4A, 0x48, 0x94, 0x91, 0xE7, 0x1C, +0xDE, 0xFB, 0x00, 0x00, 0xA5, 0x34, 0xFF, 0xDF, +0xF7, 0xBE, 0xEF, 0x7D, 0xBD, 0xD7, 0xEF, 0x5D, +0xFF, 0xDE, 0xD6, 0xF9, 0xBE, 0x36, 0xCE, 0x98, +0xDF, 0x5A, 0xE7, 0x3B, 0xF7, 0xBE, 0xC6, 0x38, +0x00, 0x00, 0xAD, 0x55, 0xFF, 0xFF, 0xFF, 0xFF, +0x8C, 0x71, 0x00, 0x00, 0xEF, 0x7D, 0xDF, 0x3B, +0xA5, 0xB0, 0xB6, 0x6E, 0xB6, 0x4D, 0xA5, 0xEC, +0x95, 0x8F, 0xD6, 0xF9, 0xFF, 0xDE, 0x21, 0x24, +0x52, 0xAA, 0xFF, 0xFF, 0xFF, 0xFF, 0xBD, 0xF7, +0x00, 0x00, 0xB5, 0xB6, 0xEF, 0x5D, 0x8C, 0x71, +0x3A, 0x07, 0x31, 0xA5, 0x39, 0xE6, 0x73, 0x8D, +0xCE, 0x79, 0xF7, 0xBE, 0x31, 0xA6, 0x7B, 0xCF, +0xFF, 0xDF, 0xF7, 0x9E, 0xF7, 0x9E, 0x00, 0x00, +0x8C, 0x51, 0xFF, 0xFF, 0xEF, 0x7D, 0x31, 0x86, +0x10, 0x82, 0xCE, 0x59, 0xF7, 0xBE, 0xE7, 0x1C, +0xD6, 0x7A, 0xCE, 0x39, 0xDE, 0xDB, 0xF7, 0xBE, +0x00, 0x20, 0x84, 0x10, 0xF7, 0xBE, 0xD6, 0xBA, +0xB5, 0xB6, 0xAD, 0x75, 0xAD, 0x75, 0xB5, 0xB6, +0xDE, 0xDB, 0xF7, 0xBE, 0xEF, 0x5D, 0xE7, 0x1C, +0xF7, 0xBE, 0xC6, 0x38, 0xB5, 0xB6, 0xC6, 0x38, +0xF7, 0x9E, 0x6B, 0x6D, 0x10, 0x82, 0xF7, 0xBE, +0xCE, 0x59, 0x6B, 0x4D, 0x31, 0x86, 0x84, 0x30, +0xE7, 0x3C, 0xE7, 0x3C, 0xBD, 0xD7, 0xF7, 0x9E, +0xF7, 0x9E, 0xDF, 0x1B, 0xCE, 0xB8, 0xD6, 0xD9, +0xE7, 0x5B, 0xF7, 0x9D, 0xFF, 0xDF, 0xA5, 0x14, +0x00, 0x00, 0xCE, 0x79, 0xEF, 0x7D, 0xC6, 0x17, +0xBD, 0xB5, 0x94, 0x91, 0x94, 0x70, 0xB5, 0x73, +0xC5, 0xF7, 0xF7, 0x9E, 0x94, 0x92, 0x00, 0x00, +0xE7, 0x3C, 0xE7, 0x1B, 0xA5, 0x53, 0x9D, 0x50, +0x63, 0xE9, 0x95, 0x8B, 0xA5, 0xCD, 0xDF, 0x18, +0xFF, 0xDE, 0x29, 0x65, 0x52, 0x8A, 0xFF, 0xFF, +0xFF, 0xFF, 0xE7, 0x3C, 0x00, 0x00, 0x9C, 0xD3, +0xF7, 0x9D, 0xD6, 0x96, 0xBE, 0x4F, 0xAD, 0x8E, +0xE6, 0xF8, 0xF7, 0xBE, 0x94, 0xB2, 0x00, 0x00, +0xA5, 0x14, 0xEF, 0x7D, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0x1C, 0xAD, 0x55, +0x8C, 0x70, 0xA5, 0x31, 0x8C, 0x8E, 0x95, 0x10, +0x74, 0x4E, 0x53, 0x4B, 0x32, 0x26, 0x32, 0x46, +0x21, 0xE3, 0x22, 0x03, 0x21, 0xE3, 0x19, 0xC3, +0x19, 0xC3, 0x21, 0xC3, 0x11, 0x62, 0x19, 0xA3, +0x21, 0xE4, 0x2A, 0x25, 0x32, 0x86, 0x3A, 0xA6, +0x4B, 0x69, 0x6C, 0x6C, 0x3A, 0xC5, 0x64, 0x4B, +0x5A, 0x89, 0x39, 0xC6, 0x5A, 0xA9, 0x52, 0x68, +0x42, 0x06, 0x5A, 0xA8, 0x9C, 0x8F, 0xBD, 0xB4, +0xC5, 0x94, 0xA4, 0xD0, 0x7B, 0x8B, 0x8C, 0x0C, +0x9C, 0x4D, 0x83, 0xAB, 0x83, 0x8B, 0x94, 0x0D, +0xAC, 0xD0, 0xA4, 0x8F, 0xC5, 0xD5, 0xEF, 0x3C, +0xF7, 0xBE, 0x8C, 0x51, 0x42, 0x08, 0x5A, 0xCB, +0xCE, 0x59, 0xFF, 0xFF, 0xEF, 0x7D, 0xD6, 0x98, +0xCE, 0x16, 0xDE, 0xB9, 0xEF, 0x7D, 0xF7, 0x9E, +0xBD, 0xD7, 0xB5, 0x96, 0xEF, 0x7D, 0xFF, 0xFF, +0xF7, 0x9E, 0xF7, 0x9D, 0xFF, 0xDF, 0xFF, 0xDF, +0xD6, 0xBA, 0xDE, 0xFB, 0xFF, 0xFF, 0xFF, 0xDF, +0xF7, 0x9D, 0xFF, 0xBE, 0xFF, 0xFF, 0xFF, 0xFF, +0xE7, 0x1B, 0xF7, 0x9D, 0xFF, 0xDE, 0xEF, 0x7C, +0xE6, 0xF8, 0xD6, 0x96, 0xE7, 0x39, 0xF7, 0xBD, +0xFF, 0xDE, 0xFF, 0xFF, 0xFF, 0xDF, 0xEF, 0x5D, +0xF7, 0xBE, 0xE7, 0x5C, 0xCE, 0x78, 0xA5, 0x52, +0x84, 0x6C, 0x6B, 0xC8, 0x95, 0x0D, 0xAD, 0xB1, +0x7C, 0x0C, 0xAD, 0xD1, 0x84, 0x6A, 0x8C, 0xED, +0x8D, 0x2D, 0x7C, 0xAB, 0x84, 0xAB, 0x8C, 0xEC, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xF7, 0x7D, 0xD6, 0x99, 0xF7, 0x7D, 0xD6, 0x9A, +0x00, 0x00, 0xA5, 0x34, 0xF7, 0xBE, 0xE7, 0x1B, +0xF7, 0xBE, 0x9C, 0xF3, 0x00, 0x00, 0x73, 0xAE, +0xF7, 0xBE, 0xC6, 0x38, 0xA5, 0x73, 0x95, 0x30, +0xA5, 0x92, 0xD6, 0xD9, 0xFF, 0xDE, 0x39, 0xE7, +0x42, 0x08, 0xFF, 0xDE, 0xDE, 0xD9, 0xC6, 0x15, +0xE7, 0x5C, 0xEF, 0x7D, 0x00, 0x20, 0x9C, 0xD3, +0xAD, 0x55, 0x00, 0x00, 0xEF, 0x5D, 0xEF, 0x5C, +0xD6, 0x98, 0xF7, 0x9D, 0xB5, 0x96, 0x00, 0x00, +0xEF, 0x5D, 0x52, 0xAA, 0x31, 0xA6, 0xF7, 0xBE, +0xCE, 0x98, 0xA5, 0x73, 0xDF, 0x1B, 0xE7, 0x3C, +0x00, 0x00, 0x9C, 0xD3, 0xFF, 0xDE, 0xDE, 0xFA, +0xF7, 0xDC, 0xD6, 0xB9, 0x9C, 0xF3, 0xB5, 0xB7, +0xE7, 0x3D, 0xF7, 0x9E, 0x00, 0x00, 0x8C, 0x51, +0xFF, 0xDF, 0xEF, 0x7D, 0xFF, 0xDF, 0x08, 0x41, +0x08, 0x61, 0xF7, 0xBE, 0xEF, 0x5D, 0xCE, 0x98, +0xC6, 0x77, 0xA5, 0x53, 0xDF, 0x1A, 0xEF, 0x7D, +0xAD, 0x55, 0x00, 0x00, 0xCE, 0x79, 0xF7, 0xBE, +0xF7, 0xBE, 0xD6, 0x9A, 0x00, 0x00, 0xAD, 0x55, +0xF7, 0xDE, 0xBE, 0x56, 0x9D, 0x71, 0x9D, 0x92, +0xBE, 0x75, 0xBE, 0x36, 0xEF, 0x5D, 0xDF, 0x1B, +0x00, 0x00, 0x9C, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, +0xB5, 0x96, 0x00, 0x00, 0xC6, 0x18, 0xF7, 0xBD, +0xDF, 0x37, 0xC6, 0x73, 0xC6, 0xD3, 0xC6, 0xD3, +0xC6, 0xB5, 0xE7, 0x5C, 0xEF, 0x7D, 0x00, 0x00, +0x7B, 0xEF, 0xFF, 0xFF, 0xF7, 0xBE, 0xEF, 0x5C, +0x00, 0x00, 0x8C, 0x51, 0xF7, 0xBE, 0xC6, 0x38, +0x84, 0x30, 0x73, 0xCE, 0x7B, 0xEF, 0xA5, 0x13, +0xE7, 0x1C, 0xF7, 0x9E, 0x00, 0x20, 0x84, 0x30, +0xFF, 0xDF, 0xF7, 0x9E, 0xF7, 0x9E, 0x00, 0x00, +0x8C, 0x51, 0xFF, 0xFF, 0xFF, 0xDF, 0xEF, 0x7D, +0x31, 0xA6, 0x10, 0x82, 0xC6, 0x38, 0xF7, 0xBF, +0xE7, 0x1C, 0xD6, 0x7A, 0xDE, 0xFC, 0xF7, 0xBE, +0x31, 0x86, 0x52, 0x8A, 0xF7, 0xBE, 0xD6, 0x9A, +0x9C, 0xF3, 0x84, 0x30, 0x8C, 0x51, 0x9C, 0xF3, +0xD6, 0x9A, 0xF7, 0xBE, 0x39, 0xE7, 0x42, 0x08, +0xF7, 0x9E, 0xCE, 0x59, 0xAD, 0x75, 0xAD, 0x75, +0xEF, 0x7D, 0x6B, 0x6D, 0x10, 0x82, 0xFF, 0xDF, +0xD6, 0xBA, 0x94, 0x92, 0x73, 0xAE, 0x9C, 0xF3, +0xEF, 0x5D, 0xAD, 0x75, 0x00, 0x00, 0xCE, 0x79, +0xEF, 0x7D, 0xB5, 0xB6, 0x9C, 0xD3, 0xA5, 0x33, +0xB5, 0xD6, 0xCE, 0x58, 0xFF, 0xDE, 0xBD, 0xF7, +0x00, 0x00, 0xC6, 0x18, 0xF7, 0x9E, 0xDE, 0xFB, +0xE7, 0x1B, 0xDE, 0xFB, 0xDE, 0xDB, 0xDE, 0xFB, +0xE6, 0xFB, 0xF7, 0xBE, 0xB5, 0xB6, 0x00, 0x00, +0xBD, 0xF7, 0xF7, 0x9D, 0xD6, 0x98, 0xBD, 0xF4, +0xA5, 0x92, 0xB6, 0x52, 0xC6, 0x94, 0xE7, 0x7B, +0xF7, 0x9E, 0x00, 0x20, 0x7B, 0xCF, 0xFF, 0xFF, +0xFF, 0xDE, 0xE7, 0x3C, 0x00, 0x00, 0x9C, 0xD3, +0xF7, 0xBD, 0xD6, 0xD5, 0xAD, 0xEB, 0xAD, 0x8D, +0xD6, 0x97, 0xF7, 0xBE, 0xEF, 0x7D, 0x31, 0x86, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x82, +0x21, 0x04, 0x31, 0x86, 0x42, 0x08, 0x52, 0xAA, +0x73, 0xAE, 0xA5, 0x34, 0xF7, 0xBE, 0xE7, 0x3C, +0xCE, 0x78, 0xBD, 0xF4, 0x8C, 0xAE, 0x7C, 0x2C, +0x8D, 0x11, 0x95, 0x32, 0x32, 0x67, 0x2A, 0x26, +0x22, 0x04, 0x22, 0x23, 0x19, 0xC2, 0x19, 0xA2, +0x11, 0x62, 0x21, 0xE4, 0x19, 0xA3, 0x19, 0xA3, +0x32, 0x45, 0x42, 0xE8, 0x4B, 0x29, 0x4B, 0x49, +0x4B, 0x69, 0x53, 0x88, 0x2A, 0x44, 0x64, 0x2B, +0x73, 0x6C, 0x62, 0xEB, 0x83, 0xEE, 0x73, 0x6C, +0x6B, 0x0A, 0x7B, 0xCD, 0x9C, 0xD1, 0xAD, 0x32, +0x9C, 0x90, 0x6B, 0x4B, 0x6B, 0x0A, 0x83, 0xEC, +0x9C, 0x4D, 0x94, 0x4F, 0xAD, 0x33, 0x94, 0x2F, +0x83, 0xCD, 0x83, 0xED, 0x94, 0x4F, 0xBD, 0xB5, +0xDE, 0xFB, 0xF7, 0x7D, 0xFF, 0xDE, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xF7, 0x9D, +0xE7, 0x3C, 0xD6, 0x99, 0xD6, 0x78, 0xE6, 0xFB, +0xF7, 0x7D, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, +0xFF, 0xBE, 0xFF, 0xBE, 0xFF, 0xDE, 0xFF, 0xFF, +0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xBE, 0xEF, 0x5C, 0xDE, 0xD9, 0xD6, 0x77, +0xD6, 0x98, 0xE7, 0x3B, 0xF7, 0x9E, 0xFF, 0xDE, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xEF, 0x5D, +0xD6, 0xB9, 0xBE, 0x15, 0xAD, 0x32, 0x7B, 0xAB, +0x8C, 0x6C, 0xA5, 0x6F, 0x9D, 0x4F, 0x84, 0x6C, +0x84, 0x6E, 0x8C, 0xCD, 0x53, 0x05, 0x95, 0x2F, +0xAE, 0x32, 0x95, 0x2E, 0xAD, 0x90, 0xCE, 0x74, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xF7, 0xBD, 0xEF, 0x1A, 0xF7, 0x7D, 0xD6, 0x9A, +0x00, 0x00, 0xA5, 0x34, 0xF7, 0xBE, 0xE7, 0x1B, +0xF7, 0xBE, 0x9C, 0xF3, 0x00, 0x00, 0x10, 0x82, +0xE7, 0x3C, 0xF7, 0xBE, 0xEF, 0x7C, 0xE7, 0x3B, +0xE7, 0x5C, 0xF7, 0xBE, 0xC6, 0x38, 0x00, 0x00, +0x8C, 0x71, 0xF7, 0x9E, 0xCE, 0x57, 0xBD, 0xF4, +0xDE, 0xD9, 0xFF, 0xDE, 0x39, 0xE7, 0x52, 0xAA, +0x6B, 0x4D, 0x31, 0xA6, 0xFF, 0xDE, 0xE6, 0xFA, +0xD6, 0x56, 0xE7, 0x3B, 0xEF, 0x7D, 0x00, 0x20, +0xAD, 0x55, 0x10, 0xA2, 0x7B, 0xEF, 0xF7, 0xBE, +0xBE, 0x76, 0xA5, 0xB2, 0xCE, 0xB9, 0xF7, 0xDE, +0x42, 0x08, 0x29, 0x45, 0xF7, 0x9E, 0xFF, 0xDE, +0xF7, 0xDE, 0xEF, 0x5C, 0xDE, 0xFB, 0xEF, 0x5D, +0xFF, 0xDF, 0x9C, 0xD3, 0x00, 0x00, 0xCE, 0x59, +0xF7, 0x9E, 0xEF, 0x5D, 0xFF, 0xDF, 0x08, 0x41, +0x00, 0x00, 0x8C, 0x71, 0xFF, 0xDF, 0xF7, 0xBD, +0xEF, 0x9D, 0xEF, 0x9D, 0xF7, 0xBE, 0xF7, 0xBE, +0x39, 0xC7, 0x21, 0x04, 0xF7, 0xBE, 0xDF, 0x1B, +0xEF, 0x7C, 0xEF, 0x7D, 0x00, 0x20, 0x73, 0x8E, +0xFF, 0xFF, 0xEF, 0x7D, 0xDF, 0x3B, 0xDF, 0x3B, +0xE7, 0x5B, 0xEF, 0x5C, 0xF7, 0xDE, 0xAD, 0x55, +0x00, 0x00, 0xC6, 0x18, 0xF7, 0xDE, 0xF7, 0xBD, +0xEF, 0x7D, 0x08, 0x61, 0x52, 0x8A, 0xFF, 0xDF, +0xF7, 0xBD, 0xE7, 0x1B, 0xDF, 0x1A, 0xE7, 0x3B, +0xEF, 0x9D, 0xFF, 0xDF, 0x84, 0x30, 0x00, 0x00, +0xCE, 0x59, 0xF7, 0xBE, 0xE7, 0x5B, 0xFF, 0xDE, +0x42, 0x08, 0x18, 0xE3, 0xF7, 0x9E, 0xFF, 0xBE, +0xE7, 0x5C, 0xDE, 0xDA, 0xDE, 0xDB, 0xE7, 0x3C, +0xF7, 0xBE, 0x9C, 0xD3, 0x00, 0x00, 0xCE, 0x59, +0xF7, 0x9E, 0xEF, 0x7D, 0xF7, 0x9E, 0x00, 0x00, +0x8C, 0x51, 0xF7, 0xBE, 0xE7, 0x1C, 0xF7, 0x9E, +0xEF, 0x7D, 0x31, 0xA6, 0x08, 0x41, 0xBD, 0xD7, +0xF7, 0xBE, 0xE7, 0x1C, 0xE7, 0x1C, 0xFF, 0xDF, +0x8C, 0x51, 0x00, 0x20, 0xCE, 0x79, 0xF7, 0x9E, +0xE7, 0x1C, 0xD6, 0xBA, 0xD6, 0xBA, 0xE7, 0x1C, +0xF7, 0x9E, 0xDE, 0xFB, 0x00, 0x20, 0x84, 0x30, +0xEF, 0x7D, 0xCE, 0x59, 0xB5, 0xB7, 0xB5, 0x96, +0xEF, 0x7D, 0x7B, 0xEF, 0x00, 0x20, 0xF7, 0xBE, +0xF7, 0x9E, 0xDE, 0xFB, 0xDE, 0xDB, 0xE7, 0x1B, +0xF7, 0xBE, 0xD6, 0xBA, 0x00, 0x00, 0x94, 0xB2, +0xFF, 0xDF, 0xE7, 0x3C, 0xDE, 0xDB, 0xDE, 0xFB, +0xE7, 0x3C, 0xEF, 0x5D, 0xFF, 0xDF, 0x84, 0x30, +0x00, 0x00, 0xE7, 0x3C, 0xF7, 0x9D, 0xEF, 0x5D, +0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, +0xEF, 0x5D, 0xEF, 0x7D, 0xEF, 0x7D, 0x10, 0x82, +0x4A, 0x69, 0xFF, 0xDF, 0xF7, 0x9D, 0xE7, 0x3B, +0xE7, 0x3B, 0xE7, 0x3B, 0xEF, 0x9D, 0xFF, 0xDF, +0x8C, 0x51, 0x00, 0x00, 0xC6, 0x18, 0xFF, 0xDE, +0xF7, 0xBE, 0xE7, 0x3C, 0x00, 0x00, 0x9C, 0xD3, +0xF7, 0xBD, 0xBE, 0x32, 0xAD, 0xCB, 0xAD, 0x6D, +0xCE, 0x35, 0xF7, 0x9D, 0xFF, 0xDF, 0x6B, 0x4D, +0x18, 0xC3, 0x8C, 0x71, 0xA5, 0x14, 0x94, 0x92, +0x84, 0x10, 0x73, 0x8E, 0x63, 0x0C, 0x4A, 0x69, +0x21, 0x24, 0x00, 0x00, 0x21, 0x24, 0xDE, 0xDB, +0xF7, 0x9D, 0xB5, 0xD4, 0x42, 0xC6, 0x3A, 0xC6, +0x2A, 0x25, 0x32, 0x66, 0x3A, 0xA7, 0x32, 0x45, +0x22, 0x03, 0x19, 0xE2, 0x21, 0xE3, 0x19, 0x82, +0x11, 0x42, 0x2A, 0x24, 0x2A, 0x24, 0x21, 0xE4, +0x3A, 0x86, 0x53, 0x6A, 0x53, 0xAA, 0x64, 0x2C, +0x5B, 0xEA, 0x43, 0x27, 0x3A, 0xC5, 0x3A, 0xE6, +0xB5, 0xB6, 0xAD, 0x34, 0xB5, 0x53, 0xAD, 0x12, +0xA4, 0xF1, 0xA4, 0xD1, 0xAD, 0x52, 0xC5, 0xD5, +0xB5, 0x73, 0x94, 0x6F, 0x9C, 0x90, 0xA4, 0xD0, +0x94, 0x2D, 0xBD, 0xB4, 0xD6, 0x77, 0xD6, 0x57, +0xCE, 0x16, 0xC5, 0xD5, 0xC5, 0xB5, 0xBD, 0x94, +0xC5, 0xD6, 0xD6, 0x78, 0xEF, 0x3C, 0xFF, 0xDF, +0xF7, 0x9E, 0x84, 0x30, 0x5A, 0xEB, 0x8C, 0x51, +0xF7, 0x9E, 0xEF, 0x5D, 0xCE, 0x37, 0xC5, 0xB5, +0xDE, 0x99, 0xF7, 0xBE, 0xFF, 0xFF, 0x9C, 0xD3, +0x52, 0x8A, 0x63, 0x0C, 0xCE, 0x59, 0xFF, 0xDF, +0xF7, 0x9D, 0xF7, 0x9D, 0xFF, 0xDF, 0xBD, 0xF7, +0x4A, 0x69, 0x39, 0xC7, 0x84, 0x10, 0xF7, 0xBE, +0xFF, 0xBE, 0xEF, 0x1A, 0xD6, 0x56, 0xD6, 0x97, +0xEF, 0x7C, 0xF7, 0xBE, 0x7B, 0xEF, 0x29, 0x65, +0x31, 0xA6, 0x9C, 0xD3, 0xFF, 0xDF, 0xEF, 0x5C, +0xBD, 0xF5, 0x7C, 0x0C, 0x4A, 0x46, 0x39, 0xC4, +0x52, 0xC6, 0x95, 0x0E, 0xAD, 0xB0, 0x63, 0x48, +0x84, 0x4D, 0x8C, 0xCD, 0x3A, 0x83, 0x53, 0x47, +0x8C, 0xCD, 0xB5, 0xD2, 0xB5, 0x91, 0xB5, 0x50, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xEF, 0x5C, 0xC6, 0x17, 0xEF, 0x3C, 0xD6, 0x9A, +0x00, 0x00, 0xA5, 0x34, 0xF7, 0x9E, 0xDE, 0xB9, +0xF7, 0x9E, 0x9C, 0xF3, 0x00, 0x00, 0x21, 0x04, +0x21, 0x24, 0xAD, 0x55, 0xE7, 0x3C, 0xEF, 0x7D, +0xDE, 0xDB, 0x94, 0x92, 0x10, 0x82, 0x21, 0x04, +0xEF, 0x7D, 0xE7, 0x3C, 0xC6, 0x15, 0xBD, 0xD3, +0xD6, 0xB8, 0xF7, 0xBE, 0x84, 0x10, 0x10, 0xA2, +0x21, 0x24, 0x7B, 0xCF, 0xF7, 0x9E, 0xC6, 0x36, +0xB5, 0xB3, 0xE7, 0x1A, 0xFF, 0xDE, 0x39, 0xC7, +0x39, 0xE7, 0x00, 0x00, 0xBD, 0xF7, 0xEF, 0x7C, +0xA5, 0x92, 0x84, 0xAD, 0xAD, 0xD4, 0xEF, 0x5C, +0xCE, 0x79, 0x08, 0x61, 0x29, 0x65, 0xAD, 0x55, +0xE7, 0x3C, 0xFF, 0xDE, 0xEF, 0x7D, 0xCE, 0x79, +0x7B, 0xCF, 0x08, 0x41, 0x52, 0xAA, 0xFF, 0xDF, +0xE7, 0x3C, 0xE7, 0x5C, 0xFF, 0xDF, 0x08, 0x41, +0x21, 0x04, 0x00, 0x00, 0x7B, 0xCF, 0xD6, 0x9A, +0xEF, 0x7D, 0xE7, 0x3C, 0xBD, 0xD7, 0x42, 0x08, +0x00, 0x00, 0xA5, 0x34, 0xEF, 0x7D, 0xBD, 0xD7, +0xD6, 0xFA, 0xF7, 0xBE, 0x73, 0x8E, 0x00, 0x00, +0x73, 0x8E, 0xC6, 0x38, 0xEF, 0x5C, 0xFF, 0xDE, +0xEF, 0x7D, 0xD6, 0xBA, 0x8C, 0x71, 0x10, 0x82, +0x31, 0xA6, 0xF7, 0xDE, 0xE7, 0x5B, 0xD6, 0xF9, +0xF7, 0x9D, 0x8C, 0x71, 0x00, 0x00, 0x4A, 0x69, +0xB5, 0xB6, 0xE7, 0x3C, 0xEF, 0x7D, 0xE7, 0x3C, +0xC6, 0x18, 0x6B, 0x6D, 0x00, 0x00, 0x5A, 0xEB, +0xFF, 0xDE, 0xE7, 0x5B, 0xD6, 0xF8, 0xF7, 0xBD, +0xCE, 0x59, 0x00, 0x20, 0x29, 0x65, 0xAD, 0x55, +0xE7, 0x3C, 0xEF, 0x7D, 0xE7, 0x3C, 0xCE, 0x79, +0x84, 0x10, 0x08, 0x41, 0x52, 0x8A, 0xF7, 0xBE, +0xDE, 0xFB, 0xE7, 0x3C, 0xEF, 0x7D, 0x00, 0x00, +0x8C, 0x51, 0xF7, 0x9E, 0xBD, 0xF8, 0xC6, 0x59, +0xEF, 0x7D, 0xEF, 0x7D, 0x31, 0xA6, 0x00, 0x20, +0xAD, 0x75, 0xF7, 0xBE, 0xEF, 0x7D, 0xFF, 0xDF, +0xF7, 0xBE, 0x29, 0x65, 0x10, 0x82, 0x8C, 0x71, +0xD6, 0xBA, 0xF7, 0x9E, 0xF7, 0x9E, 0xDE, 0xDB, +0x9C, 0xD3, 0x21, 0x04, 0x18, 0xE3, 0xEF, 0x5D, +0xE6, 0xFC, 0xCE, 0x59, 0xB5, 0x96, 0xAD, 0x76, +0xE7, 0x3D, 0xA5, 0x34, 0x00, 0x00, 0x73, 0x8E, +0xD6, 0x9A, 0xE7, 0x3C, 0xDE, 0xFB, 0xF7, 0x9E, +0xFF, 0xDF, 0xFF, 0xFF, 0x4A, 0x69, 0x08, 0x41, +0x84, 0x10, 0xCE, 0x79, 0xEF, 0x5D, 0xFF, 0xDF, +0xEF, 0x5D, 0xCE, 0x59, 0x7B, 0xEF, 0x00, 0x20, +0x5A, 0xEB, 0xFF, 0xDE, 0xEF, 0x3C, 0xEF, 0x5D, +0xFF, 0xDF, 0x08, 0x61, 0x00, 0x00, 0xEF, 0x7D, +0xEF, 0x7D, 0xE6, 0xFB, 0xF7, 0xBE, 0x94, 0xB2, +0x00, 0x00, 0x4A, 0x49, 0xB5, 0xB6, 0xE7, 0x3C, +0xEF, 0x7D, 0xEF, 0x5D, 0xC6, 0x38, 0x73, 0x8E, +0x00, 0x00, 0x52, 0xAA, 0xFF, 0xDE, 0xEF, 0x5C, +0xF7, 0x7D, 0xE7, 0x1C, 0x00, 0x00, 0x9C, 0xD3, +0xF7, 0x9D, 0xAD, 0xB2, 0xBE, 0x0E, 0xA5, 0x2E, +0xCE, 0x76, 0xF7, 0xBD, 0xA5, 0x14, 0x08, 0x61, +0xE7, 0x1C, 0xFF, 0xDF, 0xF7, 0xBE, 0xF7, 0xBE, +0xFF, 0xDE, 0xF7, 0xBE, 0xF7, 0xBE, 0xFF, 0xDF, +0xFF, 0xFF, 0xC6, 0x18, 0x08, 0x41, 0x63, 0x2C, +0xFF, 0xDE, 0xBE, 0x16, 0x21, 0xC2, 0x32, 0x64, +0x32, 0x44, 0x42, 0xC6, 0x42, 0xC7, 0x2A, 0x24, +0x21, 0xE3, 0x21, 0xE2, 0x19, 0xC2, 0x11, 0x41, +0x21, 0xE4, 0x2A, 0x24, 0x22, 0x03, 0x21, 0xE3, +0x4B, 0x49, 0x64, 0x0B, 0x5B, 0xEB, 0x74, 0x8E, +0x53, 0x89, 0x32, 0xA5, 0x2A, 0x23, 0x21, 0xE3, +0x9C, 0xF3, 0xB5, 0x95, 0xB5, 0x53, 0xB5, 0x32, +0xB5, 0x32, 0xB5, 0x52, 0xB5, 0x53, 0xBD, 0xD4, +0xC5, 0xD5, 0xAD, 0x52, 0xB5, 0x93, 0xBD, 0xB3, +0x94, 0x0D, 0xC5, 0xD4, 0xD6, 0x36, 0xD6, 0x56, +0xD6, 0x36, 0xCE, 0x16, 0xD6, 0x36, 0xD6, 0x36, +0xD6, 0x56, 0xDE, 0x98, 0xF7, 0x9D, 0xF7, 0x9E, +0x29, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x31, 0xA6, 0xFF, 0xBE, 0xF7, 0x7C, 0xE6, 0xD9, +0xF7, 0x5B, 0xFF, 0xDF, 0x6B, 0x6D, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xBD, 0xF7, +0xFF, 0xFF, 0xFF, 0xFF, 0xBD, 0xF7, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x8A, +0xFF, 0xDF, 0xE7, 0x1A, 0xD6, 0x76, 0xE6, 0xFA, +0xF7, 0xBE, 0x63, 0x2C, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x94, 0xB2, 0xF7, 0x9D, +0xCE, 0x57, 0x7C, 0x0C, 0x6B, 0xAA, 0x63, 0x69, +0x5B, 0x68, 0x5B, 0x88, 0x8C, 0xEC, 0x8C, 0xCD, +0x63, 0x49, 0x9D, 0x2F, 0x6B, 0xA8, 0x84, 0xAD, +0x9D, 0x2F, 0xA4, 0xF0, 0x94, 0x6E, 0x94, 0x4D, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xEF, 0x5C, 0xCE, 0x57, 0xEF, 0x7C, 0xD6, 0x9A, +0x00, 0x00, 0xA5, 0x34, 0xF7, 0x9D, 0xDE, 0xB9, +0xF7, 0x9E, 0x9C, 0xF3, 0x00, 0x00, 0xDE, 0xDB, +0x4A, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x42, 0x08, 0xDE, 0xDB, +0xEF, 0x7D, 0xC6, 0x16, 0x9C, 0xAF, 0x8C, 0x2C, +0xB5, 0x73, 0xEF, 0x7D, 0xC6, 0x38, 0x00, 0x00, +0x00, 0x00, 0xBD, 0xD7, 0xEF, 0x7D, 0xBE, 0x75, +0xA5, 0xD1, 0xC6, 0x56, 0xF7, 0xBE, 0x7B, 0xCF, +0x00, 0x00, 0x08, 0x41, 0xF7, 0xBE, 0xDF, 0x1B, +0xA5, 0x71, 0x6B, 0xC9, 0x84, 0x8E, 0xC6, 0x78, +0xF7, 0x9D, 0xCE, 0x79, 0x42, 0x08, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x08, 0x41, 0x73, 0x8E, 0xF7, 0xBE, 0xEF, 0x5C, +0xC6, 0x57, 0xEF, 0x9D, 0xFF, 0xFF, 0x08, 0x41, +0x84, 0x30, 0x94, 0x92, 0x08, 0x61, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA2, +0x9C, 0xF3, 0xF7, 0xBE, 0xD6, 0xBA, 0x94, 0xD1, +0xBE, 0x55, 0xDF, 0x1B, 0xF7, 0xDE, 0x84, 0x30, +0x10, 0xA2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x52, 0xAA, +0xE7, 0x3C, 0xEF, 0xBD, 0xCE, 0xD7, 0xA5, 0xB2, +0xD6, 0xFA, 0xF7, 0xDE, 0x9D, 0x13, 0x21, 0x04, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x10, 0xA2, 0x84, 0x10, 0xF7, 0xBE, +0xEF, 0x9C, 0xCF, 0x17, 0xC6, 0xF5, 0xDF, 0x5A, +0xF7, 0xDE, 0xC6, 0x18, 0x31, 0xA6, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x08, 0x41, 0x6B, 0x4D, 0xEF, 0x9D, 0xDE, 0xFB, +0xB5, 0xB6, 0xDE, 0xDB, 0xEF, 0x7D, 0x00, 0x00, +0x8C, 0x51, 0xEF, 0x7D, 0xAD, 0x55, 0x94, 0xB3, +0xC6, 0x38, 0xEF, 0x7D, 0xEF, 0x5D, 0x31, 0xA6, +0x00, 0x20, 0xAD, 0x55, 0xFF, 0xDF, 0xFF, 0xDF, +0xFF, 0xFF, 0xEF, 0x7D, 0x63, 0x0C, 0x00, 0x20, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x4A, 0x49, 0xDE, 0xDB, 0xE7, 0x3D, +0xD6, 0x9A, 0xC6, 0x18, 0xA5, 0x35, 0x94, 0x92, +0xD6, 0x9A, 0xF7, 0x9E, 0x63, 0x0C, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE, 0x79, +0xF7, 0xBE, 0xF7, 0x9E, 0xEF, 0x7D, 0x73, 0x8E, +0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0x6B, 0x6D, +0xF7, 0x9E, 0xEF, 0x5C, 0xD6, 0x79, 0xEF, 0x3C, +0xFF, 0xDF, 0x08, 0x61, 0x00, 0x00, 0xEF, 0x7D, +0xEF, 0x3C, 0xCE, 0x58, 0xE7, 0x1B, 0xFF, 0xBE, +0xA5, 0x34, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA2, +0x7B, 0xEF, 0xF7, 0xBE, 0xF7, 0x9D, 0xDE, 0xB9, +0xEF, 0x5C, 0xE7, 0x3C, 0x00, 0x00, 0x9C, 0xD3, +0xEF, 0x7D, 0xBE, 0x33, 0xCE, 0xB2, 0x9C, 0xEE, +0xD6, 0xB7, 0xFF, 0xBE, 0x63, 0x2C, 0x39, 0xC7, +0xFF, 0xFF, 0xF7, 0x9D, 0xEF, 0x3B, 0xE7, 0x1A, +0xDF, 0x19, 0xDF, 0x1A, 0xE7, 0x3C, 0xEF, 0x5D, +0xF7, 0x9E, 0xFF, 0xFF, 0x42, 0x28, 0x39, 0xC7, +0xFF, 0xDE, 0xC6, 0x37, 0x32, 0x64, 0x42, 0xE6, +0x32, 0x64, 0x32, 0x85, 0x3A, 0xA5, 0x2A, 0x24, +0x21, 0xE3, 0x21, 0xE3, 0x19, 0xA2, 0x22, 0x03, +0x32, 0xA5, 0x32, 0x64, 0x2A, 0x24, 0x21, 0xE3, +0x53, 0x69, 0x6C, 0x6C, 0x64, 0x2B, 0x84, 0xEF, +0x32, 0xA6, 0x19, 0xE2, 0x19, 0xE2, 0x19, 0xC2, +0x94, 0x91, 0xAD, 0x12, 0xB5, 0x52, 0xB5, 0x52, +0xBD, 0x93, 0xBD, 0x93, 0xBD, 0x94, 0xCE, 0x36, +0xCD, 0xF5, 0xC5, 0xD4, 0xC5, 0xD4, 0xD6, 0x35, +0x94, 0x2D, 0xCE, 0x15, 0xD6, 0x56, 0xD6, 0x56, +0xD6, 0x56, 0xD6, 0x56, 0xD6, 0x36, 0xD6, 0x36, +0xD6, 0x56, 0xDE, 0xB9, 0xF7, 0xBE, 0x94, 0xB2, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xA5, 0x34, 0xFF, 0xBE, 0xEF, 0x1A, +0xF7, 0x7D, 0xEF, 0x5D, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x28, +0xFF, 0xFF, 0xFF, 0xFF, 0x4A, 0x49, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xDE, 0xDB, 0xEF, 0x7C, 0xD6, 0xB8, 0xEF, 0x3B, +0xF7, 0x9E, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x29, 0x45, 0xFF, 0xBE, +0xDE, 0xD9, 0x8C, 0x6E, 0x84, 0xED, 0x95, 0x6E, +0x7C, 0xAC, 0x53, 0x88, 0x6C, 0x09, 0x9D, 0x6E, +0x5B, 0x28, 0x94, 0xCE, 0xA5, 0x2F, 0x94, 0xAE, +0x7B, 0xEC, 0x73, 0x6B, 0x73, 0x6B, 0x7B, 0xAC, +0xFF, 0xFF, 0xEF, 0x7D, 0xD6, 0x9A, 0xF7, 0x9E, +0xE7, 0x1C, 0xCE, 0x37, 0xE7, 0x3C, 0xF7, 0xBE, +0xD6, 0xBA, 0xEF, 0x7D, 0xF7, 0x9D, 0xE6, 0xFA, +0xF7, 0xBE, 0xEF, 0x7D, 0xDE, 0xDB, 0xFF, 0xFF, +0xFF, 0xFF, 0xE7, 0x1C, 0xBD, 0xF7, 0xAD, 0x55, +0xB5, 0xB6, 0xDE, 0xFB, 0xF7, 0xBE, 0xE7, 0x3C, +0xBD, 0xF6, 0xC5, 0xF4, 0xB5, 0x30, 0xAD, 0x10, +0xB5, 0x92, 0xDE, 0xFA, 0xF7, 0xBE, 0xDE, 0xDB, +0xDE, 0xDB, 0xF7, 0xBE, 0xDF, 0x1A, 0xA5, 0x91, +0x8D, 0x0C, 0xB5, 0xF3, 0xEF, 0x7C, 0xEF, 0x7D, +0xDE, 0xDB, 0xE7, 0x1B, 0xF7, 0xBE, 0xD6, 0x98, +0xBD, 0xD3, 0xA4, 0xEF, 0x83, 0xED, 0xA5, 0x32, +0xD6, 0xB9, 0xF7, 0xBE, 0xFF, 0xDF, 0xE7, 0x3C, +0xBD, 0xF7, 0xAD, 0x75, 0xB5, 0xB6, 0xD6, 0x9A, +0xF7, 0x9E, 0xF7, 0xBE, 0xE7, 0x3B, 0xBE, 0x36, +0xCE, 0xB8, 0xEF, 0x9C, 0xFF, 0xDF, 0xDE, 0xFB, +0xEF, 0x7D, 0xFF, 0xFF, 0xF7, 0xBE, 0xC6, 0x38, +0xAD, 0x75, 0xAD, 0x75, 0xCE, 0x59, 0xF7, 0xBE, +0xF7, 0xBE, 0xD6, 0xDA, 0xA5, 0x92, 0x7C, 0xAC, +0x7C, 0xAB, 0xAE, 0x14, 0xEF, 0x9C, 0xF7, 0xBE, +0xF7, 0xBE, 0xCE, 0x79, 0xB5, 0x96, 0xAD, 0x55, +0xAD, 0x75, 0xBE, 0x17, 0xEF, 0x5D, 0xF7, 0xBE, +0xE7, 0x3B, 0xCE, 0xD7, 0xAE, 0x31, 0x74, 0x8B, +0xA5, 0x92, 0xD6, 0xD9, 0xEF, 0x5D, 0xF7, 0xBE, +0xDE, 0xDB, 0xBD, 0xD7, 0xAD, 0x55, 0xB5, 0xB6, +0xCE, 0x79, 0xF7, 0xBE, 0xEF, 0x9D, 0xDE, 0xFA, +0xA5, 0x73, 0x7C, 0x6D, 0x9D, 0xD0, 0xCF, 0x36, +0xE7, 0x7A, 0xEF, 0x9D, 0xFF, 0xFF, 0xE7, 0x1C, +0xBD, 0xD7, 0xAD, 0x55, 0xB5, 0xB6, 0xCE, 0x59, +0xF7, 0x9E, 0xFF, 0xFE, 0xEF, 0x7C, 0xCE, 0xB6, +0xAD, 0x92, 0xD6, 0xBA, 0xF7, 0xBE, 0xDE, 0xDB, +0xEF, 0x5D, 0xEF, 0x5D, 0x9C, 0xF3, 0x6B, 0x8E, +0x8C, 0x72, 0xBD, 0xF7, 0xEF, 0x5D, 0xF7, 0x9E, +0xDE, 0xDB, 0xDE, 0xFB, 0xFF, 0xFF, 0xFF, 0xDF, +0xF7, 0xBE, 0xFF, 0xDF, 0xFF, 0xDF, 0xF7, 0xBE, +0xC6, 0x38, 0xB5, 0x96, 0xAD, 0x75, 0xC6, 0x38, +0xE7, 0x3C, 0xF7, 0x9E, 0xE7, 0x1C, 0xC6, 0x18, +0xD6, 0x9A, 0xB5, 0xB6, 0x8C, 0x72, 0x6B, 0x4D, +0x9C, 0xD3, 0xDE, 0xDB, 0xF7, 0x9E, 0xE7, 0x3C, +0xBD, 0xF7, 0xAD, 0x55, 0xAD, 0x55, 0xEF, 0x5D, +0xE7, 0x1C, 0xBD, 0xF7, 0xDE, 0xDB, 0xF7, 0x9E, +0xF7, 0x9E, 0xC6, 0x38, 0xB5, 0x96, 0xAD, 0x55, +0xB5, 0x96, 0xC6, 0x38, 0xEF, 0x7D, 0xFF, 0xDF, +0xEF, 0x5D, 0xCE, 0x58, 0xD6, 0x79, 0xE7, 0x3C, +0xFF, 0xDF, 0xD6, 0xBA, 0xD6, 0xBA, 0xFF, 0xBE, +0xE7, 0x3C, 0xC5, 0xF6, 0xCE, 0x38, 0xE7, 0x3C, +0xF7, 0x9E, 0xFF, 0xDF, 0xDE, 0xDB, 0xBD, 0xD7, +0xAD, 0x55, 0xB5, 0xB6, 0xCE, 0x79, 0xF7, 0xDE, +0xF7, 0xDE, 0xE7, 0x5B, 0xDE, 0xB7, 0xDE, 0xD7, +0xEF, 0x5C, 0xFF, 0xDE, 0xDE, 0xFB, 0xEF, 0x7D, +0xEF, 0x9C, 0xD6, 0xD5, 0xD6, 0xD4, 0xAD, 0x90, +0xD6, 0x97, 0xF7, 0xBE, 0x6B, 0x4D, 0x10, 0xA2, +0xFF, 0xDF, 0xFF, 0xDE, 0xF7, 0x9D, 0xEF, 0x7D, +0xEF, 0x5C, 0xEF, 0x7D, 0xF7, 0x9E, 0xF7, 0xBE, +0xFF, 0xDF, 0xFF, 0xDF, 0x21, 0x04, 0x4A, 0x49, +0xF7, 0xBE, 0xB5, 0xD6, 0x32, 0x44, 0x2A, 0x44, +0x2A, 0x24, 0x2A, 0x24, 0x11, 0x81, 0x19, 0xA2, +0x21, 0xE3, 0x19, 0xA2, 0x19, 0x82, 0x32, 0x85, +0x43, 0x06, 0x3A, 0xC5, 0x2A, 0x64, 0x21, 0xE3, +0x3A, 0xE6, 0x53, 0xC9, 0x74, 0x8D, 0x8D, 0x30, +0x3A, 0xA6, 0x22, 0x03, 0x22, 0x02, 0x19, 0xE2, +0x94, 0x90, 0xB5, 0x52, 0xBD, 0xB3, 0xC5, 0xB2, +0xC5, 0xB3, 0xCE, 0x14, 0xD6, 0x35, 0xD6, 0x56, +0xD6, 0x56, 0xD6, 0x55, 0xCE, 0x15, 0xCE, 0x15, +0x94, 0x2D, 0xD6, 0x15, 0xDE, 0x56, 0xD6, 0x56, +0xD6, 0x56, 0xD6, 0x56, 0xD6, 0x36, 0xD6, 0x56, +0xD6, 0x56, 0xDE, 0xB9, 0xFF, 0xBE, 0x73, 0xAE, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x8C, 0x51, 0xFF, 0xDE, 0xEF, 0x1A, +0xF7, 0x9D, 0xD6, 0xBA, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x45, +0xFF, 0xFF, 0xFF, 0xFF, 0x39, 0xC7, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xCE, 0x59, 0xF7, 0xBD, 0xE7, 0x3A, 0xEF, 0x7C, +0xEF, 0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x18, 0xE3, 0xFF, 0xDE, +0xDE, 0xB9, 0xA5, 0x30, 0x95, 0x4F, 0x8D, 0x2F, +0x4B, 0x27, 0x53, 0x68, 0x8C, 0xED, 0xA5, 0xAF, +0x7C, 0x2B, 0x94, 0xCE, 0xC6, 0x74, 0xB5, 0x92, +0x9C, 0xD0, 0xA4, 0xD1, 0xA4, 0xD0, 0x9C, 0xAF, +0xEF, 0x3C, 0xEF, 0x5C, 0xEF, 0x5C, 0xEF, 0x3C, +0xDE, 0xB9, 0xC5, 0xD5, 0xD6, 0x99, 0xEF, 0x3C, +0xEF, 0x5C, 0xEF, 0x3C, 0xE7, 0x1B, 0xDE, 0xD9, +0xDE, 0xFA, 0xE7, 0x1C, 0xF7, 0x7D, 0xEF, 0x5C, +0xF7, 0x7C, 0xF7, 0x9D, 0xF7, 0x9D, 0xF7, 0x9D, +0xF7, 0x9D, 0xDE, 0xFB, 0xC6, 0x58, 0x9D, 0x32, +0x74, 0x0D, 0xCE, 0x75, 0xCE, 0x14, 0xBD, 0xD3, +0x9C, 0xEF, 0xBD, 0xD5, 0xDF, 0x1A, 0xEF, 0x5C, +0xEF, 0x5C, 0xE7, 0x3B, 0xCE, 0x98, 0xAD, 0x71, +0x8C, 0xAD, 0x8C, 0x6F, 0xCE, 0x58, 0xE7, 0x3C, +0xEF, 0x3C, 0xE7, 0x1C, 0xDE, 0xDA, 0xBD, 0xB4, +0x9C, 0x8F, 0xAD, 0x11, 0xD6, 0x77, 0xA5, 0x32, +0xC6, 0x57, 0xF7, 0xBD, 0xE7, 0x3C, 0xE7, 0x1C, +0xE7, 0x3C, 0xEF, 0x5C, 0xE7, 0x5C, 0xEF, 0x9C, +0xE7, 0x3B, 0xC6, 0x98, 0xBE, 0x56, 0xD7, 0x38, +0xD6, 0xF9, 0xE7, 0x5B, 0xEF, 0x9D, 0xEF, 0x9D, +0xEF, 0x7C, 0xEF, 0x5C, 0xEF, 0x9D, 0xEF, 0x5C, +0xEF, 0x9D, 0xEF, 0x7D, 0xF7, 0xBD, 0xE7, 0x3A, +0xBE, 0x56, 0x8D, 0x0F, 0x5B, 0xC8, 0x4B, 0x85, +0x5B, 0xE7, 0x7C, 0xCB, 0x8C, 0xD0, 0xB5, 0xB5, +0xD6, 0xFA, 0xE7, 0x5C, 0xE7, 0x5C, 0xEF, 0x7D, +0xEF, 0x9D, 0xE7, 0x5C, 0xDE, 0xFA, 0xC6, 0x77, +0xA5, 0xB3, 0x6C, 0x0B, 0x5B, 0xA7, 0x53, 0xA6, +0x74, 0x4A, 0x84, 0xAF, 0xA5, 0x54, 0xCE, 0x79, +0xE7, 0x7C, 0xE7, 0x5C, 0xE7, 0x5C, 0xE7, 0x5C, +0xDF, 0x1B, 0xD6, 0xB9, 0xBE, 0x35, 0x84, 0x8F, +0x52, 0xE9, 0x3A, 0x86, 0x42, 0xE5, 0x95, 0xCE, +0xA6, 0x11, 0xAD, 0xF4, 0xCE, 0xD8, 0xE7, 0x3B, +0xEF, 0x7C, 0xEF, 0x7D, 0xEF, 0x7C, 0xEF, 0x7C, +0xEF, 0x9C, 0xD6, 0xF8, 0xBE, 0x93, 0xAE, 0x0E, +0xAD, 0xEF, 0xCE, 0x97, 0xDE, 0xDB, 0xEF, 0x5C, +0xEF, 0x7C, 0xDE, 0xFA, 0x8C, 0x71, 0x63, 0x0C, +0x5B, 0x0C, 0x84, 0x10, 0xBD, 0xD7, 0xE7, 0x1C, +0xEF, 0x5D, 0xEF, 0x5D, 0xE7, 0x1C, 0xE7, 0x3C, +0xE7, 0x3C, 0xE7, 0x1C, 0xE7, 0x1C, 0xF7, 0xBE, +0xFF, 0xDF, 0xF7, 0x9E, 0xEF, 0x7D, 0xE7, 0x3C, +0xDE, 0xDB, 0xBD, 0xF7, 0x9C, 0xD3, 0xC6, 0x39, +0xBD, 0xF8, 0xAD, 0x55, 0x6B, 0x6E, 0x4A, 0x6A, +0x5A, 0xCB, 0x8C, 0x71, 0xBD, 0xF7, 0xDE, 0xDB, +0xE7, 0x3C, 0xE7, 0x3C, 0xE7, 0x3C, 0xDE, 0xDB, +0xBD, 0xD7, 0x7B, 0xEF, 0x8C, 0x51, 0xB5, 0xB6, +0xD6, 0x9A, 0xE7, 0x1C, 0xEF, 0x5D, 0xEF, 0x7D, +0xEF, 0x5D, 0xE7, 0x3C, 0xDE, 0xFB, 0xD6, 0x9A, +0xC6, 0x18, 0xAD, 0x55, 0xCE, 0x59, 0xE7, 0x3D, +0xF7, 0x9E, 0xF7, 0x9E, 0xF7, 0xBE, 0xF7, 0x9E, +0xE7, 0x5D, 0xD6, 0xBB, 0xD6, 0xDB, 0xDE, 0xFC, +0xE7, 0x1C, 0xEF, 0x5D, 0xEF, 0x7D, 0xF7, 0x9E, +0xF7, 0x9D, 0xEF, 0x7C, 0xE7, 0x5C, 0xDF, 0x3A, +0xD6, 0xD8, 0xC6, 0x35, 0xA5, 0x10, 0xBD, 0xD2, +0xF7, 0x9A, 0xEF, 0x7B, 0xE7, 0x5B, 0xEF, 0x7B, +0xDF, 0x19, 0xE7, 0x55, 0xA5, 0x6E, 0xAD, 0xB1, +0xCE, 0x37, 0xF7, 0x7D, 0xC6, 0x38, 0x00, 0x20, +0x39, 0xE7, 0x9C, 0xD3, 0xCE, 0x79, 0xDE, 0xDB, +0xEF, 0x5D, 0xEF, 0x5D, 0xDE, 0xFB, 0xCE, 0x79, +0x9C, 0xD3, 0x39, 0xE7, 0x00, 0x00, 0xAD, 0x75, +0xEF, 0x5C, 0x9D, 0x13, 0x32, 0x85, 0x32, 0x65, +0x32, 0x85, 0x19, 0xA3, 0x11, 0x41, 0x19, 0xC3, +0x2A, 0x24, 0x21, 0xC3, 0x19, 0xA2, 0x32, 0x85, +0x4B, 0x07, 0x3A, 0xC5, 0x2A, 0x64, 0x21, 0xE2, +0x32, 0x84, 0x4B, 0xA8, 0x7C, 0xEE, 0x8D, 0x50, +0x32, 0x85, 0x2A, 0x23, 0x22, 0x23, 0x21, 0xE2, +0x6B, 0x2A, 0x83, 0xAC, 0x94, 0x4D, 0x9C, 0x8E, +0xAD, 0x10, 0xBD, 0x72, 0xC5, 0xD4, 0xCD, 0xF4, +0xD6, 0x55, 0xDE, 0x76, 0xDE, 0x97, 0xCD, 0xF4, +0x9C, 0x4D, 0xCD, 0xD3, 0xDE, 0x76, 0xE6, 0x97, +0xE6, 0xB7, 0xE6, 0xB7, 0xDE, 0x76, 0xDE, 0x76, +0xDE, 0x56, 0xEE, 0xF9, 0xF7, 0xBE, 0xAD, 0x75, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xC6, 0x18, 0xFF, 0xBE, 0xDE, 0xB9, +0xF7, 0x7C, 0xFF, 0xDE, 0x18, 0xC3, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x6D, +0xFF, 0xFF, 0xFF, 0xFF, 0x84, 0x10, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xE3, +0xF7, 0xBE, 0xF7, 0x9D, 0xEF, 0x3A, 0xF7, 0x7C, +0xFF, 0xDE, 0x39, 0xE7, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x6B, 0x6D, 0xF7, 0xBE, +0xDE, 0xD8, 0xAD, 0xB1, 0x8C, 0xED, 0x53, 0x68, +0x53, 0x69, 0x6C, 0x2B, 0x84, 0xAC, 0xA5, 0xB0, +0xB5, 0xF2, 0x84, 0x6D, 0xC6, 0x54, 0xAD, 0x51, +0xA4, 0xF0, 0x9C, 0x90, 0xAD, 0x11, 0xAD, 0x11, +0xBD, 0xD5, 0xC5, 0xD5, 0xBD, 0xB4, 0xC5, 0xB4, +0xC5, 0xB4, 0xB5, 0x73, 0xAD, 0x12, 0xBD, 0x73, +0xB5, 0x53, 0x9C, 0x90, 0xBD, 0xB4, 0xA4, 0xF2, +0x84, 0x0F, 0xC6, 0x16, 0xD6, 0x77, 0xD6, 0x36, +0xD6, 0x36, 0xD6, 0x56, 0xCE, 0x15, 0xD6, 0x56, +0xCE, 0x56, 0x7C, 0x2E, 0x74, 0x0C, 0x5B, 0x88, +0x53, 0x26, 0xB5, 0xB2, 0xC6, 0x14, 0xC5, 0xD3, +0xBD, 0xB3, 0xB5, 0x52, 0xBD, 0xB3, 0xBD, 0xB3, +0xB5, 0x72, 0x9C, 0xB1, 0x73, 0x8D, 0x5A, 0xEA, +0x52, 0xA9, 0x73, 0x8C, 0xB5, 0x74, 0xBD, 0xD5, +0xB5, 0x74, 0xAD, 0x54, 0xA4, 0xF2, 0x9C, 0xD1, +0x7B, 0xCD, 0xC6, 0x57, 0xD6, 0xB7, 0xDE, 0xF9, +0xA5, 0x33, 0xE7, 0x3A, 0xDE, 0xF9, 0xA5, 0x32, +0x9D, 0x32, 0x94, 0xF1, 0x8C, 0xD0, 0xAE, 0x13, +0x9D, 0x91, 0x8C, 0xEE, 0xC6, 0xF4, 0xBE, 0x91, +0xAD, 0xF2, 0xC6, 0x97, 0xC6, 0x77, 0xAD, 0xB4, +0xA5, 0x73, 0xBE, 0x16, 0xD6, 0xF8, 0xB6, 0x34, +0xB6, 0x33, 0xBE, 0x75, 0xAD, 0xD2, 0x8C, 0xEE, +0x6C, 0x4A, 0x53, 0x86, 0x6C, 0x49, 0x85, 0x0B, +0x74, 0xA8, 0x5C, 0x06, 0x3A, 0xA6, 0x63, 0x8B, +0x9D, 0x90, 0x95, 0x50, 0x84, 0x2F, 0x95, 0x31, +0xA5, 0xD1, 0x95, 0x50, 0x84, 0xEE, 0x84, 0xED, +0x95, 0xAE, 0x85, 0x0C, 0x7C, 0xAA, 0x7C, 0xC9, +0x95, 0x8C, 0x6C, 0x28, 0x63, 0x8A, 0xA5, 0xB0, +0xA5, 0x90, 0x8C, 0xB0, 0x84, 0x2F, 0x7C, 0x2F, +0x84, 0x8F, 0x8D, 0x0E, 0x6C, 0x2B, 0x32, 0x45, +0x19, 0x42, 0x2A, 0x03, 0x4B, 0x66, 0x4B, 0xA5, +0x53, 0xC6, 0x5B, 0xE9, 0x7C, 0xCD, 0x9D, 0xB0, +0xBE, 0x93, 0xB6, 0x12, 0xA5, 0xB0, 0x9D, 0x90, +0x9D, 0x8F, 0x8D, 0x0C, 0x8D, 0x4A, 0x8D, 0x49, +0x85, 0x29, 0x95, 0x4D, 0xBE, 0x52, 0xCE, 0xD4, +0xB5, 0xF3, 0xA5, 0x52, 0x84, 0x6D, 0x63, 0x69, +0x63, 0x8A, 0x73, 0xEC, 0x8C, 0xB0, 0xB5, 0xB5, +0xBD, 0xD7, 0xAD, 0x55, 0x94, 0x92, 0xA5, 0x14, +0xBD, 0xF7, 0xCE, 0x59, 0xCE, 0x59, 0xCE, 0x59, +0xCE, 0x7A, 0xDE, 0xDA, 0xCE, 0x99, 0xAD, 0xD5, +0xB6, 0x15, 0xA5, 0x73, 0xA5, 0x34, 0xC6, 0x38, +0x9C, 0xD3, 0x8C, 0x52, 0x52, 0xAB, 0x42, 0x08, +0x31, 0x86, 0x42, 0x28, 0x63, 0x2C, 0x7B, 0xEF, +0x84, 0x30, 0x84, 0x10, 0x84, 0x30, 0x84, 0x0F, +0x63, 0x0C, 0x4A, 0x49, 0x4A, 0x29, 0x63, 0x0C, +0x73, 0x8E, 0x83, 0xEF, 0x8C, 0x50, 0x9C, 0xD2, +0x9C, 0xD3, 0xBD, 0xB6, 0xA5, 0x14, 0x8C, 0x31, +0x9C, 0xF4, 0xA5, 0x14, 0x8C, 0x72, 0xA5, 0x56, +0xB5, 0xD8, 0xAD, 0xB8, 0xB5, 0xD8, 0xB5, 0xF9, +0xB5, 0xF9, 0xA5, 0x98, 0xA5, 0xB8, 0xAD, 0xB8, +0xAD, 0x98, 0xBE, 0x19, 0xC6, 0x9B, 0xCE, 0x9B, +0xCE, 0xBA, 0xB6, 0x35, 0xA5, 0xD1, 0xAD, 0xD1, +0x9D, 0x6F, 0xB5, 0xD0, 0xCE, 0x72, 0xD6, 0xD2, +0xEF, 0x94, 0xCE, 0xB1, 0xA5, 0xAF, 0xA5, 0xCF, +0xAD, 0xEF, 0xEF, 0x93, 0xBE, 0x11, 0xDF, 0x39, +0xD6, 0xDA, 0xEF, 0x7D, 0xFF, 0xDF, 0xBD, 0xF7, +0x39, 0xC7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x29, 0x45, 0xAD, 0x55, 0xF7, 0xDE, +0xCE, 0x79, 0x7C, 0x2E, 0x2A, 0x44, 0x32, 0x85, +0x32, 0x65, 0x11, 0x62, 0x19, 0xA3, 0x19, 0xA3, +0x21, 0xC3, 0x19, 0xA3, 0x11, 0x42, 0x09, 0x21, +0x32, 0x44, 0x3A, 0xE5, 0x2A, 0x64, 0x21, 0xE2, +0x2A, 0x43, 0x53, 0xA8, 0x85, 0x2F, 0x74, 0xAD, +0x42, 0xE6, 0x22, 0x23, 0x2A, 0x64, 0x21, 0xE2, +0x7B, 0xAC, 0x7B, 0x6B, 0x73, 0x49, 0x8B, 0xEC, +0x9C, 0x4D, 0x9C, 0x4D, 0x94, 0x2C, 0x9C, 0x6D, +0x9C, 0x6E, 0xA4, 0xAE, 0xA4, 0xCF, 0xA4, 0xAE, +0xA4, 0x8E, 0xAC, 0xCF, 0xA4, 0xAF, 0x9C, 0x6E, +0xA4, 0x8E, 0xAC, 0xD0, 0xBD, 0x31, 0xC5, 0x92, +0xBD, 0x71, 0xBD, 0x72, 0xDE, 0xDA, 0xFF, 0xBE, +0x63, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x73, 0xAE, 0xFF, 0xDE, 0xF7, 0x5C, 0xE6, 0xD8, +0xF7, 0x3B, 0xFF, 0xDE, 0xBD, 0xF7, 0x10, 0xA2, +0x00, 0x00, 0x00, 0x00, 0x39, 0xE7, 0xEF, 0x7D, +0xFF, 0xBE, 0xFF, 0xDE, 0xF7, 0xBE, 0x5A, 0xCB, +0x00, 0x00, 0x00, 0x00, 0x18, 0xE3, 0xC6, 0x38, +0xFF, 0xBE, 0xEF, 0x3A, 0xE7, 0x19, 0xEF, 0x3A, +0xFF, 0xBE, 0xDE, 0xFB, 0x39, 0xC7, 0x00, 0x00, +0x00, 0x00, 0x52, 0xAA, 0xEF, 0x7D, 0xE7, 0x3B, +0xB5, 0x93, 0x5B, 0x08, 0x63, 0x89, 0x63, 0xCA, +0x5B, 0xAA, 0x95, 0x2F, 0x9D, 0x4F, 0xBE, 0x53, +0xC6, 0x74, 0x7C, 0x2B, 0xBE, 0x33, 0xB5, 0xB2, +0x9C, 0xB0, 0x94, 0x6F, 0xA4, 0xF1, 0xAD, 0x11, +0xAD, 0x31, 0xB5, 0x50, 0xB5, 0x90, 0xB5, 0x90, +0xB5, 0x50, 0xAD, 0x31, 0x73, 0x6B, 0xA4, 0xCF, +0xA4, 0xD0, 0xAD, 0x12, 0x7B, 0x8C, 0x6B, 0x4B, +0xB5, 0x52, 0xAD, 0x31, 0xBD, 0x92, 0xBD, 0x72, +0xC5, 0xB3, 0xC5, 0xB3, 0xA4, 0xD0, 0xBD, 0xB3, +0xBD, 0xD3, 0x42, 0xC4, 0x3A, 0xE4, 0x43, 0x03, +0x3A, 0xE4, 0x73, 0xEB, 0xC6, 0x14, 0xC5, 0xD3, +0xB5, 0x71, 0x94, 0x4D, 0xB5, 0x71, 0xA4, 0xCF, +0xA4, 0xAF, 0xA4, 0xF1, 0x84, 0x0E, 0x84, 0x0E, +0x94, 0x90, 0xA4, 0xF2, 0xB5, 0x74, 0xA5, 0x12, +0x94, 0x90, 0x9C, 0xD1, 0x94, 0xB0, 0x94, 0xB0, +0xBD, 0xF5, 0xDE, 0xD9, 0xBE, 0x15, 0xAD, 0xB3, +0x9D, 0x51, 0xA5, 0xB2, 0xA5, 0xB2, 0x94, 0xEF, +0x63, 0x8A, 0x74, 0x4C, 0x9D, 0x8F, 0x9D, 0xAE, +0x7C, 0x8A, 0x85, 0x0B, 0xB6, 0x8F, 0xBE, 0x8E, +0x63, 0xC9, 0xC6, 0x97, 0xD7, 0x1A, 0x84, 0x6F, +0x9D, 0x32, 0xAD, 0xD3, 0xA5, 0x90, 0xA5, 0xF0, +0x8D, 0x4D, 0x74, 0x69, 0x5B, 0xC5, 0x53, 0xC3, +0x53, 0x85, 0x95, 0x2E, 0xA5, 0x8F, 0x84, 0xCB, +0x5B, 0xE5, 0x53, 0xE5, 0x64, 0x47, 0x7C, 0xC9, +0x74, 0xA9, 0x5B, 0xC7, 0x4B, 0x26, 0x74, 0xAA, +0x9E, 0x0D, 0x8D, 0x6A, 0x7D, 0x09, 0x64, 0x47, +0x7C, 0xEA, 0x9D, 0xAE, 0xA6, 0x0F, 0x6C, 0x88, +0x4B, 0x45, 0x42, 0xE4, 0x3A, 0x84, 0x53, 0x46, +0x53, 0x66, 0x53, 0x47, 0x29, 0xC4, 0x19, 0x23, +0x29, 0xC4, 0x4B, 0x47, 0x4B, 0x26, 0x42, 0xE5, +0x2A, 0x24, 0x2A, 0x03, 0x43, 0x05, 0x4B, 0x65, +0x5B, 0xE7, 0x7C, 0xCB, 0x8D, 0x6D, 0x5B, 0xE7, +0x7C, 0xC9, 0x95, 0x8B, 0x74, 0xA7, 0x6C, 0x86, +0x6C, 0x66, 0xA5, 0xEE, 0xBE, 0xD2, 0x8D, 0x6A, +0x6C, 0x86, 0x7C, 0xA7, 0xC6, 0xD1, 0xC6, 0xF2, +0xBE, 0xD3, 0xBE, 0x93, 0xAE, 0x30, 0x6C, 0x26, +0x7C, 0xC8, 0x7C, 0xE8, 0x7C, 0xA9, 0x8C, 0xEE, +0x8C, 0x70, 0x73, 0xAE, 0x8C, 0x71, 0x9C, 0xD3, +0xCE, 0x7A, 0xAD, 0x76, 0x9C, 0xB3, 0xA4, 0xD3, +0x9C, 0xD4, 0x94, 0xB3, 0xAD, 0x75, 0x9D, 0x12, +0xAD, 0xF4, 0xB6, 0x35, 0xC6, 0x58, 0xBD, 0xF7, +0x9C, 0xD3, 0x6B, 0x4D, 0x42, 0x29, 0x31, 0x86, +0x29, 0x65, 0x29, 0x45, 0x31, 0x86, 0x39, 0xC7, +0x42, 0x28, 0x42, 0x08, 0x21, 0x04, 0x31, 0x86, +0x29, 0x45, 0x4A, 0x28, 0x5A, 0xCB, 0x39, 0xA6, +0x39, 0xC7, 0x5A, 0xCB, 0x41, 0xE7, 0x4A, 0x29, +0x42, 0x08, 0x62, 0xEB, 0x6B, 0x4D, 0x7B, 0xD0, +0x8C, 0x72, 0x9C, 0xD4, 0xA5, 0x14, 0xAD, 0x76, +0xA5, 0x35, 0x73, 0xF1, 0x8C, 0xD4, 0xB5, 0xD8, +0x7C, 0x32, 0x74, 0x32, 0x7C, 0x73, 0x84, 0xB5, +0x8C, 0xD5, 0x84, 0xB5, 0x84, 0xB5, 0x84, 0xB5, +0x84, 0x93, 0x8D, 0x11, 0x8D, 0x4C, 0x8D, 0x4B, +0x8C, 0xEB, 0xC6, 0xB1, 0xCE, 0xAF, 0xD7, 0x0F, +0xB5, 0xE9, 0xB6, 0x29, 0x95, 0x65, 0x85, 0x04, +0x95, 0x66, 0xA5, 0x8B, 0x95, 0x2F, 0x8C, 0xF2, +0x9D, 0x35, 0xB5, 0xF9, 0xDE, 0xFC, 0xF7, 0xBF, +0xFF, 0xDF, 0xEF, 0x7D, 0xCE, 0x79, 0xBD, 0xF7, +0xB5, 0x96, 0xAD, 0x55, 0xBD, 0xD7, 0xC6, 0x38, +0xE7, 0x3C, 0xF7, 0xBE, 0xF7, 0xBD, 0xDF, 0x3A, +0x94, 0xF1, 0x4B, 0x08, 0x32, 0x85, 0x4B, 0x07, +0x32, 0x45, 0x21, 0xE4, 0x2A, 0x25, 0x11, 0x42, +0x19, 0x62, 0x19, 0xA3, 0x21, 0xA4, 0x11, 0x01, +0x32, 0x45, 0x4B, 0x47, 0x2A, 0x43, 0x22, 0x03, +0x22, 0x43, 0x53, 0xA9, 0x74, 0xCD, 0x7C, 0xED, +0x3A, 0xC6, 0x09, 0x20, 0x2A, 0x44, 0x21, 0xE3, +0x83, 0xED, 0x8B, 0xED, 0x7B, 0x4A, 0x8B, 0xEB, +0xA4, 0xAE, 0xA4, 0xAE, 0xA4, 0xAE, 0xA4, 0xAF, +0xA4, 0x8E, 0xB5, 0x10, 0xB5, 0x10, 0xAD, 0x10, +0xB5, 0x10, 0xB5, 0x10, 0xBD, 0x51, 0xBD, 0x51, +0xBD, 0x72, 0xC5, 0xB2, 0xBD, 0x51, 0xB5, 0x10, +0xB5, 0x10, 0xBD, 0x72, 0xCE, 0x36, 0xEF, 0x5C, +0xFF, 0xBE, 0xCE, 0x79, 0xA5, 0x34, 0xD6, 0x9A, +0xF7, 0xBE, 0xE7, 0x1B, 0xC5, 0xB4, 0xA4, 0xAF, +0xB5, 0x32, 0xD6, 0x99, 0xF7, 0x7D, 0xEF, 0x7D, +0xBD, 0xD7, 0xCE, 0x59, 0xFF, 0xBE, 0xF7, 0x7D, +0xE6, 0xD9, 0xE6, 0xD9, 0xF7, 0x7C, 0xFF, 0xDE, +0xE7, 0x1C, 0xD6, 0x99, 0xFF, 0xBE, 0xFF, 0xBE, +0xF7, 0x5B, 0xEF, 0x19, 0xEF, 0x19, 0xEE, 0xF9, +0xF7, 0x7C, 0xF7, 0x9D, 0xFF, 0xDF, 0xE7, 0x3C, +0xEF, 0x7D, 0xFF, 0xDE, 0xEF, 0x7C, 0xD6, 0x57, +0xA4, 0xCF, 0x73, 0x89, 0x74, 0x0B, 0x63, 0xCA, +0x63, 0xCA, 0x9D, 0x91, 0x74, 0x0B, 0x8C, 0xED, +0xAE, 0x11, 0x73, 0xEB, 0x8C, 0x8E, 0xC6, 0x35, +0x7B, 0xCC, 0x8C, 0x2E, 0x9C, 0xD0, 0xB5, 0x92, +0xBE, 0x11, 0xBE, 0x50, 0xBE, 0x6F, 0xBE, 0x6F, +0xC6, 0x70, 0xC6, 0x53, 0x7B, 0x8A, 0xAD, 0x10, +0xAD, 0x11, 0x6B, 0x4B, 0x63, 0x2A, 0x9C, 0xB0, +0xB5, 0x72, 0xB5, 0x52, 0xAD, 0x31, 0xBD, 0x72, +0xBD, 0x72, 0xBD, 0x72, 0x83, 0xEC, 0xC5, 0xF4, +0xAD, 0x50, 0x4B, 0x05, 0x32, 0x82, 0x3A, 0xA2, +0x3A, 0xA3, 0x53, 0x68, 0x7C, 0x6C, 0x84, 0x6D, +0xA5, 0x51, 0x8C, 0x4D, 0xAD, 0x10, 0x9C, 0x8E, +0x9C, 0x6D, 0xB5, 0x52, 0x94, 0x8F, 0x9C, 0xF1, +0xAD, 0x73, 0xAD, 0x73, 0xA5, 0x12, 0x94, 0x90, +0x6B, 0x4B, 0x6B, 0x6C, 0x83, 0xEE, 0xC5, 0xF6, +0xCE, 0x77, 0xA5, 0x32, 0x5B, 0x4A, 0x42, 0xE8, +0x42, 0xC7, 0x6B, 0xEB, 0x9D, 0x71, 0xA5, 0x91, +0xA5, 0x92, 0x7C, 0x6C, 0xBE, 0x72, 0xBE, 0xB2, +0x7C, 0xAA, 0x74, 0x88, 0x9D, 0xCC, 0xA5, 0xED, +0x5B, 0x89, 0xD6, 0xF9, 0x94, 0xF1, 0x9D, 0x51, +0xA5, 0xB1, 0xAE, 0x32, 0x84, 0xEB, 0x8D, 0x2C, +0x95, 0x6D, 0x53, 0xC5, 0x4B, 0xA3, 0x43, 0x43, +0x63, 0x87, 0x8C, 0x8D, 0x7C, 0x2A, 0x7C, 0xA9, +0x53, 0xC4, 0x64, 0x46, 0x64, 0x26, 0x85, 0x29, +0x6C, 0x88, 0x32, 0x63, 0x21, 0xE2, 0x4B, 0x66, +0x74, 0xCA, 0x74, 0xC9, 0x74, 0xC9, 0x95, 0xAD, +0x95, 0x8C, 0x95, 0xAC, 0x7D, 0x09, 0x4B, 0x84, +0x32, 0x63, 0x43, 0x05, 0x3A, 0x84, 0x3A, 0xC5, +0x43, 0x05, 0x4B, 0x27, 0x11, 0x21, 0x11, 0x02, +0x11, 0x01, 0x2A, 0x24, 0x42, 0xC6, 0xAE, 0x11, +0x84, 0xCC, 0x4A, 0xE7, 0x74, 0x4C, 0x8D, 0x2E, +0x8D, 0x4D, 0x7C, 0xCB, 0x5B, 0xE7, 0x64, 0x49, +0x64, 0x48, 0x4B, 0xC4, 0x74, 0xE9, 0x9E, 0x0E, +0xAE, 0x71, 0xAE, 0x50, 0x9D, 0xCE, 0x7D, 0x0A, +0x6C, 0x88, 0x95, 0x4A, 0xBE, 0x8F, 0xA5, 0xEF, +0xC7, 0x14, 0xBE, 0xF4, 0xB6, 0x71, 0x53, 0xC5, +0x54, 0x03, 0x64, 0x63, 0x7C, 0xC7, 0xB6, 0x30, +0x84, 0x6D, 0x63, 0x0C, 0x9C, 0xD3, 0x9C, 0xF4, +0xBD, 0xF8, 0x8C, 0x31, 0x7B, 0x8E, 0x8B, 0xCF, +0xA4, 0xB3, 0xB5, 0x55, 0x8C, 0x51, 0x8C, 0x30, +0xAD, 0x94, 0xA5, 0x54, 0xA5, 0x34, 0x9C, 0xF4, +0x8C, 0x92, 0x52, 0xCB, 0x39, 0xC7, 0x31, 0x65, +0x21, 0x44, 0x29, 0x44, 0x31, 0x85, 0x31, 0x86, +0x52, 0x89, 0x5A, 0xCA, 0x29, 0x45, 0x21, 0x04, +0x31, 0x65, 0x52, 0x8A, 0x62, 0xEB, 0x5A, 0xAB, +0x39, 0xA6, 0x52, 0x8A, 0x6B, 0x2D, 0x41, 0xE8, +0x42, 0x08, 0x4A, 0x49, 0x5A, 0xCC, 0x7B, 0xAF, +0x94, 0x72, 0x94, 0x92, 0x94, 0x92, 0x8C, 0x71, +0x8C, 0x51, 0x94, 0xB3, 0xA5, 0x35, 0x94, 0xD4, +0x74, 0x12, 0x6B, 0xD1, 0x63, 0xB1, 0x63, 0xB1, +0x63, 0xB1, 0x63, 0xB0, 0x6B, 0xD1, 0x63, 0xB0, +0x63, 0x8F, 0x6B, 0xEE, 0x8D, 0x2D, 0x8D, 0x2B, +0x8D, 0x2A, 0xC6, 0xAF, 0xD6, 0xEE, 0xD7, 0x0E, +0xAD, 0xA7, 0xC6, 0xAA, 0xA5, 0xE7, 0x8D, 0x23, +0x8D, 0x25, 0x9D, 0x8B, 0x8C, 0xEF, 0x84, 0xB2, +0x8C, 0xD4, 0x8C, 0xF5, 0xAD, 0x97, 0xEF, 0x5C, +0xEF, 0x7C, 0xEF, 0x7D, 0xF7, 0xBE, 0xFF, 0xDF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, +0xEF, 0x7D, 0xDF, 0x1B, 0xD6, 0xF7, 0xB6, 0x31, +0x6C, 0x4A, 0x3A, 0xA6, 0x5B, 0xAA, 0x5B, 0xAA, +0x2A, 0x04, 0x2A, 0x04, 0x32, 0x66, 0x19, 0xA3, +0x21, 0xA3, 0x21, 0xE4, 0x19, 0x63, 0x2A, 0x05, +0x6C, 0x4C, 0x5C, 0x09, 0x22, 0x23, 0x22, 0x23, +0x22, 0x23, 0x3A, 0xE6, 0x4B, 0x27, 0x7C, 0xEE, +0x21, 0xC3, 0x19, 0xA3, 0x32, 0x85, 0x21, 0xE3, +0xB5, 0x73, 0x8C, 0x0D, 0x7B, 0x6A, 0x9C, 0x6E, +0xBD, 0x51, 0xB5, 0x30, 0xB5, 0x10, 0xA4, 0xAF, +0xAD, 0x10, 0xBD, 0x92, 0xC5, 0x93, 0xC5, 0x92, +0xCD, 0xF4, 0xBD, 0x72, 0xBD, 0x72, 0xBD, 0x92, +0xBD, 0x51, 0xC5, 0x92, 0xA4, 0x8E, 0x8C, 0x0C, +0x94, 0x2D, 0x9C, 0x4D, 0x9C, 0x8F, 0xC5, 0xD5, +0xE7, 0x1B, 0xF7, 0xBE, 0xFF, 0xFF, 0xFF, 0xDE, +0xF7, 0x7C, 0xE6, 0xB8, 0xD6, 0x14, 0xCD, 0xF3, +0xC5, 0x92, 0xD6, 0x56, 0xE6, 0xF9, 0xF7, 0x9D, +0xFF, 0xDF, 0xFF, 0xBE, 0xEF, 0x3C, 0xDE, 0x78, +0xB5, 0x31, 0xB5, 0x31, 0xC5, 0xF5, 0xE6, 0xFA, +0xF7, 0x9D, 0xF7, 0x9E, 0xE7, 0x3C, 0xCE, 0x37, +0xAD, 0x11, 0xA4, 0x8E, 0x9C, 0x8E, 0xA4, 0xAF, +0xBD, 0x72, 0xCE, 0x37, 0xE7, 0x1B, 0xF7, 0x9D, +0xF7, 0x7D, 0xE7, 0x1A, 0xCE, 0x36, 0xBD, 0x72, +0xA4, 0xAE, 0x8C, 0x2B, 0x63, 0x48, 0x4B, 0x07, +0x74, 0x6C, 0x84, 0xEE, 0x5B, 0x69, 0x84, 0xCC, +0x85, 0x0C, 0xB6, 0x32, 0x84, 0x4C, 0x7C, 0x0D, +0x6B, 0x2A, 0x8C, 0x2E, 0xA5, 0x10, 0xC6, 0x52, +0xBE, 0x0F, 0xB6, 0x0D, 0xB5, 0xCC, 0xB5, 0xCD, +0xB5, 0xEE, 0xAD, 0x6F, 0x7B, 0xCC, 0xB5, 0x52, +0x63, 0x0A, 0x52, 0x88, 0x63, 0x2A, 0x94, 0x8F, +0xB5, 0x92, 0xB5, 0x72, 0xAD, 0x10, 0xB5, 0x52, +0xBD, 0x72, 0xB5, 0x72, 0x7B, 0xCC, 0xCE, 0x15, +0x9C, 0xEF, 0x6C, 0x0A, 0x53, 0xA8, 0x43, 0x05, +0x32, 0x63, 0x3A, 0xC5, 0x74, 0x6C, 0x8D, 0x0F, +0xA5, 0x51, 0x94, 0xCF, 0xAD, 0x31, 0xA4, 0xAE, +0x94, 0x2D, 0xA4, 0xF1, 0xAD, 0x52, 0xB5, 0x53, +0xBD, 0x94, 0xB5, 0x74, 0xAD, 0x33, 0x7B, 0xED, +0x8C, 0x8F, 0x63, 0x6B, 0xA5, 0x53, 0xBD, 0xF5, +0xA5, 0x72, 0x7C, 0x8E, 0x63, 0xEC, 0x53, 0x48, +0x6B, 0xEA, 0x8C, 0xCE, 0xA5, 0x71, 0xAD, 0xD2, +0xA5, 0x90, 0x95, 0x0D, 0x84, 0xAB, 0xAD, 0xEF, +0x9D, 0x8D, 0x64, 0x07, 0x8D, 0x2B, 0x95, 0x2B, +0x7C, 0x8F, 0xCE, 0xD9, 0x84, 0x2F, 0x9D, 0x31, +0xB6, 0x53, 0xA5, 0xF1, 0x5B, 0xE7, 0x5B, 0xC6, +0x85, 0x0B, 0x4B, 0x63, 0x43, 0x03, 0x4A, 0xE6, +0x84, 0x2D, 0x94, 0x6D, 0x9D, 0x0E, 0x74, 0x48, +0x5B, 0xE5, 0x4B, 0x83, 0x7D, 0x09, 0x8D, 0x6A, +0x6C, 0x88, 0x11, 0x60, 0x21, 0xA3, 0x2A, 0x44, +0x3A, 0xC5, 0x2A, 0x23, 0x19, 0xA1, 0x6C, 0x49, +0xAE, 0x4F, 0x85, 0x29, 0x5C, 0x03, 0x74, 0x88, +0x95, 0x4C, 0x63, 0xC8, 0x74, 0x4A, 0x53, 0x67, +0x74, 0x6B, 0x53, 0x47, 0x21, 0x62, 0x19, 0x22, +0x11, 0x01, 0x53, 0x08, 0xA5, 0xAF, 0xBE, 0x91, +0x84, 0x8C, 0x7C, 0x2D, 0x95, 0x10, 0x74, 0x6C, +0x3A, 0x84, 0x22, 0x02, 0x74, 0x8B, 0x85, 0x4D, +0x6C, 0x89, 0x64, 0x66, 0x85, 0x4B, 0xA6, 0x30, +0xAE, 0x51, 0x7D, 0x0B, 0x6C, 0xA9, 0x85, 0x4B, +0x9D, 0xAD, 0x9D, 0xAC, 0x95, 0x6A, 0x7C, 0x68, +0x9D, 0xAF, 0xC7, 0x15, 0xAE, 0x51, 0x7C, 0xCA, +0x6C, 0xC8, 0x75, 0x08, 0x8D, 0x8A, 0xB6, 0x4E, +0x9D, 0x4D, 0x63, 0x4B, 0x8C, 0x71, 0xA5, 0x35, +0xA5, 0x14, 0x62, 0xCB, 0x62, 0xAB, 0x8B, 0xEF, +0xBD, 0x54, 0xAD, 0x33, 0x5A, 0xA9, 0x9C, 0xD2, +0x9C, 0xB2, 0xCE, 0x79, 0xDE, 0xDB, 0xB5, 0x96, +0x73, 0xD0, 0x52, 0xAA, 0x5A, 0xA9, 0x84, 0x0C, +0x4A, 0x46, 0x29, 0x64, 0x39, 0xA6, 0x39, 0xC6, +0x63, 0x0B, 0x7B, 0xAE, 0x5A, 0x8A, 0x18, 0xC3, +0x31, 0x65, 0x42, 0x08, 0x5A, 0xAA, 0x73, 0x6D, +0x52, 0x49, 0x39, 0xA7, 0x5A, 0xCB, 0x5A, 0xCB, +0x41, 0xC7, 0x52, 0x6A, 0x62, 0xCC, 0x7B, 0xD0, +0x84, 0x10, 0x83, 0xEF, 0x83, 0xEF, 0x7B, 0xCF, +0x73, 0x6E, 0x9C, 0xD3, 0xBD, 0xD7, 0xBE, 0x19, +0xB6, 0x3A, 0xB6, 0x1A, 0xAD, 0xFA, 0xAD, 0xB9, +0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, +0xA5, 0x97, 0xBE, 0x36, 0xC6, 0x73, 0x8C, 0xEB, +0xAD, 0xCC, 0xEF, 0xD2, 0xD6, 0xCE, 0xAD, 0xA8, +0xC6, 0x49, 0xD7, 0x0B, 0xC6, 0xA9, 0x95, 0x44, +0x95, 0x86, 0xBE, 0x8E, 0xA5, 0xB1, 0x95, 0x13, +0x95, 0x35, 0x95, 0x16, 0xB5, 0xB6, 0xEF, 0x79, +0xDE, 0xD6, 0x5A, 0xA9, 0x4A, 0x29, 0x4A, 0x09, +0x5A, 0xCB, 0x8C, 0x51, 0x7B, 0xEF, 0x52, 0xAA, +0x3A, 0x05, 0x9D, 0x6D, 0xB6, 0x4E, 0x8D, 0x6A, +0x64, 0x07, 0x42, 0xE7, 0x7C, 0xAE, 0x5B, 0xAB, +0x11, 0x62, 0x19, 0xA3, 0x32, 0x45, 0x19, 0xA3, +0x11, 0x62, 0x11, 0x22, 0x09, 0x01, 0x42, 0xE7, +0x64, 0x4A, 0x53, 0xC8, 0x2A, 0x43, 0x2A, 0x23, +0x19, 0xA2, 0x09, 0x21, 0x21, 0xA3, 0x42, 0xC8, +0x09, 0x21, 0x21, 0xC3, 0x2A, 0x24, 0x3A, 0x86, +0xBD, 0xB4, 0x8B, 0xCC, 0x83, 0x8A, 0x9C, 0x6E, +0x9C, 0x8E, 0x9C, 0x6E, 0x9C, 0x4E, 0x9C, 0x8E, +0xBD, 0xB3, 0xC5, 0xB3, 0xBD, 0x72, 0xAD, 0x31, +0xB5, 0x52, 0xAD, 0x11, 0xA4, 0xD0, 0xAD, 0x11, +0xAD, 0x11, 0xD6, 0x14, 0xCD, 0xB3, 0xC5, 0x72, +0xCD, 0xD3, 0xCD, 0xF4, 0xC5, 0xB3, 0xD5, 0xF4, +0xD5, 0xF4, 0xA4, 0x6D, 0xB4, 0xEF, 0xDE, 0x54, +0xDE, 0x54, 0xC5, 0x92, 0xC5, 0xB2, 0xD6, 0x34, +0xD6, 0x34, 0xD6, 0x34, 0xD6, 0x14, 0xE6, 0x96, +0xCD, 0xF3, 0xC5, 0x91, 0xC5, 0xB2, 0xD6, 0x34, +0x9C, 0x6E, 0xB5, 0x0F, 0xC5, 0xB2, 0xDE, 0x35, +0xE6, 0x75, 0xDE, 0x34, 0xCD, 0xF3, 0xCD, 0xD3, +0xAC, 0xEF, 0xA4, 0xAD, 0xAD, 0x2F, 0xB5, 0x50, +0xB5, 0x2F, 0xC5, 0xF3, 0xE7, 0x38, 0xD6, 0xD7, +0xB6, 0x33, 0xB5, 0xB1, 0xAD, 0x2F, 0xB5, 0x30, +0xB5, 0x2F, 0x94, 0xAC, 0x6B, 0xE8, 0x42, 0xA6, +0x7C, 0x8D, 0x95, 0x2F, 0x9D, 0x2F, 0x95, 0x4E, +0x74, 0x89, 0x95, 0x4C, 0xB6, 0x31, 0xB5, 0xD2, +0xB5, 0xB3, 0xD6, 0xB6, 0xCE, 0x92, 0xCE, 0x92, +0x94, 0xCB, 0x94, 0xAB, 0x94, 0x6B, 0x94, 0x2A, +0x94, 0x4B, 0x83, 0xEC, 0xA4, 0xD1, 0x6B, 0x4B, +0x6B, 0x0A, 0x83, 0xCC, 0x83, 0xED, 0x9C, 0xAF, +0xAD, 0x10, 0xA4, 0xD0, 0x8C, 0x2D, 0xA4, 0xD0, +0x9C, 0xD0, 0x94, 0x8F, 0x8C, 0x2E, 0xC6, 0x15, +0xBD, 0xD3, 0x8C, 0xED, 0x74, 0x6B, 0x74, 0x6B, +0x6C, 0x2A, 0x74, 0x4B, 0xA5, 0xD1, 0xAD, 0xF2, +0xA5, 0xB2, 0x95, 0x0F, 0xAD, 0x31, 0xAC, 0xF0, +0x8C, 0x2D, 0x9C, 0xAF, 0xAD, 0x32, 0xA4, 0xF1, +0xBD, 0xB4, 0xB5, 0x94, 0xAD, 0x73, 0x84, 0x4E, +0xCE, 0xB6, 0xB6, 0x13, 0x73, 0xCC, 0x42, 0x87, +0x42, 0xC6, 0x43, 0x07, 0x53, 0x48, 0x74, 0x2C, +0xDF, 0x16, 0xE7, 0x36, 0xC6, 0x74, 0x9D, 0x0F, +0x95, 0x0E, 0xA5, 0x6F, 0x63, 0x48, 0x7B, 0xEA, +0x7C, 0x6B, 0x95, 0x30, 0x95, 0x2E, 0x95, 0x4E, +0x84, 0x8F, 0xB5, 0xD6, 0x84, 0x50, 0x94, 0xD0, +0xC6, 0xB6, 0x7C, 0x8D, 0x6C, 0x08, 0x95, 0x6D, +0x53, 0xA6, 0x5B, 0xA7, 0x4A, 0xE6, 0xAD, 0x92, +0xB5, 0xB3, 0x84, 0x2D, 0x84, 0xAB, 0x53, 0x85, +0x3A, 0xE2, 0x5B, 0xE6, 0xA6, 0x0E, 0x95, 0xAB, +0x64, 0x27, 0x11, 0x41, 0x2A, 0x25, 0x19, 0x82, +0x42, 0xE6, 0x3A, 0xA5, 0x4B, 0x06, 0x19, 0x81, +0x64, 0x48, 0x6C, 0x86, 0x6C, 0x86, 0x9D, 0xCD, +0xA5, 0xEF, 0x4A, 0xE5, 0x5B, 0x68, 0x63, 0x88, +0x53, 0x27, 0x42, 0x44, 0x4A, 0x46, 0x5B, 0x08, +0x84, 0x8C, 0xAE, 0x10, 0xB6, 0x2F, 0xA5, 0xAE, +0x3A, 0x65, 0x73, 0xED, 0xA5, 0x73, 0x7C, 0x4E, +0x11, 0x62, 0x2A, 0x23, 0x74, 0xCC, 0x85, 0x4D, +0x85, 0x4C, 0x6C, 0xA9, 0x8D, 0x8D, 0x95, 0xEE, +0x6C, 0x69, 0x43, 0x43, 0x85, 0x6B, 0x95, 0xAD, +0x8D, 0x6C, 0x95, 0x8C, 0x8D, 0x2A, 0x95, 0x4B, +0x8D, 0x2C, 0xAE, 0x71, 0xAE, 0x71, 0x8D, 0x6D, +0x7D, 0x0A, 0x74, 0xE8, 0x8D, 0xAA, 0x8D, 0x69, +0x7C, 0xA7, 0x7C, 0xAC, 0x94, 0xF0, 0x94, 0xB1, +0x73, 0x6D, 0x52, 0x68, 0x94, 0x2E, 0x9C, 0x6E, +0xBD, 0x92, 0xC6, 0x12, 0xAD, 0x8F, 0xB5, 0xB1, +0xAD, 0x72, 0xBD, 0xD6, 0xB5, 0x96, 0xD6, 0xBB, +0xB5, 0x96, 0x63, 0x2C, 0x9C, 0xCF, 0xCE, 0x50, +0xAD, 0x2C, 0x42, 0x05, 0x42, 0x07, 0x42, 0x07, +0x73, 0x6C, 0x83, 0xAE, 0x73, 0x4C, 0x18, 0xA2, +0x29, 0x24, 0x4A, 0x28, 0x5A, 0xAB, 0x73, 0x4D, +0x73, 0x6E, 0x4A, 0x29, 0x52, 0x49, 0x6B, 0x0C, +0x5A, 0x8A, 0x7B, 0x8D, 0x73, 0x4D, 0x7B, 0xAE, +0x73, 0x6D, 0x94, 0x51, 0x83, 0xCF, 0x83, 0xEF, +0x9C, 0xD3, 0xB5, 0x76, 0xC6, 0x18, 0xC6, 0x5A, +0xCE, 0xDC, 0xCE, 0xFD, 0xCE, 0xFE, 0xCE, 0xDE, +0xCE, 0xDD, 0xCE, 0xFD, 0xCE, 0xDD, 0xC6, 0x9C, +0xCE, 0xB9, 0xDF, 0x36, 0xE7, 0x56, 0xBE, 0x10, +0xCE, 0x90, 0xCE, 0xAF, 0x8C, 0xC6, 0xA5, 0x89, +0xD6, 0xED, 0xE7, 0x6D, 0xD7, 0x2B, 0xAE, 0x28, +0xAE, 0x07, 0xB6, 0x6C, 0xC6, 0xD5, 0x9D, 0x74, +0xB6, 0x38, 0xBE, 0x5A, 0xC6, 0x59, 0xC5, 0xF6, +0x83, 0xED, 0x42, 0x07, 0x41, 0xE8, 0x41, 0xE7, +0x83, 0xEF, 0xAD, 0x34, 0x7B, 0xAE, 0x39, 0xE7, +0x63, 0xA9, 0x9D, 0x8C, 0xBE, 0x90, 0x8D, 0x6B, +0x4B, 0x65, 0x4B, 0x48, 0x6C, 0x2C, 0x3A, 0xA7, +0x19, 0xA3, 0x19, 0xA3, 0x2A, 0x04, 0x19, 0x63, +0x08, 0xE1, 0x08, 0xC1, 0x21, 0xC4, 0x32, 0x85, +0x3A, 0xC5, 0x53, 0xA8, 0x2A, 0x63, 0x22, 0x03, +0x11, 0x82, 0x11, 0x42, 0x11, 0x02, 0x11, 0x42, +0x21, 0xC4, 0x21, 0xC4, 0x19, 0xA3, 0x4B, 0x09, +0xBD, 0x93, 0x83, 0xCC, 0x83, 0xCB, 0xA4, 0xAF, +0x9C, 0x4E, 0x8B, 0xED, 0x8C, 0x0D, 0x94, 0x4E, +0x9C, 0xAF, 0x8C, 0x0D, 0xA4, 0xD0, 0xA4, 0xD0, +0xA4, 0xD0, 0x9C, 0x8F, 0x9C, 0xB0, 0x94, 0x6F, +0xAD, 0x11, 0xCD, 0xD4, 0xD5, 0xF4, 0xD5, 0xF4, +0xDE, 0x76, 0xE6, 0x96, 0xDE, 0x75, 0xDE, 0x55, +0xEE, 0x96, 0xBD, 0x10, 0xAC, 0xEF, 0xDE, 0x54, +0xD6, 0x34, 0xCE, 0x13, 0xD6, 0x14, 0xD6, 0x75, +0xD6, 0x55, 0xD6, 0x35, 0xD6, 0x34, 0xDE, 0x75, +0xD6, 0x34, 0xC5, 0xD3, 0xDE, 0x76, 0xE6, 0xB7, +0xB5, 0x31, 0xC5, 0xD3, 0xCE, 0x14, 0xCD, 0xF3, +0xD6, 0x14, 0xD6, 0x34, 0xD6, 0x14, 0xDE, 0x34, +0x9C, 0xAD, 0x84, 0x07, 0x7C, 0x47, 0x84, 0x68, +0x8C, 0x89, 0xA5, 0x6F, 0xCE, 0xF7, 0xAE, 0x14, +0x9D, 0xB1, 0xA5, 0x90, 0x9C, 0x8E, 0x9C, 0x8E, +0x9C, 0x8D, 0x7C, 0x29, 0x74, 0x49, 0x63, 0xC8, +0x74, 0x4B, 0x8C, 0xCD, 0xAD, 0xD0, 0x8C, 0xEB, +0x6C, 0x68, 0x7C, 0xA9, 0xBE, 0x71, 0xC6, 0x53, +0xC6, 0x34, 0xA5, 0x0F, 0x9C, 0xED, 0xB5, 0xCE, +0xC6, 0x70, 0xCE, 0x72, 0xB5, 0x90, 0xA4, 0xCE, +0xAD, 0x11, 0xA4, 0xF1, 0x63, 0x0A, 0x7B, 0xCD, +0x9C, 0xAF, 0x9C, 0x6E, 0x9C, 0x6E, 0x94, 0x4E, +0x9C, 0x4E, 0x9C, 0x6E, 0xA4, 0xAF, 0x94, 0x4E, +0x83, 0xEC, 0x83, 0xCC, 0x83, 0xCC, 0x83, 0xAC, +0x7B, 0x8A, 0x73, 0xAA, 0x63, 0xC9, 0x84, 0xED, +0x8D, 0x2E, 0x8D, 0x0E, 0x9D, 0x70, 0x8D, 0x0F, +0x7C, 0xAD, 0x8C, 0xCE, 0x9C, 0xCF, 0xA4, 0xEF, +0x9C, 0x8E, 0x83, 0xEC, 0x94, 0x6F, 0xA4, 0xF1, +0xAD, 0x73, 0x9C, 0xB0, 0x8C, 0x4F, 0x7C, 0x0D, +0xC6, 0x95, 0xCE, 0xF6, 0x95, 0x70, 0x4B, 0x28, +0x5B, 0xA9, 0x6C, 0x4C, 0x74, 0x6C, 0x7C, 0x6C, +0x84, 0x8D, 0x5B, 0x88, 0x42, 0xE5, 0x84, 0x6E, +0x94, 0xF0, 0xA5, 0x31, 0x7B, 0xEC, 0x6B, 0x6A, +0xA5, 0x53, 0xCE, 0xDB, 0xAD, 0xD6, 0xAD, 0xD4, +0x63, 0xAC, 0x6B, 0xCD, 0x6B, 0xAC, 0x6B, 0xAB, +0x6B, 0x8A, 0x6B, 0x8A, 0x6B, 0xEA, 0x84, 0xEB, +0x84, 0xCB, 0x32, 0x24, 0x5B, 0x09, 0xA5, 0x72, +0x84, 0x6D, 0x6B, 0xEA, 0x63, 0xE8, 0x53, 0xA5, +0x6C, 0x88, 0x6C, 0x87, 0x9D, 0xCD, 0x9D, 0xCD, +0x4B, 0x05, 0x11, 0x21, 0x19, 0xA2, 0x3A, 0x85, +0x4B, 0x66, 0x5B, 0xE8, 0x63, 0xE8, 0x19, 0x41, +0x74, 0xAA, 0x7D, 0x29, 0x95, 0xCD, 0xA6, 0x0F, +0x9D, 0xAE, 0x74, 0x29, 0x29, 0xA2, 0x52, 0xC7, +0x31, 0xE3, 0x4A, 0x45, 0x62, 0xE7, 0x63, 0x48, +0x63, 0xA8, 0xA5, 0xAE, 0xBE, 0x91, 0x6B, 0xC9, +0x21, 0x83, 0x63, 0x6C, 0xA5, 0x53, 0x84, 0x6F, +0x19, 0x82, 0x32, 0x84, 0x53, 0xA7, 0x6C, 0xAA, +0x7D, 0x0C, 0x9D, 0xF0, 0xA6, 0x30, 0x53, 0xC6, +0x32, 0xE3, 0x33, 0x02, 0x4B, 0xA6, 0x64, 0x28, +0x74, 0xAA, 0x85, 0x2B, 0x85, 0x0A, 0x7C, 0xC9, +0x64, 0x27, 0x85, 0x2C, 0xBE, 0xD3, 0xA6, 0x30, +0x95, 0xAE, 0x8D, 0x8C, 0x8D, 0x6A, 0x74, 0xA6, +0x64, 0x45, 0x64, 0x06, 0x7C, 0x4A, 0x9C, 0xCE, +0x6B, 0x09, 0x94, 0x8D, 0x94, 0x8B, 0x94, 0x8B, +0x8C, 0x6A, 0x7C, 0x28, 0xA5, 0x6E, 0x84, 0x4B, +0x8C, 0x8E, 0x9D, 0x11, 0xBD, 0xD6, 0xCE, 0x79, +0xC6, 0x18, 0xC5, 0xF7, 0xC6, 0x14, 0xCE, 0x31, +0xBD, 0xAD, 0x7B, 0xC9, 0x8C, 0x2D, 0x52, 0x48, +0x62, 0xEB, 0x94, 0x70, 0x6B, 0x0B, 0x18, 0xA2, +0x29, 0x24, 0x5A, 0x8A, 0x7B, 0x8E, 0x73, 0x6E, +0x73, 0x6E, 0x6B, 0x2D, 0x52, 0x49, 0x5A, 0xCB, +0x73, 0x4D, 0xAC, 0xF3, 0x94, 0x50, 0x62, 0xEB, +0x5A, 0x8A, 0x73, 0x6D, 0x83, 0xF0, 0x84, 0x10, +0x94, 0x92, 0xAD, 0x55, 0xBD, 0xD6, 0xAD, 0x55, +0xAD, 0x96, 0xB5, 0xF7, 0xBE, 0x7A, 0xBE, 0x5B, +0xBE, 0x5C, 0xBE, 0x5C, 0xBE, 0x7B, 0xCE, 0xDA, +0xBE, 0x55, 0xE7, 0x56, 0xE7, 0x54, 0xD6, 0xF2, +0xCE, 0xB0, 0xB5, 0xEC, 0x8C, 0xE7, 0xB6, 0x2E, +0xCF, 0x10, 0xD6, 0xED, 0xDF, 0x2C, 0xBE, 0x68, +0xB6, 0x47, 0xB6, 0x6C, 0xBE, 0xD5, 0xC6, 0xB9, +0xB6, 0x18, 0xCE, 0xDB, 0xCE, 0xDB, 0xCE, 0x99, +0xA5, 0x34, 0x63, 0x4C, 0x31, 0xA6, 0x5A, 0xCB, +0x9C, 0x91, 0xB5, 0x54, 0x7B, 0xCF, 0x31, 0xA5, +0x74, 0x6A, 0x8D, 0x6B, 0xBE, 0xB2, 0xA6, 0x10, +0x4B, 0x45, 0x32, 0x64, 0x2A, 0x04, 0x42, 0xC7, +0x3A, 0x86, 0x21, 0xE3, 0x2A, 0x05, 0x11, 0x62, +0x11, 0x42, 0x11, 0x22, 0x32, 0x45, 0x2A, 0x44, +0x2A, 0x84, 0x53, 0xE8, 0x2A, 0xA4, 0x11, 0x81, +0x11, 0x42, 0x11, 0x43, 0x19, 0x83, 0x19, 0x83, +0x21, 0xE4, 0x19, 0x83, 0x19, 0xA4, 0x4B, 0x09, +0xC5, 0xB4, 0x8B, 0xEC, 0x83, 0xCB, 0x9C, 0x4D, +0x9C, 0x6E, 0xA4, 0xD0, 0x9C, 0x8F, 0x9C, 0x8F, +0x9C, 0x8F, 0x5A, 0x88, 0x94, 0x6F, 0x9C, 0xB0, +0xA4, 0xB0, 0xA4, 0xB0, 0x9C, 0x8F, 0xA4, 0xD0, +0xAD, 0x11, 0xBD, 0x72, 0xB5, 0x31, 0xA4, 0xAF, +0xC5, 0x92, 0xCD, 0xD3, 0xCD, 0xB3, 0xCD, 0x92, +0xE6, 0x55, 0xC5, 0x72, 0xB5, 0x10, 0xDE, 0x55, +0xD6, 0x34, 0xD6, 0x55, 0xD6, 0x35, 0xD6, 0x75, +0xCE, 0x35, 0xB5, 0x52, 0xC5, 0xF4, 0xDE, 0x76, +0xD6, 0x55, 0xD6, 0x75, 0xDE, 0xB7, 0xE6, 0xD7, +0xC5, 0xD4, 0xB5, 0x52, 0xC5, 0xD3, 0xDE, 0x55, +0xDE, 0x54, 0xDE, 0x74, 0xD6, 0x54, 0xDE, 0x55, +0x9C, 0x8C, 0x94, 0xAA, 0x8C, 0xCA, 0x7C, 0xA8, +0x7C, 0x87, 0x74, 0x88, 0x7C, 0xCC, 0x95, 0x90, +0xA5, 0xD1, 0x8C, 0x8D, 0x83, 0xEB, 0x83, 0xEB, +0x73, 0xC9, 0x9D, 0x2E, 0x7C, 0x8B, 0x74, 0x2A, +0x95, 0x2E, 0x7C, 0x6A, 0x74, 0x68, 0x74, 0xA8, +0x7C, 0xC8, 0x7C, 0xA8, 0xA5, 0xEE, 0xC6, 0x73, +0x8C, 0x4D, 0x94, 0x4C, 0x94, 0x6C, 0xA4, 0xEC, +0xAD, 0x4C, 0xA5, 0x2D, 0x94, 0x6D, 0x94, 0x4E, +0xBD, 0x94, 0x6B, 0x2B, 0x73, 0x8C, 0x84, 0x0E, +0x62, 0xEA, 0x6B, 0x2A, 0x8B, 0xED, 0x62, 0xC9, +0x5A, 0x88, 0x7B, 0x6B, 0x9C, 0x8F, 0x8B, 0xEC, +0xA4, 0xCF, 0x9C, 0x6E, 0x9C, 0x8E, 0xB5, 0x71, +0xA4, 0xCF, 0xAD, 0x30, 0x63, 0xA9, 0x7C, 0xAC, +0x84, 0xCD, 0x95, 0x6F, 0x84, 0xED, 0x84, 0xCD, +0x8D, 0x2E, 0x94, 0xEE, 0x9C, 0xED, 0x9D, 0x0C, +0xA5, 0x2D, 0xA5, 0x2E, 0x9C, 0xEE, 0x94, 0x8E, +0x8C, 0x4D, 0x83, 0xEC, 0x83, 0xEC, 0x94, 0xAF, +0xA5, 0xB2, 0x9D, 0x90, 0xA5, 0xD0, 0x9D, 0xB0, +0x84, 0xEE, 0x8D, 0x2F, 0x7C, 0xAD, 0x4B, 0x47, +0x43, 0x06, 0x3B, 0x06, 0x43, 0x06, 0x84, 0xAE, +0x95, 0x10, 0x8C, 0x6E, 0x73, 0xCC, 0x6B, 0x6A, +0xAD, 0xD5, 0xC6, 0x79, 0xB6, 0x18, 0xAD, 0xF5, +0x7C, 0xAD, 0x84, 0xEC, 0x7C, 0xAB, 0x84, 0xCC, +0x9D, 0x2D, 0xB6, 0x31, 0xAD, 0xF0, 0x6C, 0x48, +0x64, 0x07, 0x4B, 0x26, 0x74, 0x6B, 0x8C, 0xED, +0x85, 0x0D, 0x6C, 0x4A, 0x5B, 0xE7, 0x8D, 0x8C, +0x7D, 0x09, 0x5C, 0x45, 0x4B, 0xA3, 0x53, 0xE5, +0x5B, 0xE8, 0x3A, 0xA4, 0x32, 0x23, 0x4B, 0x26, +0x32, 0xA3, 0x6C, 0x69, 0x2A, 0x23, 0x21, 0xA2, +0x85, 0x0C, 0xAE, 0x70, 0xAE, 0x70, 0xAE, 0x50, +0xA6, 0x0F, 0x7C, 0xCA, 0x4A, 0xC5, 0x63, 0x28, +0x5B, 0x27, 0x52, 0x86, 0x39, 0xA3, 0x42, 0x25, +0x42, 0x45, 0x32, 0x44, 0x4A, 0xE6, 0x32, 0x44, +0x29, 0xE4, 0x32, 0x06, 0x4A, 0xA8, 0x42, 0xA8, +0x32, 0x85, 0x3A, 0xE5, 0x4B, 0xA7, 0x7D, 0x0C, +0x9E, 0x30, 0x9E, 0x10, 0x6C, 0x6A, 0x2A, 0x82, +0x22, 0x41, 0x22, 0x41, 0x22, 0x42, 0x32, 0xC3, +0x43, 0x66, 0x53, 0xC7, 0x64, 0x47, 0x43, 0x64, +0x53, 0xE6, 0x85, 0x4C, 0x9D, 0xEF, 0x7C, 0xEC, +0xA6, 0x51, 0x8D, 0x6E, 0x74, 0xEB, 0x5C, 0x06, +0x5C, 0x27, 0x63, 0xE8, 0x4A, 0xA4, 0x83, 0xEA, +0x9C, 0xCC, 0xA5, 0x4D, 0x8C, 0x49, 0x5B, 0x06, +0x52, 0xA6, 0x5A, 0xC7, 0xA4, 0xAF, 0x94, 0x6F, +0x62, 0xEA, 0x83, 0xEE, 0x83, 0xEF, 0x8C, 0x51, +0xA5, 0x14, 0xDE, 0xFB, 0xC5, 0xF6, 0xA4, 0xF0, +0xB5, 0x6F, 0x94, 0xAD, 0xAD, 0x30, 0x6B, 0x0A, +0x4A, 0x27, 0x73, 0x6C, 0x29, 0x44, 0x18, 0xA2, +0x29, 0x24, 0x5A, 0xAA, 0x8C, 0x30, 0x73, 0x6E, +0x84, 0x10, 0x84, 0x10, 0x6B, 0x0C, 0x52, 0x6A, +0x62, 0xCB, 0x7B, 0xAE, 0xB5, 0x75, 0x7B, 0x8E, +0x73, 0x6D, 0x9C, 0xB3, 0x9C, 0xD3, 0x94, 0x72, +0x8C, 0x31, 0x7B, 0xEF, 0xA5, 0x34, 0x8C, 0x72, +0x84, 0x10, 0x8C, 0x71, 0xB5, 0xD7, 0xBE, 0x19, +0xB5, 0xFA, 0xAD, 0xD8, 0xD6, 0xD9, 0xE7, 0x37, +0xE7, 0x54, 0xCE, 0x8F, 0xD6, 0xCF, 0xD6, 0xF0, +0xCE, 0x8F, 0xC6, 0x4D, 0xB6, 0x2D, 0xC6, 0xD1, +0xB6, 0x6E, 0xAE, 0x09, 0xCE, 0xEA, 0xB6, 0x25, +0xAE, 0x26, 0xAE, 0x4C, 0xAE, 0x32, 0xBE, 0x56, +0xBE, 0x57, 0xD7, 0x19, 0xE7, 0x79, 0xD6, 0xD7, +0xC6, 0x76, 0xB6, 0x34, 0x8C, 0xB0, 0x9C, 0xD3, +0xC5, 0xD6, 0xB5, 0x75, 0x7B, 0xAE, 0x31, 0xE5, +0x7C, 0xCA, 0x7D, 0x07, 0x95, 0x8B, 0x9D, 0xEE, +0x6C, 0x69, 0x19, 0xC2, 0x11, 0x62, 0x21, 0xC4, +0x3A, 0xA7, 0x3A, 0x86, 0x2A, 0x25, 0x19, 0xA3, +0x21, 0xE4, 0x21, 0xC3, 0x32, 0x45, 0x2A, 0x23, +0x32, 0xA4, 0x43, 0x66, 0x32, 0xC4, 0x11, 0x41, +0x11, 0x42, 0x11, 0x62, 0x19, 0xA3, 0x19, 0x83, +0x11, 0x42, 0x11, 0x42, 0x2A, 0x46, 0x4B, 0x29, +0xC5, 0xB3, 0x8B, 0xEC, 0x83, 0xCC, 0x9C, 0x6E, +0x8C, 0x0D, 0x8C, 0x0D, 0x84, 0x0D, 0x94, 0x2E, +0x94, 0x4E, 0x62, 0xE9, 0x83, 0xAC, 0x94, 0x6F, +0x94, 0x6F, 0x94, 0x4E, 0x94, 0x2E, 0x9C, 0x8F, +0xAC, 0xF1, 0xAD, 0x11, 0xBD, 0x52, 0xBD, 0x72, +0xBD, 0x72, 0xC5, 0xB3, 0xC5, 0xB3, 0xCD, 0xB3, +0xDE, 0x55, 0xC5, 0x92, 0xA4, 0xCF, 0xD6, 0x34, +0xCD, 0xF3, 0xC5, 0xF3, 0xCE, 0x34, 0xD6, 0x55, +0xBD, 0xD4, 0x94, 0x90, 0xAD, 0x52, 0xD6, 0x76, +0xDE, 0x96, 0xDE, 0xB7, 0xBD, 0xB3, 0xD6, 0x76, +0xD6, 0x55, 0xC5, 0xD3, 0xCE, 0x14, 0xDE, 0x55, +0xD6, 0x34, 0xD6, 0x54, 0xD6, 0x34, 0xD6, 0x34, +0x9C, 0x8D, 0xA5, 0x0D, 0xA5, 0x4E, 0x84, 0x8A, +0x84, 0xAA, 0x7C, 0x69, 0x53, 0x66, 0x6C, 0x2A, +0xA5, 0xB0, 0x9C, 0xEF, 0x94, 0x6E, 0x94, 0x6D, +0x7C, 0x2A, 0xA5, 0x4F, 0x9D, 0x2F, 0xA5, 0x90, +0x84, 0xAC, 0x4B, 0x44, 0x5C, 0x04, 0x53, 0xE3, +0x6C, 0x87, 0x85, 0x09, 0x8D, 0x2C, 0xCE, 0xB5, +0x7B, 0xCA, 0x9C, 0x6D, 0xA4, 0xEF, 0x9C, 0xAE, +0x94, 0x4D, 0x94, 0x6E, 0x8C, 0x0E, 0xB5, 0x94, +0x7B, 0xAD, 0x73, 0x6C, 0x9C, 0xB1, 0x7B, 0xCD, +0x52, 0x88, 0x7B, 0xAD, 0xA4, 0xD0, 0x9C, 0xB0, +0x83, 0xCC, 0x73, 0x8B, 0x73, 0x4A, 0x6A, 0xE9, +0x5A, 0x88, 0x73, 0xAA, 0x8C, 0xAD, 0xB5, 0xD2, +0xAD, 0x92, 0xA5, 0x30, 0x63, 0x89, 0x74, 0x2B, +0x8D, 0x0E, 0x8D, 0x2E, 0x85, 0x0D, 0x85, 0x0D, +0x6B, 0xEA, 0x63, 0x68, 0x84, 0x8A, 0x84, 0xA9, +0x84, 0xA9, 0x95, 0x2C, 0x9D, 0x6E, 0xAD, 0x90, +0xAD, 0x91, 0x8C, 0x2D, 0x83, 0xEC, 0xC6, 0x35, +0xAD, 0xF3, 0x7C, 0xCC, 0x85, 0x0C, 0x8D, 0x2E, +0x95, 0x6F, 0x7C, 0xAC, 0x5B, 0xE9, 0x42, 0xE6, +0x4B, 0x26, 0x4B, 0x67, 0x53, 0xA8, 0x4B, 0x69, +0x84, 0xCF, 0xA5, 0xB2, 0x9D, 0x30, 0x9D, 0x10, +0x7C, 0x0E, 0x94, 0xF3, 0x9D, 0x54, 0x95, 0x70, +0x84, 0xEA, 0x64, 0x26, 0x5C, 0x06, 0x7D, 0x0A, +0x6C, 0x88, 0x64, 0x47, 0x4B, 0x84, 0x32, 0xE2, +0x3A, 0xE2, 0x6C, 0x48, 0x7C, 0xAB, 0x9D, 0xD0, +0xA6, 0x31, 0x9D, 0xD0, 0x9D, 0xCF, 0x9D, 0xEE, +0x85, 0x6B, 0x74, 0xE8, 0x64, 0x87, 0x74, 0xC9, +0xA6, 0x2F, 0x5C, 0x07, 0x43, 0x24, 0x43, 0x04, +0x5B, 0xE7, 0x6C, 0x49, 0x19, 0x61, 0x19, 0xA2, +0x95, 0x8F, 0xAE, 0x50, 0xAE, 0x51, 0xAE, 0x50, +0xAE, 0x71, 0x8D, 0x4C, 0x53, 0x05, 0x42, 0x85, +0x6B, 0xA9, 0x29, 0x62, 0x4A, 0x46, 0x6B, 0x69, +0x5B, 0x27, 0x3A, 0x85, 0x2A, 0x04, 0x2A, 0x04, +0x32, 0x45, 0x21, 0xC4, 0x19, 0x83, 0x3A, 0x86, +0x4B, 0x87, 0x53, 0xC7, 0x6C, 0xAA, 0x9D, 0xF0, +0x74, 0xAC, 0x3A, 0xC5, 0x2A, 0x83, 0x2A, 0x63, +0x22, 0x42, 0x22, 0x42, 0x32, 0xA3, 0x3A, 0xE4, +0x43, 0x46, 0x53, 0xE7, 0x7C, 0xEA, 0x53, 0xC5, +0x3B, 0x03, 0x3B, 0x24, 0x4B, 0x86, 0x3A, 0xC5, +0x9D, 0xF1, 0x9D, 0xF0, 0x8D, 0x6E, 0x8D, 0x4D, +0x6C, 0x49, 0x9D, 0x6E, 0x6B, 0xA8, 0x9D, 0x2D, +0x95, 0x0C, 0xB6, 0x10, 0xC6, 0x72, 0xAD, 0xB1, +0x5A, 0xC9, 0x62, 0x89, 0x6A, 0xC9, 0xA4, 0x91, +0x9C, 0x50, 0x5A, 0xCA, 0x83, 0xEF, 0x63, 0x2C, +0x94, 0x72, 0xC6, 0x38, 0xD6, 0x79, 0xB5, 0x75, +0xBD, 0xB6, 0xBD, 0xD6, 0xAD, 0x73, 0x6B, 0x2B, +0x6B, 0x2B, 0x62, 0xEB, 0x20, 0xE3, 0x39, 0xC7, +0x18, 0xC2, 0x4A, 0x48, 0x7B, 0xAE, 0x7B, 0xAE, +0x8C, 0x30, 0x94, 0x51, 0x83, 0xF0, 0x73, 0x4D, +0x6B, 0x4D, 0x42, 0x08, 0xA4, 0xF3, 0x8C, 0x30, +0x8C, 0x30, 0xAD, 0x55, 0xA4, 0xD4, 0x9C, 0xD3, +0x9C, 0x93, 0x6B, 0x4D, 0x7B, 0xF0, 0x9C, 0xB3, +0x94, 0x72, 0x94, 0x92, 0xA5, 0x14, 0xC6, 0x38, +0xB5, 0xD6, 0xDF, 0x18, 0xF7, 0x96, 0xEF, 0x32, +0xEF, 0x72, 0xDF, 0x0E, 0xD6, 0xAD, 0xEF, 0x71, +0xAD, 0x6B, 0xD6, 0xEE, 0xB6, 0x4D, 0xBE, 0xB1, +0xC6, 0xD0, 0xA5, 0xE8, 0xAE, 0x05, 0xA6, 0x04, +0x8D, 0x23, 0x95, 0x88, 0x95, 0x6D, 0xB6, 0x54, +0xBE, 0x96, 0xC6, 0x75, 0xD6, 0xD5, 0xE7, 0x97, +0xE7, 0x77, 0xB6, 0x32, 0xAD, 0xD4, 0xB5, 0xB6, +0xBD, 0xB6, 0xA5, 0x13, 0x63, 0x0C, 0x5B, 0x29, +0x95, 0x6D, 0x8D, 0x8A, 0x85, 0x27, 0x85, 0x49, +0x6C, 0x68, 0x19, 0xE2, 0x11, 0x82, 0x11, 0x62, +0x3A, 0xA7, 0x4B, 0x08, 0x32, 0x45, 0x19, 0xC3, +0x22, 0x04, 0x2A, 0x24, 0x21, 0xE3, 0x32, 0x64, +0x32, 0x84, 0x3B, 0x25, 0x22, 0x23, 0x11, 0x41, +0x11, 0x42, 0x11, 0x42, 0x21, 0xC4, 0x19, 0xA3, +0x11, 0x62, 0x21, 0xC4, 0x32, 0x66, 0x42, 0xE8, +0x9C, 0x6E, 0x83, 0x8A, 0x83, 0xAB, 0x7B, 0x8A, +0x6B, 0x29, 0x73, 0x4A, 0x8C, 0x2D, 0xAC, 0xF0, +0xBD, 0x52, 0xAC, 0xF0, 0xAC, 0xD0, 0xAC, 0xF1, +0xB5, 0x11, 0xAC, 0xF1, 0xA4, 0xAF, 0x94, 0x2E, +0xA4, 0xAF, 0xAC, 0xF0, 0xA4, 0xAF, 0x9C, 0x6E, +0xA4, 0xB0, 0xAC, 0xD0, 0xBD, 0x51, 0xC5, 0xB2, +0xE6, 0x76, 0xC5, 0x92, 0xAD, 0x10, 0xCD, 0xF3, +0xCD, 0xF3, 0xC5, 0xD3, 0xC5, 0xF3, 0xC5, 0xF4, +0xAD, 0x52, 0xA5, 0x12, 0xAD, 0x52, 0xC6, 0x15, +0xD6, 0x55, 0xDE, 0xB7, 0xDE, 0x96, 0xD6, 0x55, +0xDE, 0x96, 0xDE, 0x76, 0xCE, 0x34, 0xD6, 0x34, +0xCD, 0xF4, 0xC5, 0xD3, 0xBD, 0xB2, 0xC5, 0xD3, +0xA4, 0xAE, 0xA4, 0xEE, 0xA4, 0xEE, 0x9C, 0xEE, +0xA5, 0x0E, 0x9C, 0xEE, 0x6B, 0xA9, 0x4B, 0x06, +0x74, 0x2B, 0xB5, 0xB2, 0xB5, 0x31, 0xBD, 0x92, +0x9C, 0xEF, 0xBD, 0xF2, 0x9D, 0x0F, 0x6C, 0x2A, +0x43, 0x04, 0x43, 0x23, 0x4B, 0xA3, 0x53, 0xA4, +0x5B, 0xE6, 0x95, 0x4D, 0x84, 0x4C, 0xC6, 0x35, +0x6B, 0x29, 0xAD, 0x10, 0xAD, 0x10, 0x7B, 0xAB, +0x8C, 0x0D, 0x9C, 0xB0, 0xAD, 0x33, 0x84, 0x0E, +0x63, 0x0A, 0x94, 0x90, 0x94, 0x90, 0x62, 0xEA, +0x4A, 0x68, 0x5A, 0xC9, 0x94, 0x6F, 0xA5, 0x11, +0xAD, 0x51, 0x94, 0xAE, 0x94, 0x6E, 0x6B, 0x2A, +0x31, 0xA5, 0x5B, 0x49, 0x9D, 0x70, 0x84, 0xEF, +0x9D, 0x92, 0x94, 0xF0, 0x63, 0x69, 0x6B, 0x8A, +0x74, 0x2C, 0x63, 0xC9, 0x84, 0xED, 0x7C, 0xCC, +0x7C, 0x4B, 0x84, 0x8B, 0x7C, 0xA9, 0x84, 0xC8, +0x7C, 0xC8, 0x84, 0xEA, 0x95, 0x6D, 0xA5, 0xAF, +0xBE, 0x12, 0x5A, 0xE8, 0x84, 0x0E, 0xCE, 0xB7, +0xC6, 0xB5, 0x74, 0x49, 0x7C, 0xAA, 0x95, 0x2D, +0xBE, 0x73, 0x9D, 0x8E, 0x6C, 0x4A, 0x64, 0x2B, +0x64, 0x2B, 0x64, 0x2B, 0x85, 0x0D, 0x7C, 0xCE, +0x84, 0xEE, 0x8D, 0x2F, 0xA5, 0xB2, 0xAD, 0xD3, +0x84, 0x6F, 0x95, 0x12, 0xB6, 0x34, 0x85, 0x0B, +0x5B, 0xE4, 0x5B, 0xE5, 0x74, 0xE8, 0x64, 0x46, +0x4B, 0xA3, 0x43, 0x63, 0x32, 0xE2, 0x5C, 0x27, +0x53, 0xE5, 0x85, 0x2B, 0x8D, 0x4D, 0x9D, 0xF0, +0xA6, 0x11, 0xA6, 0x11, 0xA6, 0x31, 0x7C, 0xEA, +0x7D, 0x2A, 0x74, 0xE9, 0x74, 0xC9, 0x9D, 0xCE, +0x95, 0xAE, 0x74, 0xAA, 0x7D, 0x0B, 0x64, 0x28, +0x85, 0x4C, 0x64, 0x09, 0x19, 0x61, 0x21, 0xA3, +0x42, 0xE6, 0x3A, 0xA4, 0x42, 0xE5, 0x6C, 0x2A, +0xA6, 0x0F, 0x9D, 0xCE, 0x63, 0xE7, 0x4B, 0x25, +0x84, 0xCB, 0x42, 0xC5, 0x31, 0xE3, 0x4A, 0xC6, +0x29, 0xC2, 0x42, 0xA6, 0x32, 0x44, 0x2A, 0x04, +0x3A, 0xA7, 0x32, 0x66, 0x32, 0x45, 0x43, 0x07, +0x53, 0xA8, 0x2A, 0x63, 0x43, 0x05, 0x32, 0x85, +0x2A, 0x24, 0x3A, 0xA5, 0x22, 0x42, 0x22, 0x22, +0x22, 0x22, 0x2A, 0x83, 0x43, 0x25, 0x4B, 0xA6, +0x64, 0x69, 0x74, 0xCA, 0xAE, 0x50, 0x64, 0x47, +0x43, 0x44, 0x2A, 0xA2, 0x2A, 0x62, 0x2A, 0x43, +0x7C, 0xED, 0xAE, 0x93, 0x9D, 0xF1, 0xAE, 0x52, +0x84, 0xED, 0x7C, 0xAB, 0x95, 0x4D, 0x95, 0x6D, +0x95, 0x8E, 0xC7, 0x15, 0xA5, 0xD0, 0x8C, 0xCD, +0x73, 0x6B, 0x5A, 0x48, 0x49, 0xE7, 0x8B, 0xAE, +0xAC, 0xB1, 0x83, 0xAE, 0x5A, 0x8A, 0x52, 0x8A, +0x7B, 0xCE, 0x73, 0x8E, 0x9C, 0xD3, 0xD6, 0x99, +0xD6, 0xBA, 0xBD, 0xD7, 0x84, 0x0F, 0x4A, 0x68, +0x73, 0x6D, 0x6B, 0x0B, 0x29, 0x24, 0x29, 0x45, +0x10, 0x82, 0x31, 0x65, 0x62, 0xCA, 0x7B, 0xAE, +0x94, 0x72, 0xA4, 0xD3, 0xA4, 0xD3, 0x7B, 0xAE, +0x73, 0x4D, 0x73, 0x6D, 0x52, 0x6A, 0x9C, 0x92, +0x7B, 0xAE, 0x8C, 0x51, 0xA5, 0x14, 0x94, 0x72, +0x8C, 0x31, 0x84, 0x10, 0x94, 0x72, 0xAD, 0x55, +0xBD, 0x97, 0xC5, 0xF8, 0xAD, 0x55, 0xAD, 0x55, +0xAD, 0x74, 0xDE, 0xF5, 0xE7, 0x33, 0xEF, 0x72, +0xDF, 0x0F, 0xCE, 0x8C, 0xDF, 0x0E, 0xEF, 0x71, +0x8C, 0xA7, 0xC6, 0xAD, 0xAE, 0x2B, 0xBE, 0xB0, +0xAE, 0x4D, 0x9D, 0xC6, 0x9D, 0xA3, 0xAE, 0x46, +0xA5, 0xE8, 0xA6, 0x0B, 0xB6, 0x8F, 0xB6, 0x93, +0xAD, 0xF2, 0xCE, 0xF7, 0xC6, 0xB5, 0xB6, 0x51, +0xD6, 0xF2, 0xBE, 0x71, 0xA5, 0x92, 0xC6, 0x38, +0xBD, 0xB6, 0x8C, 0x71, 0x4A, 0x49, 0x74, 0x2D, +0xAE, 0x51, 0x9D, 0xED, 0x85, 0x27, 0x8D, 0xAA, +0x7D, 0x2A, 0x43, 0x24, 0x19, 0xC1, 0x11, 0x62, +0x42, 0xC7, 0x5B, 0xCA, 0x32, 0x66, 0x11, 0x21, +0x19, 0xC3, 0x19, 0xA3, 0x11, 0x41, 0x32, 0xA5, +0x22, 0x43, 0x32, 0xC4, 0x11, 0x61, 0x11, 0x22, +0x09, 0x22, 0x11, 0x22, 0x22, 0x04, 0x21, 0xE3, +0x19, 0xA3, 0x2A, 0x25, 0x3A, 0xA7, 0x53, 0x6A, +0x8B, 0xAB, 0x8B, 0xEC, 0x8B, 0xEC, 0x8B, 0xEC, +0x8C, 0x0C, 0x8B, 0xEC, 0x8B, 0xCC, 0x8B, 0xCB, +0x8B, 0xCC, 0x8B, 0xCC, 0x83, 0x8A, 0x7B, 0x6A, +0x7B, 0x6A, 0x7B, 0x6A, 0x83, 0xAB, 0x7B, 0x6A, +0x83, 0x8B, 0x8B, 0xCB, 0x8B, 0xEC, 0x8B, 0xCC, +0x83, 0xAB, 0x9C, 0x4D, 0xB5, 0x10, 0xCD, 0xD3, +0xD5, 0xF3, 0xBD, 0x30, 0xAC, 0xAE, 0xB5, 0x50, +0xC5, 0xB2, 0xC5, 0xD3, 0xC5, 0xF4, 0xBD, 0xB3, +0xAD, 0x32, 0xAD, 0x53, 0xAD, 0x52, 0xB5, 0x93, +0xBD, 0xD3, 0xD6, 0x55, 0xDE, 0xD7, 0xDE, 0xB7, +0xDE, 0x96, 0xD6, 0x55, 0xC5, 0xF3, 0xBD, 0xB3, +0xBD, 0x93, 0xB5, 0x72, 0xAD, 0x31, 0xAD, 0x31, +0xA4, 0xCF, 0xA4, 0xCE, 0xA4, 0xEF, 0xAD, 0x10, +0xA4, 0xCF, 0xAD, 0x30, 0x84, 0x0B, 0x3A, 0xA4, +0x3A, 0x84, 0x94, 0xCF, 0xBD, 0xB3, 0xBD, 0x72, +0xBD, 0xB3, 0xC5, 0xF3, 0xAD, 0x71, 0x42, 0xA4, +0x3A, 0xC3, 0x43, 0x23, 0x4B, 0x85, 0x5B, 0xA7, +0x9D, 0x2F, 0xBD, 0xF3, 0x83, 0xEC, 0xAD, 0x52, +0x5A, 0xA8, 0xAD, 0x10, 0xA4, 0xAE, 0x8C, 0x0D, +0x9C, 0xB0, 0x9C, 0xB0, 0xA4, 0xD1, 0x5A, 0xA9, +0x8C, 0x4F, 0x9C, 0xD1, 0x8C, 0x2F, 0x5A, 0xEA, +0xA5, 0x32, 0xA5, 0x71, 0x94, 0xAE, 0x94, 0xAE, +0xAD, 0xB1, 0xAD, 0x90, 0x94, 0x8E, 0x6B, 0x0A, +0x31, 0xA6, 0x3A, 0x26, 0x9D, 0x91, 0x7C, 0x8D, +0x6C, 0x6C, 0x5B, 0x89, 0x74, 0x0C, 0x5B, 0x29, +0x7C, 0x4D, 0x6B, 0xEB, 0x7C, 0x8B, 0x74, 0x69, +0x7C, 0x89, 0x7C, 0xA9, 0x7C, 0x69, 0x7C, 0x88, +0x7C, 0xA8, 0x84, 0xEA, 0x9D, 0x8E, 0xCE, 0xF5, +0xD7, 0x16, 0xBD, 0xF4, 0xAD, 0x73, 0x8C, 0xCF, +0x63, 0xA9, 0x74, 0x49, 0x95, 0x0C, 0xA5, 0x4E, +0xB5, 0xB1, 0x8D, 0x0D, 0x7C, 0xCC, 0x74, 0x8D, +0x7C, 0xCE, 0x74, 0x6C, 0x64, 0x2A, 0x6C, 0x6B, +0x74, 0x8C, 0x7C, 0xAD, 0x8D, 0x2F, 0x7C, 0xAD, +0x74, 0x0C, 0x95, 0x4F, 0x8D, 0x4C, 0x5C, 0x05, +0x5C, 0x25, 0x7D, 0x09, 0x53, 0xE4, 0x53, 0xC4, +0x64, 0x27, 0x74, 0x8B, 0x63, 0xC8, 0x6C, 0xA8, +0x4B, 0xA4, 0x64, 0x27, 0x74, 0xCA, 0x85, 0x2C, +0x95, 0x8F, 0x9D, 0xF0, 0x95, 0x8E, 0x7D, 0x0A, +0x7D, 0x2A, 0x7D, 0x0A, 0x8D, 0x8D, 0xAE, 0x31, +0x95, 0xAF, 0x8D, 0x6D, 0xAE, 0x71, 0x7C, 0xCA, +0x8D, 0x8D, 0x5B, 0xA8, 0x19, 0x62, 0x19, 0xA3, +0x21, 0xC3, 0x32, 0x44, 0x32, 0x24, 0x2A, 0x03, +0x53, 0x67, 0x7C, 0xCA, 0x5B, 0xE6, 0x4B, 0x64, +0x5C, 0x07, 0x42, 0xE4, 0x53, 0x66, 0x64, 0x08, +0x4B, 0x25, 0x4B, 0x26, 0x32, 0x64, 0x2A, 0x24, +0x3A, 0xC7, 0x42, 0xC7, 0x42, 0xE7, 0x43, 0x06, +0x32, 0x64, 0x2A, 0x23, 0x3A, 0xC5, 0x43, 0x06, +0x5B, 0xCA, 0x5B, 0xCA, 0x2A, 0x43, 0x22, 0x22, +0x2A, 0x42, 0x22, 0x22, 0x32, 0xA3, 0x53, 0xE7, +0x5C, 0x27, 0x85, 0x4D, 0xB6, 0x72, 0x6C, 0x89, +0x64, 0x68, 0x53, 0xC6, 0x4B, 0x85, 0x4B, 0x66, +0x4B, 0x87, 0x8D, 0xB0, 0xA6, 0x52, 0x9D, 0xF1, +0x8D, 0x4E, 0x85, 0x0D, 0xB6, 0x71, 0x85, 0x2D, +0xA6, 0x32, 0xB6, 0x93, 0x7C, 0xAB, 0x3A, 0x04, +0x5A, 0x68, 0x41, 0xA6, 0x52, 0x48, 0x7B, 0x4B, +0xAC, 0x70, 0xAC, 0xB1, 0x7B, 0x8D, 0x52, 0xAA, +0x73, 0x8E, 0x5A, 0xAA, 0x6B, 0x4D, 0xBD, 0xB6, +0x8C, 0x71, 0x5A, 0xCB, 0x4A, 0x49, 0x42, 0x28, +0x5A, 0xCA, 0x5A, 0xAA, 0x84, 0x0E, 0x73, 0x8C, +0x18, 0xA3, 0x18, 0xC3, 0x39, 0x86, 0x62, 0xCB, +0x84, 0x10, 0x9C, 0xD2, 0x9C, 0xD2, 0x7B, 0xCE, +0x6A, 0xEB, 0x6A, 0xEB, 0x5A, 0x8A, 0x83, 0xEF, +0xAD, 0x34, 0x6B, 0x4D, 0xA4, 0xF4, 0x9C, 0xB3, +0xA4, 0xF4, 0xB5, 0x56, 0xB5, 0x56, 0x83, 0xF0, +0x83, 0xF0, 0x94, 0x92, 0x94, 0x72, 0x84, 0x10, +0x6B, 0x4D, 0x6B, 0x6B, 0x84, 0x2B, 0xAD, 0xAE, +0xBE, 0x4D, 0xAD, 0xEA, 0xCE, 0xED, 0xC6, 0xAC, +0x7C, 0xA4, 0x85, 0x26, 0x8D, 0x47, 0x9D, 0xCA, +0xA6, 0x0A, 0x85, 0x03, 0x8D, 0x81, 0xAE, 0x25, +0xB6, 0x69, 0xB6, 0x6A, 0xAE, 0x4B, 0x9D, 0xED, +0x9D, 0xF0, 0xCE, 0xF6, 0xC6, 0xB4, 0xB6, 0x70, +0xBE, 0x8F, 0xDF, 0x54, 0xB5, 0xF4, 0xCE, 0x58, +0xAD, 0x55, 0x73, 0x8E, 0x31, 0xC6, 0x7C, 0x8C, +0x95, 0xCE, 0x95, 0xAB, 0x85, 0x48, 0x6C, 0x66, +0x5C, 0x06, 0x74, 0xC9, 0x43, 0x25, 0x19, 0x82, +0x3A, 0x87, 0x95, 0x51, 0x42, 0xC8, 0x19, 0x83, +0x2A, 0x44, 0x42, 0xE6, 0x19, 0x82, 0x3A, 0xC6, +0x19, 0xA2, 0x21, 0xE3, 0x11, 0x61, 0x11, 0x22, +0x09, 0x02, 0x09, 0x22, 0x21, 0xE4, 0x22, 0x04, +0x2A, 0x25, 0x4B, 0x28, 0x4B, 0x49, 0x5B, 0xEB, +0x7B, 0x8B, 0x7B, 0x8B, 0x7B, 0x8B, 0x7B, 0x6A, +0x83, 0xAB, 0x8B, 0xEC, 0x94, 0x0D, 0x9C, 0x4E, +0x9C, 0x4E, 0x9C, 0x4E, 0x9C, 0x8F, 0xA4, 0x8F, +0xA4, 0x8F, 0x94, 0x0C, 0x94, 0x0C, 0xA4, 0x8E, +0xAC, 0xD0, 0xAC, 0xD0, 0xA4, 0x8E, 0xA4, 0x6E, +0xA4, 0x8F, 0x9C, 0x6E, 0x9C, 0x2D, 0x9C, 0x4D, +0xA4, 0x8D, 0xA4, 0x6D, 0x9C, 0x4D, 0x94, 0x2C, +0x94, 0x0C, 0x8C, 0x0C, 0x94, 0x2C, 0x94, 0x4D, +0x9C, 0x8E, 0x9C, 0x6E, 0x9C, 0x6E, 0x94, 0x8F, +0xA4, 0xD0, 0xAD, 0x31, 0xBD, 0xB3, 0xCE, 0x14, +0xCD, 0xF4, 0xCE, 0x13, 0xCD, 0xF3, 0xC5, 0xB3, +0xC5, 0xD3, 0xBD, 0xB2, 0xAD, 0x10, 0xBD, 0x72, +0xAC, 0xF0, 0xB5, 0x30, 0xB5, 0x51, 0xB5, 0x51, +0xA4, 0xEF, 0xA5, 0x0F, 0x9C, 0xCE, 0x3A, 0x84, +0x42, 0xE5, 0x5B, 0x28, 0xAD, 0x51, 0xD6, 0x76, +0xBD, 0xD3, 0xBD, 0xF3, 0x9D, 0x0F, 0x42, 0xC3, +0x3B, 0x03, 0x53, 0x85, 0x63, 0xC9, 0xAD, 0x71, +0xCE, 0x55, 0xCE, 0x35, 0x8C, 0x0E, 0xAD, 0x32, +0x62, 0xEA, 0x9C, 0x8F, 0x8C, 0x0D, 0x8C, 0x2E, +0x94, 0x6F, 0x94, 0x4E, 0x7B, 0xAC, 0x83, 0xED, +0x9C, 0xB0, 0x9C, 0x90, 0x73, 0x4B, 0x4A, 0x68, +0x7C, 0x2D, 0xA5, 0xD0, 0x8D, 0x0C, 0xA5, 0xAF, +0xC6, 0x92, 0xC6, 0x72, 0x73, 0xAA, 0x52, 0x68, +0x39, 0xA6, 0x3A, 0x27, 0xBE, 0x75, 0x9D, 0x70, +0x4B, 0x27, 0x5B, 0xA9, 0x63, 0xAA, 0x4A, 0xA7, +0x84, 0x8E, 0x84, 0x8D, 0x95, 0x0E, 0x9D, 0x6E, +0x64, 0x06, 0x6C, 0x27, 0x6B, 0xE9, 0x6B, 0xCA, +0x74, 0x0A, 0x84, 0xAC, 0xB6, 0x13, 0xD7, 0x17, +0xCE, 0xB6, 0xB5, 0xF2, 0x6B, 0xEA, 0x63, 0xE9, +0x53, 0x47, 0x53, 0x27, 0x6B, 0x89, 0x9C, 0xEF, +0x73, 0xAA, 0xAD, 0xD2, 0x84, 0xCE, 0x85, 0x0F, +0x7C, 0xCD, 0x6C, 0x4B, 0x6C, 0x2A, 0x74, 0x6B, +0x8D, 0x2E, 0x8D, 0x4F, 0x85, 0x2F, 0x85, 0x0E, +0x5B, 0xC9, 0x74, 0xCA, 0x5C, 0x25, 0x53, 0xC5, +0x85, 0x4B, 0x6C, 0x47, 0x95, 0x8E, 0x7C, 0xAC, +0xA5, 0xF0, 0xB6, 0x32, 0x8D, 0x0D, 0x6C, 0x47, +0x64, 0x46, 0x5C, 0x05, 0x64, 0x48, 0x8D, 0x8D, +0x9E, 0x10, 0x8D, 0x8E, 0x6C, 0x89, 0x74, 0xE9, +0x85, 0x4B, 0x85, 0x4C, 0x9D, 0xEF, 0xA6, 0x31, +0x95, 0xAE, 0x9D, 0xCF, 0x9D, 0xCF, 0x5B, 0xC7, +0x3A, 0xE5, 0x19, 0xA2, 0x21, 0xA3, 0x21, 0xC3, +0x19, 0xA3, 0x32, 0x65, 0x3A, 0xC6, 0x2A, 0x24, +0x21, 0xE2, 0x53, 0xA6, 0x43, 0x44, 0x43, 0x24, +0x5B, 0xE7, 0x43, 0x04, 0x3A, 0xC3, 0x5C, 0x07, +0x6C, 0x68, 0x4B, 0x46, 0x2A, 0x03, 0x32, 0x65, +0x43, 0x08, 0x53, 0x49, 0x4B, 0x48, 0x4B, 0x47, +0x4B, 0x67, 0x43, 0x46, 0x3B, 0x25, 0x3B, 0x05, +0x4B, 0x67, 0x4B, 0x67, 0x3A, 0xC5, 0x2A, 0x43, +0x3A, 0xC5, 0x22, 0x02, 0x22, 0x22, 0x6C, 0xAA, +0x6C, 0xA9, 0x85, 0x4D, 0x9D, 0xF0, 0x74, 0xCA, +0x7D, 0x0A, 0x5C, 0x07, 0x4B, 0x85, 0x43, 0x65, +0x32, 0xE4, 0x3A, 0xE5, 0x64, 0x2A, 0x85, 0x4E, +0x64, 0x49, 0x53, 0x67, 0x8D, 0x6E, 0x8D, 0x8F, +0xBE, 0xD4, 0x95, 0x6F, 0x8D, 0x0D, 0x7C, 0x0A, +0x73, 0x6A, 0x52, 0x46, 0x49, 0xE7, 0x72, 0xEA, +0xA4, 0x0D, 0x72, 0xEA, 0x83, 0xAD, 0x4A, 0x48, +0x62, 0xEB, 0x52, 0x6A, 0x62, 0xEC, 0x83, 0xEF, +0x73, 0x8E, 0x6B, 0x4D, 0x6B, 0x2C, 0x94, 0x71, +0xA5, 0x13, 0x94, 0x71, 0x94, 0xB0, 0x7B, 0xCD, +0x20, 0xE4, 0x18, 0xC3, 0x18, 0xC3, 0x39, 0x86, +0x5A, 0xAA, 0x7B, 0xCE, 0x83, 0xEF, 0x63, 0x0C, +0x7B, 0x8E, 0x62, 0xEB, 0x5A, 0x8A, 0x39, 0xC7, +0x9C, 0xB3, 0xBD, 0x75, 0xBD, 0x96, 0xA4, 0xF4, +0x9C, 0xB3, 0x9C, 0xD3, 0x94, 0x72, 0x94, 0x72, +0xAD, 0x55, 0xAD, 0x55, 0xBD, 0xF7, 0xCE, 0x59, +0x7B, 0xCF, 0x62, 0xEB, 0x6B, 0x2B, 0x7C, 0x0C, +0x8D, 0x0C, 0x9D, 0xAB, 0xB6, 0x6C, 0xA5, 0xE8, +0x64, 0x41, 0x64, 0x41, 0x6C, 0x82, 0x85, 0x26, +0xBE, 0xCF, 0x8D, 0x68, 0x8D, 0x63, 0x9D, 0xC3, +0xA5, 0xE5, 0xA6, 0x06, 0x9D, 0xE6, 0x95, 0xC9, +0xA6, 0x0F, 0xBE, 0x93, 0xC6, 0xD2, 0xA6, 0x0D, +0xAE, 0x4E, 0xBE, 0x93, 0xBE, 0x36, 0xC6, 0x18, +0xB5, 0x96, 0x73, 0xAF, 0x3A, 0x05, 0x84, 0xE9, +0x7D, 0x07, 0x85, 0x68, 0x6C, 0x87, 0x32, 0xC2, +0x2A, 0x82, 0x4B, 0x85, 0x3A, 0xE4, 0x19, 0xC2, +0x4B, 0x08, 0x8D, 0x31, 0x32, 0x45, 0x21, 0xC3, +0x53, 0x88, 0x53, 0x87, 0x2A, 0x23, 0x3A, 0x85, +0x19, 0x82, 0x2A, 0x04, 0x2A, 0x44, 0x3A, 0x86, +0x42, 0xC7, 0x5B, 0xAA, 0x43, 0x28, 0x3A, 0xE7, +0x53, 0x89, 0x5B, 0xEA, 0x4B, 0x48, 0x5B, 0xEB, +0x5A, 0xCA, 0x5A, 0xC9, 0x62, 0xEA, 0x6B, 0x0A, +0x73, 0x4B, 0x83, 0xCC, 0x83, 0xED, 0x94, 0x4E, +0x9C, 0x8F, 0xA4, 0xF0, 0xBD, 0x93, 0xB5, 0x72, +0xAC, 0xF0, 0x94, 0x4D, 0x9C, 0x4E, 0xAC, 0xF0, +0xA4, 0xAF, 0xA4, 0xD0, 0xA4, 0xD0, 0xAC, 0xF0, +0xB5, 0x11, 0xBD, 0x72, 0xB5, 0x31, 0xBD, 0x51, +0xDE, 0x55, 0xDE, 0x35, 0xCD, 0xF3, 0xCD, 0xD3, +0xC5, 0x71, 0xBD, 0x51, 0xB5, 0x31, 0xB5, 0x10, +0xAC, 0xF0, 0xB5, 0x10, 0xB5, 0x31, 0xAC, 0xF0, +0x9C, 0x8E, 0x94, 0x4E, 0x9C, 0xAF, 0xAC, 0xEF, +0xAC, 0xCF, 0xAC, 0xEF, 0xAC, 0xCF, 0xAC, 0xCF, +0xB5, 0x10, 0xB5, 0x51, 0xB5, 0x51, 0xB5, 0x30, +0xB5, 0x10, 0xB5, 0x30, 0xAC, 0xF0, 0x94, 0x4D, +0x94, 0x4D, 0x9C, 0x8E, 0xAD, 0x30, 0x63, 0x48, +0x42, 0xA5, 0x53, 0x06, 0x73, 0xEB, 0xB5, 0xB3, +0x5B, 0x48, 0x4B, 0x47, 0x53, 0x86, 0x4B, 0x44, +0x43, 0x24, 0x6C, 0x09, 0xB5, 0xB2, 0xCE, 0x35, +0xCE, 0x15, 0xCE, 0x14, 0x9C, 0x8F, 0xA4, 0xF1, +0x7B, 0xAC, 0x83, 0xCD, 0x94, 0x4D, 0x8C, 0x4E, +0x8C, 0x4E, 0x9C, 0x8F, 0x9C, 0xB0, 0xAD, 0x11, +0xAD, 0x32, 0x9C, 0x90, 0x73, 0x6C, 0x42, 0x27, +0x42, 0x88, 0x8D, 0x2E, 0x95, 0x6D, 0xA5, 0xEF, +0xC6, 0xD3, 0xAD, 0xAF, 0x52, 0xA7, 0x52, 0xA8, +0x7C, 0x0D, 0xAD, 0xB3, 0xC6, 0xF6, 0xB6, 0x53, +0x74, 0x4C, 0xA5, 0xD2, 0x84, 0x8D, 0x73, 0xEB, +0x84, 0x6D, 0x8C, 0xCE, 0x9D, 0x2F, 0x9D, 0x2D, +0x6C, 0x47, 0x6B, 0xE8, 0x7C, 0x0B, 0x73, 0xAB, +0x6B, 0x8B, 0x8C, 0xAE, 0xDF, 0x59, 0xB6, 0x13, +0x7C, 0x8D, 0x7C, 0x6B, 0x5B, 0xA8, 0x4B, 0x46, +0x74, 0x4B, 0x6B, 0xCA, 0x9D, 0x30, 0xE7, 0x37, +0xAD, 0x70, 0xC6, 0x74, 0x9D, 0x70, 0xAD, 0xF2, +0x9D, 0x6F, 0xAD, 0xF1, 0x9D, 0x90, 0x74, 0x6B, +0x8D, 0x0E, 0x63, 0xEA, 0x74, 0x8C, 0x74, 0xAB, +0x6C, 0x89, 0x5C, 0x26, 0x6C, 0x87, 0x95, 0x8C, +0x9D, 0x8D, 0x63, 0xE7, 0xAD, 0xF0, 0x7C, 0x4B, +0x95, 0x0E, 0xAD, 0xF1, 0x95, 0x4D, 0x6C, 0x68, +0x4B, 0xC4, 0x4B, 0x84, 0x7D, 0x2B, 0x85, 0x4D, +0x53, 0xA7, 0x3A, 0xE4, 0x3B, 0x24, 0x64, 0x68, +0x85, 0x6B, 0x95, 0xCE, 0xA6, 0x10, 0xAE, 0x51, +0x95, 0xAE, 0x85, 0x0C, 0x53, 0xA7, 0x32, 0xA4, +0x21, 0xE3, 0x11, 0x61, 0x21, 0xE3, 0x21, 0xE3, +0x21, 0xE3, 0x3A, 0x85, 0x3A, 0xC5, 0x2A, 0x23, +0x21, 0xE2, 0x5C, 0x27, 0x53, 0xC5, 0x43, 0x24, +0x5C, 0x07, 0x64, 0x28, 0x53, 0xC6, 0x53, 0xC6, +0x64, 0x48, 0x3A, 0xA4, 0x21, 0xC3, 0x32, 0x65, +0x4B, 0x27, 0x53, 0x89, 0x4B, 0x68, 0x6C, 0x6B, +0x64, 0x4A, 0x5C, 0x08, 0x5B, 0xE8, 0x5C, 0x08, +0x74, 0xAB, 0x7C, 0xEC, 0x6C, 0x6A, 0x63, 0xE8, +0x53, 0x87, 0x42, 0xC5, 0x2A, 0x43, 0x7D, 0x0D, +0x95, 0xCF, 0x8D, 0x8E, 0x9D, 0xF0, 0x85, 0x2C, +0x9D, 0xEF, 0x64, 0x28, 0x5C, 0x07, 0x64, 0x68, +0x53, 0xA6, 0x4B, 0x87, 0x64, 0x6A, 0x85, 0x6D, +0x6C, 0x69, 0x3B, 0x05, 0x6C, 0x8B, 0xB6, 0xB4, +0xB6, 0xB4, 0x74, 0x6B, 0x53, 0x86, 0x7C, 0x6A, +0x7B, 0xCA, 0x73, 0xCA, 0x52, 0x66, 0x72, 0xC9, +0x9B, 0xAC, 0x7A, 0xEA, 0x7B, 0x2B, 0x5A, 0xAA, +0x6B, 0x2C, 0x7B, 0xAE, 0x94, 0x51, 0x9C, 0xB2, +0x7B, 0xAE, 0x83, 0xEF, 0xAD, 0x34, 0xC6, 0x18, +0xCE, 0x18, 0xC6, 0x17, 0xC6, 0x18, 0xC5, 0xD7, +0x7B, 0xAF, 0x39, 0x87, 0x29, 0x25, 0x20, 0xE4, +0x39, 0x86, 0x62, 0xCA, 0x6B, 0x0C, 0x73, 0x4C, +0x83, 0xAE, 0x6B, 0x2C, 0x73, 0x6D, 0x62, 0xCB, +0x8C, 0x10, 0xDE, 0x79, 0xD6, 0x38, 0x9C, 0x92, +0x8C, 0x31, 0xA4, 0xF4, 0xB5, 0x76, 0xBD, 0xB7, +0xBD, 0xD8, 0xCE, 0x59, 0xC6, 0x38, 0xCE, 0x38, +0x8C, 0x51, 0x84, 0x10, 0x6B, 0x2B, 0x63, 0x4B, +0x4A, 0xE8, 0x84, 0xED, 0xA6, 0x2E, 0xA5, 0xEB, +0x64, 0x41, 0x6C, 0x82, 0x74, 0xE3, 0x8D, 0x67, +0xCF, 0x32, 0x95, 0xAD, 0x85, 0x26, 0x9D, 0xC5, +0x9D, 0xC4, 0x8D, 0x62, 0x95, 0x83, 0xA6, 0x08, +0xAE, 0x6E, 0xB6, 0x50, 0xBE, 0x8F, 0xA5, 0xE9, +0x9D, 0xEB, 0xA5, 0xF1, 0xBE, 0x37, 0xC6, 0x38, +0xA5, 0x55, 0x63, 0x2C, 0x4A, 0xE6, 0x85, 0x28, +0x75, 0x05, 0x64, 0x85, 0x32, 0xE1, 0x2A, 0x61, +0x3A, 0xE4, 0x53, 0x86, 0x19, 0xC1, 0x32, 0x64, +0x53, 0x89, 0x5B, 0x8A, 0x32, 0x45, 0x19, 0x82, +0x42, 0xE5, 0x21, 0xE2, 0x2A, 0x23, 0x2A, 0x23, +0x21, 0xE3, 0x42, 0xE6, 0x5B, 0xE9, 0x5C, 0x09, +0x4B, 0x87, 0x4B, 0x87, 0x4B, 0x87, 0x43, 0x47, +0x43, 0x47, 0x43, 0x26, 0x32, 0xA5, 0x43, 0x08, +0x7B, 0xAD, 0x73, 0x6C, 0x63, 0x0B, 0x73, 0x6C, +0x7B, 0xCD, 0x94, 0x4F, 0x9C, 0x90, 0x94, 0x4F, +0x83, 0xCD, 0x83, 0xCD, 0x84, 0x0D, 0x7B, 0xCD, +0x73, 0x8B, 0x94, 0x2D, 0x94, 0x0D, 0x94, 0x2D, +0x94, 0x4E, 0x8C, 0x4E, 0x83, 0xED, 0x9C, 0x90, +0xA4, 0xF1, 0xB5, 0x73, 0xBD, 0xB3, 0xCD, 0xF4, +0xCD, 0xF4, 0xC5, 0xB2, 0xD6, 0x14, 0xCD, 0xD3, +0xBD, 0x92, 0xBD, 0x93, 0xC5, 0xF4, 0xCD, 0xF4, +0xD6, 0x35, 0xD6, 0x35, 0xDE, 0x55, 0xDE, 0x55, +0xDE, 0x55, 0xA4, 0xAF, 0xBD, 0x72, 0xCD, 0xF4, +0xA4, 0x8E, 0xAC, 0xF0, 0xB5, 0x10, 0xB5, 0x31, +0xB5, 0x30, 0xAC, 0xCF, 0xB5, 0x10, 0xBD, 0x92, +0xC5, 0xB3, 0xC5, 0xB3, 0xBD, 0x92, 0xCD, 0xD3, +0xC5, 0xB3, 0xC5, 0xB3, 0xBD, 0x71, 0xAC, 0xEF, +0x63, 0x48, 0x42, 0xA5, 0x5B, 0x89, 0x7C, 0x4D, +0x6C, 0x0B, 0x53, 0xA7, 0x43, 0x45, 0x4B, 0x45, +0x53, 0x66, 0x9D, 0x4E, 0xAD, 0x0F, 0x9C, 0xAE, +0x9C, 0x6E, 0x94, 0x6E, 0x8C, 0x4E, 0x8C, 0x2E, +0x94, 0x6F, 0x6B, 0x6A, 0xCE, 0xB5, 0xC6, 0x74, +0x9C, 0xEF, 0xBD, 0xD2, 0x9C, 0xAE, 0x94, 0x4E, +0x94, 0x4E, 0x94, 0x4D, 0x7B, 0xAC, 0x6B, 0x2A, +0x62, 0xE9, 0x5B, 0x09, 0x95, 0x0D, 0x9D, 0x6D, +0xBE, 0xB3, 0xAE, 0x32, 0x8C, 0xCF, 0xBE, 0x74, +0xC6, 0xF4, 0xC6, 0xD4, 0xB6, 0x52, 0xB6, 0x73, +0x74, 0x6C, 0x7C, 0xAD, 0x6B, 0xCA, 0x63, 0xAA, +0x7C, 0x4C, 0x84, 0x8C, 0x94, 0xED, 0x8C, 0xEC, +0x74, 0x68, 0x84, 0xCB, 0xA5, 0x30, 0x84, 0x2D, +0x6B, 0x8B, 0xD6, 0xD7, 0xDF, 0x59, 0x7C, 0x8D, +0x6C, 0x2A, 0x74, 0x6A, 0x7C, 0xAB, 0x74, 0x8B, +0x7C, 0x6C, 0x6B, 0xA9, 0xB6, 0x13, 0xCE, 0xB5, +0xBE, 0x74, 0xBE, 0x54, 0xAD, 0x70, 0xC6, 0x32, +0xD6, 0xD5, 0x8C, 0xED, 0x6C, 0x09, 0x53, 0xA7, +0x74, 0x8B, 0x74, 0x8B, 0x32, 0x83, 0x3A, 0xE4, +0x6C, 0x88, 0x53, 0xE4, 0x64, 0x27, 0x74, 0x29, +0x9D, 0x4E, 0x74, 0x69, 0x84, 0xCB, 0x6B, 0xEA, +0x84, 0xAF, 0xAD, 0xB2, 0x9D, 0x71, 0x74, 0x4B, +0x3B, 0x23, 0x4B, 0xA5, 0x64, 0x47, 0x2A, 0x81, +0x19, 0xE1, 0x22, 0x02, 0x3A, 0xE4, 0x64, 0x68, +0x95, 0xAD, 0xA6, 0x10, 0xAE, 0x51, 0x9D, 0xF0, +0x53, 0x88, 0x19, 0xC2, 0x22, 0x03, 0x2A, 0x44, +0x53, 0xA8, 0x43, 0x06, 0x3A, 0xE5, 0x32, 0xA4, +0x53, 0x87, 0x63, 0xE9, 0x43, 0x05, 0x43, 0x26, +0x2A, 0x42, 0x53, 0xC7, 0x5C, 0x26, 0x4B, 0x64, +0x64, 0x27, 0x7C, 0xEA, 0x6C, 0x69, 0x43, 0x45, +0x6C, 0xA9, 0x42, 0xE5, 0x19, 0xA2, 0x32, 0x65, +0x3A, 0xC5, 0x43, 0x06, 0x53, 0xA9, 0x9D, 0xF1, +0x8D, 0x6F, 0x85, 0x2D, 0x85, 0x4E, 0x8D, 0x8F, +0x9E, 0x11, 0x53, 0x88, 0x4B, 0x66, 0x5B, 0xE8, +0x3A, 0xE4, 0x2A, 0x23, 0x3A, 0xA4, 0x64, 0x69, +0x95, 0xCF, 0x95, 0xAF, 0xA6, 0x31, 0x7D, 0x0C, +0x7C, 0xEB, 0x4B, 0xA6, 0x95, 0xAE, 0x6C, 0x68, +0x5C, 0x47, 0x6C, 0xA9, 0x7D, 0x0B, 0x85, 0x6C, +0x8D, 0x8D, 0x95, 0x8D, 0x6C, 0x8A, 0x8D, 0x4E, +0xAE, 0x52, 0x6C, 0x4A, 0x6C, 0x49, 0x95, 0x6D, +0x63, 0x68, 0x5B, 0x47, 0x63, 0x68, 0x83, 0x69, +0x83, 0x09, 0x6A, 0xA8, 0x62, 0x89, 0x83, 0xCF, +0x94, 0x91, 0x9C, 0xB2, 0x94, 0x92, 0x8C, 0x30, +0x83, 0xEF, 0x9C, 0xB2, 0xA4, 0xD3, 0xBD, 0xB6, +0xBD, 0xB6, 0xAD, 0x34, 0xAD, 0x14, 0xCE, 0x38, +0xD6, 0x99, 0x9C, 0x92, 0x83, 0xAF, 0x5A, 0xAB, +0x20, 0xE4, 0x31, 0x65, 0x5A, 0x8A, 0x73, 0x6D, +0x73, 0x6D, 0x83, 0xAE, 0x73, 0x2C, 0x6B, 0x0C, +0x94, 0x72, 0xD6, 0x58, 0xDE, 0x79, 0xA4, 0xD3, +0xAD, 0x14, 0xAD, 0x55, 0xB5, 0x76, 0xB5, 0x96, +0xD6, 0x9A, 0xDE, 0xBB, 0x9C, 0xD3, 0x73, 0x8E, +0x73, 0x8E, 0x94, 0x71, 0x8C, 0x30, 0x73, 0x8D, +0x63, 0x4B, 0x84, 0xAD, 0x8D, 0x4D, 0x9D, 0xCC, +0x74, 0xC5, 0x74, 0xC2, 0x85, 0x44, 0x9D, 0xE9, +0xB6, 0x71, 0xCF, 0x35, 0x95, 0xAE, 0x95, 0xA8, +0x8D, 0x64, 0x7D, 0x00, 0x85, 0x42, 0x9D, 0xC7, +0xA6, 0x0B, 0xAE, 0x4D, 0xB6, 0x6D, 0xAE, 0x49, +0x95, 0x88, 0xAD, 0xD1, 0xC6, 0x58, 0xC6, 0x38, +0x9D, 0x14, 0x42, 0x49, 0x5B, 0x68, 0x85, 0x48, +0x74, 0xE5, 0x53, 0xE3, 0x32, 0xC1, 0x2A, 0x61, +0x74, 0x8A, 0x85, 0x4B, 0x2A, 0x41, 0x3A, 0xA4, +0x7C, 0xCD, 0xAE, 0x12, 0x5B, 0xAA, 0x21, 0xC3, +0x74, 0x8A, 0x53, 0x66, 0x4B, 0x46, 0x53, 0x68, +0x64, 0x0A, 0x5B, 0xE9, 0x43, 0x46, 0x32, 0xC4, +0x2A, 0x83, 0x2A, 0x63, 0x4B, 0x67, 0x4B, 0x87, +0x53, 0xE8, 0x4B, 0x87, 0x2A, 0x63, 0x32, 0x86, +0xB5, 0x53, 0xA4, 0xF2, 0x83, 0xEE, 0x94, 0x6F, +0xAD, 0x32, 0xC5, 0xD4, 0xCD, 0xF5, 0xC5, 0xB4, +0xAD, 0x32, 0x94, 0x90, 0x94, 0x6F, 0x94, 0x6F, +0x9C, 0xD1, 0x94, 0x6E, 0x94, 0x0C, 0xB5, 0x31, +0xCE, 0x15, 0xD6, 0x76, 0xD6, 0x57, 0xD6, 0x57, +0xD6, 0x77, 0xD6, 0x57, 0xDE, 0x97, 0xC5, 0xD4, +0xD6, 0x15, 0xDE, 0x96, 0xDE, 0x96, 0xD6, 0x75, +0xD6, 0x55, 0xD6, 0x76, 0xD6, 0x77, 0xD6, 0x56, +0xD6, 0x56, 0xD6, 0x76, 0xDE, 0x96, 0xD6, 0x55, +0xDE, 0x76, 0x9C, 0x4D, 0xAC, 0xF0, 0xB5, 0x52, +0x94, 0x4E, 0x9C, 0xB0, 0xAC, 0xF0, 0xB5, 0x31, +0xC5, 0xD4, 0xC5, 0xD4, 0x9C, 0xAF, 0xA4, 0xD0, +0x94, 0x6E, 0x83, 0xCC, 0x7B, 0xAC, 0x8C, 0x0D, +0x8C, 0x2E, 0x9C, 0x8F, 0xBD, 0x92, 0xC5, 0x92, +0x9C, 0xCD, 0x63, 0x88, 0x4B, 0x06, 0x53, 0x27, +0x6C, 0x2B, 0x5B, 0xE8, 0x4B, 0x65, 0x43, 0x45, +0x53, 0x66, 0x9D, 0x2E, 0xB5, 0xAF, 0xB5, 0xAE, +0x94, 0xAC, 0x63, 0x48, 0x8C, 0x6E, 0x9C, 0xAF, +0xAD, 0x11, 0x63, 0x29, 0xC6, 0xB3, 0xC6, 0x71, +0xCE, 0xB3, 0xC6, 0x52, 0xB5, 0x90, 0xA4, 0xEE, +0xA4, 0xEE, 0xAD, 0x2E, 0xC5, 0xF2, 0xB5, 0x51, +0xB5, 0x51, 0xAD, 0x10, 0xA5, 0x0F, 0xAD, 0xD0, +0xBE, 0xB4, 0xC7, 0x16, 0xAE, 0x32, 0x9D, 0xCE, +0x7C, 0xEA, 0x8D, 0x2D, 0xB6, 0x72, 0xB6, 0x32, +0x8D, 0x0E, 0x74, 0x6C, 0x74, 0x2B, 0x63, 0xC9, +0x6B, 0xE9, 0x5B, 0x66, 0x63, 0xA7, 0x8D, 0x0C, +0x7C, 0x89, 0x8C, 0xEB, 0x9D, 0x6F, 0x7C, 0x4C, +0x95, 0x10, 0xE7, 0x79, 0x9D, 0x30, 0x74, 0x6B, +0x74, 0xAB, 0x6C, 0x28, 0x7C, 0xAB, 0x8D, 0x0E, +0x6B, 0xCA, 0x6B, 0xAA, 0xC6, 0x53, 0xAD, 0xD0, +0xBE, 0x94, 0xBE, 0x95, 0xBE, 0x54, 0xB5, 0xB0, +0xD6, 0x93, 0xCE, 0xB3, 0x9D, 0x4E, 0x74, 0x8A, +0x7C, 0xCB, 0xA5, 0xCF, 0x43, 0x26, 0x3A, 0xE4, +0x5B, 0xE5, 0x4B, 0xA4, 0x7C, 0xCA, 0x5B, 0x67, +0x6B, 0xE9, 0x7C, 0xAA, 0x53, 0x86, 0x3A, 0x84, +0x9D, 0x73, 0xAD, 0xB4, 0xA5, 0xB4, 0x6C, 0x0C, +0x43, 0x45, 0x5C, 0x27, 0x32, 0xC2, 0x19, 0xE1, +0x19, 0xA1, 0x11, 0x80, 0x19, 0xE2, 0x3A, 0xC4, +0x8D, 0x6D, 0xA6, 0x51, 0x9D, 0xF0, 0x4A, 0xE7, +0x09, 0x00, 0x19, 0x62, 0x2A, 0x24, 0x4B, 0x27, +0x7D, 0x0C, 0x64, 0x48, 0x5C, 0x07, 0x53, 0xC6, +0x6C, 0x8A, 0x6C, 0x8A, 0x4B, 0x65, 0x53, 0xC7, +0x4B, 0x45, 0x32, 0xA2, 0x4B, 0x84, 0x53, 0xE5, +0x64, 0x47, 0x53, 0xC6, 0x2A, 0x02, 0x09, 0x00, +0x42, 0xE6, 0x42, 0xC6, 0x21, 0xA2, 0x22, 0x03, +0x22, 0x22, 0x2A, 0x43, 0x64, 0x2A, 0x95, 0x90, +0x95, 0xB0, 0x9D, 0xF1, 0xA6, 0x12, 0xA6, 0x52, +0x74, 0x8C, 0x32, 0x85, 0x4B, 0x47, 0x5C, 0x09, +0x4B, 0x46, 0x3A, 0x84, 0x3A, 0xA5, 0x5B, 0xE7, +0x74, 0xCB, 0x95, 0xAF, 0xA6, 0x31, 0x7D, 0x0C, +0x8D, 0x6E, 0x64, 0x49, 0xBE, 0xF3, 0x8D, 0x6C, +0x5C, 0x47, 0x53, 0xE6, 0x43, 0x64, 0x3B, 0x44, +0x8D, 0x4C, 0x9D, 0xCE, 0x9D, 0xCD, 0x85, 0x2B, +0x85, 0x2C, 0x6C, 0x89, 0x95, 0x8C, 0x95, 0x8D, +0x8C, 0xCC, 0x6B, 0xE8, 0x5B, 0x86, 0x73, 0xA7, +0x7B, 0x28, 0x52, 0x07, 0x73, 0x2C, 0x83, 0xEF, +0x94, 0x71, 0x94, 0x50, 0x94, 0x71, 0x8C, 0x0F, +0x8C, 0x30, 0xA4, 0xF3, 0x8C, 0x10, 0x9C, 0xB3, +0x9C, 0x92, 0x94, 0x51, 0xA4, 0xD3, 0xB5, 0x75, +0xC5, 0xF7, 0xAD, 0x55, 0xD6, 0x58, 0xBD, 0xB6, +0x73, 0x8E, 0x4A, 0x08, 0x41, 0xC7, 0x62, 0xEB, +0x62, 0xCA, 0x83, 0xCF, 0x73, 0x2C, 0x52, 0x69, +0xA4, 0xD3, 0xD6, 0x58, 0xCD, 0xF7, 0xAD, 0x14, +0x7B, 0xCF, 0xAD, 0x55, 0xB5, 0x96, 0xDE, 0xBB, +0xDE, 0xBB, 0xB5, 0x96, 0x6B, 0x4D, 0x94, 0x93, +0xAD, 0x35, 0x7B, 0xCF, 0x6B, 0x2C, 0xAD, 0x34, +0x84, 0x2F, 0x63, 0x8A, 0x84, 0xED, 0x85, 0x2B, +0x85, 0x27, 0x7C, 0xE4, 0x95, 0xA7, 0xA6, 0x2B, +0x95, 0xAD, 0xBE, 0xF4, 0xBE, 0xF4, 0x9D, 0xCC, +0x7D, 0x03, 0x74, 0xC0, 0x85, 0x43, 0x8D, 0x86, +0x9D, 0xE9, 0x9E, 0x09, 0x9D, 0xE8, 0xA6, 0x26, +0x95, 0x68, 0xA5, 0xB1, 0xCE, 0x99, 0xC6, 0x38, +0x94, 0xB3, 0x3A, 0x08, 0x74, 0x4B, 0x8D, 0x49, +0x7D, 0x05, 0x4B, 0xA2, 0x32, 0xC2, 0x32, 0xA2, +0x95, 0xAC, 0x95, 0xCA, 0x53, 0xC4, 0x22, 0x01, +0x8D, 0x4F, 0xBE, 0xD5, 0x63, 0xCB, 0x53, 0x47, +0x9D, 0x8B, 0x63, 0xE5, 0x5B, 0xE8, 0x74, 0xAC, +0x6C, 0x6B, 0x3A, 0xE6, 0x11, 0x81, 0x32, 0x44, +0x3A, 0xE5, 0x4B, 0x87, 0x5C, 0x29, 0x53, 0xC7, +0x64, 0x49, 0x4B, 0x86, 0x22, 0x22, 0x4B, 0x07, +0xBD, 0xB4, 0xC5, 0xD4, 0xBD, 0x93, 0xC5, 0xD4, +0xCE, 0x35, 0xC5, 0xD4, 0xBD, 0x73, 0xCE, 0x15, +0xD6, 0x55, 0xCE, 0x35, 0xCE, 0x15, 0xC5, 0xF5, +0xCE, 0x15, 0x94, 0x4E, 0x8B, 0xEC, 0xCD, 0xF3, +0xD6, 0x76, 0xD6, 0x76, 0xDE, 0x97, 0xDE, 0xB7, +0xDE, 0xB8, 0xCE, 0x36, 0xD6, 0x56, 0xCD, 0xF4, +0xBD, 0xB3, 0xC5, 0xF4, 0xD6, 0x76, 0xDE, 0x96, +0xD6, 0x56, 0xD6, 0x76, 0xDE, 0x97, 0xD6, 0x76, +0xD6, 0x76, 0xD6, 0x76, 0xD6, 0x76, 0xD6, 0x56, +0xDE, 0x76, 0x9C, 0x6E, 0xA4, 0xD0, 0xBD, 0x93, +0x94, 0x6F, 0xA4, 0xF1, 0xAC, 0xF1, 0xA4, 0xD0, +0xA4, 0xF1, 0xAD, 0x12, 0xAD, 0x11, 0xBD, 0xB4, +0xBD, 0x93, 0x9C, 0x70, 0x6B, 0x0A, 0x73, 0x6C, +0x73, 0x6C, 0x84, 0x0E, 0x94, 0x4E, 0x8C, 0x0C, +0x8C, 0x4B, 0x5B, 0x47, 0x32, 0x84, 0x32, 0x84, +0x42, 0xE5, 0x53, 0xA7, 0x4B, 0x65, 0x64, 0x28, +0x74, 0x6A, 0x9D, 0x4D, 0xA5, 0xAC, 0x9D, 0xAA, +0x9D, 0x8B, 0x8D, 0x0B, 0x74, 0x4A, 0x84, 0x6D, +0xAD, 0x92, 0x63, 0x4A, 0xAD, 0xD0, 0xAD, 0xEF, +0x9D, 0x0D, 0xA5, 0x2E, 0xA5, 0x0E, 0xAD, 0x4E, +0xA5, 0x6D, 0xAD, 0xAF, 0xC6, 0x12, 0xB5, 0x71, +0xB5, 0x51, 0x94, 0x6E, 0x7B, 0xEC, 0x94, 0xEE, +0xA5, 0xF2, 0xB6, 0x94, 0xAE, 0x12, 0x7C, 0xAB, +0x4B, 0x85, 0x8D, 0x6E, 0x9D, 0x8F, 0x95, 0x4E, +0x95, 0x6F, 0xA5, 0xD2, 0x74, 0x4B, 0x63, 0xA9, +0x8C, 0xCD, 0x84, 0x6A, 0x63, 0xA7, 0x95, 0x4D, +0x84, 0xCB, 0x7C, 0xCA, 0x8C, 0xEB, 0x94, 0xEC, +0xB6, 0x33, 0x9D, 0x50, 0x7C, 0x8C, 0x74, 0x8A, +0x5B, 0xE8, 0x5B, 0xA7, 0x74, 0x8B, 0x84, 0xCD, +0x9D, 0x71, 0xAD, 0xD3, 0xB6, 0x12, 0xB5, 0xF0, +0xBE, 0x53, 0x9D, 0x50, 0xB6, 0x54, 0xC6, 0x95, +0xB5, 0xD0, 0xCE, 0xB2, 0xBE, 0x30, 0x84, 0xAA, +0x63, 0xE8, 0x5B, 0xC7, 0x4B, 0x86, 0x4B, 0x65, +0x5B, 0xE6, 0x3A, 0xE2, 0x53, 0x87, 0x5B, 0xC8, +0x6C, 0x6A, 0x63, 0xE7, 0x43, 0x25, 0x53, 0x28, +0x9D, 0x53, 0xBE, 0x77, 0xBE, 0x77, 0x7C, 0xAE, +0x64, 0x49, 0x43, 0x64, 0x2A, 0x81, 0x19, 0xE1, +0x53, 0x67, 0x42, 0xC5, 0x2A, 0x23, 0x2A, 0x23, +0x32, 0x63, 0x4B, 0x67, 0x32, 0x44, 0x11, 0x21, +0x11, 0x41, 0x19, 0x82, 0x2A, 0x44, 0x43, 0x06, +0x74, 0xAA, 0x74, 0xCA, 0x6C, 0x89, 0x64, 0x28, +0x7C, 0xCB, 0x74, 0xAA, 0x53, 0xC6, 0x53, 0xE6, +0x5B, 0xE7, 0x4B, 0x85, 0x53, 0xA6, 0x5C, 0x26, +0x53, 0xE6, 0x32, 0x82, 0x2A, 0x03, 0x19, 0x82, +0x21, 0xE3, 0x21, 0xA2, 0x3A, 0xA5, 0x3A, 0xA5, +0x19, 0xE1, 0x32, 0xA4, 0x6C, 0x8A, 0x8D, 0x6F, +0xA6, 0x32, 0xAE, 0x53, 0x95, 0xD0, 0x7C, 0xCD, +0x2A, 0x64, 0x32, 0x85, 0x43, 0x26, 0x5B, 0xC8, +0x5C, 0x09, 0x53, 0xA7, 0x74, 0xCB, 0x74, 0xEA, +0x7D, 0x0C, 0x95, 0xD0, 0xA6, 0x31, 0x74, 0xCB, +0x53, 0xC8, 0x7C, 0xCB, 0xAE, 0x70, 0xA6, 0x2F, +0x95, 0xCE, 0x85, 0x4B, 0x7D, 0x0B, 0x53, 0xE6, +0x95, 0x8D, 0xA6, 0x0F, 0x95, 0x8C, 0x95, 0xAC, +0x8D, 0x4C, 0x7D, 0x0A, 0x7C, 0xE9, 0x4B, 0x24, +0x31, 0xA2, 0x42, 0x24, 0x5B, 0x66, 0x74, 0x68, +0x84, 0x2A, 0x8C, 0x0F, 0x9C, 0x92, 0x8C, 0x10, +0x9C, 0xB2, 0xA4, 0xD3, 0xA4, 0xF3, 0x8C, 0x30, +0x83, 0xEF, 0xCE, 0x38, 0xA5, 0x13, 0x62, 0xCB, +0x73, 0x8E, 0x9C, 0x92, 0x8C, 0x51, 0x84, 0x10, +0x94, 0x92, 0xB5, 0x75, 0xD6, 0x79, 0xAD, 0x55, +0xC6, 0x18, 0xBD, 0x96, 0x8C, 0x31, 0x7B, 0xAE, +0x52, 0x49, 0x73, 0x2C, 0x7B, 0xAE, 0x7B, 0xAE, +0xAD, 0x34, 0xD6, 0x38, 0xD6, 0x58, 0xBD, 0x96, +0x94, 0x51, 0x9C, 0xB3, 0xDE, 0xBB, 0xD6, 0x7A, +0xAD, 0x76, 0x73, 0xAF, 0x6B, 0x4D, 0x84, 0x10, +0x94, 0x71, 0x8C, 0x51, 0x7B, 0xCF, 0xA4, 0xF3, +0x7B, 0xEF, 0x5B, 0x0B, 0xA5, 0x92, 0x84, 0xED, +0x85, 0x09, 0x8D, 0x48, 0x95, 0xCA, 0x9D, 0xEB, +0x95, 0x8A, 0x9D, 0xCD, 0xA6, 0x10, 0x9E, 0x0D, +0x7D, 0x26, 0x64, 0x60, 0x6C, 0xC2, 0x8D, 0x46, +0x9E, 0x09, 0x95, 0xA6, 0x95, 0xA4, 0xA6, 0x26, +0x8D, 0x48, 0xA5, 0x92, 0xCE, 0x79, 0xBE, 0x38, +0x84, 0x31, 0x3A, 0x06, 0x84, 0xED, 0x85, 0x29, +0x74, 0xC6, 0x5C, 0x25, 0x32, 0xC1, 0x53, 0xA6, +0x95, 0xCC, 0x85, 0x47, 0x74, 0xE6, 0x32, 0x82, +0x84, 0xED, 0xB6, 0x94, 0x53, 0x69, 0x63, 0xA8, +0x9D, 0xAC, 0x53, 0x65, 0x42, 0xE5, 0x2A, 0x63, +0x22, 0x23, 0x3A, 0xA5, 0x3A, 0xC5, 0x43, 0x27, +0x43, 0x46, 0x3A, 0xC4, 0x3B, 0x05, 0x53, 0xC7, +0x64, 0x29, 0x3A, 0xC4, 0x09, 0x00, 0x21, 0xE4, diff -Nru libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-wrover-kit/main/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-wrover-kit/main/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-wrover-kit/main/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-wrover-kit/main/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,7 @@ +idf_component_register(SRCS + lws-minimal-esp32.c + devices.c + INCLUDE_DIRS "../libwebsockets/include;${IDF_PATH}/components/spi_flash/include;${IDF_PATH}/components/nvs_flash/include;${IDF_PATH}/components/mdns/include") + +target_link_libraries(${COMPONENT_LIB} websockets) +include_directories(../build/libwebsockets) diff -Nru libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-wrover-kit/main/devices.c libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-wrover-kit/main/devices.c --- libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-wrover-kit/main/devices.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-wrover-kit/main/devices.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,272 @@ +/* + * devices for ESP WROVER KIT + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + */ + +#define LWIP_PROVIDE_ERRNO 1 +#define _ESP_PLATFORM_ERRNO_H_ + +#include +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#include + +#include + +struct lws_led_state *lls; +lws_display_state_t lds; +struct lws_button_state *bcs; +lws_netdev_instance_wifi_t *wnd; + +/* + * Button controller + * + * On the WROVER KIT, it's a bit overloaded... the two buttons are reset and + * gpio0, gpio is also used for one of the RGB LEDs channels control so it's not + * really usable as a general user button. + * + * Instead we use GPIO 14 (available on J1) for a button with the other side + * of the switch connected to 0V. + */ + +static const lws_button_map_t bcm[] = { + { + .gpio = GPIO_NUM_14, + .smd_interaction_name = "user" + }, +}; + +static const lws_button_controller_t bc = { + .smd_bc_name = "bc", + .gpio_ops = &lws_gpio_plat, + .button_map = &bcm[0], + .active_state_bitmap = 0, + .count_buttons = LWS_ARRAY_SIZE(bcm), +}; + +/* + * pwm controller + */ + +static const lws_pwm_map_t pwm_map[] = { + { .gpio = GPIO_NUM_2, .index = 0, .active_level = 1 }, + { .gpio = GPIO_NUM_0, .index = 1, .active_level = 1 }, + { .gpio = GPIO_NUM_4, .index = 2, .active_level = 1 }, + { .gpio = GPIO_NUM_5, .index = 3, .active_level = 0 } +}; + +static const lws_pwm_ops_t pwm_ops = { + lws_pwm_plat_ops, + .pwm_map = &pwm_map[0], + .count_pwm_map = LWS_ARRAY_SIZE(pwm_map) +}; + +/* + * led controller + */ + +static const lws_led_gpio_map_t lgm[] = { + { + .name = "red", + .gpio = GPIO_NUM_2, + .pwm_ops = &pwm_ops, /* managed by pwm */ + .active_level = 1, + }, + { + .name = "green", + .gpio = GPIO_NUM_0, + .pwm_ops = &pwm_ops, /* managed by pwm */ + .active_level = 1, + }, + { + .name = "blue", + .gpio = GPIO_NUM_4, + .pwm_ops = &pwm_ops, /* managed by pwm */ + .active_level = 1, + }, + { + .name = "backlight", + .gpio = GPIO_NUM_5, + .pwm_ops = &pwm_ops, /* managed by pwm */ + .active_level = 0, + /* + * The wrover kit uses a 2 NPN in series to drive the backlight + * which means if the GPIO provides no current, the backlight is + * full-on. This causes a white flash during boot... they mark + * the first stage with "Modify In ESP-WROVER-KIT!" on the + * schematics but on Kit v4.1, it's still like that. + */ + }, +}; + +static const lws_led_gpio_controller_t lgc = { + .led_ops = lws_led_gpio_ops, + .gpio_ops = &lws_gpio_plat, + .led_map = &lgm[0], + .count_leds = LWS_ARRAY_SIZE(lgm) +}; + +/* + * Bitbang SPI configuration for display + */ + +static const lws_bb_spi_t lbspi = { + .bb_ops = { + lws_bb_spi_ops, + .bus_mode = LWS_SPI_BUSMODE_CLK_IDLE_LOW_SAMP_RISING + }, + .gpio = &lws_gpio_plat, + .clk = GPIO_NUM_19, + .ncs = { GPIO_NUM_22 }, + .ncmd = { GPIO_NUM_21 }, + .mosi = GPIO_NUM_23, + .miso = GPIO_NUM_25, + .flags = LWSBBSPI_FLAG_USE_NCS0 | + LWSBBSPI_FLAG_USE_NCMD0 +}; + +/* + * SPI display + */ + +static const lws_display_ili9341_t disp = { + .disp = { + lws_display_ili9341_ops, + .bl_pwm_ops = &pwm_ops, + .bl_active = &lws_pwmseq_static_on, + .bl_dim = &lws_pwmseq_static_half, + .bl_transition = &lws_pwmseq_linear_wipe, + .bl_index = 3, + .w = 320, + .h = 240, + .latency_wake_ms = 150, + }, + .spi = (lws_spi_ops_t *)&lbspi, + .gpio = &lws_gpio_plat, + .reset_gpio = GPIO_NUM_18, + .spi_index = 0 +}; + +/* + * Settings stored in platform nv + */ + +static const lws_settings_ops_t sett = { + lws_settings_ops_plat +}; + +/* + * Wifi + */ + +static const lws_netdev_ops_t wifi_ops = { + lws_netdev_wifi_plat_ops +}; + +int +init_plat_devices(struct lws_context *ctx) +{ + lws_settings_instance_t *si; + lws_netdevs_t *netdevs = lws_netdevs_from_ctx(ctx); + + si = lws_settings_init(&sett, (void *)"nvs"); + if (!si) { + lwsl_err("%s: failed to create settings instance\n", __func__); + return 1; + } + netdevs->si = si; + +#if 0 + /* + * This is a temp hack to bootstrap the settings to contain the test + * AP ssid and passphrase for one time, so the settings can be stored + * while there's no UI atm + */ + { + lws_wifi_creds_t creds; + + memset(&creds, 0, sizeof(creds)); + + lws_strncpy(creds.ssid, "xxx", sizeof(creds.ssid)); + lws_strncpy(creds.passphrase, "yyy", sizeof(creds.passphrase)); + lws_dll2_add_tail(&creds.list, &netdevs->owner_creds); + + if (lws_netdev_credentials_settings_set(netdevs)) { + lwsl_err("%s: failed to write bootstrap creds\n", + __func__); + return 1; + } + } +#endif + +// if (lws_netdev_instance_wifi_settings_get(si, "netdev.wl0", &niw, &ac)) { +// lwsl_err("%s: unable to fetch wl0 settings\n", __func__); +// return 1; +// } + + /* create the wifi network device and configure it */ + + wnd = (lws_netdev_instance_wifi_t *) + wifi_ops.create(ctx, &wifi_ops, "wl0", NULL); + if (!wnd) { + lwsl_err("%s: failed to create wifi object\n", __func__); + return 1; + } + + wnd->flags |= LNDIW_MODE_STA; + + if (wifi_ops.configure(&wnd->inst, NULL)) { + lwsl_err("%s: failed to configure wifi object\n", __func__); + return 1; + } + + wifi_ops.up(&wnd->inst); + + /* bring up the led controller */ + + lls = lgc.led_ops.create(&lgc.led_ops); + if (!lls) { + lwsl_err("%s: could not create led\n", __func__); + return 1; + } + + /* pwm init must go after the led controller init */ + + pwm_ops.init(&pwm_ops); + + /* ... and the button controller */ + + bcs = lws_button_controller_create(ctx, &bc); + if (!bcs) { + lwsl_err("%s: could not create buttons\n", __func__); + return 1; + } + + lws_button_enable(bcs, 0, lws_button_get_bit(bcs, "user")); + + /* ... bring up spi bb and the display */ + + lbspi.bb_ops.init(&lbspi.bb_ops); + lws_display_state_init(&lds, ctx, 30000, 10000, lls, &disp.disp); + + /* + * Make the RGB LED do something using sequenced PWM... pressing the + * GPIO14 button with single-presses advances the blue channel between + * different sequences + */ + + lws_led_transition(lls, "blue", &lws_pwmseq_sine_endless_fast, + &lws_pwmseq_linear_wipe); + lws_led_transition(lls, "green", &lws_pwmseq_sine_endless_slow, + &lws_pwmseq_linear_wipe); + lws_led_transition(lls, "red", &lws_pwmseq_sine_endless_slow, + &lws_pwmseq_linear_wipe); + + return 0; +} diff -Nru libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-wrover-kit/main/lws-minimal-esp32.c libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-wrover-kit/main/lws-minimal-esp32.c --- libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-wrover-kit/main/lws-minimal-esp32.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-wrover-kit/main/lws-minimal-esp32.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,249 @@ +/* + * lws-minimal-esp32 + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * Configured for ESP32 WROVER KIT + * + * What should be notable about this is there are no esp-idf apis used here or + * any related files, despite we are running on top of stock esp-idf. + */ + +#define LWIP_PROVIDE_ERRNO 1 +#define _ESP_PLATFORM_ERRNO_H_ + +#include +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#include + +#include + +struct lws_context *context; +extern struct lws_led_state *lls; +extern lws_display_state_t lds; +extern struct lws_button_state *bcs; +extern lws_netdev_instance_wifi_t *wnd; + +lws_sorted_usec_list_t sul_pass; + +extern int init_plat_devices(struct lws_context *); + +static const uint8_t logo[] = { +#include "cat-565.h" +}; + +#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) +#include "static-policy.h" +#else +#include "policy.h" +#endif + +static uint8_t flip; + + +typedef struct myss { + struct lws_ss_handle *ss; + void *opaque_data; + /* ... application specific state ... */ + + size_t amount; + +} myss_t; + +/* + * When we're actually happy we passed, we schedule the actual pass + * string to happen a few seconds later, so we can observe what the + * code did after the pass. + */ + +static void +completion_sul_cb(lws_sorted_usec_list_t *sul) +{ + /* + * In CI, we use sai-expect to look for this + * string for success + */ + + lwsl_notice("Completed: PASS\n"); +} + +static int +myss_rx(void *userobj, const uint8_t *buf, size_t len, int flags) +{ + myss_t *m = (myss_t *)userobj; + + lwsl_user("%s: len %d, flags: %d\n", __func__, (int)len, flags); +// lwsl_hexdump_info(buf, len); + m->amount += len; + + if (flags & LWSSS_FLAG_EOM) { + + /* + * If we received the whole message, for our example it means + * we are done. + * + * Howevere we want to record what happened after we received + * the last bit so we can see anything unexpected coming. So + * wait a couple of seconds before sending the PASS magic. + */ + + lwsl_notice("%s: received %u bytes, passing in 10s\n", + __func__, (unsigned int)m->amount); + + lws_sul_schedule(context, 0, &sul_pass, completion_sul_cb, + 10 * LWS_US_PER_SEC); + + return LWSSSSRET_DESTROY_ME; + } + + return 0; +} + +static int +myss_state(void *userobj, void *sh, lws_ss_constate_t state, + lws_ss_tx_ordinal_t ack) +{ + myss_t *m = (myss_t *)userobj; + + lwsl_user("%s: %s, ord 0x%x\n", __func__, lws_ss_state_name(state), + (unsigned int)ack); + + switch (state) { + case LWSSSCS_CREATING: + lws_ss_client_connect(m->ss); + break; + default: + break; + } + + return 0; +} + +static const lws_ss_info_t ssi = { + .handle_offset = offsetof(myss_t, ss), + .opaque_user_data_offset = offsetof(myss_t, opaque_data), + .rx = myss_rx, + .state = myss_state, + .user_alloc = sizeof(myss_t), + .streamtype = "test_stream", +}; + +static const lws_led_sequence_def_t *seqs[] = { + &lws_pwmseq_static_on, + &lws_pwmseq_static_off, + &lws_pwmseq_sine_endless_slow, + &lws_pwmseq_sine_endless_fast, +}; + +static int +smd_cb(void *opaque, lws_smd_class_t _class, lws_usec_t timestamp, void *buf, + size_t len) +{ + + if (!lws_json_simple_strcmp(buf, len, "\"src\":", "bc/user") && + !lws_json_simple_strcmp(buf, len, "\"event\":", "click")) { + lws_led_transition(lls, "blue", seqs[flip & 3], + &lws_pwmseq_linear_wipe); + flip++; + } + + lwsl_hexdump_notice(buf, len); + + if ((_class & LWSSMDCL_SYSTEM_STATE) && + !lws_json_simple_strcmp(buf, len, "\"state\":", "OPERATIONAL")) { + + /* create the secure stream */ + + lwsl_notice("%s: creating test secure stream\n", __func__); + + if (lws_ss_create(context, 0, &ssi, NULL, NULL, NULL, NULL)) { + lwsl_err("%s: failed to create secure stream\n", + __func__); + return -1; + } + } + + if (_class & LWSSMDCL_INTERACTION) + /* + * Any kind of user interaction brings the display back up and + * resets the dimming / blanking timers + */ + lws_display_state_active(&lds); + + return 0; +} + +void +app_main(void) +{ + struct lws_context_creation_info *info; + + lws_set_log_level(1024 | 15, NULL); + + lws_netdev_plat_init(); + lws_netdev_plat_wifi_init(); + + info = malloc(sizeof(*info)); + if (!info) + goto spin; + + memset(info, 0, sizeof(*info)); + + lwsl_notice("LWS test for Espressif ESP32 WROVER KIT\n"); + +#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) + info->pss_policies_json = ss_policy; +#else + info->pss_policies = &_ss_static_policy_entry; +#endif + info->options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | + LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + info->port = CONTEXT_PORT_NO_LISTEN; + info->early_smd_cb = smd_cb; + info->early_smd_class_filter = LWSSMDCL_INTERACTION | + LWSSMDCL_SYSTEM_STATE | + LWSSMDCL_NETWORK; + + context = lws_create_context(info); + if (!context) { + lwsl_err("lws init failed\n"); + goto spin; + } + + /* + * We don't need this after context creation... things it pointed to + * still need to exist though since the context copied the pointers. + */ + + free(info); + + /* devices and init are in devices.c */ + + if (init_plat_devices(context)) + goto spin; + + /* put the cat picture up there and enable the backlight */ + + lds.disp->blit(lds.disp, logo, 0, 0, 320, 240); + lws_display_state_active(&lds); + + /* the lws event loop */ + + do { + taskYIELD(); + } while (lws_service(context, 0) >= 0); + + lwsl_notice("%s: exited event loop\n", __func__); + + +spin: + vTaskDelay(10); + taskYIELD(); + goto spin; +} diff -Nru libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-wrover-kit/main/policy.h libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-wrover-kit/main/policy.h --- libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-wrover-kit/main/policy.h 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-wrover-kit/main/policy.h 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,131 @@ + +static const char * const ss_policy = + "{" + "\"release\":" "\"01234567\"," + "\"product\":" "\"myproduct\"," + "\"schema-version\":" "1," + + "\"retry\": [" /* named backoff / retry strategies */ + "{\"default\": {" + "\"backoff\": [" "1000," + "2000," + "3000," + "5000," + "10000" + "]," + "\"conceal\":" "25," + "\"jitterpc\":" "20," + "\"svalidping\":" "30," + "\"svalidhup\":" "35" + "}}" + "]," + "\"certs\": [" /* named individual certificates in BASE64 DER */ + /* + * Let's Encrypt certs for warmcat.com / libwebsockets.org + */ + "{\"isrg_root_x1\": \"" /* ISRG ROOT X1 */ + "MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw" + "TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh" + "cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4" + "WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu" + "ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY" + "MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc" + "h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+" + "0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U" + "A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW" + "T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH" + "B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC" + "B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv" + "KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn" + "OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn" + "jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw" + "qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI" + "rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV" + "HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq" + "hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL" + "ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ" + "3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK" + "NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5" + "ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur" + "TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC" + "jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc" + "oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq" + "4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA" + "mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d" + "emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=" + "\"}," + "{\"LEX3_isrg_root_x1\": \"" /* LE X3 signed by ISRG X1 root */ + "MIIFjTCCA3WgAwIBAgIRANOxciY0IzLc9AUoUSrsnGowDQYJKoZIhvcNAQELBQAw" + "TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh" + "cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTYxMDA2MTU0MzU1" + "WhcNMjExMDA2MTU0MzU1WjBKMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg" + "RW5jcnlwdDEjMCEGA1UEAxMaTGV0J3MgRW5jcnlwdCBBdXRob3JpdHkgWDMwggEi" + "MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCc0wzwWuUuR7dyXTeDs2hjMOrX" + "NSYZJeG9vjXxcJIvt7hLQQWrqZ41CFjssSrEaIcLo+N15Obzp2JxunmBYB/XkZqf" + "89B4Z3HIaQ6Vkc/+5pnpYDxIzH7KTXcSJJ1HG1rrueweNwAcnKx7pwXqzkrrvUHl" + "Npi5y/1tPJZo3yMqQpAMhnRnyH+lmrhSYRQTP2XpgofL2/oOVvaGifOFP5eGr7Dc" + "Gu9rDZUWfcQroGWymQQ2dYBrrErzG5BJeC+ilk8qICUpBMZ0wNAxzY8xOJUWuqgz" + "uEPxsR/DMH+ieTETPS02+OP88jNquTkxxa/EjQ0dZBYzqvqEKbbUC8DYfcOTAgMB" + "AAGjggFnMIIBYzAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADBU" + "BgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEBATAwMC4GCCsGAQUFBwIB" + "FiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQub3JnMB0GA1UdDgQWBBSo" + "SmpjBH3duubRObemRWXv86jsoTAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8vY3Js" + "LnJvb3QteDEubGV0c2VuY3J5cHQub3JnMHIGCCsGAQUFBwEBBGYwZDAwBggrBgEF" + "BQcwAYYkaHR0cDovL29jc3Aucm9vdC14MS5sZXRzZW5jcnlwdC5vcmcvMDAGCCsG" + "AQUFBzAChiRodHRwOi8vY2VydC5yb290LXgxLmxldHNlbmNyeXB0Lm9yZy8wHwYD" + "VR0jBBgwFoAUebRZ5nu25eQBc4AIiMgaWPbpm24wDQYJKoZIhvcNAQELBQADggIB" + "ABnPdSA0LTqmRf/Q1eaM2jLonG4bQdEnqOJQ8nCqxOeTRrToEKtwT++36gTSlBGx" + "A/5dut82jJQ2jxN8RI8L9QFXrWi4xXnA2EqA10yjHiR6H9cj6MFiOnb5In1eWsRM" + "UM2v3e9tNsCAgBukPHAg1lQh07rvFKm/Bz9BCjaxorALINUfZ9DD64j2igLIxle2" + "DPxW8dI/F2loHMjXZjqG8RkqZUdoxtID5+90FgsGIfkMpqgRS05f4zPbCEHqCXl1" + "eO5HyELTgcVlLXXQDgAWnRzut1hFJeczY1tjQQno6f6s+nMydLN26WuU4s3UYvOu" + "OsUxRlJu7TSRHqDC3lSE5XggVkzdaPkuKGQbGpny+01/47hfXXNB7HntWNZ6N2Vw" + "p7G6OfY+YQrZwIaQmhrIqJZuigsrbe3W+gdn5ykE9+Ky0VgVUsfxo52mwFYs1JKY" + "2PGDuWx8M6DlS6qQkvHaRUo0FMd8TsSlbF0/v965qGFKhSDeQoMpYnwcmQilRh/0" + "ayLThlHLN81gSkJjVrPI0Y8xCVPB4twb1PFUd2fPM3sA1tJ83sZ5v8vgFv2yofKR" + "PB0t6JzUA81mSqM3kxl5e+IZwhYAyO0OTg3/fs8HqGTNKd9BqoUwSRBzp06JMg5b" + "rUCGwbCUDI0mxadJ3Bz4WxR6fyNpBK2yAinWEsikxqEt" + "\"}" + "]," + "\"trust_stores\": [" /* named cert chains */ + "{" + "\"name\": \"le_via_isrg\"," + "\"stack\": [" + "\"isrg_root_x1\"," + "\"LEX3_isrg_root_x1\"" + "]" + "}" + "]," + "\"s\": [" + + "{\"test_stream\": {" + "\"endpoint\":" "\"warmcat.com\"," + "\"port\":" "443," + "\"protocol\":" "\"h2\"," + "\"http_method\":" "\"GET\"," + "\"http_url\":" "\"index.html\"," + "\"tls\":" "true," + "\"opportunistic\":" "true," + "\"retry\":" "\"default\"," + "\"tls_trust_store\":" "\"le_via_isrg\"" + "}},{" + /* + * "captive_portal_detect" describes + * what to do in order to check if the path to + * the Internet is being interrupted by a + * captive portal. + */ + "\"captive_portal_detect\": {" + "\"endpoint\":" "\"connectivitycheck.android.com\"," + "\"http_url\":" "\"generate_204\"," + "\"port\":" "80," + "\"protocol\":" "\"h1\"," + "\"http_method\":" "\"GET\"," + "\"opportunistic\":" "true," + "\"http_expect\":" "204," + "\"http_fail_redirect\": true" + "}}" + "]}" +; + + diff -Nru libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-wrover-kit/main/static-policy.h libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-wrover-kit/main/static-policy.h --- libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-wrover-kit/main/static-policy.h 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-wrover-kit/main/static-policy.h 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,488 @@ +/* + * Autogenerated from the following JSON policy + */ + +#if 0 + { + "release": "01234567", + "product": "myproduct", + "schema-version": 1, + + "retry": [ + {"default": { + "backoff": [ 1000, + 2000, + 3000, + 5000, + 10000 + ], + "conceal": 25, + "jitterpc": 20, + "svalidping": 30, + "svalidhup": 35 + }} + ], + "certs": [ + {"isrg_root_x1": + "MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygch77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6UA5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sWT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyHB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UCB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUvKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWnOlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTnjh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbwqHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CIrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkqhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZLubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KKNFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7UrTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdCjNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVcoyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPAmRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57demyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=" + }, + {"LEX3_isrg_root_x1": + "MIIFjTCCA3WgAwIBAgIRANOxciY0IzLc9AUoUSrsnGowDQYJKoZIhvcNAQELBQAwTzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTYxMDA2MTU0MzU1WhcNMjExMDA2MTU0MzU1WjBKMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3MgRW5jcnlwdDEjMCEGA1UEAxMaTGV0J3MgRW5jcnlwdCBBdXRob3JpdHkgWDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCc0wzwWuUuR7dyXTeDs2hjMOrXNSYZJeG9vjXxcJIvt7hLQQWrqZ41CFjssSrEaIcLo+N15Obzp2JxunmBYB/XkZqf89B4Z3HIaQ6Vkc/+5pnpYDxIzH7KTXcSJJ1HG1rrueweNwAcnKx7pwXqzkrrvUHlNpi5y/1tPJZo3yMqQpAMhnRnyH+lmrhSYRQTP2XpgofL2/oOVvaGifOFP5eGr7DcGu9rDZUWfcQroGWymQQ2dYBrrErzG5BJeC+ilk8qICUpBMZ0wNAxzY8xOJUWuqgzuEPxsR/DMH+ieTETPS02+OP88jNquTkxxa/EjQ0dZBYzqvqEKbbUC8DYfcOTAgMBAAGjggFnMIIBYzAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEBATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQub3JnMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8vY3JsLnJvb3QteDEubGV0c2VuY3J5cHQub3JnMHIGCCsGAQUFBwEBBGYwZDAwBggrBgEFBQcwAYYkaHR0cDovL29jc3Aucm9vdC14MS5sZXRzZW5jcnlwdC5vcmcvMDAGCCsGAQUFBzAChiRodHRwOi8vY2VydC5yb290LXgxLmxldHNlbmNyeXB0Lm9yZy8wHwYDVR0jBBgwFoAUebRZ5nu25eQBc4AIiMgaWPbpm24wDQYJKoZIhvcNAQELBQADggIBABnPdSA0LTqmRf/Q1eaM2jLonG4bQdEnqOJQ8nCqxOeTRrToEKtwT++36gTSlBGxA/5dut82jJQ2jxN8RI8L9QFXrWi4xXnA2EqA10yjHiR6H9cj6MFiOnb5In1eWsRMUM2v3e9tNsCAgBukPHAg1lQh07rvFKm/Bz9BCjaxorALINUfZ9DD64j2igLIxle2DPxW8dI/F2loHMjXZjqG8RkqZUdoxtID5+90FgsGIfkMpqgRS05f4zPbCEHqCXl1eO5HyELTgcVlLXXQDgAWnRzut1hFJeczY1tjQQno6f6s+nMydLN26WuU4s3UYvOuOsUxRlJu7TSRHqDC3lSE5XggVkzdaPkuKGQbGpny+01/47hfXXNB7HntWNZ6N2Vwp7G6OfY+YQrZwIaQmhrIqJZuigsrbe3W+gdn5ykE9+Ky0VgVUsfxo52mwFYs1JKY2PGDuWx8M6DlS6qQkvHaRUo0FMd8TsSlbF0/v965qGFKhSDeQoMpYnwcmQilRh/0ayLThlHLN81gSkJjVrPI0Y8xCVPB4twb1PFUd2fPM3sA1tJ83sZ5v8vgFv2yofKRPB0t6JzUA81mSqM3kxl5e+IZwhYAyO0OTg3/fs8HqGTNKd9BqoUwSRBzp06JMg5brUCGwbCUDI0mxadJ3Bz4WxR6fyNpBK2yAinWEsikxqEt"} + ], + "trust_stores": [ + { + "name": "le_via_isrg", + "stack": [ + "isrg_root_x1", + "LEX3_isrg_root_x1" + ] + } + ], + "s": [ + + {"test_stream": { + "endpoint": "warmcat.com", + "port": 443, + "protocol": "h2", + "http_method": "GET", + "http_url": "index.html", + "tls": true, + "opportunistic": true, + "retry": "default", + "tls_trust_store": "le_via_isrg" + }},{ + "captive_portal_detect": { + "endpoint": "connectivitycheck.android.com", + "http_url": "generate_204", + "port": 80, + "protocol": "h1", + "http_method": "GET", + "opportunistic": true, + "http_expect": 204, + "http_fail_redirect": true + }} + ]} + + + Original JSON size: 4903 +#endif + +static const uint32_t _rbo_bo_0[] = { + 1000, 2000, 3000, 5000, 10000, +}; +static const lws_retry_bo_t _rbo_0 = { + .retry_ms_table = _rbo_bo_0, + .retry_ms_table_count = 5, + .conceal_count = 25, + .secs_since_valid_ping = 30, + .secs_since_valid_hangup = 35, + .jitter_percent = 20, +}; +static const uint8_t _ss_der_isrg_root_x1[] = { + /* 0x 0 */ 0x30, 0x82, 0x05, 0x6B, 0x30, 0x82, 0x03, 0x53, + /* 0x 8 */ 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x11, 0x00, + /* 0x 10 */ 0x82, 0x10, 0xCF, 0xB0, 0xD2, 0x40, 0xE3, 0x59, + /* 0x 18 */ 0x44, 0x63, 0xE0, 0xBB, 0x63, 0x82, 0x8B, 0x00, + /* 0x 20 */ 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + /* 0x 28 */ 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, + /* 0x 30 */ 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + /* 0x 38 */ 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x29, + /* 0x 40 */ 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, + /* 0x 48 */ 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, + /* 0x 50 */ 0x74, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, + /* 0x 58 */ 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, + /* 0x 60 */ 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6F, 0x75, + /* 0x 68 */ 0x70, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, + /* 0x 70 */ 0x04, 0x03, 0x13, 0x0C, 0x49, 0x53, 0x52, 0x47, + /* 0x 78 */ 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, 0x31, + /* 0x 80 */ 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x35, 0x30, 0x36, + /* 0x 88 */ 0x30, 0x34, 0x31, 0x31, 0x30, 0x34, 0x33, 0x38, + /* 0x 90 */ 0x5A, 0x17, 0x0D, 0x33, 0x35, 0x30, 0x36, 0x30, + /* 0x 98 */ 0x34, 0x31, 0x31, 0x30, 0x34, 0x33, 0x38, 0x5A, + /* 0x a0 */ 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, + /* 0x a8 */ 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, + /* 0x b0 */ 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0A, + /* 0x b8 */ 0x13, 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, + /* 0x c0 */ 0x65, 0x74, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, + /* 0x c8 */ 0x69, 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, + /* 0x d0 */ 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6F, + /* 0x d8 */ 0x75, 0x70, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, + /* 0x e0 */ 0x55, 0x04, 0x03, 0x13, 0x0C, 0x49, 0x53, 0x52, + /* 0x e8 */ 0x47, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, + /* 0x f0 */ 0x31, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0D, 0x06, + /* 0x f8 */ 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + /* 0x100 */ 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0F, + /* 0x108 */ 0x00, 0x30, 0x82, 0x02, 0x0A, 0x02, 0x82, 0x02, + /* 0x110 */ 0x01, 0x00, 0xAD, 0xE8, 0x24, 0x73, 0xF4, 0x14, + /* 0x118 */ 0x37, 0xF3, 0x9B, 0x9E, 0x2B, 0x57, 0x28, 0x1C, + /* 0x120 */ 0x87, 0xBE, 0xDC, 0xB7, 0xDF, 0x38, 0x90, 0x8C, + /* 0x128 */ 0x6E, 0x3C, 0xE6, 0x57, 0xA0, 0x78, 0xF7, 0x75, + /* 0x130 */ 0xC2, 0xA2, 0xFE, 0xF5, 0x6A, 0x6E, 0xF6, 0x00, + /* 0x138 */ 0x4F, 0x28, 0xDB, 0xDE, 0x68, 0x86, 0x6C, 0x44, + /* 0x140 */ 0x93, 0xB6, 0xB1, 0x63, 0xFD, 0x14, 0x12, 0x6B, + /* 0x148 */ 0xBF, 0x1F, 0xD2, 0xEA, 0x31, 0x9B, 0x21, 0x7E, + /* 0x150 */ 0xD1, 0x33, 0x3C, 0xBA, 0x48, 0xF5, 0xDD, 0x79, + /* 0x158 */ 0xDF, 0xB3, 0xB8, 0xFF, 0x12, 0xF1, 0x21, 0x9A, + /* 0x160 */ 0x4B, 0xC1, 0x8A, 0x86, 0x71, 0x69, 0x4A, 0x66, + /* 0x168 */ 0x66, 0x6C, 0x8F, 0x7E, 0x3C, 0x70, 0xBF, 0xAD, + /* 0x170 */ 0x29, 0x22, 0x06, 0xF3, 0xE4, 0xC0, 0xE6, 0x80, + /* 0x178 */ 0xAE, 0xE2, 0x4B, 0x8F, 0xB7, 0x99, 0x7E, 0x94, + /* 0x180 */ 0x03, 0x9F, 0xD3, 0x47, 0x97, 0x7C, 0x99, 0x48, + /* 0x188 */ 0x23, 0x53, 0xE8, 0x38, 0xAE, 0x4F, 0x0A, 0x6F, + /* 0x190 */ 0x83, 0x2E, 0xD1, 0x49, 0x57, 0x8C, 0x80, 0x74, + /* 0x198 */ 0xB6, 0xDA, 0x2F, 0xD0, 0x38, 0x8D, 0x7B, 0x03, + /* 0x1a0 */ 0x70, 0x21, 0x1B, 0x75, 0xF2, 0x30, 0x3C, 0xFA, + /* 0x1a8 */ 0x8F, 0xAE, 0xDD, 0xDA, 0x63, 0xAB, 0xEB, 0x16, + /* 0x1b0 */ 0x4F, 0xC2, 0x8E, 0x11, 0x4B, 0x7E, 0xCF, 0x0B, + /* 0x1b8 */ 0xE8, 0xFF, 0xB5, 0x77, 0x2E, 0xF4, 0xB2, 0x7B, + /* 0x1c0 */ 0x4A, 0xE0, 0x4C, 0x12, 0x25, 0x0C, 0x70, 0x8D, + /* 0x1c8 */ 0x03, 0x29, 0xA0, 0xE1, 0x53, 0x24, 0xEC, 0x13, + /* 0x1d0 */ 0xD9, 0xEE, 0x19, 0xBF, 0x10, 0xB3, 0x4A, 0x8C, + /* 0x1d8 */ 0x3F, 0x89, 0xA3, 0x61, 0x51, 0xDE, 0xAC, 0x87, + /* 0x1e0 */ 0x07, 0x94, 0xF4, 0x63, 0x71, 0xEC, 0x2E, 0xE2, + /* 0x1e8 */ 0x6F, 0x5B, 0x98, 0x81, 0xE1, 0x89, 0x5C, 0x34, + /* 0x1f0 */ 0x79, 0x6C, 0x76, 0xEF, 0x3B, 0x90, 0x62, 0x79, + /* 0x1f8 */ 0xE6, 0xDB, 0xA4, 0x9A, 0x2F, 0x26, 0xC5, 0xD0, + /* 0x200 */ 0x10, 0xE1, 0x0E, 0xDE, 0xD9, 0x10, 0x8E, 0x16, + /* 0x208 */ 0xFB, 0xB7, 0xF7, 0xA8, 0xF7, 0xC7, 0xE5, 0x02, + /* 0x210 */ 0x07, 0x98, 0x8F, 0x36, 0x08, 0x95, 0xE7, 0xE2, + /* 0x218 */ 0x37, 0x96, 0x0D, 0x36, 0x75, 0x9E, 0xFB, 0x0E, + /* 0x220 */ 0x72, 0xB1, 0x1D, 0x9B, 0xBC, 0x03, 0xF9, 0x49, + /* 0x228 */ 0x05, 0xD8, 0x81, 0xDD, 0x05, 0xB4, 0x2A, 0xD6, + /* 0x230 */ 0x41, 0xE9, 0xAC, 0x01, 0x76, 0x95, 0x0A, 0x0F, + /* 0x238 */ 0xD8, 0xDF, 0xD5, 0xBD, 0x12, 0x1F, 0x35, 0x2F, + /* 0x240 */ 0x28, 0x17, 0x6C, 0xD2, 0x98, 0xC1, 0xA8, 0x09, + /* 0x248 */ 0x64, 0x77, 0x6E, 0x47, 0x37, 0xBA, 0xCE, 0xAC, + /* 0x250 */ 0x59, 0x5E, 0x68, 0x9D, 0x7F, 0x72, 0xD6, 0x89, + /* 0x258 */ 0xC5, 0x06, 0x41, 0x29, 0x3E, 0x59, 0x3E, 0xDD, + /* 0x260 */ 0x26, 0xF5, 0x24, 0xC9, 0x11, 0xA7, 0x5A, 0xA3, + /* 0x268 */ 0x4C, 0x40, 0x1F, 0x46, 0xA1, 0x99, 0xB5, 0xA7, + /* 0x270 */ 0x3A, 0x51, 0x6E, 0x86, 0x3B, 0x9E, 0x7D, 0x72, + /* 0x278 */ 0xA7, 0x12, 0x05, 0x78, 0x59, 0xED, 0x3E, 0x51, + /* 0x280 */ 0x78, 0x15, 0x0B, 0x03, 0x8F, 0x8D, 0xD0, 0x2F, + /* 0x288 */ 0x05, 0xB2, 0x3E, 0x7B, 0x4A, 0x1C, 0x4B, 0x73, + /* 0x290 */ 0x05, 0x12, 0xFC, 0xC6, 0xEA, 0xE0, 0x50, 0x13, + /* 0x298 */ 0x7C, 0x43, 0x93, 0x74, 0xB3, 0xCA, 0x74, 0xE7, + /* 0x2a0 */ 0x8E, 0x1F, 0x01, 0x08, 0xD0, 0x30, 0xD4, 0x5B, + /* 0x2a8 */ 0x71, 0x36, 0xB4, 0x07, 0xBA, 0xC1, 0x30, 0x30, + /* 0x2b0 */ 0x5C, 0x48, 0xB7, 0x82, 0x3B, 0x98, 0xA6, 0x7D, + /* 0x2b8 */ 0x60, 0x8A, 0xA2, 0xA3, 0x29, 0x82, 0xCC, 0xBA, + /* 0x2c0 */ 0xBD, 0x83, 0x04, 0x1B, 0xA2, 0x83, 0x03, 0x41, + /* 0x2c8 */ 0xA1, 0xD6, 0x05, 0xF1, 0x1B, 0xC2, 0xB6, 0xF0, + /* 0x2d0 */ 0xA8, 0x7C, 0x86, 0x3B, 0x46, 0xA8, 0x48, 0x2A, + /* 0x2d8 */ 0x88, 0xDC, 0x76, 0x9A, 0x76, 0xBF, 0x1F, 0x6A, + /* 0x2e0 */ 0xA5, 0x3D, 0x19, 0x8F, 0xEB, 0x38, 0xF3, 0x64, + /* 0x2e8 */ 0xDE, 0xC8, 0x2B, 0x0D, 0x0A, 0x28, 0xFF, 0xF7, + /* 0x2f0 */ 0xDB, 0xE2, 0x15, 0x42, 0xD4, 0x22, 0xD0, 0x27, + /* 0x2f8 */ 0x5D, 0xE1, 0x79, 0xFE, 0x18, 0xE7, 0x70, 0x88, + /* 0x300 */ 0xAD, 0x4E, 0xE6, 0xD9, 0x8B, 0x3A, 0xC6, 0xDD, + /* 0x308 */ 0x27, 0x51, 0x6E, 0xFF, 0xBC, 0x64, 0xF5, 0x33, + /* 0x310 */ 0x43, 0x4F, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, + /* 0x318 */ 0x42, 0x30, 0x40, 0x30, 0x0E, 0x06, 0x03, 0x55, + /* 0x320 */ 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, + /* 0x328 */ 0x02, 0x01, 0x06, 0x30, 0x0F, 0x06, 0x03, 0x55, + /* 0x330 */ 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, + /* 0x338 */ 0x03, 0x01, 0x01, 0xFF, 0x30, 0x1D, 0x06, 0x03, + /* 0x340 */ 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x79, + /* 0x348 */ 0xB4, 0x59, 0xE6, 0x7B, 0xB6, 0xE5, 0xE4, 0x01, + /* 0x350 */ 0x73, 0x80, 0x08, 0x88, 0xC8, 0x1A, 0x58, 0xF6, + /* 0x358 */ 0xE9, 0x9B, 0x6E, 0x30, 0x0D, 0x06, 0x09, 0x2A, + /* 0x360 */ 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, + /* 0x368 */ 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x55, + /* 0x370 */ 0x1F, 0x58, 0xA9, 0xBC, 0xB2, 0xA8, 0x50, 0xD0, + /* 0x378 */ 0x0C, 0xB1, 0xD8, 0x1A, 0x69, 0x20, 0x27, 0x29, + /* 0x380 */ 0x08, 0xAC, 0x61, 0x75, 0x5C, 0x8A, 0x6E, 0xF8, + /* 0x388 */ 0x82, 0xE5, 0x69, 0x2F, 0xD5, 0xF6, 0x56, 0x4B, + /* 0x390 */ 0xB9, 0xB8, 0x73, 0x10, 0x59, 0xD3, 0x21, 0x97, + /* 0x398 */ 0x7E, 0xE7, 0x4C, 0x71, 0xFB, 0xB2, 0xD2, 0x60, + /* 0x3a0 */ 0xAD, 0x39, 0xA8, 0x0B, 0xEA, 0x17, 0x21, 0x56, + /* 0x3a8 */ 0x85, 0xF1, 0x50, 0x0E, 0x59, 0xEB, 0xCE, 0xE0, + /* 0x3b0 */ 0x59, 0xE9, 0xBA, 0xC9, 0x15, 0xEF, 0x86, 0x9D, + /* 0x3b8 */ 0x8F, 0x84, 0x80, 0xF6, 0xE4, 0xE9, 0x91, 0x90, + /* 0x3c0 */ 0xDC, 0x17, 0x9B, 0x62, 0x1B, 0x45, 0xF0, 0x66, + /* 0x3c8 */ 0x95, 0xD2, 0x7C, 0x6F, 0xC2, 0xEA, 0x3B, 0xEF, + /* 0x3d0 */ 0x1F, 0xCF, 0xCB, 0xD6, 0xAE, 0x27, 0xF1, 0xA9, + /* 0x3d8 */ 0xB0, 0xC8, 0xAE, 0xFD, 0x7D, 0x7E, 0x9A, 0xFA, + /* 0x3e0 */ 0x22, 0x04, 0xEB, 0xFF, 0xD9, 0x7F, 0xEA, 0x91, + /* 0x3e8 */ 0x2B, 0x22, 0xB1, 0x17, 0x0E, 0x8F, 0xF2, 0x8A, + /* 0x3f0 */ 0x34, 0x5B, 0x58, 0xD8, 0xFC, 0x01, 0xC9, 0x54, + /* 0x3f8 */ 0xB9, 0xB8, 0x26, 0xCC, 0x8A, 0x88, 0x33, 0x89, + /* 0x400 */ 0x4C, 0x2D, 0x84, 0x3C, 0x82, 0xDF, 0xEE, 0x96, + /* 0x408 */ 0x57, 0x05, 0xBA, 0x2C, 0xBB, 0xF7, 0xC4, 0xB7, + /* 0x410 */ 0xC7, 0x4E, 0x3B, 0x82, 0xBE, 0x31, 0xC8, 0x22, + /* 0x418 */ 0x73, 0x73, 0x92, 0xD1, 0xC2, 0x80, 0xA4, 0x39, + /* 0x420 */ 0x39, 0x10, 0x33, 0x23, 0x82, 0x4C, 0x3C, 0x9F, + /* 0x428 */ 0x86, 0xB2, 0x55, 0x98, 0x1D, 0xBE, 0x29, 0x86, + /* 0x430 */ 0x8C, 0x22, 0x9B, 0x9E, 0xE2, 0x6B, 0x3B, 0x57, + /* 0x438 */ 0x3A, 0x82, 0x70, 0x4D, 0xDC, 0x09, 0xC7, 0x89, + /* 0x440 */ 0xCB, 0x0A, 0x07, 0x4D, 0x6C, 0xE8, 0x5D, 0x8E, + /* 0x448 */ 0xC9, 0xEF, 0xCE, 0xAB, 0xC7, 0xBB, 0xB5, 0x2B, + /* 0x450 */ 0x4E, 0x45, 0xD6, 0x4A, 0xD0, 0x26, 0xCC, 0xE5, + /* 0x458 */ 0x72, 0xCA, 0x08, 0x6A, 0xA5, 0x95, 0xE3, 0x15, + /* 0x460 */ 0xA1, 0xF7, 0xA4, 0xED, 0xC9, 0x2C, 0x5F, 0xA5, + /* 0x468 */ 0xFB, 0xFF, 0xAC, 0x28, 0x02, 0x2E, 0xBE, 0xD7, + /* 0x470 */ 0x7B, 0xBB, 0xE3, 0x71, 0x7B, 0x90, 0x16, 0xD3, + /* 0x478 */ 0x07, 0x5E, 0x46, 0x53, 0x7C, 0x37, 0x07, 0x42, + /* 0x480 */ 0x8C, 0xD3, 0xC4, 0x96, 0x9C, 0xD5, 0x99, 0xB5, + /* 0x488 */ 0x2A, 0xE0, 0x95, 0x1A, 0x80, 0x48, 0xAE, 0x4C, + /* 0x490 */ 0x39, 0x07, 0xCE, 0xCC, 0x47, 0xA4, 0x52, 0x95, + /* 0x498 */ 0x2B, 0xBA, 0xB8, 0xFB, 0xAD, 0xD2, 0x33, 0x53, + /* 0x4a0 */ 0x7D, 0xE5, 0x1D, 0x4D, 0x6D, 0xD5, 0xA1, 0xB1, + /* 0x4a8 */ 0xC7, 0x42, 0x6F, 0xE6, 0x40, 0x27, 0x35, 0x5C, + /* 0x4b0 */ 0xA3, 0x28, 0xB7, 0x07, 0x8D, 0xE7, 0x8D, 0x33, + /* 0x4b8 */ 0x90, 0xE7, 0x23, 0x9F, 0xFB, 0x50, 0x9C, 0x79, + /* 0x4c0 */ 0x6C, 0x46, 0xD5, 0xB4, 0x15, 0xB3, 0x96, 0x6E, + /* 0x4c8 */ 0x7E, 0x9B, 0x0C, 0x96, 0x3A, 0xB8, 0x52, 0x2D, + /* 0x4d0 */ 0x3F, 0xD6, 0x5B, 0xE1, 0xFB, 0x08, 0xC2, 0x84, + /* 0x4d8 */ 0xFE, 0x24, 0xA8, 0xA3, 0x89, 0xDA, 0xAC, 0x6A, + /* 0x4e0 */ 0xE1, 0x18, 0x2A, 0xB1, 0xA8, 0x43, 0x61, 0x5B, + /* 0x4e8 */ 0xD3, 0x1F, 0xDC, 0x3B, 0x8D, 0x76, 0xF2, 0x2D, + /* 0x4f0 */ 0xE8, 0x8D, 0x75, 0xDF, 0x17, 0x33, 0x6C, 0x3D, + /* 0x4f8 */ 0x53, 0xFB, 0x7B, 0xCB, 0x41, 0x5F, 0xFF, 0xDC, + /* 0x500 */ 0xA2, 0xD0, 0x61, 0x38, 0xE1, 0x96, 0xB8, 0xAC, + /* 0x508 */ 0x5D, 0x8B, 0x37, 0xD7, 0x75, 0xD5, 0x33, 0xC0, + /* 0x510 */ 0x99, 0x11, 0xAE, 0x9D, 0x41, 0xC1, 0x72, 0x75, + /* 0x518 */ 0x84, 0xBE, 0x02, 0x41, 0x42, 0x5F, 0x67, 0x24, + /* 0x520 */ 0x48, 0x94, 0xD1, 0x9B, 0x27, 0xBE, 0x07, 0x3F, + /* 0x528 */ 0xB9, 0xB8, 0x4F, 0x81, 0x74, 0x51, 0xE1, 0x7A, + /* 0x530 */ 0xB7, 0xED, 0x9D, 0x23, 0xE2, 0xBE, 0xE0, 0xD5, + /* 0x538 */ 0x28, 0x04, 0x13, 0x3C, 0x31, 0x03, 0x9E, 0xDD, + /* 0x540 */ 0x7A, 0x6C, 0x8F, 0xC6, 0x07, 0x18, 0xC6, 0x7F, + /* 0x548 */ 0xDE, 0x47, 0x8E, 0x3F, 0x28, 0x9E, 0x04, 0x06, + /* 0x550 */ 0xCF, 0xA5, 0x54, 0x34, 0x77, 0xBD, 0xEC, 0x89, + /* 0x558 */ 0x9B, 0xE9, 0x17, 0x43, 0xDF, 0x5B, 0xDB, 0x5F, + /* 0x560 */ 0xFE, 0x8E, 0x1E, 0x57, 0xA2, 0xCD, 0x40, 0x9D, + /* 0x568 */ 0x7E, 0x62, 0x22, 0xDA, 0xDE, 0x18, 0x27, +}; +static const lws_ss_x509_t _ss_x509_isrg_root_x1 = { + .vhost_name = "isrg_root_x1", + .ca_der = _ss_der_isrg_root_x1, + .ca_der_len = 1391, +}; +static const uint8_t _ss_der_LEX3_isrg_root_x1[] = { + /* 0x 0 */ 0x30, 0x82, 0x05, 0x8D, 0x30, 0x82, 0x03, 0x75, + /* 0x 8 */ 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x11, 0x00, + /* 0x 10 */ 0xD3, 0xB1, 0x72, 0x26, 0x34, 0x23, 0x32, 0xDC, + /* 0x 18 */ 0xF4, 0x05, 0x28, 0x51, 0x2A, 0xEC, 0x9C, 0x6A, + /* 0x 20 */ 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + /* 0x 28 */ 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, + /* 0x 30 */ 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + /* 0x 38 */ 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x29, + /* 0x 40 */ 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, + /* 0x 48 */ 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, + /* 0x 50 */ 0x74, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, + /* 0x 58 */ 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, + /* 0x 60 */ 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6F, 0x75, + /* 0x 68 */ 0x70, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, + /* 0x 70 */ 0x04, 0x03, 0x13, 0x0C, 0x49, 0x53, 0x52, 0x47, + /* 0x 78 */ 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, 0x31, + /* 0x 80 */ 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x36, 0x31, 0x30, + /* 0x 88 */ 0x30, 0x36, 0x31, 0x35, 0x34, 0x33, 0x35, 0x35, + /* 0x 90 */ 0x5A, 0x17, 0x0D, 0x32, 0x31, 0x31, 0x30, 0x30, + /* 0x 98 */ 0x36, 0x31, 0x35, 0x34, 0x33, 0x35, 0x35, 0x5A, + /* 0x a0 */ 0x30, 0x4A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, + /* 0x a8 */ 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, + /* 0x b0 */ 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, + /* 0x b8 */ 0x13, 0x0D, 0x4C, 0x65, 0x74, 0x27, 0x73, 0x20, + /* 0x c0 */ 0x45, 0x6E, 0x63, 0x72, 0x79, 0x70, 0x74, 0x31, + /* 0x c8 */ 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x03, + /* 0x d0 */ 0x13, 0x1A, 0x4C, 0x65, 0x74, 0x27, 0x73, 0x20, + /* 0x d8 */ 0x45, 0x6E, 0x63, 0x72, 0x79, 0x70, 0x74, 0x20, + /* 0x e0 */ 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, + /* 0x e8 */ 0x79, 0x20, 0x58, 0x33, 0x30, 0x82, 0x01, 0x22, + /* 0x f0 */ 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + /* 0x f8 */ 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, + /* 0x100 */ 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, + /* 0x108 */ 0x02, 0x82, 0x01, 0x01, 0x00, 0x9C, 0xD3, 0x0C, + /* 0x110 */ 0xF0, 0x5A, 0xE5, 0x2E, 0x47, 0xB7, 0x72, 0x5D, + /* 0x118 */ 0x37, 0x83, 0xB3, 0x68, 0x63, 0x30, 0xEA, 0xD7, + /* 0x120 */ 0x35, 0x26, 0x19, 0x25, 0xE1, 0xBD, 0xBE, 0x35, + /* 0x128 */ 0xF1, 0x70, 0x92, 0x2F, 0xB7, 0xB8, 0x4B, 0x41, + /* 0x130 */ 0x05, 0xAB, 0xA9, 0x9E, 0x35, 0x08, 0x58, 0xEC, + /* 0x138 */ 0xB1, 0x2A, 0xC4, 0x68, 0x87, 0x0B, 0xA3, 0xE3, + /* 0x140 */ 0x75, 0xE4, 0xE6, 0xF3, 0xA7, 0x62, 0x71, 0xBA, + /* 0x148 */ 0x79, 0x81, 0x60, 0x1F, 0xD7, 0x91, 0x9A, 0x9F, + /* 0x150 */ 0xF3, 0xD0, 0x78, 0x67, 0x71, 0xC8, 0x69, 0x0E, + /* 0x158 */ 0x95, 0x91, 0xCF, 0xFE, 0xE6, 0x99, 0xE9, 0x60, + /* 0x160 */ 0x3C, 0x48, 0xCC, 0x7E, 0xCA, 0x4D, 0x77, 0x12, + /* 0x168 */ 0x24, 0x9D, 0x47, 0x1B, 0x5A, 0xEB, 0xB9, 0xEC, + /* 0x170 */ 0x1E, 0x37, 0x00, 0x1C, 0x9C, 0xAC, 0x7B, 0xA7, + /* 0x178 */ 0x05, 0xEA, 0xCE, 0x4A, 0xEB, 0xBD, 0x41, 0xE5, + /* 0x180 */ 0x36, 0x98, 0xB9, 0xCB, 0xFD, 0x6D, 0x3C, 0x96, + /* 0x188 */ 0x68, 0xDF, 0x23, 0x2A, 0x42, 0x90, 0x0C, 0x86, + /* 0x190 */ 0x74, 0x67, 0xC8, 0x7F, 0xA5, 0x9A, 0xB8, 0x52, + /* 0x198 */ 0x61, 0x14, 0x13, 0x3F, 0x65, 0xE9, 0x82, 0x87, + /* 0x1a0 */ 0xCB, 0xDB, 0xFA, 0x0E, 0x56, 0xF6, 0x86, 0x89, + /* 0x1a8 */ 0xF3, 0x85, 0x3F, 0x97, 0x86, 0xAF, 0xB0, 0xDC, + /* 0x1b0 */ 0x1A, 0xEF, 0x6B, 0x0D, 0x95, 0x16, 0x7D, 0xC4, + /* 0x1b8 */ 0x2B, 0xA0, 0x65, 0xB2, 0x99, 0x04, 0x36, 0x75, + /* 0x1c0 */ 0x80, 0x6B, 0xAC, 0x4A, 0xF3, 0x1B, 0x90, 0x49, + /* 0x1c8 */ 0x78, 0x2F, 0xA2, 0x96, 0x4F, 0x2A, 0x20, 0x25, + /* 0x1d0 */ 0x29, 0x04, 0xC6, 0x74, 0xC0, 0xD0, 0x31, 0xCD, + /* 0x1d8 */ 0x8F, 0x31, 0x38, 0x95, 0x16, 0xBA, 0xA8, 0x33, + /* 0x1e0 */ 0xB8, 0x43, 0xF1, 0xB1, 0x1F, 0xC3, 0x30, 0x7F, + /* 0x1e8 */ 0xA2, 0x79, 0x31, 0x13, 0x3D, 0x2D, 0x36, 0xF8, + /* 0x1f0 */ 0xE3, 0xFC, 0xF2, 0x33, 0x6A, 0xB9, 0x39, 0x31, + /* 0x1f8 */ 0xC5, 0xAF, 0xC4, 0x8D, 0x0D, 0x1D, 0x64, 0x16, + /* 0x200 */ 0x33, 0xAA, 0xFA, 0x84, 0x29, 0xB6, 0xD4, 0x0B, + /* 0x208 */ 0xC0, 0xD8, 0x7D, 0xC3, 0x93, 0x02, 0x03, 0x01, + /* 0x210 */ 0x00, 0x01, 0xA3, 0x82, 0x01, 0x67, 0x30, 0x82, + /* 0x218 */ 0x01, 0x63, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, + /* 0x220 */ 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, + /* 0x228 */ 0x01, 0x86, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1D, + /* 0x230 */ 0x13, 0x01, 0x01, 0xFF, 0x04, 0x08, 0x30, 0x06, + /* 0x238 */ 0x01, 0x01, 0xFF, 0x02, 0x01, 0x00, 0x30, 0x54, + /* 0x240 */ 0x06, 0x03, 0x55, 0x1D, 0x20, 0x04, 0x4D, 0x30, + /* 0x248 */ 0x4B, 0x30, 0x08, 0x06, 0x06, 0x67, 0x81, 0x0C, + /* 0x250 */ 0x01, 0x02, 0x01, 0x30, 0x3F, 0x06, 0x0B, 0x2B, + /* 0x258 */ 0x06, 0x01, 0x04, 0x01, 0x82, 0xDF, 0x13, 0x01, + /* 0x260 */ 0x01, 0x01, 0x30, 0x30, 0x30, 0x2E, 0x06, 0x08, + /* 0x268 */ 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, + /* 0x270 */ 0x16, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, + /* 0x278 */ 0x2F, 0x63, 0x70, 0x73, 0x2E, 0x72, 0x6F, 0x6F, + /* 0x280 */ 0x74, 0x2D, 0x78, 0x31, 0x2E, 0x6C, 0x65, 0x74, + /* 0x288 */ 0x73, 0x65, 0x6E, 0x63, 0x72, 0x79, 0x70, 0x74, + /* 0x290 */ 0x2E, 0x6F, 0x72, 0x67, 0x30, 0x1D, 0x06, 0x03, + /* 0x298 */ 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0xA8, + /* 0x2a0 */ 0x4A, 0x6A, 0x63, 0x04, 0x7D, 0xDD, 0xBA, 0xE6, + /* 0x2a8 */ 0xD1, 0x39, 0xB7, 0xA6, 0x45, 0x65, 0xEF, 0xF3, + /* 0x2b0 */ 0xA8, 0xEC, 0xA1, 0x30, 0x33, 0x06, 0x03, 0x55, + /* 0x2b8 */ 0x1D, 0x1F, 0x04, 0x2C, 0x30, 0x2A, 0x30, 0x28, + /* 0x2c0 */ 0xA0, 0x26, 0xA0, 0x24, 0x86, 0x22, 0x68, 0x74, + /* 0x2c8 */ 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x63, 0x72, 0x6C, + /* 0x2d0 */ 0x2E, 0x72, 0x6F, 0x6F, 0x74, 0x2D, 0x78, 0x31, + /* 0x2d8 */ 0x2E, 0x6C, 0x65, 0x74, 0x73, 0x65, 0x6E, 0x63, + /* 0x2e0 */ 0x72, 0x79, 0x70, 0x74, 0x2E, 0x6F, 0x72, 0x67, + /* 0x2e8 */ 0x30, 0x72, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, + /* 0x2f0 */ 0x05, 0x07, 0x01, 0x01, 0x04, 0x66, 0x30, 0x64, + /* 0x2f8 */ 0x30, 0x30, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, + /* 0x300 */ 0x05, 0x07, 0x30, 0x01, 0x86, 0x24, 0x68, 0x74, + /* 0x308 */ 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x6F, 0x63, 0x73, + /* 0x310 */ 0x70, 0x2E, 0x72, 0x6F, 0x6F, 0x74, 0x2D, 0x78, + /* 0x318 */ 0x31, 0x2E, 0x6C, 0x65, 0x74, 0x73, 0x65, 0x6E, + /* 0x320 */ 0x63, 0x72, 0x79, 0x70, 0x74, 0x2E, 0x6F, 0x72, + /* 0x328 */ 0x67, 0x2F, 0x30, 0x30, 0x06, 0x08, 0x2B, 0x06, + /* 0x330 */ 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x24, + /* 0x338 */ 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x63, + /* 0x340 */ 0x65, 0x72, 0x74, 0x2E, 0x72, 0x6F, 0x6F, 0x74, + /* 0x348 */ 0x2D, 0x78, 0x31, 0x2E, 0x6C, 0x65, 0x74, 0x73, + /* 0x350 */ 0x65, 0x6E, 0x63, 0x72, 0x79, 0x70, 0x74, 0x2E, + /* 0x358 */ 0x6F, 0x72, 0x67, 0x2F, 0x30, 0x1F, 0x06, 0x03, + /* 0x360 */ 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, + /* 0x368 */ 0x14, 0x79, 0xB4, 0x59, 0xE6, 0x7B, 0xB6, 0xE5, + /* 0x370 */ 0xE4, 0x01, 0x73, 0x80, 0x08, 0x88, 0xC8, 0x1A, + /* 0x378 */ 0x58, 0xF6, 0xE9, 0x9B, 0x6E, 0x30, 0x0D, 0x06, + /* 0x380 */ 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + /* 0x388 */ 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, + /* 0x390 */ 0x00, 0x19, 0xCF, 0x75, 0x20, 0x34, 0x2D, 0x3A, + /* 0x398 */ 0xA6, 0x45, 0xFF, 0xD0, 0xD5, 0xE6, 0x8C, 0xDA, + /* 0x3a0 */ 0x32, 0xE8, 0x9C, 0x6E, 0x1B, 0x41, 0xD1, 0x27, + /* 0x3a8 */ 0xA8, 0xE2, 0x50, 0xF2, 0x70, 0xAA, 0xC4, 0xE7, + /* 0x3b0 */ 0x93, 0x46, 0xB4, 0xE8, 0x10, 0xAB, 0x70, 0x4F, + /* 0x3b8 */ 0xEF, 0xB7, 0xEA, 0x04, 0xD2, 0x94, 0x11, 0xB1, + /* 0x3c0 */ 0x03, 0xFE, 0x5D, 0xBA, 0xDF, 0x36, 0x8C, 0x94, + /* 0x3c8 */ 0x36, 0x8F, 0x13, 0x7C, 0x44, 0x8F, 0x0B, 0xF5, + /* 0x3d0 */ 0x01, 0x57, 0xAD, 0x68, 0xB8, 0xC5, 0x79, 0xC0, + /* 0x3d8 */ 0xD8, 0x4A, 0x80, 0xD7, 0x4C, 0xA3, 0x1E, 0x24, + /* 0x3e0 */ 0x7A, 0x1F, 0xD7, 0x23, 0xE8, 0xC1, 0x62, 0x3A, + /* 0x3e8 */ 0x76, 0xF9, 0x22, 0x7D, 0x5E, 0x5A, 0xC4, 0x4C, + /* 0x3f0 */ 0x50, 0xCD, 0xAF, 0xDD, 0xEF, 0x6D, 0x36, 0xC0, + /* 0x3f8 */ 0x80, 0x80, 0x1B, 0xA4, 0x3C, 0x70, 0x20, 0xD6, + /* 0x400 */ 0x54, 0x21, 0xD3, 0xBA, 0xEF, 0x14, 0xA9, 0xBF, + /* 0x408 */ 0x07, 0x3F, 0x41, 0x0A, 0x36, 0xB1, 0xA2, 0xB0, + /* 0x410 */ 0x0B, 0x20, 0xD5, 0x1F, 0x67, 0xD0, 0xC3, 0xEB, + /* 0x418 */ 0x88, 0xF6, 0x8A, 0x02, 0xC8, 0xC6, 0x57, 0xB6, + /* 0x420 */ 0x0C, 0xFC, 0x56, 0xF1, 0xD2, 0x3F, 0x17, 0x69, + /* 0x428 */ 0x68, 0x1C, 0xC8, 0xD7, 0x66, 0x3A, 0x86, 0xF1, + /* 0x430 */ 0x19, 0x2A, 0x65, 0x47, 0x68, 0xC6, 0xD2, 0x03, + /* 0x438 */ 0xE7, 0xEF, 0x74, 0x16, 0x0B, 0x06, 0x21, 0xF9, + /* 0x440 */ 0x0C, 0xA6, 0xA8, 0x11, 0x4B, 0x4E, 0x5F, 0xE3, + /* 0x448 */ 0x33, 0xDB, 0x08, 0x41, 0xEA, 0x09, 0x79, 0x75, + /* 0x450 */ 0x78, 0xEE, 0x47, 0xC8, 0x42, 0xD3, 0x81, 0xC5, + /* 0x458 */ 0x65, 0x2D, 0x75, 0xD0, 0x0E, 0x00, 0x16, 0x9D, + /* 0x460 */ 0x1C, 0xEE, 0xB7, 0x58, 0x45, 0x25, 0xE7, 0x33, + /* 0x468 */ 0x63, 0x5B, 0x63, 0x41, 0x09, 0xE8, 0xE9, 0xFE, + /* 0x470 */ 0xAC, 0xFA, 0x73, 0x32, 0x74, 0xB3, 0x76, 0xE9, + /* 0x478 */ 0x6B, 0x94, 0xE2, 0xCD, 0xD4, 0x62, 0xF3, 0xAE, + /* 0x480 */ 0x3A, 0xC5, 0x31, 0x46, 0x52, 0x6E, 0xED, 0x34, + /* 0x488 */ 0x91, 0x1E, 0xA0, 0xC2, 0xDE, 0x54, 0x84, 0xE5, + /* 0x490 */ 0x78, 0x20, 0x56, 0x4C, 0xDD, 0x68, 0xF9, 0x2E, + /* 0x498 */ 0x28, 0x64, 0x1B, 0x1A, 0x99, 0xF2, 0xFB, 0x4D, + /* 0x4a0 */ 0x7F, 0xE3, 0xB8, 0x5F, 0x5D, 0x73, 0x41, 0xEC, + /* 0x4a8 */ 0x79, 0xED, 0x58, 0xD6, 0x7A, 0x37, 0x65, 0x70, + /* 0x4b0 */ 0xA7, 0xB1, 0xBA, 0x39, 0xF6, 0x3E, 0x61, 0x0A, + /* 0x4b8 */ 0xD9, 0xC0, 0x86, 0x90, 0x9A, 0x1A, 0xC8, 0xA8, + /* 0x4c0 */ 0x96, 0x6E, 0x8A, 0x0B, 0x2B, 0x6D, 0xED, 0xD6, + /* 0x4c8 */ 0xFA, 0x07, 0x67, 0xE7, 0x29, 0x04, 0xF7, 0xE2, + /* 0x4d0 */ 0xB2, 0xD1, 0x58, 0x15, 0x52, 0xC7, 0xF1, 0xA3, + /* 0x4d8 */ 0x9D, 0xA6, 0xC0, 0x56, 0x2C, 0xD4, 0x92, 0x98, + /* 0x4e0 */ 0xD8, 0xF1, 0x83, 0xB9, 0x6C, 0x7C, 0x33, 0xA0, + /* 0x4e8 */ 0xE5, 0x4B, 0xAA, 0x90, 0x92, 0xF1, 0xDA, 0x45, + /* 0x4f0 */ 0x4A, 0x34, 0x14, 0xC7, 0x7C, 0x4E, 0xC4, 0xA5, + /* 0x4f8 */ 0x6C, 0x5D, 0x3F, 0xBF, 0xDE, 0xB9, 0xA8, 0x61, + /* 0x500 */ 0x4A, 0x85, 0x20, 0xDE, 0x42, 0x83, 0x29, 0x62, + /* 0x508 */ 0x7C, 0x1C, 0x99, 0x08, 0xA5, 0x46, 0x1F, 0xF4, + /* 0x510 */ 0x6B, 0x22, 0xD3, 0x86, 0x51, 0xCB, 0x37, 0xCD, + /* 0x518 */ 0x60, 0x4A, 0x42, 0x63, 0x56, 0xB3, 0xC8, 0xD1, + /* 0x520 */ 0x8F, 0x31, 0x09, 0x53, 0xC1, 0xE2, 0xDC, 0x1B, + /* 0x528 */ 0xD4, 0xF1, 0x54, 0x77, 0x67, 0xCF, 0x33, 0x7B, + /* 0x530 */ 0x00, 0xD6, 0xD2, 0x7C, 0xDE, 0xC6, 0x79, 0xBF, + /* 0x538 */ 0xCB, 0xE0, 0x16, 0xFD, 0xB2, 0xA1, 0xF2, 0x91, + /* 0x540 */ 0x3C, 0x1D, 0x2D, 0xE8, 0x9C, 0xD4, 0x03, 0xCD, + /* 0x548 */ 0x66, 0x4A, 0xA3, 0x37, 0x93, 0x19, 0x79, 0x7B, + /* 0x550 */ 0xE2, 0x19, 0xC2, 0x16, 0x00, 0xC8, 0xED, 0x0E, + /* 0x558 */ 0x4E, 0x0D, 0xFF, 0x7E, 0xCF, 0x07, 0xA8, 0x64, + /* 0x560 */ 0xCD, 0x29, 0xDF, 0x41, 0xAA, 0x85, 0x30, 0x49, + /* 0x568 */ 0x10, 0x73, 0xA7, 0x4E, 0x89, 0x32, 0x0E, 0x5B, + /* 0x570 */ 0xAD, 0x40, 0x86, 0xC1, 0xB0, 0x94, 0x0C, 0x8D, + /* 0x578 */ 0x26, 0xC5, 0xA7, 0x49, 0xDC, 0x1C, 0xF8, 0x5B, + /* 0x580 */ 0x14, 0x7A, 0x7F, 0x23, 0x69, 0x04, 0xAD, 0xB2, + /* 0x588 */ 0x02, 0x29, 0xD6, 0x12, 0xC8, 0xA4, 0xC6, 0xA1, + /* 0x590 */ 0x2D, +}; +static const lws_ss_x509_t _ss_x509_LEX3_isrg_root_x1 = { + .vhost_name = "LEX3_isrg_root_x1", + .ca_der = _ss_der_LEX3_isrg_root_x1, + .ca_der_len = 1425, +}; +static const lws_ss_trust_store_t _ss_ts_le_via_isrg = { + .name = "le_via_isrg", + .ssx509 = { + &_ss_x509_LEX3_isrg_root_x1, + &_ss_x509_isrg_root_x1, + } +}; + +static const lws_ss_policy_t _ssp_captive_portal_detect = { + .streamtype = "captive_portal_detect", + .endpoint = "connectivitycheck.android.com", + .u = { + .http = { + .method = "GET", + .url = "generate_204", + .resp_expect = 204, + .fail_redirect = 1, + } + }, + .flags = 0x1, + .port = 80, + .protocol = 0, +}, +_ssp_test_stream = { + .next = (void *)&_ssp_captive_portal_detect, + .streamtype = "test_stream", + .endpoint = "warmcat.com", + .u = { + .http = { + .method = "GET", + .url = "index.html", + } + }, + .retry_bo = &_rbo_0, + .flags = 0x11, + .port = 443, + .protocol = 1, + .trust = {.store = &_ss_ts_le_via_isrg}, +}; +#define _ss_static_policy_entry _ssp_test_stream +/* estimated footprint 3412 (when sizeof void * = 8) */ diff -Nru libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-wrover-kit/partitions.csv libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-wrover-kit/partitions.csv --- libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-wrover-kit/partitions.csv 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-wrover-kit/partitions.csv 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,5 @@ +# ESP-IDF Partition Table +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x6000, +phy_init, data, phy, 0xf000, 0x1000, +factory, app, factory, 0x10000, 2M, diff -Nru libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-wrover-kit/rgb565/rgb565.c libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-wrover-kit/rgb565/rgb565.c --- libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-wrover-kit/rgb565/rgb565.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-wrover-kit/rgb565/rgb565.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,26 @@ +/* + * gcc /tmp/q.c && convert cat-565.png -depth 8 rgb:- | ./a.out > cat-565.h + */ + +#include + +int main() +{ + int r, g, b, w, m = 0; + + while (1) { + r = getchar(); + g = getchar(); + b = getchar(); + + if (r == EOF || g == EOF || b == EOF) + return r == EOF; + + w = (b >> 3) | ((g >> 2) << 5) | ((r >> 3) << 11); + printf("0x%02X, 0x%02X, ", (w >> 8) & 0xFF, w & 0xFF); + + if (((++m) & 3) == 0) + printf("\n"); + } +} + diff -Nru libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-wrover-kit/sdkconfig libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-wrover-kit/sdkconfig --- libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-wrover-kit/sdkconfig 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-wrover-kit/sdkconfig 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,1151 @@ +# +# Automatically generated file. DO NOT EDIT. +# Espressif IoT Development Framework (ESP-IDF) Project Configuration +# +CONFIG_IDF_CMAKE=y +CONFIG_IDF_TARGET="esp32" +CONFIG_IDF_TARGET_ESP32=y +CONFIG_IDF_FIRMWARE_CHIP_ID=0x0000 + +# +# SDK tool configuration +# +CONFIG_SDK_TOOLPREFIX="xtensa-esp32-elf-" +# CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS is not set +# end of SDK tool configuration + +# +# Build type +# +CONFIG_APP_BUILD_TYPE_APP_2NDBOOT=y +# CONFIG_APP_BUILD_TYPE_ELF_RAM is not set +CONFIG_APP_BUILD_GENERATE_BINARIES=y +CONFIG_APP_BUILD_BOOTLOADER=y +CONFIG_APP_BUILD_USE_FLASH_SECTIONS=y +# end of Build type + +# +# Application manager +# +CONFIG_APP_COMPILE_TIME_DATE=y +# CONFIG_APP_EXCLUDE_PROJECT_VER_VAR is not set +# CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR is not set +# CONFIG_APP_PROJECT_VER_FROM_CONFIG is not set +CONFIG_APP_RETRIEVE_LEN_ELF_SHA=16 +# end of Application manager + +# +# Bootloader config +# +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_NONE is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_ERROR is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_WARN is not set +CONFIG_BOOTLOADER_LOG_LEVEL_INFO=y +# CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set +CONFIG_BOOTLOADER_LOG_LEVEL=3 +# CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_8V is not set +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y +# CONFIG_BOOTLOADER_FACTORY_RESET is not set +# CONFIG_BOOTLOADER_APP_TEST is not set +CONFIG_BOOTLOADER_WDT_ENABLE=y +# CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE is not set +CONFIG_BOOTLOADER_WDT_TIME_MS=9000 +# CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP is not set +CONFIG_BOOTLOADER_RESERVE_RTC_SIZE=0 +# CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC is not set +# end of Bootloader config + +# +# Security features +# +# CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT is not set +# CONFIG_SECURE_BOOT is not set +# CONFIG_SECURE_FLASH_ENC_ENABLED is not set +# end of Security features + +# +# Serial flasher config +# +CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 +# CONFIG_ESPTOOLPY_FLASHMODE_QIO is not set +# CONFIG_ESPTOOLPY_FLASHMODE_QOUT is not set +CONFIG_ESPTOOLPY_FLASHMODE_DIO=y +# CONFIG_ESPTOOLPY_FLASHMODE_DOUT is not set +CONFIG_ESPTOOLPY_FLASHMODE="dio" +# CONFIG_ESPTOOLPY_FLASHFREQ_80M is not set +CONFIG_ESPTOOLPY_FLASHFREQ_40M=y +# CONFIG_ESPTOOLPY_FLASHFREQ_26M is not set +# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set +CONFIG_ESPTOOLPY_FLASHFREQ="40m" +# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE="4MB" +CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y +CONFIG_ESPTOOLPY_BEFORE_RESET=y +# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set +CONFIG_ESPTOOLPY_BEFORE="default_reset" +CONFIG_ESPTOOLPY_AFTER_RESET=y +# CONFIG_ESPTOOLPY_AFTER_NORESET is not set +CONFIG_ESPTOOLPY_AFTER="hard_reset" +# CONFIG_ESPTOOLPY_MONITOR_BAUD_9600B is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_57600B is not set +CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B=y +# CONFIG_ESPTOOLPY_MONITOR_BAUD_230400B is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_921600B is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_2MB is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER is not set +CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER_VAL=115200 +CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 +# end of Serial flasher config + +# +# Partition Table +# +# CONFIG_PARTITION_TABLE_SINGLE_APP is not set +# CONFIG_PARTITION_TABLE_TWO_OTA is not set +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_OFFSET=0x8000 +CONFIG_PARTITION_TABLE_MD5=y +# end of Partition Table + +# +# Compiler options +# +CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y +# CONFIG_COMPILER_OPTIMIZATION_SIZE is not set +# CONFIG_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_COMPILER_OPTIMIZATION_NONE is not set +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set +# CONFIG_COMPILER_CXX_EXCEPTIONS is not set +# CONFIG_COMPILER_CXX_RTTI is not set +CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y +# CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_STRONG is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_ALL is not set +# CONFIG_COMPILER_WARN_WRITE_STRINGS is not set +# CONFIG_COMPILER_DISABLE_GCC8_WARNINGS is not set +# end of Compiler options + +# +# Component config +# + +# +# Application Level Tracing +# +# CONFIG_APPTRACE_DEST_TRAX is not set +CONFIG_APPTRACE_DEST_NONE=y +CONFIG_APPTRACE_LOCK_ENABLE=y +# end of Application Level Tracing + +# +# Bluetooth +# +# CONFIG_BT_ENABLED is not set +CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 +CONFIG_BTDM_CTRL_BLE_MAX_CONN_EFF=0 +CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN_EFF=0 +CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF=0 +CONFIG_BTDM_CTRL_PINNED_TO_CORE=0 +CONFIG_BTDM_BLE_SLEEP_CLOCK_ACCURACY_INDEX_EFF=1 +CONFIG_BT_RESERVE_DRAM=0 +# end of Bluetooth + +# +# CoAP Configuration +# +CONFIG_COAP_MBEDTLS_PSK=y +# CONFIG_COAP_MBEDTLS_PKI is not set +# CONFIG_COAP_MBEDTLS_DEBUG is not set +CONFIG_COAP_LOG_DEFAULT_LEVEL=0 +# end of CoAP Configuration + +# +# Driver configurations +# + +# +# ADC configuration +# +# CONFIG_ADC_FORCE_XPD_FSM is not set +CONFIG_ADC_DISABLE_DAC=y +# end of ADC configuration + +# +# SPI configuration +# +# CONFIG_SPI_MASTER_IN_IRAM is not set +CONFIG_SPI_MASTER_ISR_IN_IRAM=y +# CONFIG_SPI_SLAVE_IN_IRAM is not set +CONFIG_SPI_SLAVE_ISR_IN_IRAM=y +# end of SPI configuration + +# +# UART configuration +# +# CONFIG_UART_ISR_IN_IRAM is not set +# end of UART configuration + +# +# RTCIO configuration +# +# CONFIG_RTCIO_SUPPORT_RTC_GPIO_DESC is not set +# end of RTCIO configuration +# end of Driver configurations + +# +# eFuse Bit Manager +# +# CONFIG_EFUSE_CUSTOM_TABLE is not set +# CONFIG_EFUSE_VIRTUAL is not set +# CONFIG_EFUSE_CODE_SCHEME_COMPAT_NONE is not set +CONFIG_EFUSE_CODE_SCHEME_COMPAT_3_4=y +# CONFIG_EFUSE_CODE_SCHEME_COMPAT_REPEAT is not set +CONFIG_EFUSE_MAX_BLK_LEN=192 +# end of eFuse Bit Manager + +# +# ESP-TLS +# +CONFIG_ESP_TLS_USING_MBEDTLS=y +# CONFIG_ESP_TLS_USE_SECURE_ELEMENT is not set +# CONFIG_ESP_TLS_SERVER is not set +# CONFIG_ESP_TLS_PSK_VERIFICATION is not set +# end of ESP-TLS + +# +# ESP32-specific +# +CONFIG_ESP32_REV_MIN_0=y +# CONFIG_ESP32_REV_MIN_1 is not set +# CONFIG_ESP32_REV_MIN_2 is not set +# CONFIG_ESP32_REV_MIN_3 is not set +CONFIG_ESP32_REV_MIN=0 +CONFIG_ESP32_DPORT_WORKAROUND=y +# CONFIG_ESP32_DEFAULT_CPU_FREQ_80 is not set +CONFIG_ESP32_DEFAULT_CPU_FREQ_160=y +# CONFIG_ESP32_DEFAULT_CPU_FREQ_240 is not set +CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=160 +# CONFIG_ESP32_SPIRAM_SUPPORT is not set +# CONFIG_ESP32_TRAX is not set +CONFIG_ESP32_TRACEMEM_RESERVE_DRAM=0x0 +# CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_TWO is not set +CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR=y +CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES=4 +# CONFIG_ESP32_ULP_COPROC_ENABLED is not set +CONFIG_ESP32_ULP_COPROC_RESERVE_MEM=0 +CONFIG_ESP32_DEBUG_OCDAWARE=y +CONFIG_ESP32_BROWNOUT_DET=y +CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_0=y +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_1 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_7 is not set +CONFIG_ESP32_BROWNOUT_DET_LVL=0 +CONFIG_ESP32_REDUCE_PHY_TX_POWER=y +CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1=y +# CONFIG_ESP32_TIME_SYSCALL_USE_RTC is not set +# CONFIG_ESP32_TIME_SYSCALL_USE_FRC1 is not set +# CONFIG_ESP32_TIME_SYSCALL_USE_NONE is not set +CONFIG_ESP32_RTC_CLK_SRC_INT_RC=y +# CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS is not set +# CONFIG_ESP32_RTC_CLK_SRC_EXT_OSC is not set +# CONFIG_ESP32_RTC_CLK_SRC_INT_8MD256 is not set +CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024 +CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=2000 +CONFIG_ESP32_XTAL_FREQ_40=y +# CONFIG_ESP32_XTAL_FREQ_26 is not set +# CONFIG_ESP32_XTAL_FREQ_AUTO is not set +CONFIG_ESP32_XTAL_FREQ=40 +# CONFIG_ESP32_DISABLE_BASIC_ROM_CONSOLE is not set +# CONFIG_ESP32_NO_BLOBS is not set +# CONFIG_ESP32_COMPATIBLE_PRE_V2_1_BOOTLOADERS is not set +# CONFIG_ESP32_USE_FIXED_STATIC_RAM_SIZE is not set +CONFIG_ESP32_DPORT_DIS_INTERRUPT_LVL=5 +# end of ESP32-specific + +# +# Power Management +# +# CONFIG_PM_ENABLE is not set +# end of Power Management + +# +# ADC-Calibration +# +CONFIG_ADC_CAL_EFUSE_TP_ENABLE=y +CONFIG_ADC_CAL_EFUSE_VREF_ENABLE=y +CONFIG_ADC_CAL_LUT_ENABLE=y +# end of ADC-Calibration + +# +# Common ESP-related +# +CONFIG_ESP_ERR_TO_NAME_LOOKUP=y +CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=6584 +CONFIG_ESP_IPC_TASK_STACK_SIZE=1024 +CONFIG_ESP_IPC_USES_CALLERS_PRIORITY=y +CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048 +CONFIG_ESP_CONSOLE_UART_DEFAULT=y +# CONFIG_ESP_CONSOLE_UART_CUSTOM is not set +# CONFIG_ESP_CONSOLE_UART_NONE is not set +CONFIG_ESP_CONSOLE_UART_NUM=0 +CONFIG_ESP_CONSOLE_UART_TX_GPIO=1 +CONFIG_ESP_CONSOLE_UART_RX_GPIO=3 +CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 +CONFIG_ESP_INT_WDT=y +CONFIG_ESP_INT_WDT_TIMEOUT_MS=300 +CONFIG_ESP_INT_WDT_CHECK_CPU1=y +CONFIG_ESP_TASK_WDT=y +# CONFIG_ESP_TASK_WDT_PANIC is not set +CONFIG_ESP_TASK_WDT_TIMEOUT_S=5 +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +# CONFIG_ESP_PANIC_HANDLER_IRAM is not set +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_BT=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH=y +# end of Common ESP-related + +# +# Ethernet +# +CONFIG_ETH_ENABLED=y +CONFIG_ETH_USE_ESP32_EMAC=y +CONFIG_ETH_PHY_INTERFACE_RMII=y +# CONFIG_ETH_PHY_INTERFACE_MII is not set +CONFIG_ETH_RMII_CLK_INPUT=y +# CONFIG_ETH_RMII_CLK_OUTPUT is not set +CONFIG_ETH_RMII_CLK_IN_GPIO=0 +CONFIG_ETH_DMA_BUFFER_SIZE=512 +CONFIG_ETH_DMA_RX_BUFFER_NUM=10 +CONFIG_ETH_DMA_TX_BUFFER_NUM=10 +CONFIG_ETH_USE_SPI_ETHERNET=y +# CONFIG_ETH_SPI_ETHERNET_DM9051 is not set +# CONFIG_ETH_USE_OPENETH is not set +# end of Ethernet + +# +# Event Loop Library +# +# CONFIG_ESP_EVENT_LOOP_PROFILING is not set +CONFIG_ESP_EVENT_POST_FROM_ISR=y +CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR=y +# end of Event Loop Library + +# +# GDB Stub +# +# end of GDB Stub + +# +# ESP HTTP client +# +CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y +# CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH is not set +# end of ESP HTTP client + +# +# HTTP Server +# +CONFIG_HTTPD_MAX_REQ_HDR_LEN=512 +CONFIG_HTTPD_MAX_URI_LEN=512 +CONFIG_HTTPD_ERR_RESP_NO_DELAY=y +CONFIG_HTTPD_PURGE_BUF_LEN=32 +# CONFIG_HTTPD_LOG_PURGE_DATA is not set +# CONFIG_HTTPD_WS_SUPPORT is not set +# end of HTTP Server + +# +# ESP HTTPS OTA +# +# CONFIG_OTA_ALLOW_HTTP is not set +# end of ESP HTTPS OTA + +# +# ESP HTTPS server +# +# CONFIG_ESP_HTTPS_SERVER_ENABLE is not set +# end of ESP HTTPS server + +# +# ESP NETIF Adapter +# +CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL=120 +CONFIG_ESP_NETIF_TCPIP_LWIP=y +# CONFIG_ESP_NETIF_LOOPBACK is not set +CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER=y +# end of ESP NETIF Adapter + +# +# ESP System Settings +# +# CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT is not set +CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT=y +# CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set +# CONFIG_ESP_SYSTEM_PANIC_GDBSTUB is not set +# end of ESP System Settings + +# +# High resolution timer (esp_timer) +# +# CONFIG_ESP_TIMER_PROFILING is not set +CONFIG_ESP_TIMER_TASK_STACK_SIZE=6584 +# CONFIG_ESP_TIMER_IMPL_FRC2 is not set +CONFIG_ESP_TIMER_IMPL_TG0_LAC=y +# end of High resolution timer (esp_timer) + +# +# Wi-Fi +# +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 +# CONFIG_ESP32_WIFI_STATIC_TX_BUFFER is not set +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y +CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32 +# CONFIG_ESP32_WIFI_CSI_ENABLED is not set +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=6 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=6 +CONFIG_ESP32_WIFI_NVS_ENABLED=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y +# CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 is not set +CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752 +CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32 +# CONFIG_ESP32_WIFI_DEBUG_LOG_ENABLE is not set +CONFIG_ESP32_WIFI_IRAM_OPT=y +CONFIG_ESP32_WIFI_RX_IRAM_OPT=y +CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE=y +# end of Wi-Fi + +# +# PHY +# +CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP32_PHY_MAX_TX_POWER=20 +# end of PHY + +# +# Core dump +# +# CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set +# CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set +CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y +# end of Core dump + +# +# FAT Filesystem support +# +# CONFIG_FATFS_CODEPAGE_DYNAMIC is not set +CONFIG_FATFS_CODEPAGE_437=y +# CONFIG_FATFS_CODEPAGE_720 is not set +# CONFIG_FATFS_CODEPAGE_737 is not set +# CONFIG_FATFS_CODEPAGE_771 is not set +# CONFIG_FATFS_CODEPAGE_775 is not set +# CONFIG_FATFS_CODEPAGE_850 is not set +# CONFIG_FATFS_CODEPAGE_852 is not set +# CONFIG_FATFS_CODEPAGE_855 is not set +# CONFIG_FATFS_CODEPAGE_857 is not set +# CONFIG_FATFS_CODEPAGE_860 is not set +# CONFIG_FATFS_CODEPAGE_861 is not set +# CONFIG_FATFS_CODEPAGE_862 is not set +# CONFIG_FATFS_CODEPAGE_863 is not set +# CONFIG_FATFS_CODEPAGE_864 is not set +# CONFIG_FATFS_CODEPAGE_865 is not set +# CONFIG_FATFS_CODEPAGE_866 is not set +# CONFIG_FATFS_CODEPAGE_869 is not set +# CONFIG_FATFS_CODEPAGE_932 is not set +# CONFIG_FATFS_CODEPAGE_936 is not set +# CONFIG_FATFS_CODEPAGE_949 is not set +# CONFIG_FATFS_CODEPAGE_950 is not set +CONFIG_FATFS_CODEPAGE=437 +CONFIG_FATFS_LFN_NONE=y +# CONFIG_FATFS_LFN_HEAP is not set +# CONFIG_FATFS_LFN_STACK is not set +CONFIG_FATFS_FS_LOCK=0 +CONFIG_FATFS_TIMEOUT_MS=10000 +CONFIG_FATFS_PER_FILE_CACHE=y +# end of FAT Filesystem support + +# +# Modbus configuration +# +CONFIG_FMB_COMM_MODE_RTU_EN=y +CONFIG_FMB_COMM_MODE_ASCII_EN=y +CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND=150 +CONFIG_FMB_MASTER_DELAY_MS_CONVERT=200 +CONFIG_FMB_QUEUE_LENGTH=20 +CONFIG_FMB_SERIAL_TASK_STACK_SIZE=2048 +CONFIG_FMB_SERIAL_BUF_SIZE=256 +CONFIG_FMB_SERIAL_ASCII_BITS_PER_SYMB=8 +CONFIG_FMB_SERIAL_ASCII_TIMEOUT_RESPOND_MS=1000 +CONFIG_FMB_SERIAL_TASK_PRIO=10 +# CONFIG_FMB_CONTROLLER_SLAVE_ID_SUPPORT is not set +CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT=20 +CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE=20 +CONFIG_FMB_CONTROLLER_STACK_SIZE=4096 +CONFIG_FMB_EVENT_QUEUE_TIMEOUT=20 +CONFIG_FMB_TIMER_PORT_ENABLED=y +CONFIG_FMB_TIMER_GROUP=0 +CONFIG_FMB_TIMER_INDEX=0 +# CONFIG_FMB_TIMER_ISR_IN_IRAM is not set +# end of Modbus configuration + +# +# FreeRTOS +# +# CONFIG_FREERTOS_UNICORE is not set +CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF +CONFIG_FREERTOS_CORETIMER_0=y +# CONFIG_FREERTOS_CORETIMER_1 is not set +CONFIG_FREERTOS_HZ=100 +CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y +# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set +CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y +CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 +CONFIG_FREERTOS_ASSERT_FAIL_ABORT=y +# CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE is not set +# CONFIG_FREERTOS_ASSERT_DISABLE is not set +CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536 +CONFIG_FREERTOS_ISR_STACKSIZE=1536 +# CONFIG_FREERTOS_LEGACY_HOOKS is not set +CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 +# CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION is not set +CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1 +CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=6048 +CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10 +CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 +# CONFIG_FREERTOS_USE_TRACE_FACILITY is not set +# CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS is not set +CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y +CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y +# CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set +CONFIG_FREERTOS_DEBUG_OCDAWARE=y +# CONFIG_FREERTOS_FPU_IN_ISR is not set +# end of FreeRTOS + +# +# Heap memory debugging +# +CONFIG_HEAP_POISONING_DISABLED=y +# CONFIG_HEAP_POISONING_LIGHT is not set +# CONFIG_HEAP_POISONING_COMPREHENSIVE is not set +CONFIG_HEAP_TRACING_OFF=y +# CONFIG_HEAP_TRACING_STANDALONE is not set +# CONFIG_HEAP_TRACING_TOHOST is not set +# CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS is not set +# end of Heap memory debugging + +# +# jsmn +# +# CONFIG_JSMN_PARENT_LINKS is not set +# CONFIG_JSMN_STRICT is not set +# end of jsmn + +# +# libsodium +# +# end of libsodium + +# +# Log output +# +# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set +# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set +# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set +CONFIG_LOG_DEFAULT_LEVEL_INFO=y +# CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set +# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set +CONFIG_LOG_DEFAULT_LEVEL=3 +CONFIG_LOG_COLORS=y +CONFIG_LOG_TIMESTAMP_SOURCE_RTOS=y +# CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM is not set +# end of Log output + +# +# LWIP +# +CONFIG_LWIP_LOCAL_HOSTNAME="espressif" +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +# CONFIG_LWIP_L2_TO_L3_COPY is not set +# CONFIG_LWIP_IRAM_OPTIMIZATION is not set +CONFIG_LWIP_TIMERS_ONDEMAND=y +CONFIG_LWIP_MAX_SOCKETS=10 +# CONFIG_LWIP_USE_ONLY_LWIP_SELECT is not set +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +# CONFIG_LWIP_SO_RCVBUF is not set +# CONFIG_LWIP_NETBUF_RECVINFO is not set +CONFIG_LWIP_IP_FRAG=y +# CONFIG_LWIP_IP_REASSEMBLY is not set +# CONFIG_LWIP_IP_FORWARD is not set +# CONFIG_LWIP_STATS is not set +# CONFIG_LWIP_ETHARP_TRUST_IP_MAC is not set +CONFIG_LWIP_ESP_GRATUITOUS_ARP=y +CONFIG_LWIP_GARP_TMR_INTERVAL=60 +CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32 +CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set + +# +# DHCP server +# +CONFIG_LWIP_DHCPS_LEASE_UNIT=60 +CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8 +# end of DHCP server + +# CONFIG_LWIP_AUTOIP is not set +# CONFIG_LWIP_IPV6_AUTOCONFIG is not set +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 + +# +# TCP +# +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_LWIP_TCP_MAXRTX=12 +CONFIG_LWIP_TCP_SYNMAXRTX=6 +CONFIG_LWIP_TCP_MSS=1440 +CONFIG_LWIP_TCP_TMR_INTERVAL=250 +CONFIG_LWIP_TCP_MSL=60000 +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5744 +CONFIG_LWIP_TCP_WND_DEFAULT=5744 +CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 +CONFIG_LWIP_TCP_QUEUE_OOSEQ=y +# CONFIG_LWIP_TCP_SACK_OUT is not set +# CONFIG_LWIP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set +CONFIG_LWIP_TCP_OVERSIZE_MSS=y +# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set +# end of TCP + +# +# UDP +# +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 +# end of UDP + +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0 is not set +# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU1 is not set +CONFIG_LWIP_TCPIP_TASK_AFFINITY=0x7FFFFFFF +# CONFIG_LWIP_PPP_SUPPORT is not set + +# +# ICMP +# +# CONFIG_LWIP_MULTICAST_PING is not set +# CONFIG_LWIP_BROADCAST_PING is not set +# end of ICMP + +# +# LWIP RAW API +# +CONFIG_LWIP_MAX_RAW_PCBS=16 +# end of LWIP RAW API + +# +# SNTP +# +CONFIG_LWIP_DHCP_MAX_NTP_SERVERS=1 +CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000 +# end of SNTP + +CONFIG_LWIP_ESP_LWIP_ASSERT=y +# end of LWIP + +# +# mbedTLS +# +CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y +# CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set +# CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC is not set +CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y +CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=16384 +CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 +# CONFIG_MBEDTLS_DYNAMIC_BUFFER is not set +# CONFIG_MBEDTLS_DEBUG is not set + +# +# Certificate Bundle +# +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN is not set +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE is not set +# CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE is not set +# end of Certificate Bundle + +# CONFIG_MBEDTLS_ECP_RESTARTABLE is not set +# CONFIG_MBEDTLS_CMAC_C is not set +CONFIG_MBEDTLS_HARDWARE_AES=y +CONFIG_MBEDTLS_HARDWARE_MPI=y +CONFIG_MBEDTLS_HARDWARE_SHA=y +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN is not set +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY is not set +CONFIG_MBEDTLS_HAVE_TIME=y +# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set +CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y +CONFIG_MBEDTLS_SHA512_C=y +CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y +# CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set +# CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set +# CONFIG_MBEDTLS_TLS_DISABLED is not set +CONFIG_MBEDTLS_TLS_SERVER=y +CONFIG_MBEDTLS_TLS_CLIENT=y +CONFIG_MBEDTLS_TLS_ENABLED=y + +# +# TLS Key Exchange Methods +# +# CONFIG_MBEDTLS_PSK_MODES is not set +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y +# end of TLS Key Exchange Methods + +CONFIG_MBEDTLS_SSL_RENEGOTIATION=y +# CONFIG_MBEDTLS_SSL_PROTO_SSL3 is not set +CONFIG_MBEDTLS_SSL_PROTO_TLS1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +# CONFIG_MBEDTLS_SSL_PROTO_DTLS is not set +CONFIG_MBEDTLS_SSL_ALPN=y +CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS=y +CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS=y + +# +# Symmetric Ciphers +# +CONFIG_MBEDTLS_AES_C=y +# CONFIG_MBEDTLS_CAMELLIA_C is not set +# CONFIG_MBEDTLS_DES_C is not set +CONFIG_MBEDTLS_RC4_DISABLED=y +# CONFIG_MBEDTLS_RC4_ENABLED_NO_DEFAULT is not set +# CONFIG_MBEDTLS_RC4_ENABLED is not set +# CONFIG_MBEDTLS_BLOWFISH_C is not set +# CONFIG_MBEDTLS_XTEA_C is not set +CONFIG_MBEDTLS_CCM_C=y +CONFIG_MBEDTLS_GCM_C=y +# end of Symmetric Ciphers + +# CONFIG_MBEDTLS_RIPEMD160_C is not set + +# +# Certificates +# +CONFIG_MBEDTLS_PEM_PARSE_C=y +CONFIG_MBEDTLS_PEM_WRITE_C=y +CONFIG_MBEDTLS_X509_CRL_PARSE_C=y +CONFIG_MBEDTLS_X509_CSR_PARSE_C=y +# end of Certificates + +CONFIG_MBEDTLS_ECP_C=y +CONFIG_MBEDTLS_ECDH_C=y +CONFIG_MBEDTLS_ECDSA_C=y +# CONFIG_MBEDTLS_ECJPAKE_C is not set +CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y +CONFIG_MBEDTLS_ECP_NIST_OPTIM=y +# CONFIG_MBEDTLS_POLY1305_C is not set +# CONFIG_MBEDTLS_CHACHA20_C is not set +# CONFIG_MBEDTLS_HKDF_C is not set +# CONFIG_MBEDTLS_THREADING_C is not set +# CONFIG_MBEDTLS_SECURITY_RISKS is not set +# end of mbedTLS + +# +# mDNS +# +CONFIG_MDNS_MAX_SERVICES=10 +CONFIG_MDNS_TASK_PRIORITY=1 +CONFIG_MDNS_TASK_STACK_SIZE=4096 +# CONFIG_MDNS_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_MDNS_TASK_AFFINITY_CPU0=y +# CONFIG_MDNS_TASK_AFFINITY_CPU1 is not set +CONFIG_MDNS_TASK_AFFINITY=0x0 +CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS=2000 +CONFIG_MDNS_TIMER_PERIOD_MS=100 +# end of mDNS + +# +# ESP-MQTT Configurations +# +CONFIG_MQTT_PROTOCOL_311=y +CONFIG_MQTT_TRANSPORT_SSL=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y +# CONFIG_MQTT_USE_CUSTOM_CONFIG is not set +# CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED is not set +# CONFIG_MQTT_CUSTOM_OUTBOX is not set +# end of ESP-MQTT Configurations + +# +# Newlib +# +CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_LF is not set +CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y +# CONFIG_NEWLIB_NANO_FORMAT is not set +# end of Newlib + +# +# NVS +# +# end of NVS + +# +# OpenSSL +# +# CONFIG_OPENSSL_DEBUG is not set +# CONFIG_OPENSSL_ASSERT_DO_NOTHING is not set +CONFIG_OPENSSL_ASSERT_EXIT=y +# end of OpenSSL + +# +# PThreads +# +CONFIG_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_PTHREAD_STACK_MIN=768 +CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY=y +# CONFIG_PTHREAD_DEFAULT_CORE_0 is not set +# CONFIG_PTHREAD_DEFAULT_CORE_1 is not set +CONFIG_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_PTHREAD_TASK_NAME_DEFAULT="pthread" +# end of PThreads + +# +# SPI Flash driver +# +# CONFIG_SPI_FLASH_VERIFY_WRITE is not set +# CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set +CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y +CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS is not set +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set +# CONFIG_SPI_FLASH_USE_LEGACY_IMPL is not set +# CONFIG_SPI_FLASH_SHARE_SPI1_BUS is not set +# CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE is not set +CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y +CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS=20 +CONFIG_SPI_FLASH_ERASE_YIELD_TICKS=1 + +# +# Auto-detect flash chips +# +CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_GD_CHIP=y +# end of Auto-detect flash chips +# end of SPI Flash driver + +# +# SPIFFS Configuration +# +CONFIG_SPIFFS_MAX_PARTITIONS=3 + +# +# SPIFFS Cache Configuration +# +CONFIG_SPIFFS_CACHE=y +CONFIG_SPIFFS_CACHE_WR=y +# CONFIG_SPIFFS_CACHE_STATS is not set +# end of SPIFFS Cache Configuration + +CONFIG_SPIFFS_PAGE_CHECK=y +CONFIG_SPIFFS_GC_MAX_RUNS=10 +# CONFIG_SPIFFS_GC_STATS is not set +CONFIG_SPIFFS_PAGE_SIZE=256 +CONFIG_SPIFFS_OBJ_NAME_LEN=32 +# CONFIG_SPIFFS_FOLLOW_SYMLINKS is not set +CONFIG_SPIFFS_USE_MAGIC=y +CONFIG_SPIFFS_USE_MAGIC_LENGTH=y +CONFIG_SPIFFS_META_LENGTH=4 +CONFIG_SPIFFS_USE_MTIME=y + +# +# Debug Configuration +# +# CONFIG_SPIFFS_DBG is not set +# CONFIG_SPIFFS_API_DBG is not set +# CONFIG_SPIFFS_GC_DBG is not set +# CONFIG_SPIFFS_CACHE_DBG is not set +# CONFIG_SPIFFS_CHECK_DBG is not set +# CONFIG_SPIFFS_TEST_VISUALISATION is not set +# end of Debug Configuration +# end of SPIFFS Configuration + +# +# TinyUSB +# + +# +# Descriptor configuration +# +CONFIG_USB_DESC_CUSTOM_VID=0x1234 +CONFIG_USB_DESC_CUSTOM_PID=0x5678 +# end of Descriptor configuration +# end of TinyUSB + +# +# Unity unit testing library +# +CONFIG_UNITY_ENABLE_FLOAT=y +CONFIG_UNITY_ENABLE_DOUBLE=y +# CONFIG_UNITY_ENABLE_COLOR is not set +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y +# CONFIG_UNITY_ENABLE_FIXTURE is not set +# CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL is not set +# end of Unity unit testing library + +# +# Virtual file system +# +CONFIG_VFS_SUPPORT_IO=y +CONFIG_VFS_SUPPORT_DIR=y +CONFIG_VFS_SUPPORT_SELECT=y +CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_VFS_SUPPORT_TERMIOS=y + +# +# Host File System I/O (Semihosting) +# +CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +CONFIG_VFS_SEMIHOSTFS_HOST_PATH_MAX_LEN=128 +# end of Host File System I/O (Semihosting) +# end of Virtual file system + +# +# Wear Levelling +# +# CONFIG_WL_SECTOR_SIZE_512 is not set +CONFIG_WL_SECTOR_SIZE_4096=y +CONFIG_WL_SECTOR_SIZE=4096 +# end of Wear Levelling + +# +# Wi-Fi Provisioning Manager +# +CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16 +CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT=30 +# end of Wi-Fi Provisioning Manager + +# +# Supplicant +# +CONFIG_WPA_MBEDTLS_CRYPTO=y +# CONFIG_WPA_DEBUG_PRINT is not set +# CONFIG_WPA_TESTING_OPTIONS is not set +# CONFIG_WPA_TLS_V12 is not set +# CONFIG_WPA_WPS_WARS is not set +# end of Supplicant +# end of Component config + +# +# Compatibility options +# +# CONFIG_LEGACY_INCLUDE_COMMON_HEADERS is not set +# end of Compatibility options + +# Deprecated options for backward compatibility +CONFIG_TOOLPREFIX="xtensa-esp32-elf-" +# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set +CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y +# CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set +CONFIG_LOG_BOOTLOADER_LEVEL=3 +# CONFIG_APP_ROLLBACK_ENABLE is not set +# CONFIG_FLASH_ENCRYPTION_ENABLED is not set +# CONFIG_FLASHMODE_QIO is not set +# CONFIG_FLASHMODE_QOUT is not set +CONFIG_FLASHMODE_DIO=y +# CONFIG_FLASHMODE_DOUT is not set +# CONFIG_MONITOR_BAUD_9600B is not set +# CONFIG_MONITOR_BAUD_57600B is not set +CONFIG_MONITOR_BAUD_115200B=y +# CONFIG_MONITOR_BAUD_230400B is not set +# CONFIG_MONITOR_BAUD_921600B is not set +# CONFIG_MONITOR_BAUD_2MB is not set +# CONFIG_MONITOR_BAUD_OTHER is not set +CONFIG_MONITOR_BAUD_OTHER_VAL=115200 +CONFIG_MONITOR_BAUD=115200 +CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG=y +# CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE is not set +CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y +# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set +# CONFIG_CXX_EXCEPTIONS is not set +CONFIG_STACK_CHECK_NONE=y +# CONFIG_STACK_CHECK_NORM is not set +# CONFIG_STACK_CHECK_STRONG is not set +# CONFIG_STACK_CHECK_ALL is not set +# CONFIG_WARN_WRITE_STRINGS is not set +# CONFIG_DISABLE_GCC8_WARNINGS is not set +# CONFIG_ESP32_APPTRACE_DEST_TRAX is not set +CONFIG_ESP32_APPTRACE_DEST_NONE=y +CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y +CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN_EFF=0 +CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN_EFF=0 +CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN_EFF=0 +CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0 +CONFIG_ADC2_DISABLE_DAC=y +# CONFIG_SPIRAM_SUPPORT is not set +CONFIG_TRACEMEM_RESERVE_DRAM=0x0 +# CONFIG_TWO_UNIVERSAL_MAC_ADDRESS is not set +CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS=y +CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS=4 +# CONFIG_ULP_COPROC_ENABLED is not set +CONFIG_ULP_COPROC_RESERVE_MEM=0 +CONFIG_BROWNOUT_DET=y +CONFIG_BROWNOUT_DET_LVL_SEL_0=y +# CONFIG_BROWNOUT_DET_LVL_SEL_1 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_7 is not set +CONFIG_BROWNOUT_DET_LVL=0 +CONFIG_REDUCE_PHY_TX_POWER=y +CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y +# CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL is not set +# CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_OSC is not set +# CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_8MD256 is not set +# CONFIG_DISABLE_BASIC_ROM_CONSOLE is not set +# CONFIG_NO_BLOBS is not set +# CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS is not set +CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_MAIN_TASK_STACK_SIZE=3584 +CONFIG_IPC_TASK_STACK_SIZE=1024 +CONFIG_CONSOLE_UART_DEFAULT=y +# CONFIG_CONSOLE_UART_CUSTOM is not set +# CONFIG_CONSOLE_UART_NONE is not set +CONFIG_CONSOLE_UART_NUM=0 +CONFIG_CONSOLE_UART_TX_GPIO=1 +CONFIG_CONSOLE_UART_RX_GPIO=3 +CONFIG_CONSOLE_UART_BAUDRATE=115200 +CONFIG_INT_WDT=y +CONFIG_INT_WDT_TIMEOUT_MS=300 +CONFIG_INT_WDT_CHECK_CPU1=y +CONFIG_TASK_WDT=y +# CONFIG_TASK_WDT_PANIC is not set +CONFIG_TASK_WDT_TIMEOUT_S=5 +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +# CONFIG_EVENT_LOOP_PROFILING is not set +CONFIG_POST_EVENTS_FROM_ISR=y +CONFIG_POST_EVENTS_FROM_IRAM_ISR=y +# CONFIG_ESP32S2_PANIC_PRINT_HALT is not set +CONFIG_ESP32S2_PANIC_PRINT_REBOOT=y +# CONFIG_ESP32S2_PANIC_SILENT_REBOOT is not set +# CONFIG_ESP32S2_PANIC_GDBSTUB is not set +CONFIG_TIMER_TASK_STACK_SIZE=6584 +CONFIG_MB_MASTER_TIMEOUT_MS_RESPOND=150 +CONFIG_MB_MASTER_DELAY_MS_CONVERT=200 +CONFIG_MB_QUEUE_LENGTH=20 +CONFIG_MB_SERIAL_TASK_STACK_SIZE=2048 +CONFIG_MB_SERIAL_BUF_SIZE=256 +CONFIG_MB_SERIAL_TASK_PRIO=10 +# CONFIG_MB_CONTROLLER_SLAVE_ID_SUPPORT is not set +CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT=20 +CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE=20 +CONFIG_MB_CONTROLLER_STACK_SIZE=4096 +CONFIG_MB_EVENT_QUEUE_TIMEOUT=20 +CONFIG_MB_TIMER_PORT_ENABLED=y +CONFIG_MB_TIMER_GROUP=0 +CONFIG_MB_TIMER_INDEX=0 +# CONFIG_SUPPORT_STATIC_ALLOCATION is not set +CONFIG_TIMER_TASK_PRIORITY=1 +CONFIG_TIMER_TASK_STACK_DEPTH=6048 +CONFIG_TIMER_QUEUE_LENGTH=10 +# CONFIG_L2_TO_L3_COPY is not set +# CONFIG_USE_ONLY_LWIP_SELECT is not set +CONFIG_ESP_GRATUITOUS_ARP=y +CONFIG_GARP_TMR_INTERVAL=60 +CONFIG_TCPIP_RECVMBOX_SIZE=32 +CONFIG_TCP_MAXRTX=12 +CONFIG_TCP_SYNMAXRTX=6 +CONFIG_TCP_MSS=1440 +CONFIG_TCP_MSL=60000 +CONFIG_TCP_SND_BUF_DEFAULT=5744 +CONFIG_TCP_WND_DEFAULT=5744 +CONFIG_TCP_RECVMBOX_SIZE=6 +CONFIG_TCP_QUEUE_OOSEQ=y +# CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set +CONFIG_TCP_OVERSIZE_MSS=y +# CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_TCP_OVERSIZE_DISABLE is not set +CONFIG_UDP_RECVMBOX_SIZE=6 +CONFIG_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_TCPIP_TASK_AFFINITY_CPU0 is not set +# CONFIG_TCPIP_TASK_AFFINITY_CPU1 is not set +CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF +# CONFIG_PPP_SUPPORT is not set +CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_ESP32_PTHREAD_STACK_MIN=768 +CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY=y +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_0 is not set +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_1 is not set +CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread" +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS is not set +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is not set +CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_SUPPORT_TERMIOS=y +CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN=128 +# End of deprecated options diff -Nru libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-wrover-kit/sdkconfig.h libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-wrover-kit/sdkconfig.h --- libwebsockets-4.0.20/minimal-examples/embedded/esp32/esp-wrover-kit/sdkconfig.h 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/embedded/esp32/esp-wrover-kit/sdkconfig.h 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,426 @@ +/* + * Automatically generated file. DO NOT EDIT. + * Espressif IoT Development Framework (ESP-IDF) Configuration Header + */ +#pragma once +#define CONFIG_IDF_CMAKE 1 +#define CONFIG_IDF_TARGET "esp32" +#define CONFIG_IDF_TARGET_ESP32 1 +#define CONFIG_IDF_FIRMWARE_CHIP_ID 0x0000 +#define CONFIG_SDK_TOOLPREFIX "xtensa-esp32-elf-" +#define CONFIG_APP_BUILD_TYPE_APP_2NDBOOT 1 +#define CONFIG_APP_BUILD_GENERATE_BINARIES 1 +#define CONFIG_APP_BUILD_BOOTLOADER 1 +#define CONFIG_APP_BUILD_USE_FLASH_SECTIONS 1 +#define CONFIG_APP_COMPILE_TIME_DATE 1 +#define CONFIG_APP_RETRIEVE_LEN_ELF_SHA 16 +#define CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE 1 +#define CONFIG_BOOTLOADER_LOG_LEVEL_INFO 1 +#define CONFIG_BOOTLOADER_LOG_LEVEL 3 +#define CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V 1 +#define CONFIG_BOOTLOADER_WDT_ENABLE 1 +#define CONFIG_BOOTLOADER_WDT_TIME_MS 9000 +#define CONFIG_BOOTLOADER_RESERVE_RTC_SIZE 0x0 +#define CONFIG_ESPTOOLPY_BAUD_OTHER_VAL 115200 +#define CONFIG_ESPTOOLPY_FLASHMODE_DIO 1 +#define CONFIG_ESPTOOLPY_FLASHMODE "dio" +#define CONFIG_ESPTOOLPY_FLASHFREQ_40M 1 +#define CONFIG_ESPTOOLPY_FLASHFREQ "40m" +#define CONFIG_ESPTOOLPY_FLASHSIZE_4MB 1 +#define CONFIG_ESPTOOLPY_FLASHSIZE "4MB" +#define CONFIG_ESPTOOLPY_FLASHSIZE_DETECT 1 +#define CONFIG_ESPTOOLPY_BEFORE_RESET 1 +#define CONFIG_ESPTOOLPY_BEFORE "default_reset" +#define CONFIG_ESPTOOLPY_AFTER_RESET 1 +#define CONFIG_ESPTOOLPY_AFTER "hard_reset" +#define CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B 1 +#define CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER_VAL 115200 +#define CONFIG_ESPTOOLPY_MONITOR_BAUD 115200 +#define CONFIG_PARTITION_TABLE_SINGLE_APP 1 +#define CONFIG_PARTITION_TABLE_CUSTOM_FILENAME "partitions.csv" +#define CONFIG_PARTITION_TABLE_FILENAME "partitions_singleapp.csv" +#define CONFIG_PARTITION_TABLE_OFFSET 0x8000 +#define CONFIG_PARTITION_TABLE_MD5 1 +#define CONFIG_COMPILER_OPTIMIZATION_DEFAULT 1 +#define CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE 1 +#define CONFIG_COMPILER_STACK_CHECK_MODE_NONE 1 +#define CONFIG_APPTRACE_DEST_NONE 1 +#define CONFIG_APPTRACE_LOCK_ENABLE 1 +#define CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF 0 +#define CONFIG_BTDM_CTRL_BLE_MAX_CONN_EFF 0 +#define CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN_EFF 0 +#define CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF 0 +#define CONFIG_BTDM_CTRL_PINNED_TO_CORE 0 +#define CONFIG_BTDM_BLE_SLEEP_CLOCK_ACCURACY_INDEX_EFF 1 +#define CONFIG_BT_RESERVE_DRAM 0x0 +#define CONFIG_COAP_MBEDTLS_PSK 1 +#define CONFIG_COAP_LOG_DEFAULT_LEVEL 0 +#define CONFIG_ADC_DISABLE_DAC 1 +#define CONFIG_SPI_MASTER_ISR_IN_IRAM 1 +#define CONFIG_SPI_SLAVE_ISR_IN_IRAM 1 +#define CONFIG_EFUSE_CODE_SCHEME_COMPAT_3_4 1 +#define CONFIG_EFUSE_MAX_BLK_LEN 192 +#define CONFIG_ESP_TLS_USING_MBEDTLS 1 +#define CONFIG_ESP32_REV_MIN_0 1 +#define CONFIG_ESP32_REV_MIN 0 +#define CONFIG_ESP32_DPORT_WORKAROUND 1 +#define CONFIG_ESP32_DEFAULT_CPU_FREQ_160 1 +#define CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ 160 +#define CONFIG_ESP32_TRACEMEM_RESERVE_DRAM 0x0 +#define CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR 1 +#define CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES 4 +#define CONFIG_ESP32_ULP_COPROC_RESERVE_MEM 0 +#define CONFIG_ESP32_DEBUG_OCDAWARE 1 +#define CONFIG_ESP32_BROWNOUT_DET 1 +#define CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_0 1 +#define CONFIG_ESP32_BROWNOUT_DET_LVL 0 +#define CONFIG_ESP32_REDUCE_PHY_TX_POWER 1 +#define CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1 1 +#define CONFIG_ESP32_RTC_CLK_SRC_INT_RC 1 +#define CONFIG_ESP32_RTC_CLK_CAL_CYCLES 1024 +#define CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY 2000 +#define CONFIG_ESP32_XTAL_FREQ_40 1 +#define CONFIG_ESP32_XTAL_FREQ 40 +#define CONFIG_ESP32_DPORT_DIS_INTERRUPT_LVL 5 +#define CONFIG_ADC_CAL_EFUSE_TP_ENABLE 1 +#define CONFIG_ADC_CAL_EFUSE_VREF_ENABLE 1 +#define CONFIG_ADC_CAL_LUT_ENABLE 1 +#define CONFIG_ESP_ERR_TO_NAME_LOOKUP 1 +#define CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE 32 +#define CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE 2304 +#define CONFIG_ESP_MAIN_TASK_STACK_SIZE 6584 +#define CONFIG_ESP_IPC_TASK_STACK_SIZE 1024 +#define CONFIG_ESP_IPC_USES_CALLERS_PRIORITY 1 +#define CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE 2048 +#define CONFIG_ESP_CONSOLE_UART_DEFAULT 1 +#define CONFIG_ESP_CONSOLE_UART_NUM 0 +#define CONFIG_ESP_CONSOLE_UART_TX_GPIO 1 +#define CONFIG_ESP_CONSOLE_UART_RX_GPIO 3 +#define CONFIG_ESP_CONSOLE_UART_BAUDRATE 115200 +#define CONFIG_ESP_INT_WDT 1 +#define CONFIG_ESP_INT_WDT_TIMEOUT_MS 300 +#define CONFIG_ESP_INT_WDT_CHECK_CPU1 1 +#define CONFIG_ESP_TASK_WDT 1 +#define CONFIG_ESP_TASK_WDT_TIMEOUT_S 5 +#define CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0 1 +#define CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_BT 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH 1 +#define CONFIG_ETH_ENABLED 1 +#define CONFIG_ETH_USE_ESP32_EMAC 1 +#define CONFIG_ETH_PHY_INTERFACE_RMII 1 +#define CONFIG_ETH_RMII_CLK_INPUT 1 +#define CONFIG_ETH_RMII_CLK_IN_GPIO 0 +#define CONFIG_ETH_DMA_BUFFER_SIZE 512 +#define CONFIG_ETH_DMA_RX_BUFFER_NUM 10 +#define CONFIG_ETH_DMA_TX_BUFFER_NUM 10 +#define CONFIG_ETH_USE_SPI_ETHERNET 1 +#define CONFIG_ESP_EVENT_POST_FROM_ISR 1 +#define CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR 1 +#define CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS 1 +#define CONFIG_HTTPD_MAX_REQ_HDR_LEN 512 +#define CONFIG_HTTPD_MAX_URI_LEN 512 +#define CONFIG_HTTPD_ERR_RESP_NO_DELAY 1 +#define CONFIG_HTTPD_PURGE_BUF_LEN 32 +#define CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL 120 +#define CONFIG_ESP_NETIF_TCPIP_LWIP 1 +#define CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER 1 +#define CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT 1 +#define CONFIG_ESP_TIMER_TASK_STACK_SIZE 6584 +#define CONFIG_ESP_TIMER_IMPL_TG0_LAC 1 +#define CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM 10 +#define CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM 32 +#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER 1 +#define CONFIG_ESP32_WIFI_TX_BUFFER_TYPE 1 +#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM 32 +#define CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED 1 +#define CONFIG_ESP32_WIFI_TX_BA_WIN 6 +#define CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED 1 +#define CONFIG_ESP32_WIFI_RX_BA_WIN 6 +#define CONFIG_ESP32_WIFI_NVS_ENABLED 1 +#define CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0 1 +#define CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN 752 +#define CONFIG_ESP32_WIFI_MGMT_SBUF_NUM 32 +#define CONFIG_ESP32_WIFI_IRAM_OPT 1 +#define CONFIG_ESP32_WIFI_RX_IRAM_OPT 1 +#define CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE 1 +#define CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE 1 +#define CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER 20 +#define CONFIG_ESP32_PHY_MAX_TX_POWER 20 +#define CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE 1 +#define CONFIG_FATFS_CODEPAGE_437 1 +#define CONFIG_FATFS_CODEPAGE 437 +#define CONFIG_FATFS_LFN_NONE 1 +#define CONFIG_FATFS_FS_LOCK 0 +#define CONFIG_FATFS_TIMEOUT_MS 10000 +#define CONFIG_FATFS_PER_FILE_CACHE 1 +#define CONFIG_FMB_COMM_MODE_RTU_EN 1 +#define CONFIG_FMB_COMM_MODE_ASCII_EN 1 +#define CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND 150 +#define CONFIG_FMB_MASTER_DELAY_MS_CONVERT 200 +#define CONFIG_FMB_QUEUE_LENGTH 20 +#define CONFIG_FMB_SERIAL_TASK_STACK_SIZE 2048 +#define CONFIG_FMB_SERIAL_BUF_SIZE 256 +#define CONFIG_FMB_SERIAL_ASCII_BITS_PER_SYMB 8 +#define CONFIG_FMB_SERIAL_ASCII_TIMEOUT_RESPOND_MS 1000 +#define CONFIG_FMB_SERIAL_TASK_PRIO 10 +#define CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT 20 +#define CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE 20 +#define CONFIG_FMB_CONTROLLER_STACK_SIZE 4096 +#define CONFIG_FMB_EVENT_QUEUE_TIMEOUT 20 +#define CONFIG_FMB_TIMER_PORT_ENABLED 1 +#define CONFIG_FMB_TIMER_GROUP 0 +#define CONFIG_FMB_TIMER_INDEX 0 +#define CONFIG_FREERTOS_NO_AFFINITY 0x7FFFFFFF +#define CONFIG_FREERTOS_CORETIMER_0 1 +#define CONFIG_FREERTOS_HZ 100 +#define CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION 1 +#define CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY 1 +#define CONFIG_FREERTOS_INTERRUPT_BACKTRACE 1 +#define CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS 1 +#define CONFIG_FREERTOS_ASSERT_FAIL_ABORT 1 +#define CONFIG_FREERTOS_IDLE_TASK_STACKSIZE 1536 +#define CONFIG_FREERTOS_ISR_STACKSIZE 1536 +#define CONFIG_FREERTOS_MAX_TASK_NAME_LEN 16 +#define CONFIG_FREERTOS_TIMER_TASK_PRIORITY 1 +#define CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH 6048 +#define CONFIG_FREERTOS_TIMER_QUEUE_LENGTH 10 +#define CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE 0 +#define CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER 1 +#define CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER 1 +#define CONFIG_FREERTOS_DEBUG_OCDAWARE 1 +#define CONFIG_HEAP_POISONING_DISABLED 1 +#define CONFIG_HEAP_TRACING_OFF 1 +#define CONFIG_LOG_DEFAULT_LEVEL_INFO 1 +#define CONFIG_LOG_DEFAULT_LEVEL 3 +#define CONFIG_LOG_COLORS 1 +#define CONFIG_LOG_TIMESTAMP_SOURCE_RTOS 1 +#define CONFIG_LWIP_LOCAL_HOSTNAME "espressif" +#define CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES 1 +#define CONFIG_LWIP_TIMERS_ONDEMAND 1 +#define CONFIG_LWIP_MAX_SOCKETS 10 +#define CONFIG_LWIP_SO_REUSE 1 +#define CONFIG_LWIP_SO_REUSE_RXTOALL 1 +#define CONFIG_LWIP_IP_FRAG 1 +#define CONFIG_LWIP_ESP_GRATUITOUS_ARP 1 +#define CONFIG_LWIP_GARP_TMR_INTERVAL 60 +#define CONFIG_LWIP_TCPIP_RECVMBOX_SIZE 32 +#define CONFIG_LWIP_DHCP_DOES_ARP_CHECK 1 +#define CONFIG_LWIP_DHCPS_LEASE_UNIT 60 +#define CONFIG_LWIP_DHCPS_MAX_STATION_NUM 8 +#define CONFIG_LWIP_NETIF_LOOPBACK 1 +#define CONFIG_LWIP_LOOPBACK_MAX_PBUFS 8 +#define CONFIG_LWIP_MAX_ACTIVE_TCP 16 +#define CONFIG_LWIP_MAX_LISTENING_TCP 16 +#define CONFIG_LWIP_TCP_MAXRTX 12 +#define CONFIG_LWIP_TCP_SYNMAXRTX 6 +#define CONFIG_LWIP_TCP_MSS 1440 +#define CONFIG_LWIP_TCP_TMR_INTERVAL 250 +#define CONFIG_LWIP_TCP_MSL 60000 +#define CONFIG_LWIP_TCP_SND_BUF_DEFAULT 5744 +#define CONFIG_LWIP_TCP_WND_DEFAULT 5744 +#define CONFIG_LWIP_TCP_RECVMBOX_SIZE 6 +#define CONFIG_LWIP_TCP_QUEUE_OOSEQ 1 +#define CONFIG_LWIP_TCP_OVERSIZE_MSS 1 +#define CONFIG_LWIP_MAX_UDP_PCBS 16 +#define CONFIG_LWIP_UDP_RECVMBOX_SIZE 6 +#define CONFIG_LWIP_TCPIP_TASK_STACK_SIZE 3072 +#define CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY 1 +#define CONFIG_LWIP_TCPIP_TASK_AFFINITY 0x7FFFFFFF +#define CONFIG_LWIP_MAX_RAW_PCBS 16 +#define CONFIG_LWIP_DHCP_MAX_NTP_SERVERS 1 +#define CONFIG_LWIP_SNTP_UPDATE_DELAY 3600000 +#define CONFIG_LWIP_ESP_LWIP_ASSERT 1 +#define CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC 1 +#define CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN 1 +#define CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN 16384 +#define CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN 4096 +#define CONFIG_MBEDTLS_CERTIFICATE_BUNDLE 1 +#define CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL 1 +#define CONFIG_MBEDTLS_HARDWARE_AES 1 +#define CONFIG_MBEDTLS_HARDWARE_MPI 1 +#define CONFIG_MBEDTLS_HARDWARE_SHA 1 +#define CONFIG_MBEDTLS_HAVE_TIME 1 +#define CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT 1 +#define CONFIG_MBEDTLS_TLS_SERVER 1 +#define CONFIG_MBEDTLS_TLS_CLIENT 1 +#define CONFIG_MBEDTLS_TLS_ENABLED 1 +#define CONFIG_MBEDTLS_PSK_MODES 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_PSK 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_PSK 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_PSK 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_PSK 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_RSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA 1 +#define CONFIG_MBEDTLS_SSL_RENEGOTIATION 1 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1 1 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_1 1 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_2 1 +#define CONFIG_MBEDTLS_SSL_PROTO_DTLS 1 +#define CONFIG_MBEDTLS_SSL_ALPN 1 +#define CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS 1 +#define CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS 1 +#define CONFIG_MBEDTLS_AES_C 1 +#define CONFIG_MBEDTLS_RC4_DISABLED 1 +#define CONFIG_MBEDTLS_CCM_C 1 +#define CONFIG_MBEDTLS_GCM_C 1 +#define CONFIG_MBEDTLS_PEM_PARSE_C 1 +#define CONFIG_MBEDTLS_PEM_WRITE_C 1 +#define CONFIG_MBEDTLS_X509_CRL_PARSE_C 1 +#define CONFIG_MBEDTLS_X509_CSR_PARSE_C 1 +#define CONFIG_MBEDTLS_ECP_C 1 +#define CONFIG_MBEDTLS_ECDH_C 1 +#define CONFIG_MBEDTLS_ECDSA_C 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_NIST_OPTIM 1 +#define CONFIG_MDNS_MAX_SERVICES 10 +#define CONFIG_MDNS_TASK_PRIORITY 1 +#define CONFIG_MDNS_TASK_AFFINITY_CPU0 1 +#define CONFIG_MDNS_TASK_AFFINITY 0x0 +#define CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS 2000 +#define CONFIG_MDNS_TIMER_PERIOD_MS 100 +#define CONFIG_MQTT_PROTOCOL_311 1 +#define CONFIG_MQTT_TRANSPORT_SSL 1 +#define CONFIG_MQTT_TRANSPORT_WEBSOCKET 1 +#define CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE 1 +#define CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF 1 +#define CONFIG_NEWLIB_STDIN_LINE_ENDING_CR 1 +#define CONFIG_OPENSSL_ASSERT_EXIT 1 +#define CONFIG_PTHREAD_TASK_PRIO_DEFAULT 5 +#define CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT 3072 +#define CONFIG_PTHREAD_STACK_MIN 768 +#define CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY 1 +#define CONFIG_PTHREAD_TASK_CORE_DEFAULT -1 +#define CONFIG_PTHREAD_TASK_NAME_DEFAULT "pthread" +#define CONFIG_SPI_FLASH_ROM_DRIVER_PATCH 1 +#define CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS 1 +#define CONFIG_SPI_FLASH_YIELD_DURING_ERASE 1 +#define CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS 20 +#define CONFIG_SPI_FLASH_ERASE_YIELD_TICKS 1 +#define CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP 1 +#define CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP 1 +#define CONFIG_SPI_FLASH_SUPPORT_GD_CHIP 1 +#define CONFIG_SPIFFS_MAX_PARTITIONS 3 +#define CONFIG_SPIFFS_CACHE 1 +#define CONFIG_SPIFFS_CACHE_WR 1 +#define CONFIG_SPIFFS_PAGE_CHECK 1 +#define CONFIG_SPIFFS_GC_MAX_RUNS 10 +#define CONFIG_SPIFFS_PAGE_SIZE 256 +#define CONFIG_SPIFFS_OBJ_NAME_LEN 32 +#define CONFIG_SPIFFS_USE_MAGIC 1 +#define CONFIG_SPIFFS_USE_MAGIC_LENGTH 1 +#define CONFIG_SPIFFS_META_LENGTH 4 +#define CONFIG_SPIFFS_USE_MTIME 1 +#define CONFIG_USB_DESC_CUSTOM_VID 0x1234 +#define CONFIG_USB_DESC_CUSTOM_PID 0x5678 +#define CONFIG_UNITY_ENABLE_FLOAT 1 +#define CONFIG_UNITY_ENABLE_DOUBLE 1 +#define CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER 1 +#define CONFIG_VFS_SUPPORT_IO 1 +#define CONFIG_VFS_SUPPORT_DIR 1 +#define CONFIG_VFS_SUPPORT_SELECT 1 +#define CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT 1 +#define CONFIG_VFS_SUPPORT_TERMIOS 1 +#define CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS 1 +#define CONFIG_VFS_SEMIHOSTFS_HOST_PATH_MAX_LEN 128 +#define CONFIG_WL_SECTOR_SIZE_4096 1 +#define CONFIG_WL_SECTOR_SIZE 4096 +#define CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES 16 +#define CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT 30 +#define CONFIG_WPA_MBEDTLS_CRYPTO 1 + +/* List of deprecated options */ +#define CONFIG_ADC2_DISABLE_DAC CONFIG_ADC_DISABLE_DAC +#define CONFIG_BROWNOUT_DET CONFIG_ESP32_BROWNOUT_DET +#define CONFIG_BROWNOUT_DET_LVL_SEL_0 CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_0 +#define CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG CONFIG_COMPILER_OPTIMIZATION_DEFAULT +#define CONFIG_CONSOLE_UART_BAUDRATE CONFIG_ESP_CONSOLE_UART_BAUDRATE +#define CONFIG_CONSOLE_UART_DEFAULT CONFIG_ESP_CONSOLE_UART_DEFAULT +#define CONFIG_CONSOLE_UART_RX_GPIO CONFIG_ESP_CONSOLE_UART_RX_GPIO +#define CONFIG_CONSOLE_UART_TX_GPIO CONFIG_ESP_CONSOLE_UART_TX_GPIO +#define CONFIG_ESP32S2_PANIC_PRINT_REBOOT CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT +#define CONFIG_ESP32_APPTRACE_DEST_NONE CONFIG_APPTRACE_DEST_NONE +#define CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY +#define CONFIG_ESP32_PANIC_PRINT_REBOOT CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT +#define CONFIG_ESP32_PTHREAD_STACK_MIN CONFIG_PTHREAD_STACK_MIN +#define CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT CONFIG_PTHREAD_TASK_NAME_DEFAULT +#define CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT CONFIG_PTHREAD_TASK_PRIO_DEFAULT +#define CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT +#define CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC CONFIG_ESP32_RTC_CLK_SRC_INT_RC +#define CONFIG_ESP_GRATUITOUS_ARP CONFIG_LWIP_ESP_GRATUITOUS_ARP +#define CONFIG_FLASHMODE_DIO CONFIG_ESPTOOLPY_FLASHMODE_DIO +#define CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR +#define CONFIG_GARP_TMR_INTERVAL CONFIG_LWIP_GARP_TMR_INTERVAL +#define CONFIG_INT_WDT CONFIG_ESP_INT_WDT +#define CONFIG_INT_WDT_CHECK_CPU1 CONFIG_ESP_INT_WDT_CHECK_CPU1 +#define CONFIG_INT_WDT_TIMEOUT_MS CONFIG_ESP_INT_WDT_TIMEOUT_MS +#define CONFIG_IPC_TASK_STACK_SIZE CONFIG_ESP_IPC_TASK_STACK_SIZE +#define CONFIG_LOG_BOOTLOADER_LEVEL_INFO CONFIG_BOOTLOADER_LOG_LEVEL_INFO +#define CONFIG_MAIN_TASK_STACK_SIZE CONFIG_ESP_MAIN_TASK_STACK_SIZE +#define CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE +#define CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT +#define CONFIG_MB_CONTROLLER_STACK_SIZE CONFIG_FMB_CONTROLLER_STACK_SIZE +#define CONFIG_MB_EVENT_QUEUE_TIMEOUT CONFIG_FMB_EVENT_QUEUE_TIMEOUT +#define CONFIG_MB_MASTER_DELAY_MS_CONVERT CONFIG_FMB_MASTER_DELAY_MS_CONVERT +#define CONFIG_MB_MASTER_TIMEOUT_MS_RESPOND CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND +#define CONFIG_MB_QUEUE_LENGTH CONFIG_FMB_QUEUE_LENGTH +#define CONFIG_MB_SERIAL_BUF_SIZE CONFIG_FMB_SERIAL_BUF_SIZE +#define CONFIG_MB_SERIAL_TASK_PRIO CONFIG_FMB_SERIAL_TASK_PRIO +#define CONFIG_MB_SERIAL_TASK_STACK_SIZE CONFIG_FMB_SERIAL_TASK_STACK_SIZE +#define CONFIG_MB_TIMER_GROUP CONFIG_FMB_TIMER_GROUP +#define CONFIG_MB_TIMER_INDEX CONFIG_FMB_TIMER_INDEX +#define CONFIG_MB_TIMER_PORT_ENABLED CONFIG_FMB_TIMER_PORT_ENABLED +#define CONFIG_MONITOR_BAUD_115200B CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B +#define CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE +#define CONFIG_OPTIMIZATION_LEVEL_DEBUG CONFIG_COMPILER_OPTIMIZATION_DEFAULT +#define CONFIG_POST_EVENTS_FROM_IRAM_ISR CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR +#define CONFIG_POST_EVENTS_FROM_ISR CONFIG_ESP_EVENT_POST_FROM_ISR +#define CONFIG_REDUCE_PHY_TX_POWER CONFIG_ESP32_REDUCE_PHY_TX_POWER +#define CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN CONFIG_VFS_SEMIHOSTFS_HOST_PATH_MAX_LEN +#define CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS +#define CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS +#define CONFIG_STACK_CHECK_NONE CONFIG_COMPILER_STACK_CHECK_MODE_NONE +#define CONFIG_SUPPORT_TERMIOS CONFIG_VFS_SUPPORT_TERMIOS +#define CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT +#define CONFIG_SYSTEM_EVENT_QUEUE_SIZE CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE +#define CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE +#define CONFIG_TASK_WDT CONFIG_ESP_TASK_WDT +#define CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0 CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0 +#define CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1 CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1 +#define CONFIG_TASK_WDT_TIMEOUT_S CONFIG_ESP_TASK_WDT_TIMEOUT_S +#define CONFIG_TCPIP_RECVMBOX_SIZE CONFIG_LWIP_TCPIP_RECVMBOX_SIZE +#define CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY +#define CONFIG_TCPIP_TASK_STACK_SIZE CONFIG_LWIP_TCPIP_TASK_STACK_SIZE +#define CONFIG_TCP_MAXRTX CONFIG_LWIP_TCP_MAXRTX +#define CONFIG_TCP_MSL CONFIG_LWIP_TCP_MSL +#define CONFIG_TCP_MSS CONFIG_LWIP_TCP_MSS +#define CONFIG_TCP_OVERSIZE_MSS CONFIG_LWIP_TCP_OVERSIZE_MSS +#define CONFIG_TCP_QUEUE_OOSEQ CONFIG_LWIP_TCP_QUEUE_OOSEQ +#define CONFIG_TCP_RECVMBOX_SIZE CONFIG_LWIP_TCP_RECVMBOX_SIZE +#define CONFIG_TCP_SND_BUF_DEFAULT CONFIG_LWIP_TCP_SND_BUF_DEFAULT +#define CONFIG_TCP_SYNMAXRTX CONFIG_LWIP_TCP_SYNMAXRTX +#define CONFIG_TCP_WND_DEFAULT CONFIG_LWIP_TCP_WND_DEFAULT +#define CONFIG_TIMER_QUEUE_LENGTH CONFIG_FREERTOS_TIMER_QUEUE_LENGTH +#define CONFIG_TIMER_TASK_PRIORITY CONFIG_FREERTOS_TIMER_TASK_PRIORITY +#define CONFIG_TIMER_TASK_STACK_DEPTH CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH +#define CONFIG_TIMER_TASK_STACK_SIZE CONFIG_ESP_TIMER_TASK_STACK_SIZE +#define CONFIG_TOOLPREFIX CONFIG_SDK_TOOLPREFIX +#define CONFIG_UDP_RECVMBOX_SIZE CONFIG_LWIP_UDP_RECVMBOX_SIZE diff -Nru libwebsockets-4.0.20/minimal-examples/gtk/minimal-gtk/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/gtk/minimal-gtk/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/gtk/minimal-gtk/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/gtk/minimal-gtk/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,68 +1,13 @@ -project(lws-minimal-gtk) +project(lws-minimal-gtk C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-gtk) set(SRCS main.c) - -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) @@ -94,9 +39,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared ${extralibs}) + target_link_libraries(${SAMP} websockets_shared ${extralibs} ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets ${extralibs}) + target_link_libraries(${SAMP} websockets ${extralibs} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/gtk/minimal-gtk/main.c libwebsockets-4.1.6/minimal-examples/gtk/minimal-gtk/main.c --- libwebsockets-4.0.20/minimal-examples/gtk/minimal-gtk/main.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/gtk/minimal-gtk/main.c 2020-12-01 17:40:26.000000000 +0000 @@ -156,7 +156,7 @@ info.foreign_loops = foreign_loops; info.register_notifier_list = na; -#if defined(LWS_WITH_MBEDTLS) +#if defined(LWS_WITH_MBEDTLS) || defined(USE_WOLFSSL) /* * OpenSSL uses the system trust store. mbedTLS has to be told which * CA to trust explicitly. diff -Nru libwebsockets-4.0.20/minimal-examples/gtk/minimal-gtk/warmcat.com.cer libwebsockets-4.1.6/minimal-examples/gtk/minimal-gtk/warmcat.com.cer --- libwebsockets-4.0.20/minimal-examples/gtk/minimal-gtk/warmcat.com.cer 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/gtk/minimal-gtk/warmcat.com.cer 2020-12-01 17:40:26.000000000 +0000 @@ -56,3 +56,23 @@ PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6 KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg== -----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow +PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD +Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O +rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq +OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b +xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw +7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD +aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG +SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 +ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr +AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz +R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 +JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo +Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +-----END CERTIFICATE----- diff -Nru libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,80 +1,36 @@ -project(lws-minimal-http-client) +project(lws-minimal-http-client C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-client) set(SRCS minimal-http-client.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) +require_lws_config(LWS_WITH_SYS_STATE 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) + # if (LWS_CTEST_INTERNET_AVAILABLE) + # add_test(NAME http-client-warmcat COMMAND lws-minimal-http-client --ignore-sigterm) + # add_test(NAME http-client-warmcat-h1 COMMAND lws-minimal-http-client --ignore-sigterm --h1) + # set_tests_properties(http-client-warmcat + # http-client-warmcat-h1 + # PROPERTIES + # WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/http-client/minimal-http-client + # TIMEOUT 20) + # + #endif() + if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() -endif() \ No newline at end of file +endif() diff -Nru libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client/minimal-http-client.c libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client/minimal-http-client.c --- libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client/minimal-http-client.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client/minimal-http-client.c 2020-12-01 17:40:26.000000000 +0000 @@ -204,6 +204,9 @@ if (lws_cmdline_option(a->argc, a->argv, "--h1")) i.alpn = "http/1.1"; + if (lws_cmdline_option(a->argc, a->argv, "--h2-prior-knowledge")) + i.ssl_connection |= LCCSCF_H2_PRIOR_KNOWLEDGE; + if ((p = lws_cmdline_option(a->argc, a->argv, "-p"))) i.port = atoi(p); @@ -279,6 +282,7 @@ info.protocols = protocols; info.user = &args; info.register_notifier_list = na; + info.connect_timeout_secs = 30; /* * since we know this lws context is only ever going to be used with @@ -289,7 +293,7 @@ */ info.fd_limit_per_thread = 1 + 1 + 1; -#if defined(LWS_WITH_MBEDTLS) +#if defined(LWS_WITH_MBEDTLS) || defined(USE_WOLFSSL) /* * OpenSSL uses the system trust store. mbedTLS has to be told which * CA to trust explicitly. diff -Nru libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client/selftest.sh libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client/selftest.sh --- libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client/selftest.sh 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client/selftest.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -#!/bin/bash -# -# $1: path to minimal example binaries... -# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 -# that will be ./bin from your build dir -# -# $2: path for logs and results. The results will go -# in a subdir named after the directory this script -# is in -# -# $3: offset for test index count -# -# $4: total test count -# -# $5: path to ./minimal-examples dir in lws -# -# Test return code 0: OK, 254: timed out, other: error indication - -. $5/selftests-library.sh - -COUNT_TESTS=4 - -dotest $1 $2 warmcat -dotest $1 $2 warmcat-h1 --h1 - -spawn "" $5/http-server/minimal-http-server-tls $1/lws-minimal-http-server-tls -dotest $1 $2 localhost -l -spawn $SPID $5/http-server/minimal-http-server-tls $1/lws-minimal-http-server-tls -dotest $1 $2 localhost-h1 -l --h1 - -kill $SPID 2>/dev/null -wait $SPID 2>/dev/null -exit $FAILS diff -Nru libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client/warmcat.com.cer libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client/warmcat.com.cer --- libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client/warmcat.com.cer 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client/warmcat.com.cer 2020-12-01 17:40:26.000000000 +0000 @@ -56,3 +56,23 @@ PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6 KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg== -----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow +PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD +Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O +rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq +OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b +xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw +7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD +aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG +SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 +ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr +AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz +R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 +JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo +Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +-----END CERTIFICATE----- diff -Nru libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-attach/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-attach/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-attach/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-attach/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,95 +1,26 @@ -project(lws-minimal-http-client-attach) +project(lws-minimal-http-client-attach C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckIncludeFile) include(CheckCSourceCompiles) +include(LwsCheckRequirements) -Project(lws-minimal-http-client-attach) set(SAMP lws-minimal-http-client-attach) set(SRCS minimal-http-client-attach.c) -MACRO(require_pthreads result) - CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) - if (NOT LWS_HAVE_PTHREAD_H) - if (LWS_WITH_MINIMAL_EXAMPLES) - set(result 0) - else() - message(FATAL_ERROR "threading support requires pthreads") - endif() - endif() -ENDMACRO() - -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) -if (WIN32) - set(requirements 0) -endif() require_pthreads(requirements) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) -if (requirements) +if (requirements AND NOT WIN32) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared pthread) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets pthread) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-attach/minimal-http-client-attach.c libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-attach/minimal-http-client-attach.c --- libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-attach/minimal-http-client-attach.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-attach/minimal-http-client-attach.c 2020-12-01 17:40:26.000000000 +0000 @@ -15,6 +15,12 @@ #include #include #include +#if defined(WIN32) +#define HAVE_STRUCT_TIMESPEC +#if defined(pid_t) +#undef pid_t +#endif +#endif #include static struct lws_context *context; @@ -119,10 +125,7 @@ /* * Even though it was asked for from a different thread, we are called * back by lws from the lws event loop thread context - */ - lwsl_user("%s: called from tid %p\n", __func__, (void *)pthread_self()); - - /* + * * We can set up our operations on the lws event loop and return so * they can happen asynchronously */ @@ -218,7 +221,6 @@ logs = atoi(p); lws_set_log_level(logs, NULL); - lwsl_user("%s: main thread tid %p\n", __func__, (void *)pthread_self()); lwsl_user("LWS minimal http client attach\n"); pthread_mutex_init(&lock, NULL); diff -Nru libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-captive-portal/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-captive-portal/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-captive-portal/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-captive-portal/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,27 @@ +project(lws-minimal-http-client-captive-portal C) +cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) +include(CheckIncludeFile) +include(CheckCSourceCompiles) +include(LwsCheckRequirements) + +set(SAMP lws-minimal-http-client-captive-portal) +set(SRCS minimal-http-client-captive-portal.c) + +set(requirements 1) +require_lws_config(LWS_ROLE_H1 1 requirements) +require_lws_config(LWS_WITH_TLS 1 requirements) +require_lws_config(LWS_WITH_CLIENT 1 requirements) +require_lws_config(LWS_WITH_SYS_STATE 1 requirements) + +if (NOT WIN32 AND requirements) + add_executable(${SAMP} ${SRCS}) + + if (websockets_shared) + target_link_libraries(${SAMP} websockets_shared pthread ${LIBWEBSOCKETS_DEP_LIBS}) + add_dependencies(${SAMP} websockets_shared) + else() + target_link_libraries(${SAMP} websockets pthread ${LIBWEBSOCKETS_DEP_LIBS}) + endif() +endif() diff -Nru libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-captive-portal/minimal-http-client-captive-portal.c libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-captive-portal/minimal-http-client-captive-portal.c --- libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-captive-portal/minimal-http-client-captive-portal.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-captive-portal/minimal-http-client-captive-portal.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,321 @@ +/* + * lws-minimal-http-client-captive-portal + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * This demonstrates how to use the lws_system captive portal detect integration + * + * We check for a captive portal by doing a GET from + * http://connectivitycheck.android.com/generate_204, if we really are going + * out on the Internet he'll return with a 204 response code and we will + * understand there's no captive portal. If we get something else, we take it + * there is a captive portal. + */ + +#include +#include +#include + +static struct lws_context *context; +static int interrupted, bad = 1, status; +static lws_state_notify_link_t nl; + +/* + * this is the user code http handler + */ + +static int +callback_http(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) +{ + switch (reason) { + + /* because we are protocols[0] ... */ + case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: + lwsl_err("CLIENT_CONNECTION_ERROR: %s\n", + in ? (char *)in : "(null)"); + interrupted = 1; + break; + + case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: + { + char buf[128]; + + lws_get_peer_simple(wsi, buf, sizeof(buf)); + status = lws_http_client_http_response(wsi); + + lwsl_user("Connected to %s, http response: %d\n", + buf, status); + } + break; + + /* chunks of chunked content, with header removed */ + case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: + lwsl_user("RECEIVE_CLIENT_HTTP_READ: read %d\n", (int)len); + +#if 0 /* enable to dump the html */ + { + const char *p = in; + + while (len--) + if (*p < 0x7f) + putchar(*p++); + else + putchar('.'); + } +#endif + return 0; /* don't passthru */ + + /* uninterpreted http content */ + case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: + { + char buffer[1024 + LWS_PRE]; + char *px = buffer + LWS_PRE; + int lenx = sizeof(buffer) - LWS_PRE; + + if (lws_http_client_read(wsi, &px, &lenx) < 0) + return -1; + } + return 0; /* don't passthru */ + + case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: + lwsl_user("LWS_CALLBACK_COMPLETED_CLIENT_HTTP\n"); + interrupted = 1; + bad = status != 200; + lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ + break; + + case LWS_CALLBACK_CLOSED_CLIENT_HTTP: + interrupted = 1; + bad = status != 200; + lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ + break; + + default: + break; + } + + return lws_callback_http_dummy(wsi, reason, user, in, len); +} + +/* + * This is the platform's custom captive portal detection handler + */ + +static int +callback_cpd_http(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) +{ + int resp; + + switch (reason) { + + case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: + resp = lws_http_client_http_response(wsi); + if (!resp) + break; + lwsl_user("%s: established with resp %d\n", __func__, resp); + switch (resp) { + + case HTTP_STATUS_NO_CONTENT: + /* + * We got the 204 which is used to distinguish the real + * endpoint + */ + lws_system_cpd_set(lws_get_context(wsi), + LWS_CPD_INTERNET_OK); + return 0; + + /* also case HTTP_STATUS_OK: ... */ + default: + break; + } + + /* fallthru */ + + case LWS_CALLBACK_CLIENT_HTTP_REDIRECT: + lws_system_cpd_set(lws_get_context(wsi), LWS_CPD_CAPTIVE_PORTAL); + /* don't follow it, just report it */ + return 1; + + case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: + case LWS_CALLBACK_CLOSED_CLIENT_HTTP: + /* only the first result counts */ + lws_system_cpd_set(lws_get_context(wsi), LWS_CPD_NO_INTERNET); + break; + + default: + break; + } + + return lws_callback_http_dummy(wsi, reason, user, in, len); +} + +static const struct lws_protocols protocols[] = { + { + "http", + callback_http, + 0, + 0, + }, { + "lws-cpd-http", + callback_cpd_http + }, + { NULL, NULL, 0, 0 } +}; + +void sigint_handler(int sig) +{ + interrupted = 1; +} + +/* + * This triggers our platform implementation of captive portal detection, the + * actual test can be whatever you need. + * + * In this example, we detect it using Android's + * + * http://connectivitycheck.android.com/generate_204 + * + * and seeing if we get an http 204 back. + */ + +static int +captive_portal_detect_request(struct lws_context *context) +{ + struct lws_client_connect_info i; + + memset(&i, 0, sizeof i); + i.context = context; + i.port = 80; + i.address = "connectivitycheck.android.com"; + i.path = "/generate_204"; + i.host = i.address; + i.origin = i.address; + i.method = "GET"; + + i.protocol = "lws-cpd-http"; + + return !lws_client_connect_via_info(&i); +} + + +lws_system_ops_t ops = { + .captive_portal_detect_request = captive_portal_detect_request +}; + + +static int +app_system_state_nf(lws_state_manager_t *mgr, lws_state_notify_link_t *link, + int current, int target) +{ + struct lws_context *cx = lws_system_context_from_system_mgr(mgr); + + switch (target) { + case LWS_SYSTATE_CPD_PRE_TIME: + if (lws_system_cpd_state_get(cx)) + return 0; /* allow it */ + + lwsl_info("%s: LWS_SYSTATE_CPD_PRE_TIME\n", __func__); + lws_system_cpd_start(cx); + /* we'll move the state on when we get a result */ + return 1; + + case LWS_SYSTATE_OPERATIONAL: + if (current == LWS_SYSTATE_OPERATIONAL) { + struct lws_client_connect_info i; + + lwsl_user("%s: OPERATIONAL, cpd %d\n", __func__, + lws_system_cpd_state_get(cx)); + + /* + * When we reach the OPERATIONAL lws_system state, we + * can do our main job knowing we have DHCP, ntpclient, + * captive portal testing done. + */ + + if (lws_system_cpd_state_get(cx) != LWS_CPD_INTERNET_OK) { + lwsl_warn("%s: There's no internet...\n", __func__); + interrupted = 1; + break; + } + + memset(&i, 0, sizeof i); + i.context = context; + i.ssl_connection = LCCSCF_USE_SSL; + i.ssl_connection |= LCCSCF_H2_QUIRK_OVERFLOWS_TXCR | + LCCSCF_H2_QUIRK_NGHTTP2_END_STREAM; + i.port = 443; + i.address = "warmcat.com"; + i.path = "/"; + i.host = i.address; + i.origin = i.address; + i.method = "GET"; + + i.protocol = protocols[0].name; + + lws_client_connect_via_info(&i); + break; + } + default: + break; + } + + return 0; +} + +static lws_state_notify_link_t * const app_notifier_list[] = { + &nl, NULL +}; + +/* + * We made this into a different thread to model it being run from completely + * different codebase that's all linked together + */ + + +int main(int argc, const char **argv) +{ + int logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE; + struct lws_context_creation_info info; + const char *p; + + signal(SIGINT, sigint_handler); + + if ((p = lws_cmdline_option(argc, argv, "-d"))) + logs = atoi(p); + + lws_set_log_level(logs, NULL); + lwsl_user("LWS minimal http client captive portal detect\n"); + + memset(&info, 0, sizeof info); + info.port = CONTEXT_PORT_NO_LISTEN; + info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + info.system_ops = &ops; + info.protocols = protocols; + + /* integrate us with lws system state management when context created */ + + nl.name = "app"; + nl.notify_cb = app_system_state_nf; + info.register_notifier_list = app_notifier_list; + + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + return 1; + } + + while (!interrupted) + if (lws_service(context, 0)) + interrupted = 1; + + lws_context_destroy(context); + + lwsl_user("%s: finished %s\n", __func__, bad ? "FAIL": "OK"); + + return bad; +} diff -Nru libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-captive-portal/README.md libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-captive-portal/README.md --- libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-captive-portal/README.md 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-captive-portal/README.md 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,45 @@ +# lws minimal http client captive portal detect + +This demonstrates how to perform captive portal detection integrated +with `lws_system` states. + +After reaching the `lws_system` DHCP state, the application tries to +connect through to `http://connectivitycheck.android.com/generate_204` +over http... if it succeeds, it will get a 204 response and set the +captive portal detection state to `LWS_CPD_INTERNET_OK` and perform +a GET from warmcat.com. + +If there is a problem detected, the captive portal detection state is +set accordingly and the app will respond by exiting without trying the +read from warmcat.com. + +The captive portal detection scheme is implemented in the user code +and can be modified according to the strategy that's desired for +captive portal detection. + +## build + +``` + $ cmake . && make +``` + +## usage + +``` +$ ./bin/lws-minimal-http-client-captive-portal +[2020/03/11 13:07:07:4519] U: LWS minimal http client captive portal detect +[2020/03/11 13:07:07:4519] N: lws_create_context: using ss proxy bind '(null)', port 0, ads '(null)' +[2020/03/11 13:07:07:5022] U: callback_cpd_http: established with resp 204 +[2020/03/11 13:07:07:5023] U: app_system_state_nf: OPERATIONAL, cpd 1 +[2020/03/11 13:07:07:5896] U: Connected to 46.105.127.147, http response: 200 +[2020/03/11 13:07:07:5931] U: RECEIVE_CLIENT_HTTP_READ: read 4087 +[2020/03/11 13:07:07:5931] U: RECEIVE_CLIENT_HTTP_READ: read 4096 +[2020/03/11 13:07:07:6092] U: RECEIVE_CLIENT_HTTP_READ: read 4087 +[2020/03/11 13:07:07:6092] U: RECEIVE_CLIENT_HTTP_READ: read 4096 +[2020/03/11 13:07:07:6112] U: RECEIVE_CLIENT_HTTP_READ: read 4087 +[2020/03/11 13:07:07:6113] U: RECEIVE_CLIENT_HTTP_READ: read 4096 +[2020/03/11 13:07:07:6113] U: RECEIVE_CLIENT_HTTP_READ: read 2657 +[2020/03/11 13:07:07:6113] U: LWS_CALLBACK_COMPLETED_CLIENT_HTTP +[2020/03/11 13:07:07:6119] U: main: finished OK +``` + diff -Nru libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-certinfo/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-certinfo/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-certinfo/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-certinfo/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,81 +1,25 @@ -project(lws-minimal-http-client-certinfo) +project(lws-minimal-http-client-certinfo C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-client-certinfo) set(SRCS minimal-http-client-certinfo.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) -require_lws_config(LWS_OPENSSL_SUPPORT 1 requirements) +require_lws_config(LWS_WITH_TLS 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-certinfo/minimal-http-client-certinfo.c libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-certinfo/minimal-http-client-certinfo.c --- libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-certinfo/minimal-http-client-certinfo.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-certinfo/minimal-http-client-certinfo.c 2020-12-01 17:40:26.000000000 +0000 @@ -167,7 +167,7 @@ */ info.fd_limit_per_thread = 1 + 1 + 1; -#if defined(LWS_WITH_MBEDTLS) +#if defined(LWS_WITH_MBEDTLS) || defined(USE_WOLFSSL) /* * OpenSSL uses the system trust store. mbedTLS has to be told which * CA to trust explicitly. diff -Nru libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-certinfo/warmcat.com.cer libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-certinfo/warmcat.com.cer --- libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-certinfo/warmcat.com.cer 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-certinfo/warmcat.com.cer 2020-12-01 17:40:26.000000000 +0000 @@ -56,3 +56,23 @@ PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6 KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg== -----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow +PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD +Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O +rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq +OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b +xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw +7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD +aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG +SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 +ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr +AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz +R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 +JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo +Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +-----END CERTIFICATE----- diff -Nru libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-custom-headers/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-custom-headers/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-custom-headers/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-custom-headers/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,69 +1,13 @@ -project(lws-minimal-http-client-custom-headers) +project(lws-minimal-http-client-custom-headers C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-client-custom-headers) set(SRCS minimal-http-client-custom-headers.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) @@ -72,9 +16,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-custom-headers/minimal-http-client-custom-headers.c libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-custom-headers/minimal-http-client-custom-headers.c --- libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-custom-headers/minimal-http-client-custom-headers.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-custom-headers/minimal-http-client-custom-headers.c 2020-12-01 17:40:26.000000000 +0000 @@ -177,7 +177,7 @@ */ info.fd_limit_per_thread = 1 + 1 + 1; -#if defined(LWS_WITH_MBEDTLS) +#if defined(LWS_WITH_MBEDTLS) || defined(USE_WOLFSSL) /* * OpenSSL uses the system trust store. mbedTLS has to be told which * CA to trust explicitly. diff -Nru libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-custom-headers/warmcat.com.cer libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-custom-headers/warmcat.com.cer --- libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-custom-headers/warmcat.com.cer 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-custom-headers/warmcat.com.cer 2020-12-01 17:40:26.000000000 +0000 @@ -56,3 +56,23 @@ PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6 KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg== -----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow +PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD +Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O +rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq +OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b +xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw +7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD +aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG +SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 +ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr +AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz +R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 +JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo +Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +-----END CERTIFICATE----- diff -Nru libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-h2-rxflow/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-h2-rxflow/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-h2-rxflow/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-h2-rxflow/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,80 +1,34 @@ -project(lws-minimal-http-client-h2-rxflow) +project(lws-minimal-http-client-h2-rxflow C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-client-h2-rxflow) set(SRCS minimal-http-client.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H2 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) +require_lws_config(LWS_WITH_SYS_STATE 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) + if (LWS_CTEST_INTERNET_AVAILABLE) + add_test(NAME http-client-h2-rxflow-warmcat COMMAND lws-minimal-http-client-h2-rxflow --ignore-sigterm) + add_test(NAME http-client-h2-rxflow-warmcat-h1 COMMAND lws-minimal-http-client-h2-rxflow --ignore-sigterm --h1) + set_tests_properties(http-client-h2-rxflow-warmcat + http-client-h2-rxflow-warmcat-h1 + PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/http-client/minimal-http-client-h2-rxflow + TIMEOUT 30) + endif() if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-h2-rxflow/minimal-http-client.c libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-h2-rxflow/minimal-http-client.c --- libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-h2-rxflow/minimal-http-client.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-h2-rxflow/minimal-http-client.c 2020-12-01 17:40:26.000000000 +0000 @@ -115,8 +115,7 @@ case LWS_CALLBACK_CLOSED_CLIENT_HTTP: interrupted = 1; bad = status != 200; - lws_sul_schedule(lws_get_context(wsi), 0, &pss->sul, NULL, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&pss->sul); lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ break; @@ -259,6 +258,8 @@ info.protocols = protocols; info.user = &args; info.register_notifier_list = na; + info.timeout_secs = 10; + info.connect_timeout_secs = 30; /* * since we know this lws context is only ever going to be used with @@ -269,7 +270,7 @@ */ info.fd_limit_per_thread = 1 + 1 + 1; -#if defined(LWS_WITH_MBEDTLS) +#if defined(LWS_WITH_MBEDTLS) || defined(USE_WOLFSSL) /* * OpenSSL uses the system trust store. mbedTLS has to be told which * CA to trust explicitly. diff -Nru libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-h2-rxflow/selftest.sh libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-h2-rxflow/selftest.sh --- libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-h2-rxflow/selftest.sh 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-h2-rxflow/selftest.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -#!/bin/bash -# -# $1: path to minimal example binaries... -# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 -# that will be ./bin from your build dir -# -# $2: path for logs and results. The results will go -# in a subdir named after the directory this script -# is in -# -# $3: offset for test index count -# -# $4: total test count -# -# $5: path to ./minimal-examples dir in lws -# -# Test return code 0: OK, 254: timed out, other: error indication - -. $5/selftests-library.sh - -COUNT_TESTS=4 - -dotest $1 $2 warmcat -dotest $1 $2 warmcat-h1 --h1 - -spawn "" $5/http-server/minimal-http-server-tls $1/lws-minimal-http-server-tls -dotest $1 $2 localhost -l -spawn $SPID $5/http-server/minimal-http-server-tls $1/lws-minimal-http-server-tls -dotest $1 $2 localhost-h1 -l --h1 - -kill $SPID 2>/dev/null -wait $SPID 2>/dev/null -exit $FAILS diff -Nru libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-h2-rxflow/warmcat.com.cer libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-h2-rxflow/warmcat.com.cer --- libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-h2-rxflow/warmcat.com.cer 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-h2-rxflow/warmcat.com.cer 2020-12-01 17:40:26.000000000 +0000 @@ -56,3 +56,23 @@ PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6 KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg== -----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow +PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD +Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O +rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq +OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b +xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw +7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD +aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG +SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 +ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr +AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz +R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 +JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo +Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +-----END CERTIFICATE----- diff -Nru libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-hugeurl/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-hugeurl/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-hugeurl/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-hugeurl/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,68 +1,13 @@ -project(lws-minimal-http-client-hugeurl) +project(lws-minimal-http-client-hugeurl C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-client-hugeurl) set(SRCS minimal-http-client-hugeurl.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) @@ -70,10 +15,21 @@ if (requirements) add_executable(${SAMP} ${SRCS}) + if (LWS_CTEST_INTERNET_AVAILABLE) + add_test(NAME http-client-hugeurl-warmcat COMMAND lws-minimal-http-client-hugeurl --ignore-sigterm) + add_test(NAME http-client-hugeurl-warmcat-h1 COMMAND lws-minimal-http-client-hugeurl --ignore-sigterm --h1) + set_tests_properties(http-client-hugeurl-warmcat + http-client-hugeurl-warmcat-h1 + PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/http-client/minimal-http-client-hugeurl + TIMEOUT 20) + + endif() + if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-hugeurl/minimal-http-client-hugeurl.c libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-hugeurl/minimal-http-client-hugeurl.c --- libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-hugeurl/minimal-http-client-hugeurl.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-hugeurl/minimal-http-client-hugeurl.c 2020-12-01 17:40:26.000000000 +0000 @@ -149,27 +149,21 @@ struct lws_context_creation_info info; struct lws_client_connect_info i; struct lws_context *context; - const char *p; - int n = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE - /* for LLL_ verbosity above NOTICE to be built into lws, - * lws must have been configured and built with - * -DCMAKE_BUILD_TYPE=DEBUG instead of =RELEASE */ - /* | LLL_INFO */ /* | LLL_PARSER */ /* | LLL_HEADER */ - /* | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY */ - /* | LLL_DEBUG */; - - if ((p = lws_cmdline_option(argc, argv, "-d"))) - logs = atoi(p); + int n = 0; signal(SIGINT, sigint_handler); - lws_set_log_level(logs, NULL); - lwsl_user("LWS minimal http client hugeurl [-d ] [-l] [--h1]\n"); memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ + lws_cmdline_option_handle_builtin(argc, argv, &info); + + lwsl_user("LWS minimal http client hugeurl [-d ] [-l] [--h1]\n"); + info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ info.protocols = protocols; info.pt_serv_buf_size = 8192; + info.timeout_secs = 10; + info.connect_timeout_secs = 30; /* * since we know this lws context is only ever going to be used with * one client wsis / fds / sockets at a time, let lws know it doesn't @@ -179,7 +173,7 @@ */ info.fd_limit_per_thread = 1 + 1 + 1; -#if defined(LWS_WITH_MBEDTLS) +#if defined(LWS_WITH_MBEDTLS) || defined(USE_WOLFSSL) /* * OpenSSL uses the system trust store. mbedTLS has to be told which * CA to trust explicitly. diff -Nru libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-hugeurl/selftest.sh libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-hugeurl/selftest.sh --- libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-hugeurl/selftest.sh 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-hugeurl/selftest.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -#!/bin/bash -# -# $1: path to minimal example binaries... -# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 -# that will be ./bin from your build dir -# -# $2: path for logs and results. The results will go -# in a subdir named after the directory this script -# is in -# -# $3: offset for test index count -# -# $4: total test count -# -# $5: path to ./minimal-examples dir in lws -# -# Test return code 0: OK, 254: timed out, other: error indication - -. $5/selftests-library.sh - -COUNT_TESTS=6 - -dotest $1 $2 warmcat -dotest $1 $2 warmcat-h1 --h1 - -spawn "" $5/http-server/minimal-http-server-tls $1/lws-minimal-http-server-tls -dotest $1 $2 localhost -l -spawn $SPID $5/http-server/minimal-http-server-tls $1/lws-minimal-http-server-tls -dotest $1 $2 localhost-h1 -l --h1 -kill $SPID 2>/dev/null -wait $SPID 2>/dev/null - - -if [ -z "$TRAVIS_OS_NAME" ] ; then - SPID="" - spawn "" $5/http-server/minimal-http-server-eventlib $1/lws-minimal-http-server-eventlib --uv -s - dotest $1 $2 localhost-suv -l - spawn $SPID $5/http-server/minimal-http-server-eventlib $1/lws-minimal-http-server-eventlib --uv -s - dotest $1 $2 localhost-suv-h1 -l --h1 - - kill $SPID 2>/dev/null - wait $SPID 2>/dev/null -fi - -exit $FAILS - - diff -Nru libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-hugeurl/warmcat.com.cer libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-hugeurl/warmcat.com.cer --- libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-hugeurl/warmcat.com.cer 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-hugeurl/warmcat.com.cer 2020-12-01 17:40:26.000000000 +0000 @@ -56,3 +56,23 @@ PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6 KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg== -----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow +PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD +Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O +rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq +OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b +xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw +7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD +aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG +SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 +ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr +AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz +R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 +JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo +Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +-----END CERTIFICATE----- diff -Nru libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-multi/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-multi/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-multi/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-multi/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,80 +1,174 @@ -project(lws-minimal-http-client-multi) +project(lws-minimal-http-client-multi C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-client-multi) set(SRCS minimal-http-client-multi.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) +require_lws_config(LWS_WITH_TLS 1 requirements) + if (requirements) add_executable(${SAMP} ${SRCS}) + + # + # instantiate the server per sai builder instance, they are running in the same + # machine context in parallel so they can tread on each other otherwise + # + set(PORT_HCM_SRV "7670") + if ("$ENV{SAI_INSTANCE_IDX}" STREQUAL "0") + set(PORT_HCM_SRV 7671) + endif() + if ("$ENV{SAI_INSTANCE_IDX}" STREQUAL "1") + set(PORT_HCM_SRV 7672) + endif() + if ("$ENV{SAI_INSTANCE_IDX}" STREQUAL "2") + set(PORT_HCM_SRV 7673) + endif() + if ("$ENV{SAI_INSTANCE_IDX}" STREQUAL "3") + set(PORT_HCM_SRV 7674) + endif() + + +# hack +if (NOT WIN32 AND LWS_WITH_SERVER) + + # + # Tests against built server running locally (needs daemonization...) + # + +if (WIN32) + add_test(NAME st_hcm_srv COMMAND cmd.exe /c start /b $ --port ${PORT_HCM_SRV}) + add_test(NAME ki_hcm_srv COMMAND taskkill /F /IM $ /T) + add_test(NAME st_hcmp_srv COMMAND cmd.exe /c start /b $ -s --port 1${PORT_HCM_SRV}) + add_test(NAME ki_hcmp_srv COMMAND taskkill /F /IM $ /T) +else() + add_test(NAME st_hcm_srv COMMAND + ${CMAKE_SOURCE_DIR}/scripts/ctest-background.sh + hcm_srv $ + --port ${PORT_HCM_SRV} --ignore-sigterm) + add_test(NAME ki_hcm_srv COMMAND + ${CMAKE_SOURCE_DIR}/scripts/ctest-background-kill.sh + hcm_srv $ + --port ${PORT_HCM_SRV}) + add_test(NAME st_hcmp_srv COMMAND + ${CMAKE_SOURCE_DIR}/scripts/ctest-background.sh + hcmp_srv $ -s + -r ${CMAKE_SOURCE_DIR}/destdir/usr/local/share/libwebsockets-test-server/ + --port 1${PORT_HCM_SRV} --ignore-sigterm) + add_test(NAME ki_hcmp_srv COMMAND + ${CMAKE_SOURCE_DIR}/scripts/ctest-background-kill.sh + hcmp_srv $ + --port 1${PORT_HCM_SRV}) +endif() + + set_tests_properties(st_hcm_srv PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/http-server/minimal-http-server-tls + FIXTURES_SETUP hcm_srv + TIMEOUT 800) + set_tests_properties(ki_hcm_srv PROPERTIES + FIXTURES_CLEANUP hcm_srv) + + set_tests_properties(st_hcmp_srv PROPERTIES + WORKING_DIRECTORY . + FIXTURES_SETUP hcmp_srv + TIMEOUT 800) + set_tests_properties(ki_hcmp_srv PROPERTIES + FIXTURES_CLEANUP hcmp_srv) + + # + # Tests against local server peer + # + + add_test(NAME http-client-multi COMMAND lws-minimal-http-client-multi + -l --port ${PORT_HCM_SRV}) + add_test(NAME http-client-multi-h1 COMMAND lws-minimal-http-client-multi + --h1 -l --port ${PORT_HCM_SRV}) + add_test(NAME http-client-multi-pipe COMMAND lws-minimal-http-client-multi + -p -l --port ${PORT_HCM_SRV}) + add_test(NAME http-client-multi-h1-pipe COMMAND lws-minimal-http-client-multi + --h1 -p -l --port ${PORT_HCM_SRV}) + add_test(NAME http-client-multi-stag COMMAND lws-minimal-http-client-multi + -s -l --port ${PORT_HCM_SRV}) + add_test(NAME http-client-multi-stag-h1 COMMAND lws-minimal-http-client-multi + --h1 -s -l --port ${PORT_HCM_SRV}) + add_test(NAME http-client-multi-stag-pipe COMMAND lws-minimal-http-client-multi + -p -s -l --port ${PORT_HCM_SRV}) + add_test(NAME http-client-multi-stag-h1-pipe COMMAND lws-minimal-http-client-multi + --h1 -p -s -l --port ${PORT_HCM_SRV}) + + # confirm that the pipelined mode really is doing it in one connection + add_test(NAME http-client-multi-restrict-pipe COMMAND lws-minimal-http-client-multi -d1151 --limit 1 -p -l --port ${PORT_HCM_SRV}) + add_test(NAME http-client-multi-restrict-h1-pipe COMMAND lws-minimal-http-client-multi -d1151 --limit 1 --h1 -p -l --port ${PORT_HCM_SRV}) + add_test(NAME http-client-multi-restrict-stag-pipe COMMAND lws-minimal-http-client-multi -d1151 --limit 1 -p -s -l --port ${PORT_HCM_SRV}) + add_test(NAME http-client-multi-restrict-stag-h1-pipe COMMAND lws-minimal-http-client-multi -d1151 --limit 1 --h1 -p -s -l --port ${PORT_HCM_SRV}) + # confirm that we do fail with a one connection limit and no pipelining + add_test(NAME http-client-multi-restrict-nopipe-fail COMMAND lws-minimal-http-client-multi --limit 1 -l --port ${PORT_HCM_SRV}) + set_property(TEST http-client-multi-restrict-nopipe-fail PROPERTY WILL_FAIL TRUE) + add_test(NAME http-client-multi-restrict-h1-nopipe-fail COMMAND lws-minimal-http-client-multi --limit 1 --h1 -l --port ${PORT_HCM_SRV}) + set_property(TEST http-client-multi-restrict-h1-nopipe-fail PROPERTY WILL_FAIL TRUE) + + set_tests_properties(http-client-multi-restrict-pipe + http-client-multi-restrict-h1-pipe + http-client-multi-restrict-stag-pipe + http-client-multi-restrict-stag-h1-pipe + http-client-multi-restrict-nopipe-fail + http-client-multi-restrict-h1-nopipe-fail + http-client-multi + http-client-multi-h1 + http-client-multi-pipe + http-client-multi-h1-pipe + http-client-multi-stag + http-client-multi-stag-h1 + http-client-multi-stag-pipe + http-client-multi-stag-h1-pipe + PROPERTIES + FIXTURES_REQUIRED "hcm_srv" + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/http-client/minimal-http-client-multi + TIMEOUT 20) + + # POSTs against local http-server-form-post + add_test(NAME http-client-multi-post COMMAND lws-minimal-http-client-multi + --post -l --port 1${PORT_HCM_SRV}) + add_test(NAME http-client-multi-post-h1 COMMAND lws-minimal-http-client-multi + --post --h1 -l --port 1${PORT_HCM_SRV}) + add_test(NAME http-client-multi-post-pipe COMMAND lws-minimal-http-client-multi + --post -p -l --port 1${PORT_HCM_SRV}) + add_test(NAME http-client-multi-post-h1-pipe COMMAND lws-minimal-http-client-multi + --post --h1 -p -l --port 1${PORT_HCM_SRV}) + add_test(NAME http-client-multi-post-stag COMMAND lws-minimal-http-client-multi + --post -s -l -d1151 --port 1${PORT_HCM_SRV}) + add_test(NAME http-client-multi-post-stag-h1 COMMAND lws-minimal-http-client-multi + --post --h1 -d1151 -s -l --port 1${PORT_HCM_SRV}) + add_test(NAME http-client-multi-post-stag-pipe COMMAND lws-minimal-http-client-multi + --post -p -s -l --port 1${PORT_HCM_SRV}) + add_test(NAME http-client-multi-post-stag-h1-pipe COMMAND lws-minimal-http-client-multi + --post --h1 -p -s -l --port 1${PORT_HCM_SRV}) + set_tests_properties(http-client-multi-post + http-client-multi-post-h1 + http-client-multi-post-pipe + http-client-multi-post-h1-pipe + http-client-multi-post-stag + http-client-multi-post-stag-h1 + http-client-multi-post-stag-pipe + http-client-multi-post-stag-h1-pipe + PROPERTIES + FIXTURES_REQUIRED "hcmp_srv" + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/http-client/minimal-http-client-multi + TIMEOUT 20) + +endif(NOT WIN32 AND LWS_WITH_SERVER) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-multi/minimal-http-client-multi.c libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-multi/minimal-http-client-multi.c --- libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-multi/minimal-http-client-multi.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-multi/minimal-http-client-multi.c 2020-12-01 17:40:26.000000000 +0000 @@ -44,7 +44,7 @@ static lws_sorted_usec_list_t sul_stagger; static struct lws_client_connect_info i; static struct lws *client_wsi[COUNT]; -static char urlpath[64]; +static char urlpath[64], intr; static struct lws_context *context; /* we only need this for tracking POST emit state */ @@ -132,7 +132,9 @@ break; if (lws_http_is_redirected_to_get(wsi)) break; - lwsl_user("LWS_CALLBACK_CLIENT_HTTP_WRITEABLE: %p, part %d\n", wsi, pss->body_part); + lwsl_info("LWS_CALLBACK_CLIENT_HTTP_WRITEABLE: %p, idx %d," + " part %d\n", wsi, idx, pss->body_part); + n = LWS_WRITE_HTTP; /* @@ -198,7 +200,7 @@ lwsl_user("Done: all OK\n"); else lwsl_err("Done: failed: %d\n", failed); - //interrupted = 1; + intr = 1; /* * This is how we can exit the event loop even when it's an * event library backing it... it will start and stage the @@ -318,18 +320,14 @@ { struct lws_context_creation_info info; unsigned long long start; + int m, staggered = 0; const char *p; - int m, staggered = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE - /* for LLL_ verbosity above NOTICE to be built into lws, - * lws must have been configured and built with - * -DCMAKE_BUILD_TYPE=DEBUG instead of =RELEASE */ - /* | LLL_INFO */ /* | LLL_PARSER */ /* | LLL_HEADER */ - /* | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY */ - /* | LLL_DEBUG */; memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ memset(&i, 0, sizeof i); /* otherwise uninitialized garbage */ + lws_cmdline_option_handle_builtin(argc, argv, &info); + info.signal_cb = signal_cb; info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; @@ -348,10 +346,7 @@ signal(SIGINT, sigint_handler); staggered = !!lws_cmdline_option(argc, argv, "-s"); - if ((p = lws_cmdline_option(argc, argv, "-d"))) - logs = atoi(p); - lws_set_log_level(logs, NULL); lwsl_user("LWS minimal http client [-s (staggered)] [-p (pipeline)]\n"); lwsl_user(" [--h1 (http/1 only)] [-l (localhost)] [-d ]\n"); lwsl_user(" [-n (numbered)] [--post]\n"); @@ -367,7 +362,7 @@ */ info.fd_limit_per_thread = 1 + COUNT + 1; -#if defined(LWS_WITH_MBEDTLS) +#if defined(LWS_WITH_MBEDTLS) || defined(USE_WOLFSSL) /* * OpenSSL uses the system trust store. mbedTLS has to be told which * CA to trust explicitly. @@ -424,6 +419,9 @@ strcpy(urlpath, "/testserver/formtest"); } + if (lws_cmdline_option(argc, argv, "--no-tls")) + i.ssl_connection &= ~(LCCSCF_USE_SSL); + if (lws_cmdline_option(argc, argv, "-n")) numbered = 1; @@ -459,7 +457,7 @@ 100 * LWS_US_PER_MS); start = us(); - while (!lws_service(context, 0)) + while (!intr && !lws_service(context, 0)) ; lwsl_user("Duration: %lldms\n", (us() - start) / 1000); diff -Nru libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-multi/selftest.sh libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-multi/selftest.sh --- libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-multi/selftest.sh 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-multi/selftest.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,66 +0,0 @@ -#!/bin/bash -# -# $1: path to minimal example binaries... -# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 -# that will be ./bin from your build dir -# -# $2: path for logs and results. The results will go -# in a subdir named after the directory this script -# is in -# -# $3: offset for test index count -# -# $4: total test count -# -# $5: path to ./minimal-examples dir in lws -# -# Test return code 0: OK, 254: timed out, other: error indication - -. $5/selftests-library.sh - -COUNT_TESTS=30 - -dotest $1 $2 warmcat -dotest $1 $2 warmcat-pipe -p -dotest $1 $2 warmcat-h1 --h1 -dotest $1 $2 warmcat-h1-pipe --h1 -p -dotest $1 $2 warmcat-stag -s -dotest $1 $2 warmcat-pipe-stag -p -s -dotest $1 $2 warmcat-h1-stag --h1 -s -dotest $1 $2 warmcat-h1-pipe-stag --h1 -p -s -dotest $1 $2 warmcat-post --post -dotest $1 $2 warmcat-post-pipe --post -p -dotest $1 $2 warmcat-post-pipe-stag --post -p -s -dotest $1 $2 warmcat-h1-post --post --h1 -dotest $1 $2 warmcat-h1-post-pipe --post --h1 -p -dotest $1 $2 warmcat-h1-post-pipe-stag --post --h1 -p -s -dotest $1 $2 warmcat-restrict-pipe --limit 1 -p -dotest $1 $2 warmcat-restrict-h1-pipe --limit 1 -p --h1 -dotest $1 $2 warmcat-restrict-pipe-stag --limit 1 -p -s -dotest $1 $2 warmcat-restrict-h1-pipe-stag --limit 1 -p --h1 -s -dofailtest $1 $2 fail-warmcat-restrict --limit 1 -dofailtest $1 $2 fail-warmcat-restrict-h1 --limit 1 --h1 -dofailtest $1 $2 fail-warmcat-restrict-stag --limit 1 -s -dofailtest $1 $2 fail-warmcat-restrict-h1-stag --limit 1 --h1 -s - -spawn "" $5/http-server/minimal-http-server-tls $1/lws-minimal-http-server-tls -dotest $1 $2 localhost -l -spawn $SPID $5/http-server/minimal-http-server-tls $1/lws-minimal-http-server-tls -dotest $1 $2 localhost-pipe -l -p -spawn $SPID $5/http-server/minimal-http-server-tls $1/lws-minimal-http-server-tls -dotest $1 $2 localhost-h1 -l --h1 -spawn $SPID $5/http-server/minimal-http-server-tls $1/lws-minimal-http-server-tls -dotest $1 $2 localhost-h1-pipe -l --h1 -p -spawn $SPID $5/http-server/minimal-http-server-tls $1/lws-minimal-http-server-tls -dotest $1 $2 localhost-stag -l -s -spawn $SPID $5/http-server/minimal-http-server-tls $1/lws-minimal-http-server-tls -dotest $1 $2 localhost-pipe-stag -l -p -s -spawn $SPID $5/http-server/minimal-http-server-tls $1/lws-minimal-http-server-tls -dotest $1 $2 localhost-h1-stag -l --h1 -s -spawn $SPID $5/http-server/minimal-http-server-tls $1/lws-minimal-http-server-tls -dotest $1 $2 localhost-h1-pipe-stag -l --h1 -p -s - -kill $SPID 2>/dev/null -wait $SPID 2>/dev/null -exit $FAILS - diff -Nru libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-multi/warmcat.com.cer libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-multi/warmcat.com.cer --- libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-multi/warmcat.com.cer 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-multi/warmcat.com.cer 2020-12-01 17:40:26.000000000 +0000 @@ -56,3 +56,23 @@ PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6 KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg== -----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow +PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD +Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O +rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq +OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b +xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw +7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD +aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG +SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 +ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr +AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz +R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 +JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo +Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +-----END CERTIFICATE----- diff -Nru libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-post/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-post/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-post/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-post/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,79 +1,90 @@ -project(lws-minimal-http-client-post) +project(lws-minimal-http-client-post C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-client-post) set(SRCS minimal-http-client-post.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) + + # + # instantiate the server per sai builder instance, they are running in the same + # machine context in parallel so they can tread on each other otherwise + # + set(PORT_HCP_SRV "7640") + if ("$ENV{SAI_INSTANCE_IDX}" STREQUAL "0") + set(PORT_HCP_SRV 7641) + endif() + if ("$ENV{SAI_INSTANCE_IDX}" STREQUAL "1") + set(PORT_HCP_SRV 7642) + endif() + if ("$ENV{SAI_INSTANCE_IDX}" STREQUAL "2") + set(PORT_HCP_SRV 7643) + endif() + if ("$ENV{SAI_INSTANCE_IDX}" STREQUAL "3") + set(PORT_HCP_SRV 7644) + endif() + +# hack +if (NOT WIN32 AND LWS_WITH_SERVER) + + # + # Tests against built server running locally (needs daemonization...) + # + +if (WIN32) + add_test(NAME st_hcp_srv COMMAND cmd.exe /c start /b $ -s --port ${PORT_HCP_SRV}) + add_test(NAME ki_hcp_srv COMMAND taskkill /F /IM $ /T) +else() + add_test(NAME st_hcp_srv COMMAND + ${CMAKE_SOURCE_DIR}/scripts/ctest-background.sh + hcp_srv + $ + -r ${CMAKE_SOURCE_DIR}/destdir/usr/local/share/libwebsockets-test-server/ + -s --port ${PORT_HCP_SRV} --ignore-sigterm) + add_test(NAME ki_hcp_srv COMMAND + ${CMAKE_SOURCE_DIR}/scripts/ctest-background-kill.sh hcp_srv + $ --port ${PORT_HCP_SRV}) +endif() + + set_tests_properties(st_hcp_srv PROPERTIES + WORKING_DIRECTORY . + FIXTURES_SETUP hcp_srv + TIMEOUT 800) + set_tests_properties(ki_hcp_srv PROPERTIES + FIXTURES_CLEANUP hcp_srv) + + add_test(NAME http-client-post COMMAND + lws-minimal-http-client-post -l --port ${PORT_HCP_SRV}) + add_test(NAME http-client-post-m COMMAND + lws-minimal-http-client-post -l -m --port ${PORT_HCP_SRV}) + add_test(NAME http-client-post-h1 COMMAND + lws-minimal-http-client-post -l --h1 --port ${PORT_HCP_SRV}) + add_test(NAME http-client-post-m-h1 COMMAND + lws-minimal-http-client-post -l -m --h1 --port ${PORT_HCP_SRV}) + set_tests_properties(http-client-post + http-client-post-m + http-client-post-h1 + http-client-post-m-h1 + PROPERTIES + FIXTURES_REQUIRED "hcp_srv" + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/http-client/minimal-http-client-post + TIMEOUT 20) +endif() + if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-post/libwebsockets.org.cer libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-post/libwebsockets.org.cer --- libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-post/libwebsockets.org.cer 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-post/libwebsockets.org.cer 2020-12-01 17:40:26.000000000 +0000 @@ -56,3 +56,24 @@ PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6 KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg== -----END CERTIFICATE----- + -----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow +PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD +Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O +rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq +OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b +xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw +7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD +aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG +SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 +ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr +AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz +R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 +JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo +Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +-----END CERTIFICATE----- + diff -Nru libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-post/minimal-http-client-post.c libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-post/minimal-http-client-post.c --- libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-post/minimal-http-client-post.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-post/minimal-http-client-post.c 2020-12-01 17:40:26.000000000 +0000 @@ -189,6 +189,7 @@ struct lws_context_creation_info info; struct lws_client_connect_info i; struct lws_context *context; + const char *p; int n = 0; signal(SIGINT, sigint_handler); @@ -212,7 +213,7 @@ */ info.fd_limit_per_thread = 1 + count_clients + 1; -#if defined(LWS_WITH_MBEDTLS) +#if defined(LWS_WITH_MBEDTLS) || defined(USE_WOLFSSL) /* * OpenSSL uses the system trust store. mbedTLS has to be told which * CA to trust explicitly. @@ -245,6 +246,9 @@ if (lws_cmdline_option(argc, argv, "--form1")) i.path = "/form1"; + if ((p = lws_cmdline_option(argc, argv, "--port"))) + i.port = atoi(p); + i.host = i.address; i.origin = i.address; i.method = "POST"; @@ -257,6 +261,8 @@ for (n = 0; n < count_clients; n++) { i.pwsi = &client_wsi[n]; + lwsl_notice("%s: connecting to %s:%d\n", __func__, + i.address, i.port); if (!lws_client_connect_via_info(&i)) completed++; } diff -Nru libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-post/selftest.sh libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-post/selftest.sh --- libwebsockets-4.0.20/minimal-examples/http-client/minimal-http-client-post/selftest.sh 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-client/minimal-http-client-post/selftest.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -#!/bin/bash -# -# $1: path to minimal example binaries... -# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 -# that will be ./bin from your build dir -# -# $2: path for logs and results. The results will go -# in a subdir named after the directory this script -# is in -# -# $3: offset for test index count -# -# $4: total test count -# -# $5: path to ./minimal-examples dir in lws -# -# Test return code 0: OK, 254: timed out, other: error indication - -. $5/selftests-library.sh - -COUNT_TESTS=8 - -dotest $1 $2 warmcat -dotest $1 $2 warmcat-h1 --h1 -dotest $1 $2 warmcat-m -m -dotest $1 $2 warmcat-m-h1 -m --h1 - -spawn "" $5 $1/libwebsockets-test-server -s -dotest $1 $2 localhost -l -d1151 -spawn $SPID $5 $1/libwebsockets-test-server -s -dotest $1 $2 localhost-h1 -l --h1 -spawn $SPID $5 $1/libwebsockets-test-server -s -dotest $1 $2 localhost-m -l -m -spawn $SPID $5 $1/libwebsockets-test-server -s -dotest $1 $2 localhost-m-h1 -l -m --h1 - -kill $SPID 2>/dev/null -wait $SPID 2>/dev/null -exit $FAILS diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,69 +1,13 @@ -project(lws-minimal-http-server) +project(lws-minimal-http-server C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server) set(SRCS minimal-http-server.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) @@ -72,9 +16,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() \ No newline at end of file diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server/minimal-http-server.c libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server/minimal-http-server.c --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server/minimal-http-server.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server/minimal-http-server.c 2020-12-01 17:40:26.000000000 +0000 @@ -72,6 +72,9 @@ info.options = LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; + if (lws_cmdline_option(argc, argv, "--h2-prior-knowledge")) + info.options |= LWS_SERVER_OPTION_H2_PRIOR_KNOWLEDGE; + context = lws_create_context(&info); if (!context) { lwsl_err("lws init failed\n"); diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-basicauth/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-basicauth/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-basicauth/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-basicauth/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,67 +1,13 @@ -project(lws-minimal-http-server-basicauth) +project(lws-minimal-http-server-basicauth C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-basicauth) set(SRCS minimal-http-server-basicauth.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) @@ -71,9 +17,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-cgi/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-cgi/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-cgi/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-cgi/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,69 +1,13 @@ -project(lws-minimal-http-server-cgi) +project(lws-minimal-http-server-cgi C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-cgi) set(SRCS minimal-http-server.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_CGI 1 requirements) @@ -73,9 +17,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-cgi/minimal-http-server.c libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-cgi/minimal-http-server.c --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-cgi/minimal-http-server.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-cgi/minimal-http-server.c 2020-12-01 17:40:26.000000000 +0000 @@ -82,11 +82,13 @@ info.options = LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; +#if defined(LWS_WITH_TLS) if (lws_cmdline_option(argc, argv, "-s")) { info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; info.ssl_cert_filepath = "localhost-100y.cert"; info.ssl_private_key_filepath = "localhost-100y.key"; } +#endif context = lws_create_context(&info); if (!context) { diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-cgi/my-cgi-script.sh libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-cgi/my-cgi-script.sh --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-cgi/my-cgi-script.sh 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-cgi/my-cgi-script.sh 2020-12-01 17:40:26.000000000 +0000 @@ -14,7 +14,7 @@ >&2 echo "lwstest script stderr: doing read" echo "CONTENT_LENGTH=$CONTENT_LENGTH" read -n $CONTENT_LENGTH line - >&2 echo "lwstest script stderr: done read" + >&2 echo "lwstest script stderr: done read $line" echo "read=\"$line\"" else @@ -31,6 +31,6 @@ echo "
done" echo "" - +sleep 0.5 exit 0 diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-custom-headers/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-custom-headers/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-custom-headers/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-custom-headers/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,67 +1,13 @@ -project(lws-minimal-http-server-custom-headers) +project(lws-minimal-http-server-custom-headers C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-custom-headers) set(SRCS minimal-http-server-custom-headers.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_CUSTOM_HEADERS 1 requirements) @@ -71,9 +17,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-custom-headers/minimal-http-server-custom-headers.c libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-custom-headers/minimal-http-server-custom-headers.c --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-custom-headers/minimal-http-server-custom-headers.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-custom-headers/minimal-http-server-custom-headers.c 2020-12-01 17:40:26.000000000 +0000 @@ -201,8 +201,10 @@ info.port = 7682; info.error_document_404 = "/404.html"; +#if defined(LWS_WITH_TLS) info.ssl_cert_filepath = "localhost-100y.cert"; info.ssl_private_key_filepath = "localhost-100y.key"; +#endif info.vhost_name = "https"; if (!lws_create_vhost(context, &info)) { diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-deaddrop/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-deaddrop/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-deaddrop/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-deaddrop/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,6 +1,9 @@ -project(lws-minimal-http-server-deaddrop) +project(lws-minimal-http-server-deaddrop C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-deaddrop) set(SRCS minimal-http-server-deaddrop.c) @@ -9,70 +12,13 @@ # to the lws plugins dir so it can pick up the plugin source. Eg, # cmake . -DLWS_PLUGINS_DIR=~/libwebsockets/plugins -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_ROLE_WS 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) require_lws_config(LWS_WITH_HTTP_BASIC_AUTH 1 requirements) -if (requirements) +if (requirements AND UNIX) add_executable(${SAMP} ${SRCS}) if (LWS_PLUGINS_DIR) @@ -80,9 +26,9 @@ endif() if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-deaddrop/minimal-http-server-deaddrop.c libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-deaddrop/minimal-http-server-deaddrop.c --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-deaddrop/minimal-http-server-deaddrop.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-deaddrop/minimal-http-server-deaddrop.c 2020-12-01 17:40:26.000000000 +0000 @@ -153,8 +153,10 @@ info.error_document_404 = "/404.html"; info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT | LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; +#if defined(LWS_WITH_TLS) info.ssl_cert_filepath = "localhost-100y.cert"; info.ssl_private_key_filepath = "localhost-100y.key"; +#endif context = lws_create_context(&info); if (!context) { diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-dynamic/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-dynamic/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-dynamic/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-dynamic/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,68 +1,13 @@ -project(lws-minimal-http-server-dynamic) +project(lws-minimal-http-server-dynamic C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-dynamic) set(SRCS minimal-http-server-dynamic.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) @@ -71,9 +16,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-dynamic/minimal-http-server-dynamic.c libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-dynamic/minimal-http-server-dynamic.c --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-dynamic/minimal-http-server-dynamic.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-dynamic/minimal-http-server-dynamic.c 2020-12-01 17:40:26.000000000 +0000 @@ -49,11 +49,27 @@ switch (reason) { case LWS_CALLBACK_HTTP: - /* in contains the url part after our mountpoint /dyn, if any */ - lws_snprintf(pss->path, sizeof(pss->path), "%s", (const char *)in); + /* + * If you want to know the full url path used, you can get it + * like this + * + * n = lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_GET_URI); + * + * The base path is the first (n - strlen((const char *)in)) + * chars in buf. + */ + + /* + * In contains the url part after the place the mount was + * positioned at, eg, if positioned at "/dyn" and given + * "/dyn/mypath", in will contain /mypath + */ + lws_snprintf(pss->path, sizeof(pss->path), "%s", + (const char *)in); lws_get_peer_simple(wsi, (char *)buf, sizeof(buf)); - lwsl_notice("%s: HTTP: connection %s\n", __func__, (const char *)buf); + lwsl_notice("%s: HTTP: connection %s, path %s\n", __func__, + (const char *)buf, pss->path); /* * prepare and write http headers... with regards to content- @@ -178,10 +194,11 @@ return lws_callback_http_dummy(wsi, reason, user, in, len); } -static const struct lws_protocols protocol = +static const struct lws_protocols defprot = + { "defprot", lws_callback_http_dummy, 0, 0 }, protocol = { "http", callback_dynamic_http, sizeof(struct pss), 0 }; -static const struct lws_protocols *pprotocols[] = { &protocol, NULL }; +static const struct lws_protocols *pprotocols[] = { &defprot, &protocol, NULL }; /* override the default mount for /dyn in the URL space */ @@ -284,8 +301,10 @@ info.port = 7682; info.error_document_404 = "/404.html"; +#if defined(LWS_WITH_TLS) info.ssl_cert_filepath = "localhost-100y.cert"; info.ssl_private_key_filepath = "localhost-100y.key"; +#endif info.vhost_name = "localhost"; if (!lws_create_vhost(context, &info)) { diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-eventlib/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-eventlib/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-eventlib/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-eventlib/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,68 +1,13 @@ -project(lws-minimal-http-server-eventlib) +project(lws-minimal-http-server-eventlib C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-eventlib) set(SRCS minimal-http-server-eventlib.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) @@ -71,9 +16,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-eventlib/minimal-http-server-eventlib.c libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-eventlib/minimal-http-server-eventlib.c --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-eventlib/minimal-http-server-eventlib.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-eventlib/minimal-http-server-eventlib.c 2020-12-01 17:40:26.000000000 +0000 @@ -86,11 +86,13 @@ info.options = LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; +#if defined(LWS_WITH_TLS) if (lws_cmdline_option(argc, argv, "-s")) { info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; info.ssl_cert_filepath = "localhost-100y.cert"; info.ssl_private_key_filepath = "localhost-100y.key"; } +#endif if (lws_cmdline_option(argc, argv, "--uv")) info.options |= LWS_SERVER_OPTION_LIBUV; diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-eventlib-demos/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-eventlib-demos/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-eventlib-demos/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-eventlib-demos/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,68 +1,13 @@ -project(lws-minimal-http-server-eventlib-demos) +project(lws-minimal-http-server-eventlib-demos C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-eventlib-demos) set(SRCS minimal-http-server-eventlib-demos.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_ROLE_WS 1 requirements) @@ -72,9 +17,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-eventlib-demos/minimal-http-server-eventlib-demos.c libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-eventlib-demos/minimal-http-server-eventlib-demos.c --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-eventlib-demos/minimal-http-server-eventlib-demos.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-eventlib-demos/minimal-http-server-eventlib-demos.c 2020-12-01 17:40:26.000000000 +0000 @@ -41,10 +41,30 @@ * mount handlers for sections of the URL space */ -static const struct lws_http_mount mount_ziptest = { +static const struct lws_http_mount mount_ziptest_uncomm = { NULL, /* linked-list pointer to next*/ + "/uncommziptest", /* mountpoint in URL namespace on this vhost */ + "./mount-origin/candide-uncompressed.zip", /* handler */ + NULL, /* default filename if none given */ + NULL, + NULL, + NULL, + NULL, + 0, + 0, + 0, + 0, + 0, + 0, + LWSMPRO_FILE, /* origin points to a callback */ + 14, /* strlen("/ziptest"), ie length of the mountpoint */ + NULL, + + { NULL, NULL } // sentinel +}, mount_ziptest = { + (struct lws_http_mount *)&mount_ziptest_uncomm, /* linked-list pointer to next*/ "/ziptest", /* mountpoint in URL namespace on this vhost */ - "candide.zip", /* handler */ + "./mount-origin/candide.zip", /* handler */ NULL, /* default filename if none given */ NULL, NULL, @@ -61,9 +81,7 @@ NULL, { NULL, NULL } // sentinel -}; - -static const struct lws_http_mount mount_post = { +}, mount_post = { (struct lws_http_mount *)&mount_ziptest, /* linked-list pointer to next*/ "/formtest", /* mountpoint in URL namespace on this vhost */ "protocol-post-demo", /* handler */ @@ -83,10 +101,7 @@ NULL, { NULL, NULL } // sentinel -}; - - -static const struct lws_http_mount mount = { +}, mount = { /* .mount_next */ &mount_post, /* linked-list "next" */ /* .mountpoint */ "/", /* mountpoint URL */ /* .origin */ "./mount-origin", /* serve from dir */ @@ -157,8 +172,10 @@ if (lws_cmdline_option(argc, argv, "-s")) { info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; +#if defined(LWS_WITH_TLS) info.ssl_cert_filepath = "localhost-100y.cert"; info.ssl_private_key_filepath = "localhost-100y.key"; +#endif } if (lws_cmdline_option(argc, argv, "--uv")) Binary files /tmp/tmpmec97nsd/m0nuW2sR0N/libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-eventlib-demos/mount-origin/candide-uncompressed.zip and /tmp/tmpmec97nsd/q8JCI83EXS/libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-eventlib-demos/mount-origin/candide-uncompressed.zip differ diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-eventlib-foreign/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-eventlib-foreign/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-eventlib-foreign/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-eventlib-foreign/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,73 +1,19 @@ -project(lws-minimal-http-server-eventlib-foreign) +project(lws-minimal-http-server-eventlib-foreign C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) +include(CheckIncludeFile) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-eventlib-foreign) set(SRCS minimal-http-server-eventlib-foreign.c) - -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) +require_pthreads(requirements) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) - - +require_lws_config(LWS_WITH_TLS 1 requirements) CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(LWS_WITH_LIBUV)\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" LWS_WITH_LIBUV) CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(LWS_WITH_LIBEVENT)\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" LWS_WITH_LIBEVENT) @@ -76,13 +22,31 @@ if (LWS_WITH_LIBUV) - set(extralibs ${extralibs} uv) + find_path(LIBUV_INCLUDE_DIRS NAMES uv.h) + find_library(LIBUV_LIBRARIES NAMES uv) + message("libuv include dir: ${LIBUV_INCLUDE_DIRS}") + message("libuv libraries: ${LIBUV_LIBRARIES}") + include_directories("${LIBUV_INCLUDE_DIRS}") + set(extralibs ${extralibs} ${LIBUV_LIBRARIES}) + list(APPEND SRCS libuv.c) endif() if (LWS_WITH_LIBEVENT) - set(extralibs ${extralibs} event) + find_path(LIBEVENT_INCLUDE_DIRS NAMES event2/event.h) + find_library(LIBEVENT_LIBRARIES NAMES event) + message("libevent include dir: ${LIBEVENT_INCLUDE_DIRS}") + message("libevent libraries: ${LIBEVENT_LIBRARIES}") + include_directories("${LIBEVENT_INCLUDE_DIRS}") + set(extralibs ${extralibs} ${LIBEVENT_LIBRARIES}) + list(APPEND SRCS libevent.c) endif() if (LWS_WITH_LIBEV) - set(extralibs ${extralibs} ev) + find_path(LIBEV_INCLUDE_DIRS NAMES ev.h) + find_library(LIBEV_LIBRARIES NAMES ev) + message("libev include dir: ${LIBEV_INCLUDE_DIRS}") + message("libev libraries: ${LIBEV_LIBRARIES}") + include_directories("${LIBEV_INCLUDE_DIRS}") + set(extralibs ${extralibs} ${LIBEV_LIBRARIES}) + list(APPEND SRCS libev.c) endif() if (LWS_WITH_GLIB) set(LWS_GLIB_INCLUDE_DIRS CACHE PATH "Path to the glib include directory") @@ -106,6 +70,7 @@ message("glib libraries: ${GLIB_LIBRARIES}") include_directories("${GLIB_INCLUDE_DIRS}") set(extralibs ${extralibs} ${GLIB_LIBRARIES}) + list(APPEND SRCS glib.c) endif() message("Extra libs: ${extralibs}") @@ -118,9 +83,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared ${extralibs}) + target_link_libraries(${SAMP} websockets_shared ${extralibs} ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets ${extralibs}) + target_link_libraries(${SAMP} websockets ${extralibs} ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-eventlib-foreign/glib.c libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-eventlib-foreign/glib.c --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-eventlib-foreign/glib.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-eventlib-foreign/glib.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,92 @@ +/* + * lws-minimal-http-server-eventlib-foreign + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * The glib specific code + */ + +#include + +#include +#include + +#include +#include + +#include "private.h" + +typedef struct lws_glib_tag { + GSource *gs; + guint tag; +} lws_glib_tag_t; + +#define lws_gs_valid(t) (t.gs) +#define lws_gs_destroy(t) if (lws_gs_valid(t)) { \ + g_source_remove(t.tag); \ + g_source_unref(t.gs); \ + t.gs = NULL; t.tag = 0; } + +static GMainLoop *loop_glib; +static lws_glib_tag_t timer_outer_glib, sighandler_glib; + +static int +timer_cb_glib(void *p) +{ + foreign_timer_service(loop_glib); + return 1; +} + +static void +signal_cb_glib(void *p) +{ + signal_cb(SIGINT); +} + +static void +foreign_event_loop_init_and_run_glib(void) +{ + /* we create and start our "foreign loop" */ + + loop_glib = g_main_loop_new(NULL, 0); + + sighandler_glib.gs = g_unix_signal_source_new(SIGINT); + g_source_set_callback(sighandler_glib.gs, G_SOURCE_FUNC(signal_cb_glib), + NULL, NULL); + sighandler_glib.tag = g_source_attach(sighandler_glib.gs, + g_main_loop_get_context(loop_glib)); + + timer_outer_glib.gs = g_timeout_source_new(1000); + g_source_set_callback(timer_outer_glib.gs, timer_cb_glib, NULL, NULL); + timer_outer_glib.tag = g_source_attach(timer_outer_glib.gs, + g_main_loop_get_context(loop_glib)); + + g_main_loop_run(loop_glib); +} + +static void +foreign_event_loop_stop_glib(void) +{ + g_main_loop_quit(loop_glib); +} + +static void +foreign_event_loop_cleanup_glib(void) +{ + /* cleanup the foreign loop assets */ + + lws_gs_destroy(sighandler_glib); + lws_gs_destroy(timer_outer_glib); + + g_main_loop_unref(loop_glib); + loop_glib = NULL; +} + +const struct ops ops_glib = { + foreign_event_loop_init_and_run_glib, + foreign_event_loop_stop_glib, + foreign_event_loop_cleanup_glib +}; diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-eventlib-foreign/libev.c libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-eventlib-foreign/libev.c --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-eventlib-foreign/libev.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-eventlib-foreign/libev.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,76 @@ +/* + * lws-minimal-http-server-eventlib-foreign + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * The libev specific code + */ + +#include + +#include + +#include +#include + +#include "private.h" + +static struct ev_loop *loop_ev; +static struct ev_timer timer_outer_ev; +static struct ev_signal sighandler_ev; + +static void +timer_cb_ev(struct ev_loop *loop, struct ev_timer *watcher, int revents) +{ + foreign_timer_service(loop_ev); +} + +static void +signal_cb_ev(struct ev_loop *loop, struct ev_signal *watcher, int revents) +{ + signal_cb(watcher->signum); +} + +static void +foreign_event_loop_init_and_run_libev(void) +{ + /* we create and start our "foreign loop" */ + + loop_ev = ev_loop_new(0); + + ev_signal_init(&sighandler_ev, signal_cb_ev, SIGINT); + ev_signal_start(loop_ev, &sighandler_ev); + + ev_timer_init(&timer_outer_ev, timer_cb_ev, 0, 1); + ev_timer_start(loop_ev, &timer_outer_ev); + + ev_run(loop_ev, 0); +} + +static void +foreign_event_loop_stop_libev(void) +{ + ev_break(loop_ev, EVBREAK_ALL); +} + +static void +foreign_event_loop_cleanup_libev(void) +{ + /* cleanup the foreign loop assets */ + + ev_timer_stop(loop_ev, &timer_outer_ev); + ev_signal_stop(loop_ev, &sighandler_ev); + + ev_run(loop_ev, 0); + ev_loop_destroy(loop_ev); +} + +const struct ops ops_libev = { + foreign_event_loop_init_and_run_libev, + foreign_event_loop_stop_libev, + foreign_event_loop_cleanup_libev +}; + diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-eventlib-foreign/libevent.c libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-eventlib-foreign/libevent.c --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-eventlib-foreign/libevent.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-eventlib-foreign/libevent.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,84 @@ +/* + * lws-minimal-http-server-eventlib-foreign + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * The libevent specific code + */ + +#include + +#include + +#include +#include + +#include "private.h" + +static struct event_base *loop_event; +static struct event *timer_outer_event; +static struct event *sighandler_event; + +static void +timer_cb_event(int fd, short event, void *arg) +{ + foreign_timer_service(loop_event); +} + +static void +signal_cb_event(int fd, short event, void *arg) +{ + signal_cb((int)(lws_intptr_t)arg); +} + +static void +foreign_event_loop_init_and_run_libevent(void) +{ + struct timeval tv; + + /* we create and start our "foreign loop" */ + + tv.tv_sec = 1; + tv.tv_usec = 0; + + loop_event = event_base_new(); + + sighandler_event = evsignal_new(loop_event, SIGINT, signal_cb_event, + (void*)SIGINT); + + timer_outer_event = event_new(loop_event, -1, EV_PERSIST, + timer_cb_event, NULL); + //evtimer_new(loop_event, timer_cb_event, NULL); + evtimer_add(timer_outer_event, &tv); + + event_base_loop(loop_event, 0); +} + +static void +foreign_event_loop_stop_libevent(void) +{ + event_base_loopexit(loop_event, NULL); +} + +static void +foreign_event_loop_cleanup_libevent(void) +{ + /* cleanup the foreign loop assets */ + + evtimer_del(timer_outer_event); + event_free(timer_outer_event); + evsignal_del(sighandler_event); + event_free(sighandler_event); + + event_base_loop(loop_event, 0); + event_base_free(loop_event); +} + +const struct ops ops_libevent = { + foreign_event_loop_init_and_run_libevent, + foreign_event_loop_stop_libevent, + foreign_event_loop_cleanup_libevent +}; diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-eventlib-foreign/libuv.c libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-eventlib-foreign/libuv.c --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-eventlib-foreign/libuv.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-eventlib-foreign/libuv.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,91 @@ +/* + * lws-minimal-http-server-eventlib-foreign + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * The libuv specific code + */ + +#include + +#include +#include + +#include +#ifdef LWS_HAVE_UV_VERSION_H +#include +#endif +#ifdef LWS_HAVE_NEW_UV_VERSION_H +#include +#endif + +#include "private.h" + +static uv_loop_t loop_uv; +static uv_timer_t timer_outer_uv; +static uv_signal_t sighandler_uv; + +static void +timer_cb_uv(uv_timer_t *t) +{ + foreign_timer_service(&loop_uv); +} + +static void +signal_cb_uv(uv_signal_t *watcher, int signum) +{ + signal_cb(signum); +} + +static void +foreign_event_loop_init_and_run_libuv(void) +{ + /* we create and start our "foreign loop" */ + +#if (UV_VERSION_MAJOR > 0) // Travis... + uv_loop_init(&loop_uv); +#endif + uv_signal_init(&loop_uv, &sighandler_uv); + uv_signal_start(&sighandler_uv, signal_cb_uv, SIGINT); + + uv_timer_init(&loop_uv, &timer_outer_uv); +#if (UV_VERSION_MAJOR > 0) // Travis... + uv_timer_start(&timer_outer_uv, timer_cb_uv, 0, 1000); +#else + (void)timer_cb_uv; +#endif + + uv_run(&loop_uv, UV_RUN_DEFAULT); +} + +static void +foreign_event_loop_stop_libuv(void) +{ + uv_stop(&loop_uv); +} + +static void +foreign_event_loop_cleanup_libuv(void) +{ + /* cleanup the foreign loop assets */ + + uv_timer_stop(&timer_outer_uv); + uv_close((uv_handle_t*)&timer_outer_uv, NULL); + uv_signal_stop(&sighandler_uv); + uv_close((uv_handle_t *)&sighandler_uv, NULL); + + uv_run(&loop_uv, UV_RUN_DEFAULT); +#if (UV_VERSION_MAJOR > 0) // Travis... + uv_loop_close(&loop_uv); +#endif +} + +const struct ops ops_libuv = { + foreign_event_loop_init_and_run_libuv, + foreign_event_loop_stop_libuv, + foreign_event_loop_cleanup_libuv +}; + diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-eventlib-foreign.c libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-eventlib-foreign.c --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-eventlib-foreign.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-eventlib-foreign.c 2020-12-01 17:40:26.000000000 +0000 @@ -23,11 +23,12 @@ #include #include -struct lws_context_creation_info info; -static struct lws_context *context; -static int lifetime = 5, reported; +#include "private.h" -static void foreign_timer_service(void *foreign_loop); +static struct lws_context_creation_info info; +static const struct ops *ops = NULL; +struct lws_context *context; +int lifetime = 5, reported; enum { TEST_STATE_CREATE_LWS_CONTEXT, @@ -57,7 +58,7 @@ /* .basic_auth_login_file */ NULL, }; -static void +void signal_cb(int signum) { lwsl_notice("Signal %d caught, exiting...\n", signum); @@ -73,248 +74,9 @@ lws_context_destroy(context); } -/* - * The event-loop specific foreign loop code, one set for each event loop lib - * - * Only the code in this section is specific to the event library used. - */ - -#if defined(LWS_WITH_LIBUV) - -static uv_loop_t loop_uv; -static uv_timer_t timer_outer_uv; -static uv_signal_t sighandler_uv; - -static void -timer_cb_uv(uv_timer_t *t) -{ - foreign_timer_service(&loop_uv); -} - -static void -signal_cb_uv(uv_signal_t *watcher, int signum) -{ - signal_cb(signum); -} - -static void -foreign_event_loop_init_and_run_libuv(void) -{ - /* we create and start our "foreign loop" */ - -#if (UV_VERSION_MAJOR > 0) // Travis... - uv_loop_init(&loop_uv); -#endif - uv_signal_init(&loop_uv, &sighandler_uv); - uv_signal_start(&sighandler_uv, signal_cb_uv, SIGINT); - - uv_timer_init(&loop_uv, &timer_outer_uv); -#if (UV_VERSION_MAJOR > 0) // Travis... - uv_timer_start(&timer_outer_uv, timer_cb_uv, 0, 1000); -#else - (void)timer_cb_uv; -#endif - - uv_run(&loop_uv, UV_RUN_DEFAULT); -} - -static void -foreign_event_loop_stop_libuv(void) -{ - uv_stop(&loop_uv); -} - -static void -foreign_event_loop_cleanup_libuv(void) -{ - /* cleanup the foreign loop assets */ - - uv_timer_stop(&timer_outer_uv); - uv_close((uv_handle_t*)&timer_outer_uv, NULL); - uv_signal_stop(&sighandler_uv); - uv_close((uv_handle_t *)&sighandler_uv, NULL); - - uv_run(&loop_uv, UV_RUN_DEFAULT); -#if (UV_VERSION_MAJOR > 0) // Travis... - uv_loop_close(&loop_uv); -#endif -} - -#endif - -#if defined(LWS_WITH_LIBEVENT) - -static struct event_base *loop_event; -static struct event *timer_outer_event; -static struct event *sighandler_event; - -static void -timer_cb_event(int fd, short event, void *arg) -{ - foreign_timer_service(loop_event); -} - -static void -signal_cb_event(int fd, short event, void *arg) -{ - signal_cb((int)(lws_intptr_t)arg); -} - -static void -foreign_event_loop_init_and_run_libevent(void) -{ - struct timeval tv; - - /* we create and start our "foreign loop" */ - - tv.tv_sec = 1; - tv.tv_usec = 0; - - loop_event = event_base_new(); - - sighandler_event = evsignal_new(loop_event, SIGINT, signal_cb_event, - (void*)SIGINT); - - timer_outer_event = event_new(loop_event, -1, EV_PERSIST, - timer_cb_event, NULL); - //evtimer_new(loop_event, timer_cb_event, NULL); - evtimer_add(timer_outer_event, &tv); - - event_base_loop(loop_event, 0); -} - -static void -foreign_event_loop_stop_libevent(void) -{ - event_base_loopexit(loop_event, NULL); -} - -static void -foreign_event_loop_cleanup_libevent(void) -{ - /* cleanup the foreign loop assets */ - - evtimer_del(timer_outer_event); - event_free(timer_outer_event); - evsignal_del(sighandler_event); - event_free(sighandler_event); - - event_base_loop(loop_event, 0); - event_base_free(loop_event); -} - -#endif - -#if defined(LWS_WITH_GLIB) - -#include -#include - -static GMainLoop *loop_glib; -static guint timer_outer_glib; -static guint sighandler_glib; - -static int -timer_cb_glib(void *p) -{ - foreign_timer_service(loop_glib); - return 1; -} - -static void -signal_cb_glib(void *p) -{ - signal_cb(SIGINT); -} - -static void -foreign_event_loop_init_and_run_glib(void) -{ - /* we create and start our "foreign loop" */ - - loop_glib = g_main_loop_new(NULL, 0); - - sighandler_glib = g_unix_signal_add(SIGINT, - G_SOURCE_FUNC(signal_cb_glib), NULL); - - timer_outer_glib = g_timeout_add(1000, timer_cb_glib, NULL); - - g_main_loop_run(loop_glib); -} - -static void -foreign_event_loop_stop_glib(void) -{ - g_main_loop_quit(loop_glib); -} - -static void -foreign_event_loop_cleanup_glib(void) -{ - /* cleanup the foreign loop assets */ - g_source_remove(sighandler_glib); - g_main_loop_unref(loop_glib); -} - -#endif - -#if defined(LWS_WITH_LIBEV) - -static struct ev_loop *loop_ev; -static struct ev_timer timer_outer_ev; -static struct ev_signal sighandler_ev; - -static void -timer_cb_ev(struct ev_loop *loop, struct ev_timer *watcher, int revents) -{ - foreign_timer_service(loop_ev); -} - -static void -signal_cb_ev(struct ev_loop *loop, struct ev_signal *watcher, int revents) -{ - signal_cb(watcher->signum); -} - -static void -foreign_event_loop_init_and_run_libev(void) -{ - /* we create and start our "foreign loop" */ - - loop_ev = ev_loop_new(0); - - ev_signal_init(&sighandler_ev, signal_cb_ev, SIGINT); - ev_signal_start(loop_ev, &sighandler_ev); - - ev_timer_init(&timer_outer_ev, timer_cb_ev, 0, 1); - ev_timer_start(loop_ev, &timer_outer_ev); - - ev_run(loop_ev, 0); -} - -static void -foreign_event_loop_stop_libev(void) -{ - ev_break(loop_ev, EVBREAK_ALL); -} - -static void -foreign_event_loop_cleanup_libev(void) -{ - /* cleanup the foreign loop assets */ - - ev_timer_stop(loop_ev, &timer_outer_ev); - ev_signal_stop(loop_ev, &sighandler_ev); - - ev_run(loop_ev, 0); - ev_loop_destroy(loop_ev); -} - -#endif - /* this is called at 1Hz using a foreign loop timer */ -static void +void foreign_timer_service(void *foreign_loop) { void *foreign_loops[1]; @@ -357,22 +119,7 @@ case TEST_STATE_EXIT: lwsl_user("Deciding to exit foreign loop too\n"); -#if defined(LWS_WITH_LIBUV) - if (info.options & LWS_SERVER_OPTION_LIBUV) - foreign_event_loop_stop_libuv(); -#endif -#if defined(LWS_WITH_LIBEVENT) - if (info.options & LWS_SERVER_OPTION_LIBEVENT) - foreign_event_loop_stop_libevent(); -#endif -#if defined(LWS_WITH_LIBEV) - if (info.options & LWS_SERVER_OPTION_LIBEV) - foreign_event_loop_stop_libev(); -#endif -#if defined(LWS_WITH_GLIB) - if (info.options & LWS_SERVER_OPTION_GLIB) - foreign_event_loop_stop_glib(); -#endif + ops->stop(); break; default: break; @@ -417,23 +164,45 @@ info.ssl_private_key_filepath = "localhost-100y.key"; } - if (lws_cmdline_option(argc, argv, "--uv")) + /* + * We configure lws to use the chosen event loop, and select the + * matching event-lib specific code for our demo operations + */ + +#if defined(LWS_WITH_LIBUV) + if (lws_cmdline_option(argc, argv, "--uv")) { info.options |= LWS_SERVER_OPTION_LIBUV; - else - if (lws_cmdline_option(argc, argv, "--event")) + ops = &ops_libuv; + lwsl_notice("%s: using libuv event loop\n", __func__); + } else +#endif +#if defined(LWS_WITH_LIBEVENT) + if (lws_cmdline_option(argc, argv, "--event")) { info.options |= LWS_SERVER_OPTION_LIBEVENT; - else - if (lws_cmdline_option(argc, argv, "--ev")) + ops = &ops_libevent; + lwsl_notice("%s: using libevent loop\n", __func__); + } else +#endif +#if defined(LWS_WITH_LIBEV) + if (lws_cmdline_option(argc, argv, "--ev")) { info.options |= LWS_SERVER_OPTION_LIBEV; - else - if (lws_cmdline_option(argc, argv, "--glib")) + ops = &ops_libev; + lwsl_notice("%s: using libev loop\n", __func__); + } else +#endif +#if defined(LWS_WITH_GLIB) + if (lws_cmdline_option(argc, argv, "--glib")) { info.options |= LWS_SERVER_OPTION_GLIB; - else { + ops = &ops_glib; + lwsl_notice("%s: using glib loop\n", __func__); + } else +#endif + { lwsl_err("This app only makes sense when used\n"); lwsl_err(" with a foreign loop, --uv, --event, --glib, or --ev\n"); return 1; - } + } lwsl_user(" This app creates a foreign event loop with a timer +\n"); lwsl_user(" signalhandler, and performs a test in three phases:\n"); @@ -449,43 +218,13 @@ /* foreign loop specific startup and run */ -#if defined(LWS_WITH_LIBUV) - if (info.options & LWS_SERVER_OPTION_LIBUV) - foreign_event_loop_init_and_run_libuv(); -#endif -#if defined(LWS_WITH_LIBEVENT) - if (info.options & LWS_SERVER_OPTION_LIBEVENT) - foreign_event_loop_init_and_run_libevent(); -#endif -#if defined(LWS_WITH_LIBEV) - if (info.options & LWS_SERVER_OPTION_LIBEV) - foreign_event_loop_init_and_run_libev(); -#endif -#if defined(LWS_WITH_GLIB) - if (info.options & LWS_SERVER_OPTION_GLIB) - foreign_event_loop_init_and_run_glib(); -#endif + ops->init_and_run(); lws_context_destroy(context); /* foreign loop specific cleanup and exit */ -#if defined(LWS_WITH_LIBUV) - if (info.options & LWS_SERVER_OPTION_LIBUV) - foreign_event_loop_cleanup_libuv(); -#endif -#if defined(LWS_WITH_LIBEVENT) - if (info.options & LWS_SERVER_OPTION_LIBEVENT) - foreign_event_loop_cleanup_libevent(); -#endif -#if defined(LWS_WITH_LIBEV) - if (info.options & LWS_SERVER_OPTION_LIBEV) - foreign_event_loop_cleanup_libev(); -#endif -#if defined(LWS_WITH_GLIB) - if (info.options & LWS_SERVER_OPTION_GLIB) - foreign_event_loop_cleanup_glib(); -#endif + ops->cleanup(); lwsl_user("%s: exiting...\n", __func__); diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-eventlib-foreign/private.h libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-eventlib-foreign/private.h --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-eventlib-foreign/private.h 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-eventlib-foreign/private.h 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,15 @@ + + +struct ops { + void (*init_and_run)(void); + void (*stop)(void); + void (*cleanup)(void); +}; + +extern struct lws_context *context; +extern int lifetime, reported; + +void foreign_timer_service(void *foreign_loop); +void signal_cb(int signum); + +extern const struct ops ops_libuv, ops_libevent, ops_glib, ops_libev; diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-eventlib-smp/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-eventlib-smp/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-eventlib-smp/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-eventlib-smp/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,80 +1,14 @@ -project(lws-minimal-http-server-eventlib-smp) +project(lws-minimal-http-server-eventlib-smp C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckIncludeFile) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-eventlib-smp) set(SRCS minimal-http-server-eventlib-smp.c) -MACRO(require_pthreads result) - CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) - if (NOT LWS_HAVE_PTHREAD_H) - if (LWS_WITH_MINIMAL_EXAMPLES) - set(result 0) - else() - message(FATAL_ERROR "threading support requires pthreads") - endif() - endif() -ENDMACRO() - -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_pthreads(requirements) require_lws_config(LWS_ROLE_H1 1 requirements) @@ -84,9 +18,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared pthread) - add_dependencies(${SAMP} websockets_shared pthread) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) + add_dependencies(${SAMP} websockets_shared ${PTHREAD_LIB}) else() - target_link_libraries(${SAMP} websockets pthread) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-eventlib-smp/minimal-http-server-eventlib-smp.c libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-eventlib-smp/minimal-http-server-eventlib-smp.c --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-eventlib-smp/minimal-http-server-eventlib-smp.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-eventlib-smp/minimal-http-server-eventlib-smp.c 2020-12-01 17:40:26.000000000 +0000 @@ -18,6 +18,13 @@ #include #include +#if defined(WIN32) +#define HAVE_STRUCT_TIMESPEC +#if defined(pid_t) +#undef pid_t +#endif +#endif + #include #define COUNT_THREADS 8 @@ -115,11 +122,13 @@ } else info.count_threads = COUNT_THREADS; +#if defined(LWS_WITH_TLS) if (lws_cmdline_option(argc, argv, "-s")) { info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; info.ssl_cert_filepath = "localhost-100y.cert"; info.ssl_private_key_filepath = "localhost-100y.key"; } +#endif if (lws_cmdline_option(argc, argv, "--uv")) info.options |= LWS_SERVER_OPTION_LIBUV; diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-form-get/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-form-get/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-form-get/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-form-get/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,67 +1,13 @@ -project(lws-minimal-http-server-form-get) +project(lws-minimal-http-server-form-get C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-form-get) set(SRCS minimal-http-server-form-get.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) @@ -70,9 +16,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-form-post/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-form-post/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-form-post/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-form-post/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,67 +1,13 @@ -project(lws-minimal-http-server-form-post) +project(lws-minimal-http-server-form-post C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-form-post) set(SRCS minimal-http-server-form-post.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) @@ -70,9 +16,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-form-post/minimal-http-server-form-post.c libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-form-post/minimal-http-server-form-post.c --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-form-post/minimal-http-server-form-post.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-form-post/minimal-http-server-form-post.c 2020-12-01 17:40:26.000000000 +0000 @@ -195,12 +195,16 @@ info.mounts = &mount; info.options = LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; - +#if defined(LWS_WITH_TLS) if (lws_cmdline_option(argc, argv, "-s")) { info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; info.ssl_cert_filepath = "localhost-100y.cert"; info.ssl_private_key_filepath = "localhost-100y.key"; } +#endif + + if ((p = lws_cmdline_option(argc, argv, "--port"))) + info.port = atoi(p); if (lws_cmdline_option(argc, argv, "--303")) { lwsl_user("%s: using 303 redirect\n", __func__); diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-form-post-file/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-form-post-file/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-form-post-file/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-form-post-file/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,67 +1,13 @@ -project(lws-minimal-http-server-form-post-file) +project(lws-minimal-http-server-form-post-file C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-form-post-file) set(SRCS minimal-http-server-form-post-file.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) @@ -70,9 +16,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-form-post-file/minimal-http-server-form-post-file.c libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-form-post-file/minimal-http-server-form-post-file.c --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-form-post-file/minimal-http-server-form-post-file.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-form-post-file/minimal-http-server-form-post-file.c 2020-12-01 17:40:26.000000000 +0000 @@ -15,7 +15,9 @@ #include #include #include +#if !defined(WIN32) #include +#endif #include #include #include diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-form-post-lwsac/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-form-post-lwsac/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-form-post-lwsac/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-form-post-lwsac/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,67 +1,13 @@ -project(lws-minimal-http-server-form-post-lwsac) +project(lws-minimal-http-server-form-post-lwsac C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-form-post-lwsac) set(SRCS minimal-http-server-form-post.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) @@ -70,9 +16,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-form-post-lwsac/minimal-http-server-form-post.c libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-form-post-lwsac/minimal-http-server-form-post.c --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-form-post-lwsac/minimal-http-server-form-post.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-form-post-lwsac/minimal-http-server-form-post.c 2020-12-01 17:40:26.000000000 +0000 @@ -198,8 +198,10 @@ if (lws_cmdline_option(argc, argv, "-s")) { info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; +#if defined(LWS_WITH_TLS) info.ssl_cert_filepath = "localhost-100y.cert"; info.ssl_private_key_filepath = "localhost-100y.key"; +#endif } context = lws_create_context(&info); diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-fulltext-search/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-fulltext-search/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-fulltext-search/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-fulltext-search/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,71 +1,15 @@ -project(lws-minimal-http-server-fulltext-search) +project(lws-minimal-http-server-fulltext-search C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-fulltext-search) set(SRCS minimal-http-server.c) include_directories(../../../plugins) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_FTS 1 requirements) @@ -75,9 +19,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,83 +0,0 @@ -project(lws-minimal-http-server-generic-sessions) -cmake_minimum_required(VERSION 2.8) -include(CheckCSourceCompiles) - -set(SAMP lws-minimal-http-server-generic-sessions) -set(SRCS minimal-http-server-generic-sessions.c) - -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - -set(requirements 1) -require_lws_config(LWS_ROLE_H1 1 requirements) -require_lws_config(LWS_WITH_SERVER 1 requirements) -require_lws_config(LWS_OPENSSL_SUPPORT 1 requirements) -require_lws_config(LWS_WITH_GENERIC_SESSIONS 1 requirements) -require_lws_config(LWS_WITH_LIBUV 1 requirements) -require_lws_config(LWS_WITH_PLUGINS 1 requirements) - -if (requirements) - add_executable(${SAMP} ${SRCS}) - - if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) - add_dependencies(${SAMP} websockets_shared) - else() - target_link_libraries(${SAMP} websockets) - endif() -endif() diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/localhost-100y.cert libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/localhost-100y.cert --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/localhost-100y.cert 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/localhost-100y.cert 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIF5jCCA86gAwIBAgIJANq50IuwPFKgMA0GCSqGSIb3DQEBCwUAMIGGMQswCQYD -VQQGEwJHQjEQMA4GA1UECAwHRXJld2hvbjETMBEGA1UEBwwKQWxsIGFyb3VuZDEb -MBkGA1UECgwSbGlid2Vic29ja2V0cy10ZXN0MRIwEAYDVQQDDAlsb2NhbGhvc3Qx -HzAdBgkqhkiG9w0BCQEWEG5vbmVAaW52YWxpZC5vcmcwIBcNMTgwMzIwMDQxNjA3 -WhgPMjExODAyMjQwNDE2MDdaMIGGMQswCQYDVQQGEwJHQjEQMA4GA1UECAwHRXJl -d2hvbjETMBEGA1UEBwwKQWxsIGFyb3VuZDEbMBkGA1UECgwSbGlid2Vic29ja2V0 -cy10ZXN0MRIwEAYDVQQDDAlsb2NhbGhvc3QxHzAdBgkqhkiG9w0BCQEWEG5vbmVA -aW52YWxpZC5vcmcwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCjYtuW -aICCY0tJPubxpIgIL+WWmz/fmK8IQr11Wtee6/IUyUlo5I602mq1qcLhT/kmpoR8 -Di3DAmHKnSWdPWtn1BtXLErLlUiHgZDrZWInmEBjKM1DZf+CvNGZ+EzPgBv5nTek -LWcfI5ZZtoGuIP1Dl/IkNDw8zFz4cpiMe/BFGemyxdHhLrKHSm8Eo+nT734tItnH -KT/m6DSU0xlZ13d6ehLRm7/+Nx47M3XMTRH5qKP/7TTE2s0U6+M0tsGI2zpRi+m6 -jzhNyMBTJ1u58qAe3ZW5/+YAiuZYAB6n5bhUp4oFuB5wYbcBywVR8ujInpF8buWQ -Ujy5N8pSNp7szdYsnLJpvAd0sibrNPjC0FQCNrpNjgJmIK3+mKk4kXX7ZTwefoAz -TK4l2pHNuC53QVc/EF++GBLAxmvCDq9ZpMIYi7OmzkkAKKC9Ue6Ef217LFQCFIBK -Izv9cgi9fwPMLhrKleoVRNsecBsCP569WgJXhUnwf2lon4fEZr3+vRuc9shfqnV0 -nPN1IMSnzXCast7I2fiuRXdIz96KjlGQpP4XfNVA+RGL7aMnWOFIaVrKWLzAtgzo -GMTvP/AuehKXncBJhYtW0ltTioVx+5yTYSAZWl+IssmXjefxJqYi2/7QWmv1QC9p -sNcjTMaBQLN03T1Qelbs7Y27sxdEnNUth4kI+wIDAQABo1MwUTAdBgNVHQ4EFgQU -9mYU23tW2zsomkKTAXarjr2vjuswHwYDVR0jBBgwFoAU9mYU23tW2zsomkKTAXar -jr2vjuswDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEANjIBMrow -YNCbhAJdP7dhlhT2RUFRdeRUJD0IxrH/hkvb6myHHnK8nOYezFPjUlmRKUgNEDuA -xbnXZzPdCRNV9V2mShbXvCyiDY7WCQE2Bn44z26O0uWVk+7DNNLH9BnkwUtOnM9P -wtmD9phWexm4q2GnTsiL6Ul6cy0QlTJWKVLEUQQ6yda582e23J1AXqtqFcpfoE34 -H3afEiGy882b+ZBiwkeV+oq6XVF8sFyr9zYrv9CvWTYlkpTQfLTZSsgPdEHYVcjv -xQ2D+XyDR0aRLRlvxUa9dHGFHLICG34Juq5Ai6lM1EsoD8HSsJpMcmrH7MWw2cKk -ujC3rMdFTtte83wF1uuF4FjUC72+SmcQN7A386BC/nk2TTsJawTDzqwOu/VdZv2g -1WpTHlumlClZeP+G/jkSyDwqNnTu1aodDmUa4xZodfhP1HWPwUKFcq8oQr148QYA -AOlbUOJQU7QwRWd1VbnwhDtQWXC92A2w1n/xkZSR1BM/NUSDhkBSUU1WjMbWg6Gg -mnIZLRerQCu1Oozr87rOQqQakPkyt8BUSNK3K42j2qcfhAONdRl8Hq8Qs5pupy+s -8sdCGDlwR3JNCMv6u48OK87F4mcIxhkSefFJUFII25pCGN5WtE4p5l+9cnO1GrIX -e2Hl/7M0c/lbZ4FvXgARlex2rkgS0Ka06HE= ------END CERTIFICATE----- diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/localhost-100y.key libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/localhost-100y.key --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/localhost-100y.key 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/localhost-100y.key 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQCjYtuWaICCY0tJ -PubxpIgIL+WWmz/fmK8IQr11Wtee6/IUyUlo5I602mq1qcLhT/kmpoR8Di3DAmHK -nSWdPWtn1BtXLErLlUiHgZDrZWInmEBjKM1DZf+CvNGZ+EzPgBv5nTekLWcfI5ZZ -toGuIP1Dl/IkNDw8zFz4cpiMe/BFGemyxdHhLrKHSm8Eo+nT734tItnHKT/m6DSU -0xlZ13d6ehLRm7/+Nx47M3XMTRH5qKP/7TTE2s0U6+M0tsGI2zpRi+m6jzhNyMBT -J1u58qAe3ZW5/+YAiuZYAB6n5bhUp4oFuB5wYbcBywVR8ujInpF8buWQUjy5N8pS -Np7szdYsnLJpvAd0sibrNPjC0FQCNrpNjgJmIK3+mKk4kXX7ZTwefoAzTK4l2pHN -uC53QVc/EF++GBLAxmvCDq9ZpMIYi7OmzkkAKKC9Ue6Ef217LFQCFIBKIzv9cgi9 -fwPMLhrKleoVRNsecBsCP569WgJXhUnwf2lon4fEZr3+vRuc9shfqnV0nPN1IMSn -zXCast7I2fiuRXdIz96KjlGQpP4XfNVA+RGL7aMnWOFIaVrKWLzAtgzoGMTvP/Au -ehKXncBJhYtW0ltTioVx+5yTYSAZWl+IssmXjefxJqYi2/7QWmv1QC9psNcjTMaB -QLN03T1Qelbs7Y27sxdEnNUth4kI+wIDAQABAoICAFWe8MQZb37k2gdAV3Y6aq8f -qokKQqbCNLd3giGFwYkezHXoJfg6Di7oZxNcKyw35LFEghkgtQqErQqo35VPIoH+ -vXUpWOjnCmM4muFA9/cX6mYMc8TmJsg0ewLdBCOZVw+wPABlaqz+0UOiSMMftpk9 -fz9JwGd8ERyBsT+tk3Qi6D0vPZVsC1KqxxL/cwIFd3Hf2ZBtJXe0KBn1pktWht5A -Kqx9mld2Ovl7NjgiC1Fx9r+fZw/iOabFFwQA4dr+R8mEMK/7bd4VXfQ1o/QGGbMT -G+ulFrsiDyP+rBIAaGC0i7gDjLAIBQeDhP409ZhswIEc/GBtODU372a2CQK/u4Q/ -HBQvuBtKFNkGUooLgCCbFxzgNUGc83GB/6IwbEM7R5uXqsFiE71LpmroDyjKTlQ8 -YZkpIcLNVLw0usoGYHFm2rvCyEVlfsE3Ub8cFyTFk50SeOcF2QL2xzKmmbZEpXgl -xBHR0hjgon0IKJDGfor4bHO7Nt+1Ece8u2oTEKvpz5aIn44OeC5mApRGy83/0bvs -esnWjDE/bGpoT8qFuy+0urDEPNId44XcJm1IRIlG56ErxC3l0s11wrIpTmXXckqw -zFR9s2z7f0zjeyxqZg4NTPI7wkM3M8BXlvp2GTBIeoxrWB4V3YArwu8QF80QBgVz -mgHl24nTg00UH1OjZsABAoIBAQDOxftSDbSqGytcWqPYP3SZHAWDA0O4ACEM+eCw -au9ASutl0IDlNDMJ8nC2ph25BMe5hHDWp2cGQJog7pZ/3qQogQho2gUniKDifN77 -40QdykllTzTVROqmP8+efreIvqlzHmuqaGfGs5oTkZaWj5su+B+bT+9rIwZcwfs5 -YRINhQRx17qa++xh5mfE25c+M9fiIBTiNSo4lTxWMBShnK8xrGaMEmN7W0qTMbFH -PgQz5FcxRjCCqwHilwNBeLDTp/ZECEB7y34khVh531mBE2mNzSVIQcGZP1I/DvXj -W7UUNdgFwii/GW+6M0uUDy23UVQpbFzcV8o1C2nZc4Fb4zwBAoIBAQDKSJkFwwuR -naVJS6WxOKjX8MCu9/cKPnwBv2mmI2jgGxHTw5sr3ahmF5eTb8Zo19BowytN+tr6 -2ZFoIBA9Ubc9esEAU8l3fggdfM82cuR9sGcfQVoCh8tMg6BP8IBLOmbSUhN3PG2m -39I802u0fFNVQCJKhx1m1MFFLOu7lVcDS9JN+oYVPb6MDfBLm5jOiPuYkFZ4gH79 -J7gXI0/YKhaJ7yXthYVkdrSF6Eooer4RZgma62Dd1VNzSq3JBo6rYjF7Lvd+RwDC -R1thHrmf/IXplxpNVkoMVxtzbrrbgnC25QmvRYc0rlS/kvM4yQhMH3eA7IycDZMp -Y+0xm7I7jTT7AoIBAGKzKIMDXdCxBWKhNYJ8z7hiItNl1IZZMW2TPUiY0rl6yaCh -BVXjM9W0r07QPnHZsUiByqb743adkbTUjmxdJzjaVtxN7ZXwZvOVrY7I7fPWYnCE -fXCr4+IVpZI/ZHZWpGX6CGSgT6EOjCZ5IUufIvEpqVSmtF8MqfXO9o9uIYLokrWQ -x1dBl5UnuTLDqw8bChq7O5y6yfuWaOWvL7nxI8NvSsfj4y635gIa/0dFeBYZEfHI -UlGdNVomwXwYEzgE/c19ruIowX7HU/NgxMWTMZhpazlxgesXybel+YNcfDQ4e3RM -OMz3ZFiaMaJsGGNf4++d9TmMgk4Ns6oDs6Tb9AECggEBAJYzd+SOYo26iBu3nw3L -65uEeh6xou8pXH0Tu4gQrPQTRZZ/nT3iNgOwqu1gRuxcq7TOjt41UdqIKO8vN7/A -aJavCpaKoIMowy/aGCbvAvjNPpU3unU8jdl/t08EXs79S5IKPcgAx87sTTi7KDN5 -SYt4tr2uPEe53NTXuSatilG5QCyExIELOuzWAMKzg7CAiIlNS9foWeLyVkBgCQ6S -me/L8ta+mUDy37K6vC34jh9vK9yrwF6X44ItRoOJafCaVfGI+175q/eWcqTX4q+I -G4tKls4sL4mgOJLq+ra50aYMxbcuommctPMXU6CrrYyQpPTHMNVDQy2ttFdsq9iK -TncCggEBAMmt/8yvPflS+xv3kg/ZBvR9JB1In2n3rUCYYD47ReKFqJ03Vmq5C9nY -56s9w7OUO8perBXlJYmKZQhO4293lvxZD2Iq4NcZbVSCMoHAUzhzY3brdgtSIxa2 -gGveGAezZ38qKIU26dkz7deECY4vrsRkwhpTW0LGVCpjcQoaKvymAoCmAs8V2oMr -Ziw1YQ9uOUoWwOqm1wZqmVcOXvPIS2gWAs3fQlWjH9hkcQTMsUaXQDOD0aqkSY3E -NqOvbCV1/oUpRi3076khCoAXI1bKSn/AvR3KDP14B5toHI/F5OTSEiGhhHesgRrs -fBrpEY1IATtPq1taBZZogRqI3rOkkPk= ------END PRIVATE KEY----- diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/minimal-http-server-generic-sessions.c libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/minimal-http-server-generic-sessions.c --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/minimal-http-server-generic-sessions.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/minimal-http-server-generic-sessions.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,202 +0,0 @@ -/* - * lws-minimal-http-server-generic-sessions - * - * Copyright (C) 2019 Andy Green - * - * This file is made available under the Creative Commons CC0 1.0 - * Universal Public Domain Dedication. - * - * This demonstrates setting up and using generic sessions - */ - -#include -#include -#include - -static int interrupted; -struct lws_context *context; - -static const struct lws_protocol_vhost_options - pvo_mm1 = { - NULL, NULL, "message-db", (void *)"/var/www/sessions/messageboard.sqlite3" -}, pvo_m1 = { - NULL, &pvo_mm1, "protocol-lws-messageboard", "" -}, - - pvo13 = { - NULL, NULL, "email-confirm-url-base", (void *)"https://localhost:7681/" -}, pvo12 = { - &pvo13, NULL, "urlroot", (void *)"https://127.0.0.1:7681/" -}, pvo11 = { - &pvo12, NULL, "email-contact-person", (void *)"andy@warmcat.com" -}, pvo10 = { - &pvo11, NULL, "email-helo", (void *)"warmcat.com" -}, pvo9 = { - &pvo10, NULL, "email-expire", (void *)"3600" -}, pvo8 = { - &pvo9, NULL, "email-smtp-ip", (void *)"127.0.0.1" -}, pvo7 = { - &pvo8, NULL, "email-from", (void *)"noreply@warmcat.com" -}, pvo6 = { - &pvo7, NULL, "confounder", (void *)"some kind of secret confounder" -}, pvo5 = { - &pvo6, NULL, "timeout-anon-idle-secs", (void *)"1200" -}, pvo4 = { - &pvo5, NULL, "timeout-idle-secs", (void *)"6000" -}, pvo3 = { - &pvo4, NULL, "session-db", (void *)"/var/www/sessions/lws.sqlite3" -}, pvo2 = { - &pvo3, NULL, "admin-password-sha256", - (void *)"25d08521d996bad92605f5a40fe71179dc968e70f669cb1db6190dcd53258200" /* pvo value */ -}, pvo1 = { - &pvo2, NULL, "admin-user", (void *)"admin" -}, pvo = { - &pvo_m1, &pvo1, "protocol-generic-sessions", "" -}, - - interpret1 = { - NULL, NULL, ".js", "protocol-lws-messageboard" -}, - - pvo_hsbph[] = {{ - NULL, NULL, "referrer-policy:", "no-referrer" -}, { - &pvo_hsbph[0], NULL, "x-xss-protection:", "1; mode=block" -}, { - &pvo_hsbph[1], NULL, "x-content-type-options:", "nosniff" -}, { - &pvo_hsbph[2], NULL, "content-security-policy:", - "default-src 'self'; " - "img-src https://www.gravatar.com 'self' data: ; " - "script-src 'self'; " - "font-src 'self'; " - "style-src 'self'; " - "connect-src 'self'; " - "frame-ancestors 'self'; " - "base-uri 'none'; " - "form-action 'self';" -}}; - - static const struct lws_http_mount mount2 = { - /* .mount_next */ NULL, /* linked-list "next" */ - /* .mountpoint */ "/needadmin", /* mountpoint URL */ - /* .origin */ "./mount-origin/needadmin", /* serve from dir */ - /* .def */ "index.html", /* default filename */ - /* .protocol */ "protocol-lws-messageboard", - /* .cgienv */ NULL, - /* .extra_mimetypes */ NULL, - /* .interpret */ &interpret1, - /* .cgi_timeout */ 0, - /* .cache_max_age */ 0, - /* .auth_mask */ 7, - /* .cache_reusable */ 0, - /* .cache_revalidate */ 0, - /* .cache_intermediaries */ 0, - /* .origin_protocol */ LWSMPRO_FILE, /* files in a dir */ - /* .mountpoint_len */ 1, /* char count */ - /* .basic_auth_login_file */ NULL, - }; - - static const struct lws_http_mount mount1 = { - /* .mount_next */ &mount2, /* linked-list "next" */ - /* .mountpoint */ "/needauth", /* mountpoint URL */ - /* .origin */ "./mount-origin/needauth", /* serve from dir */ - /* .def */ "index.html", /* default filename */ - /* .protocol */ "protocol-lws-messageboard", - /* .cgienv */ NULL, - /* .extra_mimetypes */ NULL, - /* .interpret */ &interpret1, - /* .cgi_timeout */ 0, - /* .cache_max_age */ 0, - /* .auth_mask */ 5, - /* .cache_reusable */ 0, - /* .cache_revalidate */ 0, - /* .cache_intermediaries */ 0, - /* .origin_protocol */ LWSMPRO_FILE, /* files in a dir */ - /* .mountpoint_len */ 1, /* char count */ - /* .basic_auth_login_file */ NULL, - }; - -static const struct lws_http_mount mount = { - /* .mount_next */ &mount1, /* linked-list "next" */ - /* .mountpoint */ "/", /* mountpoint URL */ - /* .origin */ "./mount-origin", /* serve from dir */ - /* .def */ "index.html", /* default filename */ - /* .protocol */ "protocol-lws-messageboard", - /* .cgienv */ NULL, - /* .extra_mimetypes */ NULL, - /* .interpret */ &interpret1, - /* .cgi_timeout */ 0, - /* .cache_max_age */ 0, - /* .auth_mask */ 0, - /* .cache_reusable */ 0, - /* .cache_revalidate */ 0, - /* .cache_intermediaries */ 0, - /* .origin_protocol */ LWSMPRO_FILE, /* files in a dir */ - /* .mountpoint_len */ 1, /* char count */ - /* .basic_auth_login_file */ NULL, -}; - -void sigint_handler(int sig) -{ - lws_context_destroy(context); - - interrupted = 1; -} - -int main(int argc, const char **argv) -{ - struct lws_context_creation_info info; - const char *p, *plugin_dirs[] = { - "/usr/local/share/libwebsockets-test-server/plugins", - NULL }; - int n = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE - /* for LLL_ verbosity above NOTICE to be built into lws, - * lws must have been configured and built with - * -DCMAKE_BUILD_TYPE=DEBUG instead of =RELEASE */ - /* | LLL_INFO */ /* | LLL_PARSER */ /* | LLL_HEADER */ - /* | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY */ - /* | LLL_DEBUG */; - - if ((p = lws_cmdline_option(argc, argv, "-d"))) - logs = atoi(p); - - lws_set_log_level(logs, NULL); - lwsl_user("LWS minimal http server TLS | visit https://localhost:7681\n"); - - signal(SIGINT, sigint_handler); - - memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ - info.port = 7681; - info.mounts = &mount; - info.error_document_404 = "/404.html"; - info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT | - LWS_SERVER_OPTION_EXPLICIT_VHOSTS; - info.ssl_cert_filepath = "localhost-100y.cert"; - info.ssl_private_key_filepath = "localhost-100y.key"; - info.plugin_dirs = plugin_dirs; - info.pvo = &pvo; - - if (lws_cmdline_option(argc, argv, "-h")) - info.options |= LWS_SERVER_OPTION_VHOST_UPG_STRICT_HOST_CHECK; - - context = lws_create_context(&info); - if (!context) { - lwsl_err("lws init failed\n"); - return 1; - } - - info.headers = &pvo_hsbph[3]; - - if (!lws_create_vhost(context, &info)) { - lwsl_err("lws init failed\n"); - return 1; - } - - while (n >= 0 && !interrupted) - n = lws_service(context, 0); - - lws_context_destroy(context); - - return 0; -} diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/404.html libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/404.html --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/404.html 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/404.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ - - - - -
- -

404

- Sorry, that file doesn't exist. - - - diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/admin-login.html libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/admin-login.html --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/admin-login.html 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/admin-login.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ - -This is an example destination that will appear after successful Admin login. - -This URL cannot be served if you're not logged in as admin. - diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/example.js libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/example.js --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/example.js 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/example.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -document.addEventListener("DOMContentLoaded", function() { - - var transport_protocol = ""; - - if ( performance && performance.timing.nextHopProtocol ) { - transport_protocol = performance.timing.nextHopProtocol; - } else if ( window.chrome && window.chrome.loadTimes ) { - transport_protocol = window.chrome.loadTimes().connectionInfo; - } else { - - var p = performance.getEntriesByType("resource"); - for (var i=0; i < p.length; i++) { - var value = "nextHopProtocol" in p[i]; - if (value) - transport_protocol = p[i].nextHopProtocol; - } - } - - if (transport_protocol === "h2") - document.getElementById("transport").innerHTML = ""; -}, false); \ No newline at end of file diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/failed-login.html libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/failed-login.html --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/failed-login.html 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/failed-login.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ - -This is an example destination that will appear after a failed login - Binary files /tmp/tmpmec97nsd/m0nuW2sR0N/libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/favicon.ico and /tmp/tmpmec97nsd/q8JCI83EXS/libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/favicon.ico differ Binary files /tmp/tmpmec97nsd/m0nuW2sR0N/libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/http2.png and /tmp/tmpmec97nsd/q8JCI83EXS/libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/http2.png differ diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/index.html libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/index.html --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/index.html 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/index.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - -
-
-
- -
- - This is a demo application for lws generic-sessions.

- It's a simple messageboard.

- What's interesting about it is there is no serverside scripting,
- instead client js makes a wss:// connection back to the server
- and then reacts to JSON from the ws protocol. Sessions stuff is
- handled by lws generic sessions, making the actual
- test application
very small.

- And because it's natively websocket, it's naturally connected
- for dynamic events and easy to maintain. -

- Register / Login at the top right to see and create new messages. -
- -
-
- New message
-
- -
-
-
-
- -
- -
-
- - - diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/libwebsockets.org-logo.svg libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/libwebsockets.org-logo.svg --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/libwebsockets.org-logo.svg 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/libwebsockets.org-logo.svg 1970-01-01 00:00:00.000000000 +0000 @@ -1,66 +0,0 @@ - - - - - -image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/lws-common.js libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/lws-common.js --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/lws-common.js 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/lws-common.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,125 +0,0 @@ -/* - * This section around grayOut came from here: - * http://www.codingforums.com/archive/index.php/t-151720.html - * Assumed public domain - * - * Init like this in your main html script, this also reapplies the gray - * - * lws_gray_out(true,{'zindex':'499'}); - * - * To remove the gray - * - * lws_gray_out(false); - * - */ - -function gsize(ptype) -{ - var h = document.compatMode === "CSS1Compat" && - !window.opera ? - document.documentElement.clientHeight : - document.body.clientHeight; - var w = document.compatMode === "CSS1Compat" && - !window.opera ? - document.documentElement.clientWidth : - document.body.clientWidth; - var pageWidth, pageHeight, t; - - if (document.body && - (document.body.scrollWidth || document.body.scrollHeight)) { - t = document.body.scrollWidth; - pageWidth = (w > t) ? ("" + w + "px") : ("" + (t) + "px"); - t = document.body.scrollHeight; - pageHeight = (h > t) ? ("" + h + "px") : ("" + (t) + "px"); - } else if (document.body.offsetWidth) { - t = document.body.offsetWidth; - pageWidth = (w > t) ? ("" + w + "px") : ("" + (t) + "px"); - t = document.body.offsetHeight; - pageHeight =(h > t) ? ("" + h + "px") : ("" + (t) + "px"); - } else { - pageWidth = "100%"; - pageHeight = "100%"; - } - return (ptype === 1) ? pageWidth : pageHeight; -} - -function addEvent( obj, type, fn ) { - if ( obj.attachEvent ) { - obj["e" + type + fn] = fn; - obj[type+fn] = function() { obj["e" + type + fn]( window.event );}; - obj.attachEvent("on" + type, obj[type + fn]); - } else - obj.addEventListener(type, fn, false); -} - -function removeEvent( obj, type, fn ) { - if ( obj.detachEvent ) { - obj.detachEvent("on" + type, obj[type + fn]); - obj[type + fn] = null; - } else - obj.removeEventListener(type, fn, false); -} - -function lws_gray_out(vis, _options) { - - var options = _options || {}; - var zindex = options.zindex || 50; - var opacity = options.opacity || 70; - var opaque = (opacity / 100); - var bgcolor = options.bgcolor || "#000000"; - var dark = document.getElementById("darkenScreenObject"); - - if (!dark) { - var tbody = document.getElementsByTagName("body")[0]; - var tnode = document.createElement("div"); - tnode.style.position = "absolute"; - tnode.style.top = "0px"; - tnode.style.left = "0px"; - tnode.style.overflow = "hidden"; - tnode.style.display ="none"; - tnode.id = "darkenScreenObject"; - tbody.appendChild(tnode); - dark = document.getElementById("darkenScreenObject"); - } - if (vis) { - dark.style.opacity = opaque; - dark.style.MozOpacity = opaque; - // dark.style.filter ='alpha(opacity='+opacity+')'; - dark.style.zIndex = zindex; - dark.style.backgroundColor = bgcolor; - dark.style.width = gsize(1); - dark.style.height = gsize(0); - dark.style.display = "block"; - addEvent(window, "resize", - function() { - dark.style.height = gsize(0); - dark.style.width = gsize(1); - } - ); - } else { - dark.style.display = "none"; - removeEvent(window, "resize", - function() { - dark.style.height = gsize(0); - dark.style.width = gsize(1); - } - ); - } -} - -/* - * end of grayOut related stuff - */ - -function new_ws(urlpath, protocol) -{ - return new WebSocket(urlpath, protocol); -} - -function lws_san(s) -{ - if (s.search("<") !== -1) - return "invalid string"; - - return s; -} diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/lwsgs.css libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/lwsgs.css --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/lwsgs.css 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/lwsgs.css 1970-01-01 00:00:00.000000000 +0000 @@ -1,144 +0,0 @@ -.body { font-size: 12px } -.gstitle { font-size: 18px } - -.group1 { - vertical-align:middle; - text-align:center; - background:#f0f0e0; - padding:12px; - border-radius:10px; -} -.group2 { - display:block; - vertical-align:middle; - font-size: 22px; - text-align:center; - margin:auto; - align:center; - background-color: rgba(255, 255, 255, 0.8); - padding:12px; - border-radius:10px; -} - -body { - background-color: rgba(205, 205, 205, 1); -} - -div.lwsgs { - z-index: 3; - text-align:right; - background-color: rgba(255, 255, 255, 0.8); -} - -table.lwsgs { - width:100%; - height:100%; - transition: max-height 2s; -} -table.c100 { - text-align:center; - width:100%; -} - -table.r { - vertical-align:top; - text-align:right; -} - -table.l { - vertical-align:top; - text-align:left; -} - -table.fixed { - table-layout: fixed; -} - -td.logo { - vertical-align:top; - text-align:left; - width:200px -} - -td.rlogo { - vertical-align:top; - text-align:right -} - -td.lwsgs { - vertical-align:top; - float:right; -} - -td.h99 { - height:99%; - vertical-align:middle; -} - -td.c { - margin:auto; - align:center -} - -td.tac { - text-align:center -} - -td.ava { - display:inline-block; - vertical-align:top; - word-wrap:break-word; -} - -iframe.hidden { - display:none; -} - -div.hidden { - display:none; -} - -div.hiddenr { - display:none; - text-align:right; -} - -input { - margin: 2px; - padding: 2px; -} - -input.em { - margin: 4px; - font-weight:bold; -} - -input.wide { - margin: 6px; - padding: 6px; -} - -input.hidden { - display: none; -} - -form.r { - text-align:right; -} - -span.bad { - color: red; -} - -span.small { - font-size:8pt; -} - -img.av { - width: 64px; - height: 64px; -} - -.green { - color: green; -} diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/lwsgs.js libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/lwsgs.js --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/lwsgs.js 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/lwsgs.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,634 +0,0 @@ - - -var lwsgs_user = "$lwsgs_user"; -var lwsgs_auth = "$lwsgs_auth"; -var lwsgs_email = "$lwsgs_email"; - -var lwsgs_html = '\ - \ -\ -
\ -
\ - \ - \ - \ - \ -
\ - \ -
\ - \ -
\ -\ - \ - \ - \ - \ - \ -'; - -/*-- this came from - -- https://raw.githubusercontent.com/blueimp/JavaScript-MD5/master/js/md5.min.js - -- under MIT license */ -!function(n){"use strict";function t(n,t){var r=(65535&n)+(65535&t),e=(n>>16)+(t>>16)+(r>>16);return e<<16|65535&r}function r(n,t){return n<>>32-t}function e(n,e,o,u,c,f){return t(r(t(t(e,n),t(u,f)),c),o)}function o(n,t,r,o,u,c,f){return e(t&r|~t&o,n,t,u,c,f)}function u(n,t,r,o,u,c,f){return e(t&o|r&~o,n,t,u,c,f)}function c(n,t,r,o,u,c,f){return e(t^r^o,n,t,u,c,f)}function f(n,t,r,o,u,c,f){return e(r^(t|~o),n,t,u,c,f)}function i(n,r){n[r>>5]|=128<>>9<<4)+14]=r;var e,i,a,h,d,l=1732584193,g=-271733879,v=-1732584194,m=271733878;for(e=0;e>5]>>>t%32&255);return r}function h(n){var t,r=[];for(r[(n.length>>2)-1]=void 0,t=0;t>5]|=(255&n.charCodeAt(t/8))<16&&(o=i(o,8*n.length)),r=0;16>r;r+=1)u[r]=909522486^o[r],c[r]=1549556828^o[r];return e=i(u.concat(h(t)),512+8*t.length),a(i(c.concat(e),640))}function g(n){var t,r,e="0123456789abcdef",o="";for(r=0;r>>4&15)+e.charAt(15&t);return o}function v(n){return unescape(encodeURIComponent(n))}function m(n){return d(v(n))}function p(n){return g(m(n))}function s(n,t){return l(v(n),v(t))}function C(n,t){return g(s(n,t))}function A(n,t,r){return t?r?s(t,n):C(t,n):r?m(n):p(n)}"function"==typeof define&&define.amd?define(function(){return A}):"object"==typeof module&&module.exports?module.exports=A:n.md5=A}(this); - -if (lwsgs_user.substring(0, 1) == "$") { - alert("lwsgs.js: lws generic sessions misconfigured and not providing vars"); -} -function lwsgs_san(s) -{ - if (s.search("<") != -1) - return "invalid string"; - - return s; -} - -function lwsgs_update() -{ - var en_login = 1, en_forgot = 1; - - if (document.getElementById('password').value.length && - document.getElementById('password').value.length < 8) - en_login = 0; - - if (!document.getElementById('username').value || - !document.getElementById('password').value) - en_login = 0; - - if (!document.getElementById('username').value || - document.getElementById('password').value) - en_forgot = 0; - - document.getElementById('login').disabled = !en_login; - document.getElementById('forgot').disabled = !en_forgot; - - if (lwsgs_user) - document.getElementById("curuser").innerHTML = lwsgs_san(lwsgs_user); - - if (lwsgs_user === "") - document.getElementById("dlogin").style.display = "inline"; - else - document.getElementById("dlogout").style.display = "inline"; - } - -function lwsgs_open_registration() -{ - document.getElementById("dadmin").style.display = "none"; - document.getElementById("dlogin").style.display = "none"; - document.getElementById("dlogout").style.display = "none"; - document.getElementById("dchange").style.display = "none"; - document.getElementById("dregister").style.display = "inline"; -} - -function lwsgs_cancel_registration() -{ - document.getElementById("dadmin").style.display = "none"; - document.getElementById("dregister").style.display = "none"; - document.getElementById("dchange").style.display = "none"; - - if (lwsgs_user === "") - document.getElementById("dlogin").style.display = "inline"; - else - document.getElementById("dlogout").style.display = "inline"; -} - -function lwsgs_select_change() -{ - document.getElementById("dlogin").style.display = "none"; - document.getElementById("dlogout").style.display = "none"; - document.getElementById("dregister").style.display = "none"; - if (lwsgs_auth & 2) { - document.getElementById("dadmin").style.display = "inline"; - document.getElementById("dchange").style.display = "none"; - } else { - document.getElementById("dadmin").style.display = "none"; - document.getElementById("dchange").style.display = "inline"; - } - - event.preventDefault() -} - -var lwsgs_user_check = '0'; -var lwsgs_email_check = '0'; - -function lwsgs_rupdate() -{ - var en_register = 1, en_forgot = 0, op; - - if (document.getElementById('rpassword').value == - document.getElementById('password2').value) { - if (document.getElementById('rpassword').value.length) - document.getElementById('match').innerHTML = - "\u2713"; - else - document.getElementById('match').innerHTML = ""; - document.getElementById('pw2').style = ""; - } else { - if (document.getElementById('password2').value || - document.getElementById('email').value) { // ie, he is filling in "register" path and cares - document.getElementById('match').innerHTML = - "\u2718 Passwords do not match"; - } else - document.getElementById('match').innerHTML = - "\u2718 Passwords do not match"; - - en_register = 0; - } - - if (document.getElementById('rpassword').value.length && - document.getElementById('rpassword').value.length < 8) { - en_register = 0; - document.getElementById('rpw1').innerHTML = "Need 8 chars"; - } else - if (document.getElementById('rpassword').value.length) - document.getElementById('rpw1').innerHTML = "\u2713"; - else - document.getElementById('rpw1').innerHTML = ""; - - if (!document.getElementById('rpassword').value || - !document.getElementById('password2').value || - !document.getElementById('rusername').value || - !document.getElementById('email').value || - lwsgs_email_check === '1'|| - lwsgs_user_check === '1') - en_register = 0; - - document.getElementById('register').disabled = !en_register; - document.getElementById('rpassword').disabled = lwsgs_user_check === '1'; - document.getElementById('password2').disabled = lwsgs_user_check === '1'; - document.getElementById('email').disabled = lwsgs_user_check === '1'; - - if (lwsgs_user_check === '0') { - var uc = document.getElementById('uchk'); - - if (uc) { - if (document.getElementById('rusername').value) - uc.innerHTML = "\u2713"; - else - uc.innerHTML = ""; - } - } else { - if (document.getElementById('uchk')) - ocument.getElementById('uchk').innerHTML = "\u2718 Already registered"; - en_forgot = 1; - } - - if (lwsgs_email_check === '0') { - var ec = document.getElementById('echk'); - - if (ec) { - if (document.getElementById('email').value) - ec.innerHTML = "\u2713"; - else - ec.innerHTML = ""; - } - } else { - if (document.getElementById('echk')) - document.getElementById('echk').innerHTML = "\u2718 Already registered"; - en_forgot = 1; - } - - if (en_forgot) - document.getElementById('rforgot').style.display = "inline"; - else - document.getElementById('rforgot').style.display = "none"; - - if (lwsgs_user_check === '1') - op = '0.5'; - else - op = '1.0'; - document.getElementById('rpassword').style.opacity = op; - document.getElementById('password2').style.opacity = op; - document.getElementById('email').style.opacity = op; - } - -function lwsgs_cupdate() -{ - var en_change = 1, en_forgot = 1, pwok = 1, op; - - if (lwsgs_auth & 8) { - document.getElementById('ccurpw').style.display = "none"; - document.getElementById('ccurpw_name').style.display = "none"; - } else { - if (!document.getElementById('ccurpw').value || - document.getElementById('ccurpw').value.length < 8) { - en_change = 0; - pwok = 0; - document.getElementById('cuchk').innerHTML = "\u2718"; - } else { - en_forgot = 0; - document.getElementById('cuchk').innerHTML = ""; - } - document.getElementById('ccurpw').style.display = "inline"; - document.getElementById('ccurpw_name').style.display = "inline"; - } - - if (document.getElementById('cpassword').value == - document.getElementById('cpassword2').value) { - if (document.getElementById('cpassword').value.length) - document.getElementById('cmatch').innerHTML = "\u2713"; - else - document.getElementById('cmatch').innerHTML = ""; - document.getElementById('pw2').style = ""; - } else { - if (document.getElementById('cpassword2').value //|| - //document.getElementById('cemail').value - ) { // ie, he is filling in "register" path and cares - document.getElementById('cmatch').innerHTML = - "\u2718 Passwords do not match"; - } else - document.getElementById('cmatch').innerHTML = "\u2718 Passwords do not match"; - - en_change = 0; - } - - if (document.getElementById('cpassword').value.length && - document.getElementById('cpassword').value.length < 8) { - en_change = 0; - document.getElementById('cpw1').innerHTML = "Need 8 chars"; - } else { - var cpw = document.getElementById('cpw1'); - - if (cpw) { - if (document.getElementById('cpassword').value.length) - cpw.innerHTML = "\u2713"; - else - cpw.innerHTML = ""; - } - } - - if (!document.getElementById('cpassword').value || - !document.getElementById('cpassword2').value || - pwok === 0) - en_change = 0; - - if (document.getElementById('showdel').checked) - document.getElementById('delete').style.display = "inline"; - else - document.getElementById('delete').style.display = "none"; - - document.getElementById('change').disabled = !en_change; - document.getElementById('cpassword').disabled = pwok === 0; - document.getElementById('cpassword2').disabled = pwok === 0; - document.getElementById('showdel').disabled = pwok === 0; - document.getElementById('delete').disabled = pwok === 0; - //document.getElementById('cemail').disabled = pwok === 0; - - /* - if (lwsgs_auth & 8) { - document.getElementById('cemail').style.display = "none"; - document.getElementById('cemail_name').style.display = "none"; - } else { - document.getElementById('cemail').style.display = "inline"; - document.getElementById('cemail_name').style.display = "inline"; - if (lwsgs_email_check === '0' && - document.getElementById('cemail').value != lwsgs_email) { - if (document.getElementById('cemail').value) - document.getElementById('cechk').innerHTML = "\u2713"; - else - document.getElementById('cechk').innerHTML = ""; - } else { - document.getElementById('cechk').innerHTML = "\u2718 Already registered"; - en_forgot = 1; - } - } */ - - if (lwsgs_auth & 8) - en_forgot = 0; - - if (en_forgot) - document.getElementById('cforgot').style.display = "inline"; - else - document.getElementById('cforgot').style.display = "none"; - - if (pwok === 0) - op = '0.5'; - else - op = '1.0'; - document.getElementById('cpassword').style.opacity = op; - document.getElementById('cpassword2').style.opacity = op; - // document.getElementById('cemail').style.opacity = op; - } - -function lwsgs_check_user() -{ - var xmlHttp = new XMLHttpRequest(); - xmlHttp.onreadystatechange = function() { - if (xmlHttp.readyState === 4 && xmlHttp.status === 200) { - lwsgs_user_check = xmlHttp.responseText; - lwsgs_rupdate(); - } - } - xmlHttp.open("GET", "lwsgs-check/username="+document.getElementById('rusername').value, true); - xmlHttp.send(null); -} - -function lwsgs_check_email(id) -{ - var xmlHttp = new XMLHttpRequest(); - xmlHttp.onreadystatechange = function() { - if (xmlHttp.readyState === 4 && xmlHttp.status === 200) { - lwsgs_email_check = xmlHttp.responseText; - lwsgs_rupdate(); - } - } - xmlHttp.open("GET", "lwsgs-check/email="+document.getElementById(id).value, true); - xmlHttp.send(null); -} - -function rupdate_user() -{ - lwsgs_rupdate(); - lwsgs_check_user(); -} - -function rupdate_email() -{ - lwsgs_rupdate(); - lwsgs_check_email('email'); -} - -function cupdate_email() -{ - lwsgs_cupdate(); - lwsgs_check_email('cemail'); -} - - -function lwsgs_initial() -{ - document.getElementById('lwsgs').innerHTML = lwsgs_html; - - if (lwsgs_user) { - document.getElementById("curuser").innerHTML = - "currently logged in as " + lwsgs_san(lwsgs_user) + "
"; - - document.getElementById("ccuruser").innerHTML = - "Login settings for " + - lwsgs_san(lwsgs_user) + "
"; - } - - document.getElementById('username').oninput = lwsgs_update; - document.getElementById('username').onchange = lwsgs_update; - document.getElementById('password').oninput = lwsgs_update; - document.getElementById('password').onchange = lwsgs_update; - document.getElementById('doreg').onclick = lwsgs_open_registration; - document.getElementById('clink').onclick = lwsgs_select_change; - document.getElementById('cancel').onclick =lwsgs_cancel_registration; - document.getElementById('cancel2').onclick =lwsgs_cancel_registration; - document.getElementById('rpassword').oninput = lwsgs_rupdate; - document.getElementById('password2').oninput = lwsgs_rupdate; - document.getElementById('rusername').oninput = rupdate_user; - document.getElementById('email').oninput = rupdate_email; - document.getElementById('ccurpw').oninput = lwsgs_cupdate; - document.getElementById('cpassword').oninput = lwsgs_cupdate; - document.getElementById('cpassword2').oninput = lwsgs_cupdate; - - document.getElementById('showdel').onchange = lwsgs_cupdate; - - if (lwsgs_email) - document.getElementById('grav').innerHTML = - ""; - //if (lwsgs_email) - //document.getElementById('cemail').placeholder = lwsgs_email; - document.getElementById('cusername').value = lwsgs_user; - lwsgs_update(); - lwsgs_cupdate(); -} - -window.addEventListener("load", function() { - lwsgs_initial(); - document.getElementById("nolog").style.display = !!lwsgs_user ? "none" : "inline-block"; - document.getElementById("logged").style.display = !lwsgs_user ? "none" : "inline-block"; - - document.getElementById("msg").onkeyup = mupd; - document.getElementById("msg").onchange = mupd; - - var ws; - - function mb_format(s) - { - var r = "", n, wos = 0; - - for (n = 0; n < s.length; n++) { - if (s[n] == ' ') - wos = 0; - else { - wos++; - if (wos === 40) { - wos = 0; - r = r + ' '; - } - } - if (s[n] == '<') { - r = r + "<"; - continue; - } - if (s[n] == '\n') { - r = r + "
"; - continue; - } - - r = r + s[n]; - } - - return r; - } - - function add_div(n, m) - { - var q = document.getElementById(n); - var d = new Date(m.time * 1000), s = d.toTimeString(), t; - - t = s.indexOf('('); - if (t) - s = s.substring(0, t); - - q.innerHTML = "
" + - "
" + - "" + lwsgs_san(m.username) + "
" + - "" + d.toDateString() + - "
" + s + "

" + - "IP: " + lwsgs_san(m.ip) + - "
" + - mb_format(m.content) + - "

" + q.innerHTML; - } - - function get_appropriate_ws_url() - { - var pcol; - var u = document.URL; - - if (u.substring(0, 5) == "https") { - pcol = "wss://"; - u = u.substr(8); - } else { - pcol = "ws://"; - if (u.substring(0, 4) == "http") - u = u.substr(7); - } - u = u.split('/'); - - return pcol + u[0] + "/xxx"; - } - - if (lwsgs_user) { - - ws = new WebSocket(get_appropriate_ws_url(), - "protocol-lws-messageboard"); - - try { - ws.onopen = function() { - document.getElementById("debug").textContent = "ws opened"; - } - ws.onmessage =function got_packet(msg) { - add_div("messages", JSON.parse(msg.data)); - } - ws.onclose = function(){ - } - } catch(exception) { - alert('

Error' + exception); - } - } - - function mupd() - { - document.getElementById("send").disabled = !document.getElementById("msg").value; - } -}, false); Binary files /tmp/tmpmec97nsd/m0nuW2sR0N/libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/lwsgs-logo.png and /tmp/tmpmec97nsd/q8JCI83EXS/libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/lwsgs-logo.png differ diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/md5.min.js libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/md5.min.js --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/md5.min.js 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/md5.min.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -!function(n){"use strict";function t(n,t){var r=(65535&n)+(65535&t),e=(n>>16)+(t>>16)+(r>>16);return e<<16|65535&r}function r(n,t){return n<>>32-t}function e(n,e,o,u,c,f){return t(r(t(t(e,n),t(u,f)),c),o)}function o(n,t,r,o,u,c,f){return e(t&r|~t&o,n,t,u,c,f)}function u(n,t,r,o,u,c,f){return e(t&o|r&~o,n,t,u,c,f)}function c(n,t,r,o,u,c,f){return e(t^r^o,n,t,u,c,f)}function f(n,t,r,o,u,c,f){return e(r^(t|~o),n,t,u,c,f)}function i(n,r){n[r>>5]|=128<>>9<<4)+14]=r;var e,i,a,h,d,l=1732584193,g=-271733879,v=-1732584194,m=271733878;for(e=0;e>5]>>>t%32&255);return r}function h(n){var t,r=[];for(r[(n.length>>2)-1]=void 0,t=0;t>5]|=(255&n.charCodeAt(t/8))<16&&(o=i(o,8*n.length)),r=0;16>r;r+=1)u[r]=909522486^o[r],c[r]=1549556828^o[r];return e=i(u.concat(h(t)),512+8*t.length),a(i(c.concat(e),640))}function g(n){var t,r,e="0123456789abcdef",o="";for(r=0;r>>4&15)+e.charAt(15&t);return o}function v(n){return unescape(encodeURIComponent(n))}function m(n){return d(v(n))}function p(n){return g(m(n))}function s(n,t){return l(v(n),v(t))}function C(n,t){return g(s(n,t))}function A(n,t,r){return t?r?s(t,n):C(t,n):r?m(n):p(n)}"function"==typeof define&&define.amd?define(function(){return A}):"object"==typeof module&&module.exports?module.exports=A:n.md5=A}(this); -//# sourceMappingURL=md5.min.js.map \ No newline at end of file diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/needadmin/admin-login.html libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/needadmin/admin-login.html --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/needadmin/admin-login.html 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/needadmin/admin-login.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ - -This is an example destination that will appear after successful Admin login. - -This URL cannot be served if you're not logged in as admin. - diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/needauth/successful-login.html libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/needauth/successful-login.html --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/needauth/successful-login.html 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/needauth/successful-login.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ - -This is an example destination that will appear after successful non-Admin login - - diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/post-forgot-fail.html libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/post-forgot-fail.html --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/post-forgot-fail.html 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/post-forgot-fail.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ - -Sorry, something went wrong. - -Click here to continue. - diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/post-forgot-ok.html libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/post-forgot-ok.html --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/post-forgot-ok.html 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/post-forgot-ok.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ - -This is a one-time password recovery login. - -Please click here and click your username at the top to reset your password. - - diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/post-register-fail.html libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/post-register-fail.html --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/post-register-fail.html 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/post-register-fail.html 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -Registration failed, sorry diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/post-register-ok.html libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/post-register-ok.html --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/post-register-ok.html 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/post-register-ok.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ - - - - - - - - - - - - -
- -
- Your registration as is accepted,
- you will receive an email shortly with instructions
- to verify and enable the account for normal use.

- The link is only valid for an hour, after that if it has
- not been verified your account will be deleted. -
- - - - diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/post-verify-fail.html libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/post-verify-fail.html --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/post-verify-fail.html 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/post-verify-fail.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ - - - - - - - - - - - - -
- -
- Sorry, the link was invalid. -
- - - diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/post-verify-ok.html libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/post-verify-ok.html --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/post-verify-ok.html 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/post-verify-ok.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ - - - - - - - - - - - - -
- -
- Thanks for signing up, your registration as is verified.
-
- Click here to continue. -
- - - - Binary files /tmp/tmpmec97nsd/m0nuW2sR0N/libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/seats.jpg and /tmp/tmpmec97nsd/q8JCI83EXS/libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/seats.jpg differ diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/sent-forgot-fail.html libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/sent-forgot-fail.html --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/sent-forgot-fail.html 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/sent-forgot-fail.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ - -Sorry, something went wrong. - -Click here to continue. - diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/sent-forgot-ok.html libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/sent-forgot-ok.html --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/sent-forgot-ok.html 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/sent-forgot-ok.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -An email has been sent to your registered address. - -Please follow the instructions to reset your password. - diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/strict-csp.svg libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/strict-csp.svg --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/strict-csp.svg 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/strict-csp.svg 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/successful-login.html libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/successful-login.html --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/successful-login.html 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/mount-origin/successful-login.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ - -This is an example destination that will appear after successful non-Admin login - - diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/README.md libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/README.md --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-generic-sessions/README.md 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-generic-sessions/README.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -# lws minimal http server with generic-sessions - -## build - -``` - $ cmake . && make -``` - -## usage - -``` - $ ./lws-minimal-http-server-tls -[2018/03/20 13:23:13:0131] USER: LWS minimal http server TLS | visit https://localhost:7681 -[2018/03/20 13:23:13:0142] NOTICE: Creating Vhost 'default' port 7681, 1 protocols, IPv6 off -[2018/03/20 13:23:13:0142] NOTICE: Using SSL mode -[2018/03/20 13:23:13:0146] NOTICE: SSL ECDH curve 'prime256v1' -[2018/03/20 13:23:13:0146] NOTICE: HTTP2 / ALPN enabled -[2018/03/20 13:23:13:0195] NOTICE: lws_tls_client_create_vhost_context: doing cert filepath localhost-100y.cert -[2018/03/20 13:23:13:0195] NOTICE: Loaded client cert localhost-100y.cert -[2018/03/20 13:23:13:0195] NOTICE: lws_tls_client_create_vhost_context: doing private key filepath -[2018/03/20 13:23:13:0196] NOTICE: Loaded client cert private key localhost-100y.key -[2018/03/20 13:23:13:0196] NOTICE: created client ssl context for default -[2018/03/20 13:23:14:0207] NOTICE: vhost default: cert expiry: 730459d -``` - - diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-h2-long-poll/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-h2-long-poll/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-h2-long-poll/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-h2-long-poll/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,69 +1,13 @@ -project(lws-minimal-http-server-h2-long-poll) +project(lws-minimal-http-server-h2-long-poll C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-h2-long-poll) set(SRCS minimal-http-server.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) @@ -73,9 +17,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-h2-long-poll/minimal-http-server.c libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-h2-long-poll/minimal-http-server.c --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-h2-long-poll/minimal-http-server.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-h2-long-poll/minimal-http-server.c 2020-12-01 17:40:26.000000000 +0000 @@ -79,8 +79,7 @@ case LWS_CALLBACK_CLOSED_HTTP: if (!pss) break; - lws_sul_schedule(lws_get_context(wsi), 0, &pss->sul, sul_cb, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&pss->sul); break; case LWS_CALLBACK_HTTP_WRITEABLE: @@ -129,8 +128,10 @@ memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ info.port = 7681; +#if defined(LWS_WITH_TLS) info.ssl_cert_filepath = "localhost-100y.cert"; info.ssl_private_key_filepath = "localhost-100y.key"; +#endif info.protocols = protocols; info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT | diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-mimetypes/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-mimetypes/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-mimetypes/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-mimetypes/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,69 +1,13 @@ -project(lws-minimal-http-server-mimetypes) +project(lws-minimal-http-server-mimetypes C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-mimetypes) set(SRCS minimal-http-server-mimetypes.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) @@ -72,9 +16,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-multivhost/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-multivhost/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-multivhost/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-multivhost/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,67 +1,13 @@ -project(lws-minimal-http-server-multivhost) +project(lws-minimal-http-server-multivhost C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-multivhost) set(SRCS minimal-http-server.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) @@ -70,9 +16,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() \ No newline at end of file diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-proxy/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-proxy/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-proxy/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-proxy/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,81 +1,26 @@ -project(lws-minimal-http-server-proxy) +project(lws-minimal-http-server-proxy C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-proxy) set(SRCS minimal-http-server-proxy.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) require_lws_config(LWS_WITH_HTTP_PROXY 1 requirements) -require_lws_config(LWS_OPENSSL_SUPPORT 1 requirements) +require_lws_config(LWS_WITH_TLS 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-smp/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-smp/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-smp/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-smp/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,80 +1,14 @@ -project(lws-minimal-http-server-smp) +project(lws-minimal-http-server-smp C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckIncludeFile) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-smp) set(SRCS minimal-http-server-smp.c) -MACRO(require_pthreads result) - CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) - if (NOT LWS_HAVE_PTHREAD_H) - if (LWS_WITH_MINIMAL_EXAMPLES) - set(result 0) - else() - message(FATAL_ERROR "threading support requires pthreads") - endif() - endif() -ENDMACRO() - -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_pthreads(requirements) require_lws_config(LWS_ROLE_H1 1 requirements) @@ -84,9 +18,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared pthread) - add_dependencies(${SAMP} websockets_shared pthread) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) + add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets pthread) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() \ No newline at end of file diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-smp/minimal-http-server-smp.c libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-smp/minimal-http-server-smp.c --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-smp/minimal-http-server-smp.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-smp/minimal-http-server-smp.c 2020-12-01 17:40:26.000000000 +0000 @@ -21,6 +21,12 @@ #include #include #include +#if defined(WIN32) +#define HAVE_STRUCT_TIMESPEC +#if defined(pid_t) +#undef pid_t +#endif +#endif #include #define COUNT_THREADS 8 @@ -100,11 +106,13 @@ } else info.count_threads = COUNT_THREADS; +#if defined(LWS_WITH_TLS) if (lws_cmdline_option(argc, argv, "-s")) { info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT | LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT; info.ssl_cert_filepath = "localhost-100y.cert"; info.ssl_private_key_filepath = "localhost-100y.key"; } +#endif context = lws_create_context(&info); if (!context) { diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-sse/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-sse/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-sse/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-sse/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,69 +1,15 @@ -project(lws-minimal-http-server-sse) +project(lws-minimal-http-server-sse C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-sse) set(SRCS minimal-http-server-sse.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) +require_pthreads(requirements) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) @@ -71,9 +17,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-sse/minimal-http-server-sse.c libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-sse/minimal-http-server-sse.c --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-sse/minimal-http-server-sse.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-sse/minimal-http-server-sse.c 2020-12-01 17:40:26.000000000 +0000 @@ -19,6 +19,12 @@ #include #include #include +#if defined(WIN32) +#define HAVE_STRUCT_TIMESPEC +#if defined(pid_t) +#undef pid_t +#endif +#endif #include /* @@ -202,12 +208,15 @@ info.options = LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; info.port = 7681; + +#if defined(LWS_WITH_TLS) if (lws_cmdline_option(argc, argv, "-s")) { info.port = 443; info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; info.ssl_cert_filepath = "localhost-100y.cert"; info.ssl_private_key_filepath = "localhost-100y.key"; } +#endif context = lws_create_context(&info); if (!context) { diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-sse-ring/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-sse-ring/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-sse-ring/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-sse-ring/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,80 +1,12 @@ -project(lws-minimal-http-server-sse-ring) +project(lws-minimal-http-server-sse-ring C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) include(CheckIncludeFile) include(CheckCSourceCompiles) set(SAMP lws-minimal-http-server-sse-ring) set(SRCS minimal-http-server-sse-ring.c) -MACRO(require_pthreads result) - CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) - if (NOT LWS_HAVE_PTHREAD_H) - if (LWS_WITH_MINIMAL_EXAMPLES) - set(result 0) - else() - message(FATAL_ERROR "threading support requires pthreads") - endif() - endif() -ENDMACRO() - -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_pthreads(requirements) require_lws_config(LWS_ROLE_H1 1 requirements) @@ -84,9 +16,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared pthread) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets pthread) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-sse-ring/minimal-http-server-sse-ring.c libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-sse-ring/minimal-http-server-sse-ring.c --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-sse-ring/minimal-http-server-sse-ring.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-sse-ring/minimal-http-server-sse-ring.c 2020-12-01 17:40:26.000000000 +0000 @@ -19,6 +19,12 @@ #include #include #include +#if defined(WIN32) +#define HAVE_STRUCT_TIMESPEC +#if defined(pid_t) +#undef pid_t +#endif +#endif #include #include @@ -86,7 +92,11 @@ { struct vhd *vhd = (struct vhd *)d; struct msg amsg; - int len = 128, index = 1, n; + int len = 128, index = 1, n, whoami = 0; + + for (n = 0; n < (int)LWS_ARRAY_SIZE(vhd->pthread_spam); n++) + if (pthread_equal(pthread_self(), vhd->pthread_spam[n])) + whoami = n + 1; do { /* don't generate output if nobody connected */ @@ -108,10 +118,9 @@ goto wait_unlock; } n = lws_snprintf((char *)amsg.payload, len, - "%s: tid: %p, msg: %d", __func__, - (void *)pthread_self(), index++); + "%s: tid: %d, msg: %d", __func__, whoami, index++); amsg.len = n; - n = lws_ring_insert(vhd->ring, &amsg, 1); + n = (int)lws_ring_insert(vhd->ring, &amsg, 1); if (n != 1) { __minimal_destroy_message(&amsg); lwsl_user("dropping!\n"); @@ -131,7 +140,7 @@ } while (!vhd->finished); - lwsl_notice("thread_spam %p exiting\n", (void *)pthread_self()); + lwsl_notice("thread_spam %d exiting\n", whoami); pthread_exit(NULL); @@ -186,8 +195,7 @@ init_fail: vhd->finished = 1; for (n = 0; n < (int)LWS_ARRAY_SIZE(vhd->pthread_spam); n++) - if (vhd->pthread_spam[n]) - pthread_join(vhd->pthread_spam[n], &retval); + pthread_join(vhd->pthread_spam[n], &retval); if (vhd->ring) lws_ring_destroy(vhd->ring); diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-tls/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-tls/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-tls/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-tls/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,80 +1,25 @@ -project(lws-minimal-http-server-tls) +project(lws-minimal-http-server-tls C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-tls) set(SRCS minimal-http-server-tls.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) -require_lws_config(LWS_OPENSSL_SUPPORT 1 requirements) +require_lws_config(LWS_WITH_TLS 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-tls/minimal-http-server-tls.c libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-tls/minimal-http-server-tls.c --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-tls/minimal-http-server-tls.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-tls/minimal-http-server-tls.c 2020-12-01 17:40:26.000000000 +0000 @@ -52,24 +52,17 @@ struct lws_context_creation_info info; struct lws_context *context; const char *p; - int n = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE - /* for LLL_ verbosity above NOTICE to be built into lws, - * lws must have been configured and built with - * -DCMAKE_BUILD_TYPE=DEBUG instead of =RELEASE */ - /* | LLL_INFO */ /* | LLL_PARSER */ /* | LLL_HEADER */ - /* | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY */ - /* | LLL_DEBUG */; - - if ((p = lws_cmdline_option(argc, argv, "-d"))) - logs = atoi(p); - - lws_set_log_level(logs, NULL); - lwsl_user("LWS minimal http server TLS | visit https://localhost:7681\n"); + int n = 0; signal(SIGINT, sigint_handler); memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ + lws_cmdline_option_handle_builtin(argc, argv, &info); + lwsl_user("LWS minimal http server TLS | visit https://localhost:7681\n"); + info.port = 7681; + if ((p = lws_cmdline_option(argc, argv, "--port"))) + info.port = atoi(p); info.mounts = &mount; info.error_document_404 = "/404.html"; info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT | diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-tls-80/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-tls-80/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-tls-80/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-tls-80/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,80 +1,25 @@ -project(lws-minimal-http-server-tls-80) +project(lws-minimal-http-server-tls-80 C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-tls-80) set(SRCS minimal-http-server-tls-80.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) -require_lws_config(LWS_OPENSSL_SUPPORT 1 requirements) +require_lws_config(LWS_WITH_TLS 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-tls-mem/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-tls-mem/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-tls-mem/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-tls-mem/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,80 +1,25 @@ -project(lws-minimal-http-server-tls-mem) +project(lws-minimal-http-server-tls-mem C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-tls-mem) set(SRCS minimal-http-server-tls-mem.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) -require_lws_config(LWS_OPENSSL_SUPPORT 1 requirements) +require_lws_config(LWS_WITH_TLS 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-tls-mem/minimal-http-server-tls-mem.c libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-tls-mem/minimal-http-server-tls-mem.c --- libwebsockets-4.0.20/minimal-examples/http-server/minimal-http-server-tls-mem/minimal-http-server-tls-mem.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/http-server/minimal-http-server-tls-mem/minimal-http-server-tls-mem.c 2020-12-01 17:40:26.000000000 +0000 @@ -429,9 +429,9 @@ info.mounts = &mount; info.error_document_404 = "/404.html"; info.server_ssl_cert_mem = cert_pem; - info.server_ssl_cert_mem_len = strlen(cert_pem); + info.server_ssl_cert_mem_len = (unsigned int)strlen(cert_pem); info.server_ssl_private_key_mem = key_pem; - info.server_ssl_private_key_mem_len = strlen(key_pem); + info.server_ssl_private_key_mem_len = (unsigned int)strlen(key_pem); info.vhost_name = "first"; if (!lws_create_vhost(context, &info)) { @@ -443,9 +443,9 @@ info.mounts = &mount; info.error_document_404 = "/404.html"; info.server_ssl_cert_mem = cert_der; - info.server_ssl_cert_mem_len = sizeof(cert_der); + info.server_ssl_cert_mem_len = (unsigned int)sizeof(cert_der); info.server_ssl_private_key_mem = key_der; - info.server_ssl_private_key_mem_len = sizeof(key_der); + info.server_ssl_private_key_mem_len = (unsigned int)sizeof(key_der); info.vhost_name = "second"; if (!lws_create_vhost(context, &info)) { diff -Nru libwebsockets-4.0.20/minimal-examples/mqtt-client/minimal-mqtt-client/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/mqtt-client/minimal-mqtt-client/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/mqtt-client/minimal-mqtt-client/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/mqtt-client/minimal-mqtt-client/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,79 +1,23 @@ +project(lws-minimal-mqtt-client C) cmake_minimum_required(VERSION 2.8) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-mqtt-client) set(SRCS minimal-mqtt-client.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_MQTT 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) +require_lws_config(LWS_WITH_SYS_STATE 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/mqtt-client/minimal-mqtt-client/minimal-mqtt-client.c libwebsockets-4.1.6/minimal-examples/mqtt-client/minimal-mqtt-client/minimal-mqtt-client.c --- libwebsockets-4.0.20/minimal-examples/mqtt-client/minimal-mqtt-client/minimal-mqtt-client.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/mqtt-client/minimal-mqtt-client/minimal-mqtt-client.c 2020-12-01 17:40:26.000000000 +0000 @@ -11,6 +11,12 @@ #include #include #include +#if defined(WIN32) +#define HAVE_STRUCT_TIMESPEC +#if defined(pid_t) +#undef pid_t +#endif +#endif #include #include @@ -318,7 +324,7 @@ info.fd_limit_per_thread = 1 + 1 + 1; info.retry_and_idle_policy = &retry; -#if defined(LWS_WITH_MBEDTLS) +#if defined(LWS_WITH_MBEDTLS) || defined(USE_WOLFSSL) /* * OpenSSL uses the system trust store. mbedTLS has to be told which * CA to trust explicitly. diff -Nru libwebsockets-4.0.20/minimal-examples/mqtt-client/minimal-mqtt-client-multi/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/mqtt-client/minimal-mqtt-client-multi/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/mqtt-client/minimal-mqtt-client-multi/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/mqtt-client/minimal-mqtt-client-multi/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,79 +1,25 @@ +project(lws-minimal-mqtt-client-multi C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-mqtt-client-multi) set(SRCS minimal-mqtt-client-multi.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_MQTT 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) +require_lws_config(LWS_WITH_SYS_STATE 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/mqtt-client/minimal-mqtt-client-multi/minimal-mqtt-client-multi.c libwebsockets-4.1.6/minimal-examples/mqtt-client/minimal-mqtt-client-multi/minimal-mqtt-client-multi.c --- libwebsockets-4.0.20/minimal-examples/mqtt-client/minimal-mqtt-client-multi/minimal-mqtt-client-multi.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/mqtt-client/minimal-mqtt-client-multi/minimal-mqtt-client-multi.c 2020-12-01 17:40:26.000000000 +0000 @@ -11,6 +11,12 @@ #include #include #include +#if defined(WIN32) +#define HAVE_STRUCT_TIMESPEC +#if defined(pid_t) +#undef pid_t +#endif +#endif #include #include @@ -411,7 +417,7 @@ info.fd_limit_per_thread = 1 + COUNT + 1; info.retry_and_idle_policy = &retry; -#if defined(LWS_WITH_MBEDTLS) +#if defined(LWS_WITH_MBEDTLS) || defined(USE_WOLFSSL) /* * OpenSSL uses the system trust store. mbedTLS has to be told which * CA to trust explicitly. diff -Nru libwebsockets-4.0.20/minimal-examples/mqtt-client/minimal-mqtt-client-multi/warmcat.com.cer libwebsockets-4.1.6/minimal-examples/mqtt-client/minimal-mqtt-client-multi/warmcat.com.cer --- libwebsockets-4.0.20/minimal-examples/mqtt-client/minimal-mqtt-client-multi/warmcat.com.cer 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/mqtt-client/minimal-mqtt-client-multi/warmcat.com.cer 2020-12-01 17:40:26.000000000 +0000 @@ -56,3 +56,23 @@ PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6 KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg== -----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow +PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD +Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O +rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq +OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b +xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw +7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD +aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG +SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 +ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr +AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz +R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 +JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo +Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +-----END CERTIFICATE----- diff -Nru libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-adopt-tcp/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-adopt-tcp/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-adopt-tcp/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-adopt-tcp/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,67 +1,13 @@ -project(lws-minimal-raw-adopt-tcp) +project(lws-minimal-raw-adopt-tcp C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-raw-adopt-tcp) set(SRCS minimal-raw-adopt-tcp.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_SERVER 1 requirements) @@ -69,9 +15,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-adopt-tcp/minimal-raw-adopt-tcp.c libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-adopt-tcp/minimal-raw-adopt-tcp.c --- libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-adopt-tcp/minimal-raw-adopt-tcp.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-adopt-tcp/minimal-raw-adopt-tcp.c 2020-12-01 17:40:26.000000000 +0000 @@ -31,7 +31,9 @@ #include #include #include +#if !defined(WIN32) #include +#endif #include static int diff -Nru libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-adopt-udp/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-adopt-udp/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-adopt-udp/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-adopt-udp/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,67 +1,13 @@ -project(lws-minimal-raw-adopt-udp) +project(lws-minimal-raw-adopt-udp C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-raw-adopt-udp) set(SRCS minimal-raw-adopt-udp.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_SERVER 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) @@ -72,9 +18,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-adopt-udp/minimal-raw-adopt-udp.c libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-adopt-udp/minimal-raw-adopt-udp.c --- libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-adopt-udp/minimal-raw-adopt-udp.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-adopt-udp/minimal-raw-adopt-udp.c 2020-12-01 17:40:26.000000000 +0000 @@ -28,7 +28,9 @@ #include #include #include +#if !defined(WIN32) #include +#endif #include static uint8_t sendbuf[4096]; @@ -40,7 +42,7 @@ void *user, void *in, size_t len) { ssize_t n; - int fd; + lws_sockfd_type fd; switch (reason) { @@ -84,8 +86,13 @@ break; fd = lws_get_socket_fd(wsi); +#if defined(WIN32) + if ((int)fd < 0) + break; +#else if (fd < 0) /* keep Coverity happy: actually it cannot be < 0 */ break; +#endif /* * We can write directly on the UDP socket, specifying @@ -102,7 +109,11 @@ #if defined(WIN32) (const char *) #endif - sendbuf, sendlen, 0, &udp.sa, udp.salen); + sendbuf, +#if defined(WIN32) + (int) +#endif + sendlen, 0, &udp.sa, (socklen_t)udp.salen); if (n < (ssize_t)len) lwsl_notice("%s: send returned %d\n", __func__, (int)n); break; diff -Nru libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-audio/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-audio/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-audio/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-audio/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,68 +1,13 @@ -project(lws-minimal-raw-audio) +project(lws-minimal-raw-audio C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-raw-audio) set(SRCS audio.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_ALSA 1 requirements) require_lws_config(LWS_WITH_NETWORK 1 requirements) @@ -71,9 +16,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared asound) + target_link_libraries(${SAMP} websockets_shared asound ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets asound) + target_link_libraries(${SAMP} websockets asound ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-fallback-http-server/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-fallback-http-server/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-fallback-http-server/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-fallback-http-server/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,69 +1,13 @@ -project(lws-minimal-raw-fallback-http-server) +project(lws-minimal-raw-fallback-http-server C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-raw-fallback-http-server) set(SRCS minimal-raw-fallback-http-server.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) @@ -72,9 +16,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-fallback-http-server/minimal-raw-fallback-http-server.c libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-fallback-http-server/minimal-raw-fallback-http-server.c --- libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-fallback-http-server/minimal-raw-fallback-http-server.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-fallback-http-server/minimal-raw-fallback-http-server.c 2020-12-01 17:40:26.000000000 +0000 @@ -63,7 +63,7 @@ if (len > sizeof(pss->buf)) len = sizeof(pss->buf); memcpy(pss->buf, in, len); - pss->len = len; + pss->len = (int)len; lws_callback_on_writable(wsi); break; @@ -119,6 +119,7 @@ info.listen_accept_role = "raw-skt"; info.listen_accept_protocol = "raw-echo"; +#if defined(LWS_WITH_TLS) if (lws_cmdline_option(argc, argv, "-s")) { info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT | LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT; @@ -131,6 +132,7 @@ if (lws_cmdline_option(argc, argv, "-h")) info.options |= LWS_SERVER_OPTION_ALLOW_HTTP_ON_HTTPS_LISTENER; } +#endif context = lws_create_context(&info); if (!context) { diff -Nru libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-file/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-file/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-file/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-file/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,68 +1,13 @@ -project(lws-minimal-raw-file) +project(lws-minimal-raw-file C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-raw-file) set(SRCS minimal-raw-file.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_SERVER 1 requirements) @@ -70,9 +15,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() \ No newline at end of file diff -Nru libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-netcat/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-netcat/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-netcat/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-netcat/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,67 +1,13 @@ -project(lws-minimal-raw-netcat) +project(lws-minimal-raw-netcat C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-raw-netcat) set(SRCS minimal-raw-netcat.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_SERVER 1 requirements) @@ -69,9 +15,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-netcat/minimal-raw-netcat.c libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-netcat/minimal-raw-netcat.c --- libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-netcat/minimal-raw-netcat.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-netcat/minimal-raw-netcat.c 2020-12-01 17:40:26.000000000 +0000 @@ -26,7 +26,9 @@ #include #include #include +#if !defined(WIN32) #include +#endif #include static struct lws *raw_wsi, *stdin_wsi; diff -Nru libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-proxy/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-proxy/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-proxy/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-proxy/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,6 +1,9 @@ -project(lws-minimal-raw-proxy) +project(lws-minimal-raw-proxy C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-raw-proxy) set(SRCS minimal-raw-proxy.c) @@ -9,63 +12,6 @@ # to the lws plugins dir so it can pick up the plugin source. Eg, # cmake . -DLWS_PLUGINS_DIR=~/libwebsockets/plugins -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_RAW_PROXY 1 requirements) @@ -77,9 +23,9 @@ endif() if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-proxy-fallback/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-proxy-fallback/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-proxy-fallback/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-proxy-fallback/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,6 +1,9 @@ -project(lws-minimal-raw-proxy-fallback) +project(lws-minimal-raw-proxy-fallback C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-raw-proxy-fallback) set(SRCS minimal-raw-proxy-fallback.c) @@ -9,63 +12,6 @@ # to the lws plugins dir so it can pick up the plugin source. Eg, # cmake . -DLWS_PLUGINS_DIR=~/libwebsockets/plugins -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_RAW_PROXY 1 requirements) @@ -77,9 +23,9 @@ endif() if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-proxy-fallback/minimal-raw-proxy-fallback.c libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-proxy-fallback/minimal-raw-proxy-fallback.c --- libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-proxy-fallback/minimal-raw-proxy-fallback.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-proxy-fallback/minimal-raw-proxy-fallback.c 2020-12-01 17:40:26.000000000 +0000 @@ -106,6 +106,7 @@ info.listen_accept_role = "raw-proxy"; info.listen_accept_protocol = "raw-proxy"; +#if defined(LWS_WITH_TLS) if (lws_cmdline_option(argc, argv, "-s")) { info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT | LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT; @@ -118,6 +119,7 @@ if (lws_cmdline_option(argc, argv, "-h")) info.options |= LWS_SERVER_OPTION_ALLOW_HTTP_ON_HTTPS_LISTENER; } +#endif context = lws_create_context(&info); if (!context) { diff -Nru libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-serial/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-serial/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-serial/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-serial/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,78 +1,23 @@ -project(lws-minimal-raw-serial) +project(lws-minimal-raw-serial C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-raw-serial) set(SRCS minimal-raw-file.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_SERVER 1 requirements) -if (requirements) +if (requirements AND UNIX) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-serial/minimal-raw-file.c libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-serial/minimal-raw-file.c --- libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-serial/minimal-raw-file.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-serial/minimal-raw-file.c 2020-12-01 17:40:26.000000000 +0000 @@ -153,7 +153,7 @@ case LWS_CALLBACK_RAW_CLOSE_FILE: lwsl_notice("LWS_CALLBACK_RAW_CLOSE_FILE\n"); - lws_sul_schedule(lws_get_context(wsi), 0, &vhd->sul, sul_cb, LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&vhd->sul); break; case LWS_CALLBACK_RAW_WRITEABLE_FILE: diff -Nru libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-vhost/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-vhost/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-vhost/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-vhost/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,67 +1,13 @@ -project(lws-minimal-raw-vhost) +project(lws-minimal-raw-vhost C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-raw-vhost) set(SRCS minimal-raw-vhost.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_SERVER 1 requirements) @@ -69,9 +15,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-vhost/minimal-raw-vhost.c libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-vhost/minimal-raw-vhost.c --- libwebsockets-4.0.20/minimal-examples/raw/minimal-raw-vhost/minimal-raw-vhost.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/raw/minimal-raw-vhost/minimal-raw-vhost.c 2020-12-01 17:40:26.000000000 +0000 @@ -75,7 +75,7 @@ case LWS_CALLBACK_RAW_RX: lwsl_user("LWS_CALLBACK_RAW_RX: %d\n", (int)len); - vhd->len = len; + vhd->len = (int)len; if (vhd->len > (int)sizeof(vhd->buf)) vhd->len = sizeof(vhd->buf); memcpy(vhd->buf, in, vhd->len); @@ -137,11 +137,13 @@ info.protocols = protocols; info.options = LWS_SERVER_OPTION_ONLY_RAW; /* vhost accepts RAW */ +#if defined(LWS_WITH_TLS) if (lws_cmdline_option(argc, argv, "-s")) { info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; info.ssl_cert_filepath = "localhost-100y.cert"; info.ssl_private_key_filepath = "localhost-100y.key"; } +#endif context = lws_create_context(&info); if (!context) { diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,90 +1,48 @@ +project(lws-minimal-secure-streams C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-secure-streams) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 requirements) +require_lws_config(LWS_WITH_SYS_STATE 1 requirements) if (requirements) add_executable(${SAMP} minimal-secure-streams.c) + if (LWS_CTEST_INTERNET_AVAILABLE) + add_test(NAME ss-warmcat COMMAND lws-minimal-secure-streams) + set_tests_properties(ss-warmcat + PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/secure-streams/minimal-secure-streams + TIMEOUT 20) + endif() + if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() - if (LWS_WITH_SECURE_STREAMS_PROXY_API) + CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\ni#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)\n return 0;\n #else\n fail\n #endif\n return 0;\n}\n" HAS_LWS_WITH_SECURE_STREAMS_PROXY_API) + + if (HAS_LWS_WITH_SECURE_STREAMS_PROXY_API OR LWS_WITH_SECURE_STREAMS_PROXY_API) add_compile_options(-DLWS_SS_USE_SSPC) add_executable(${SAMP}-client minimal-secure-streams.c) if (websockets_shared) - target_link_libraries(${SAMP}-client websockets_shared) + target_link_libraries(${SAMP}-client websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP}-client websockets_shared) else() - target_link_libraries(${SAMP}-client websockets) + target_link_libraries(${SAMP}-client websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c 2020-12-01 17:40:26.000000000 +0000 @@ -37,7 +37,9 @@ */ // #define VIA_LOCALHOST_SOCKS -static int interrupted, bad = 1; +static int interrupted, bad = 1, force_cpd_fail_portal, + force_cpd_fail_no_internet; +static unsigned int timeout_ms = 3000; static lws_state_notify_link_t nl; /* @@ -154,6 +156,11 @@ "}" "]," "\"s\": [" + /* + * "fetch_policy" decides from where the real policy + * will be fetched, if present. Otherwise the initial + * policy is treated as the whole, hardcoded, policy. + */ "{\"fetch_policy\": {" "\"endpoint\":" "\"warmcat.com\"," "\"port\":" "443," @@ -168,8 +175,27 @@ "\"opportunistic\":" "true," "\"retry\":" "\"default\"," "\"tls_trust_store\":" "\"le_via_isrg\"" - "}}" - "}" + "}},{" + /* + * "captive_portal_detect" describes + * what to do in order to check if the path to + * the Internet is being interrupted by a + * captive portal. If there's a larger policy + * fetched from elsewhere, it should also include + * this since it needs to be done at least after + * every DHCP acquisition + */ + "\"captive_portal_detect\": {" + "\"endpoint\": \"connectivitycheck.android.com\"," + "\"http_url\": \"generate_204\"," + "\"port\": 80," + "\"protocol\": \"h1\"," + "\"http_method\": \"GET\"," + "\"opportunistic\": true," + "\"http_expect\": 204," + "\"http_fail_redirect\": true" + "}}" + "]}" ; #endif @@ -181,6 +207,8 @@ lws_sorted_usec_list_t sul; } myss_t; +#if !defined(LWS_SS_USE_SSPC) + static const char *canned_root_token_payload = "grant_type=refresh_token" "&refresh_token=Atzr|IwEBIJedGXjDqsU_vMxykqOMg" @@ -195,6 +223,8 @@ "&client_id=" "amzn1.application-oa2-client.4823334c434b4190a2b5a42c07938a2d"; +#endif + /* secure streams payload interface */ static int @@ -223,7 +253,9 @@ { //myss_t *m = (myss_t *)userobj; - return 0; + /* in this example, we don't send stuff */ + + return LWSSSSRET_TX_DONT_SEND; } static int @@ -237,6 +269,7 @@ switch (state) { case LWSSSCS_CREATING: + lws_ss_start_timeout(m->ss, timeout_ms); lws_ss_set_metadata(m->ss, "uptag", "myuptag123", 10); lws_ss_set_metadata(m->ss, "ctype", "myctype", 7); lws_ss_client_connect(m->ss); @@ -248,6 +281,10 @@ case LWSSSCS_QOS_ACK_REMOTE: lwsl_notice("%s: LWSSSCS_QOS_ACK_REMOTE\n", __func__); break; + + case LWSSSCS_TIMEOUT: + lwsl_notice("%s: LWSSSCS_TIMEOUT\n", __func__); + break; default: break; } @@ -260,9 +297,12 @@ int current, int target) { struct lws_context *context = lws_system_context_from_system_mgr(mgr); +#if !defined(LWS_SS_USE_SSPC) + lws_system_blob_t *ab = lws_system_get_blob(context, LWS_SYSBLOB_TYPE_AUTH, 1 /* AUTH_IDX_ROOT */); size_t size; +#endif /* * For the things we care about, let's notice if we are trying to get @@ -270,6 +310,45 @@ * state wait while we trigger the dependent action. */ switch (target) { + +#if !defined(LWS_SS_USE_SSPC) + + /* + * The proxy takes responsibility for this stuff if we get things + * done through that + */ + + case LWS_SYSTATE_INITIALIZED: /* overlay on the hardcoded policy */ + case LWS_SYSTATE_POLICY_VALID: /* overlay on the loaded policy */ + + if (target != current) + break; + + if (force_cpd_fail_portal) + + /* this makes it look like we're behind a captive portal + * because the overriden address does a redirect */ + + lws_ss_policy_overlay(context, + "{\"s\": [{\"captive_portal_detect\": {" + "\"endpoint\": \"google.com\"," + "\"http_url\": \"/\"," + "\"port\": 80" + "}}]}"); + + if (force_cpd_fail_no_internet) + + /* this looks like no internet, because the overridden + * port doesn't have anything that will connect to us */ + + lws_ss_policy_overlay(context, + "{\"s\": [{\"captive_portal_detect\": {" + "\"endpoint\": \"warmcat.com\"," + "\"http_url\": \"/\"," + "\"port\": 999" + "}}]}"); + break; + case LWS_SYSTATE_REGISTERED: size = lws_system_blob_get_size(ab); if (size) @@ -281,6 +360,8 @@ strlen(canned_root_token_payload)); break; +#endif + case LWS_SYSTATE_OPERATIONAL: if (current == LWS_SYSTATE_OPERATIONAL) { lws_ss_info_t ssi; @@ -324,6 +405,7 @@ { struct lws_context_creation_info info; struct lws_context *context; + const char *p; int n = 0; signal(SIGINT, sigint_handler); @@ -333,6 +415,17 @@ lwsl_user("LWS secure streams test client [-d]\n"); + /* these options are mutually exclusive if given */ + + if (lws_cmdline_option(argc, argv, "--force-portal")) + force_cpd_fail_portal = 1; + + if (lws_cmdline_option(argc, argv, "--force-no-internet")) + force_cpd_fail_no_internet = 1; + + if ((p = lws_cmdline_option(argc, argv, "--timeout_ms"))) + timeout_ms = atoi(p); + info.fd_limit_per_thread = 1 + 6 + 1; info.port = CONTEXT_PORT_NO_LISTEN; #if defined(LWS_SS_USE_SSPC) @@ -379,6 +472,11 @@ return 1; } +#if !defined(LWS_SS_USE_SSPC) + /* + * If we're being a proxied client, the proxy does all this + */ + /* * Set the related lws_system blobs * @@ -407,6 +505,7 @@ lws_system_blob_heap_append(lws_system_get_blob(context, LWS_SYSBLOB_TYPE_DEVICE_TYPE, 0), (const uint8_t *)"spacerocket", 11); +#endif /* the event loop */ diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams/README.md libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams/README.md --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams/README.md 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams/README.md 2020-12-01 17:40:26.000000000 +0000 @@ -23,6 +23,8 @@ -d |Debug verbosity in decimal, eg, -d15 -f| Force connecting to the wrong endpoint to check backoff retry flow -p| Run as proxy server for clients to connect to over unix domain socket +--force-portal|Force the SS Captive Portal Detection to feel it's behind a portal +--force-no-internet|Force the SS Captive Portal Detection to feel it can't reach the internet ``` [2019/08/12 07:16:11:0045] USR: LWS minimal secure streams [-d] [-f] diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-alexa/alexa.c libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-alexa/alexa.c --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-alexa/alexa.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-alexa/alexa.c 2020-12-01 17:40:26.000000000 +0000 @@ -234,8 +234,7 @@ /* * Put a hold on bringing in any more data */ - lws_sul_schedule(context, 0, &m->sul, NULL, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&m->sul); #endif /* destroy our copy of the handle */ m->mh = NULL; @@ -391,8 +390,7 @@ /* * Put a hold on bringing in any more data */ - lws_sul_schedule(context, 0, &m->sul, NULL, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&m->sul); #endif /* destroy our copy of the handle */ m->mh = NULL; @@ -549,8 +547,7 @@ lws_ss_request_tx(m->ss); break; case LWSSSCS_DISCONNECTED: - lws_sul_schedule(context, 0, &m->sul, NULL, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&m->sul); //if (m->mh) { play_mp3(NULL, NULL, NULL); m->mh = NULL; diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-alexa/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-alexa/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-alexa/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-alexa/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,92 +1,42 @@ +project(lws-minimal-secure-streams-alexa C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-secure-streams-alexa) set(SRCS main.c alexa.c audio.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 requirements) require_lws_config(LWS_WITH_ALSA 1 requirements) +require_lws_config(LWS_WITH_SYS_STATE 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared asound pv_porcupine mpg123) + target_link_libraries(${SAMP} websockets_shared asound pv_porcupine mpg123 ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets asound pv_porcupine mpg123) + target_link_libraries(${SAMP} websockets asound pv_porcupine mpg123 ${LIBWEBSOCKETS_DEP_LIBS}) endif() - if (LWS_WITH_SECURE_STREAMS_PROXY_API) + CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\ni#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)\n return 0;\n #else\n fail\n #endif\n return 0;\n}\n" HAS_LWS_WITH_SECURE_STREAMS_PROXY_API) + + if (HAS_LWS_WITH_SECURE_STREAMS_PROXY_API OR LWS_WITH_SECURE_STREAMS_PROXY_API) add_compile_options(-DLWS_SS_USE_SSPC) add_executable(${SAMP}-client ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP}-client websockets_shared asound pv_porcupine mpg123) + target_link_libraries(${SAMP}-client websockets_shared asound pv_porcupine mpg123 ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP}-client websockets_shared) else() - target_link_libraries(${SAMP}-client websockets asound pv_porcupine mpg123) + target_link_libraries(${SAMP}-client websockets asound pv_porcupine mpg123 ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-alexa/main.c libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-alexa/main.c --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-alexa/main.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-alexa/main.c 2020-12-01 17:40:26.000000000 +0000 @@ -203,6 +203,7 @@ "\"h2q_oflow_txcr\":" "true," "\"http_auth_header\":" "\"authorization:\"," "\"http_auth_preamble\":" "\"Bearer \"," + "\"http_multipart_ss_in\":" "true," "\"nailed_up\":" "true," "\"long_poll\":" "true," "\"retry\":" "\"default\"," @@ -229,6 +230,7 @@ "\"http_multipart_name\":" "\"metadata\"," "\"http_mime_content_type\":" "\"application/json; charset=UTF-8\"," "\"http_no_content_length\":" "true," + "\"http_multipart_ss_in\":" "true," "\"rideshare\":" "\"avs_audio\"," "\"retry\":" "\"default\"," "\"plugins\":" "[]," @@ -246,6 +248,7 @@ "\"h2q_oflow_txcr\":" "true," "\"http_auth_header\":" "\"authorization:\"," "\"http_auth_preamble\":" "\"Bearer \"," + "\"http_multipart_ss_in\":" "true," "\"http_multipart_name\":" "\"audio\"," "\"http_mime_content_type\":" "\"application/octet-stream\"," "\"http_no_content_length\":" "true," diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-avs/avs.c libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-avs/avs.c --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-avs/avs.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-avs/avs.c 2020-12-01 17:40:26.000000000 +0000 @@ -17,7 +17,9 @@ #include #include #include +#if !defined(WIN32) #include +#endif #include #include @@ -102,7 +104,7 @@ if (n < (sizeof(m->buf) * 2) / 3 && e < (int)(sizeof(m->buf) - 1 - n)) { lwsl_info("%s: requesting additional %d\n", __func__, (int)(sizeof(m->buf) - 1 - e - n)); - lws_ss_add_peer_tx_credit(m->ss, (sizeof(m->buf) - 1 - e - n)); + lws_ss_add_peer_tx_credit(m->ss, (int32_t)(sizeof(m->buf) - 1 - e - n)); } lws_sul_schedule(context, 0, &m->sul, use_buffer_50ms, @@ -118,7 +120,9 @@ lwsl_notice("%s: rideshare %s, len %d, flags 0x%x\n", __func__, lws_ss_rideshare(m->ss), (int)len, flags); - // lwsl_hexdump_warn(buf, len); +#if 0 + lwsl_hexdump_warn(buf, len); +#endif n = sizeof(m->buf) - ((m->head - m->tail) % sizeof(m->buf)); lwsl_info("%s: len %d, buf h %d, t %d, space %d\n", __func__, @@ -221,7 +225,7 @@ { ss_avs_metadata_t *m = (ss_avs_metadata_t *)userobj; - struct lws_context *context = (struct lws_context *)m->opaque_data; + // struct lws_context *context = (struct lws_context *)m->opaque_data; lwsl_user("%s: %s, ord 0x%x\n", __func__, lws_ss_state_name(state), (unsigned int)ack); @@ -241,13 +245,11 @@ /* for this demo app, we want to exit on fail to connect */ case LWSSSCS_DISCONNECTED: /* for this demo app, we want to exit after complete flow */ - lws_sul_schedule(context, 0, &m->sul, use_buffer_50ms, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&m->sul); interrupted = 1; break; case LWSSSCS_DESTROYING: - lws_sul_schedule(context, 0, &m->sul, use_buffer_50ms, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&m->sul); break; default: break; @@ -387,7 +389,11 @@ goto bail; } - if (read(fd, wav, wav_len) != (int)wav_len) { + if (read(fd, wav, +#if defined(WIN32) + (unsigned int) +#endif + wav_len) != (int)wav_len) { lwsl_err("%s: failed to read wav\n", __func__); goto bail; diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-avs/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-avs/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-avs/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-avs/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,90 +1,40 @@ +project(lws-minimal-secure-streams-avs C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-secure-streams-avs) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 requirements) +require_lws_config(LWS_WITH_SYS_STATE 1 requirements) if (requirements) add_executable(${SAMP} main.c avs.c) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() - if (LWS_WITH_SECURE_STREAMS_PROXY_API) + CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\ni#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)\n return 0;\n #else\n fail\n #endif\n return 0;\n}\n" HAS_LWS_WITH_SECURE_STREAMS_PROXY_API) + + if (HAS_LWS_WITH_SECURE_STREAMS_PROXY_API OR LWS_WITH_SECURE_STREAMS_PROXY_API) add_compile_options(-DLWS_SS_USE_SSPC) add_executable(${SAMP}-client main-client.c avs.c) if (websockets_shared) - target_link_libraries(${SAMP}-client websockets_shared) + target_link_libraries(${SAMP}-client websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP}-client websockets_shared) else() - target_link_libraries(${SAMP}-client websockets) + target_link_libraries(${SAMP}-client websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-avs/main.c libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-avs/main.c --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-avs/main.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-avs/main.c 2020-12-01 17:40:26.000000000 +0000 @@ -195,6 +195,9 @@ "\"http_auth_preamble\":" "\"Bearer \"," "\"http_multipart_name\":" "\"metadata\"," "\"http_mime_content_type\":" "\"application/json; charset=UTF-8\"," +#if 1 + "\"http_multipart_ss_in\":" "true," +#endif "\"rideshare\":" "\"avs_audio\"," "\"retry\":" "\"default\"," "\"plugins\":" "[]," @@ -211,6 +214,9 @@ "\"plugins\":" "[]," "\"tls\":" "true," "\"h2q_oflow_txcr\":" "true," +#if 1 + "\"http_multipart_ss_in\":" "true," +#endif "\"http_auth_header\":" "\"authorization:\"," "\"http_auth_preamble\":" "\"Bearer \"," "\"http_multipart_name\":" "\"audio\"," diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-client-tx/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-client-tx/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-client-tx/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-client-tx/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,67 +1,13 @@ +project(lws-minimal-secure-streams-client-tx C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-secure-streams-client-tx) set(SRCS minimal-secure-streams-client-tx.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) @@ -73,9 +19,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-client-tx/minimal-secure-streams-client-tx.c libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-client-tx/minimal-secure-streams-client-tx.c --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-client-tx/minimal-secure-streams-client-tx.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-client-tx/minimal-secure-streams-client-tx.c 2020-12-01 17:40:26.000000000 +0000 @@ -112,8 +112,7 @@ lws_sul_schedule(context, 0, &m->sul, txcb, RATE_US); break; case LWSSSCS_DISCONNECTED: - lws_sul_schedule(context, 0, &m->sul, txcb, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&m->sul); break; case LWSSSCS_ALL_RETRIES_FAILED: /* if we're out of retries, we want to close the app and FAIL */ diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-metadata/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-metadata/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-metadata/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-metadata/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,91 +1,40 @@ -project(minimal-secure-streams-metadata) +project(lws-minimal-secure-streams-metadata C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-secure-streams-metadata) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 requirements) +require_lws_config(LWS_WITH_SYS_STATE 1 requirements) if (requirements) add_executable(${SAMP} minimal-secure-streams.c) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() - if (LWS_WITH_SECURE_STREAMS_PROXY_API) + CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\ni#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)\n return 0;\n #else\n fail\n #endif\n return 0;\n}\n" HAS_LWS_WITH_SECURE_STREAMS_PROXY_API) + + if (HAS_LWS_WITH_SECURE_STREAMS_PROXY_API OR LWS_WITH_SECURE_STREAMS_PROXY_API) add_compile_options(-DLWS_SS_USE_SSPC) add_executable(${SAMP}-client minimal-secure-streams.c) if (websockets_shared) - target_link_libraries(${SAMP}-client websockets_shared) + target_link_libraries(${SAMP}-client websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP}-client websockets_shared) else() - target_link_libraries(${SAMP}-client websockets) + target_link_libraries(${SAMP}-client websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-metadata/minimal-secure-streams.c libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-metadata/minimal-secure-streams.c --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-metadata/minimal-secure-streams.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-metadata/minimal-secure-streams.c 2020-12-01 17:40:26.000000000 +0000 @@ -40,6 +40,7 @@ static int interrupted, bad = 1, force_cpd_fail_portal, force_cpd_fail_no_internet; static lws_state_notify_link_t nl; +static const char *server_name_or_url = "warmcat.com"; /* * If the -proxy app is fulfilling our connection, then we don't need to have @@ -223,7 +224,9 @@ switch (state) { case LWSSSCS_CREATING: - lws_ss_set_metadata(m->ss, "servername", "warmcat.com", 11); + lwsl_notice("%s: CREATING: setting servername metadata to %s\n", + __func__, server_name_or_url); + lws_ss_set_metadata(m->ss, "servername", server_name_or_url, strlen(server_name_or_url)); lws_ss_client_connect(m->ss); break; case LWSSSCS_ALL_RETRIES_FAILED: @@ -296,6 +299,7 @@ { struct lws_context_creation_info info; struct lws_context *context; + const char *p; int n = 0; signal(SIGINT, sigint_handler); @@ -318,30 +322,30 @@ #if defined(LWS_SS_USE_SSPC) info.protocols = lws_sspc_protocols; - { - const char *p; - /* connect to ssproxy via UDS by default, else via - * tcp connection to this port */ - if ((p = lws_cmdline_option(argc, argv, "-p"))) - info.ss_proxy_port = atoi(p); - - /* UDS "proxy.ss.lws" in abstract namespace, else this socket - * path; when -p given this can specify the network interface - * to bind to */ - if ((p = lws_cmdline_option(argc, argv, "-i"))) - info.ss_proxy_bind = p; - - /* if -p given, -a specifies the proxy address to connect to */ - if ((p = lws_cmdline_option(argc, argv, "-a"))) - info.ss_proxy_address = p; - } + /* connect to ssproxy via UDS by default, else via + * tcp connection to this port */ + if ((p = lws_cmdline_option(argc, argv, "-p"))) + info.ss_proxy_port = atoi(p); + + /* UDS "proxy.ss.lws" in abstract namespace, else this socket + * path; when -p given this can specify the network interface + * to bind to */ + if ((p = lws_cmdline_option(argc, argv, "-i"))) + info.ss_proxy_bind = p; + + /* if -p given, -a specifies the proxy address to connect to */ + if ((p = lws_cmdline_option(argc, argv, "-a"))) + info.ss_proxy_address = p; #else info.pss_policies_json = default_ss_policy; info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; #endif + if ((p = lws_cmdline_option(argc, argv, "-u"))) + server_name_or_url = p; + /* integrate us with lws system state management when context created */ nl.name = "app"; diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-policy2c/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-policy2c/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-policy2c/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-policy2c/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,28 @@ +project(lws-minimal-secure-streams-policy2c C) +cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) +include(CheckCSourceCompiles) +include(LwsCheckRequirements) + +set(SAMP lws-minimal-secure-streams-policy2c) + +set(requirements 1) +require_lws_config(LWS_ROLE_H1 1 requirements) +require_lws_config(LWS_ROLE_H2 1 requirements) +require_lws_config(LWS_ROLE_MQTT 1 requirements) +require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 requirements) + +if (requirements) + add_executable(${SAMP} minimal-secure-streams.c) + + if (websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) + add_dependencies(${SAMP} websockets_shared) + else() + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) + endif() + +endif() diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,573 @@ +/* + * lws-minimal-secure-streams-policy2c + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * + * This reads policy JSON on stdin and emits it as compileable + * C structs. + * + * It's useful if your platform is too space-constrained for a + * JSON policy and needs to build a static policy in C via + * LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY... this way you can + * still create and maintain the JSON policy but implement it directly + * as C structs in your code. + */ + +#include +#include +#include +#include +#include + +static int interrupted, bad = 1; + + +static void +sigint_handler(int sig) +{ + interrupted = 1; +} + +struct aggstr { + struct aggstr *next; + + const char *orig; + size_t offset; +}; + +static struct aggstr *rbomap, /* retry / backoff object map */ + *trustmap, /* trust store map */ + *certmap; /* x.509 cert map */ +static size_t last_offset; + + + +static const char * +purify_csymbol(const char *in, char *temp, size_t templen) +{ + const char *otemp = temp; + + assert (strlen(in) < templen); + + while (*in) { + if ((*in >= 'a' && *in <= 'z') || (*in >= 'A' && *in <= 'Z') || + (*in >= '0' && *in <= '9')) + *temp++ = *in; + else + *temp++ = '_'; + + in++; + } + + *temp = '\0'; + + return otemp; +} + +int main(int argc, const char **argv) +{ + const lws_ss_policy_t *pol, *lastpol = NULL; + struct lws_context_creation_info info; + size_t json_size = 0, est = 0; + struct lws_context *context; + char prev[128], curr[128]; + int unique_rbo = 0, m, n; + char buf[64], buf1[64]; + lws_ss_metadata_t *md; + struct aggstr *a, *a1; + + signal(SIGINT, sigint_handler); + + memset(&info, 0, sizeof info); + lws_cmdline_option_handle_builtin(argc, argv, &info); + + lwsl_user("LWS secure streams policy2c [-d]\n"); + + info.fd_limit_per_thread = 1 + 6 + 1; + info.port = CONTEXT_PORT_NO_LISTEN; + + info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | + LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + + /* create the context */ + + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + return 1; + } + + lws_ss_policy_parse_begin(context, 0); + + printf("/*\n * Autogenerated from the following JSON policy\n */\n\n#if 0\n"); + + do { + int m, n = read(0, buf, sizeof(buf)); + + if (n < 1) + break; + + m = lws_ss_policy_parse(context, (uint8_t *)buf, (size_t)n); + + printf("%.*s", n, buf); + json_size += n; + + if (m < 0 && m != LEJP_CONTINUE) { + lwsl_err("%s: policy parse failed... lws has WITH_ROLEs" + "for what's in the JSON?\n", __func__); + goto bail; + } + } while (1); + + printf("\n\n Original JSON size: %zu\n#endif\n\n", json_size); + + lwsl_notice("%s: parsed JSON\n", __func__); + + /* + * Well, this is fun, isn't it... we have parsed the JSON into in-memory + * policy objects, and it has set the context policy pointer to the head + * of those but has not set the new policy (which would free the x.509). + * + * We want to walk the streamtype list first discovering unique objects + * and strings referenced there and emitting them compactly as C data, + * and then second to emit the streamtype linked-list referring to those + * objects. + * + * For const strings, we aggregate them and avoid generating extra + * pointers by encoding the reference as &_lws_ss_staticpol_str[xxx] + * where xxx is the fixed offset in the aggregated monster-string. When + * doing that, we keep a map of original pointers to offsets. + * + * Although we want to minimize memory used by the emitted C, we don't + * have to sweat memory during this conversion since it's happening on a + * PC + */ + + pol = lws_ss_policy_get(context); + + while (pol) { + + /* + * Walk the metadata list gathering strings and issuing the + * C struct + */ + + md = pol->metadata; + + if (md) { + int idx = 0; + + printf("\nstatic const lws_ss_metadata_t "); + + prev[0] = '\0'; + md = pol->metadata; + while (md) { + + est += sizeof(lws_ss_metadata_t); + + lws_snprintf(curr, sizeof(curr), "_md_%s_%s", + purify_csymbol(pol->streamtype, buf, + sizeof(buf)), + purify_csymbol(md->name, buf1, + sizeof(buf1))); + + printf("%s = {\n", curr); + if (prev[0]) + printf("\t.next = (void *)&%s, \n", prev); + + printf("\t.name = \"%s\",\n", (const char *)md->name); + if (md->value) + printf("\t.value = (void *)\"%s\",\n", (const char *)md->value); + + printf("\t.length = %d,\n", idx++); // md->length); + + printf("}"); + if (md->next) + printf(",\n"); + + lws_strncpy(prev, curr, sizeof(prev)); + + md = md->next; + } + + printf(";\n\n"); + } + + /* + * Create unique retry policies... have we seen this guy? + */ + + if (pol->retry_bo) { + a = rbomap; + while (a) { + if (a->orig == (const char *)pol->retry_bo) + break; + + a = a->next; + } + + if (!a) { + + /* We haven't seen it before and need to create it */ + + a = malloc(sizeof(*a)); + if (!a) + goto bail; + a->next = rbomap; + a->offset = unique_rbo++; + a->orig = (const char *)pol->retry_bo; + rbomap = a; + + printf("static const uint32_t _rbo_bo_%zu[] = {\n", + a->offset); + for (n = 0; n < pol->retry_bo->retry_ms_table_count; n++) + printf(" %u, ", (unsigned int) + pol->retry_bo->retry_ms_table[n]); + + est += sizeof(uint32_t) * + pol->retry_bo->retry_ms_table_count; + + printf("\n};\nstatic const " + "lws_retry_bo_t _rbo_%zu = {\n", a->offset); + + printf("\t.retry_ms_table = _rbo_bo_%zu,\n", + a->offset); + printf("\t.retry_ms_table_count = %u,\n", + pol->retry_bo->retry_ms_table_count); + printf("\t.conceal_count = %u,\n", + pol->retry_bo->conceal_count); + printf("\t.secs_since_valid_ping = %u,\n", + pol->retry_bo->secs_since_valid_ping); + printf("\t.secs_since_valid_hangup = %u,\n", + pol->retry_bo->secs_since_valid_hangup); + printf("\t.jitter_percent = %u,\n", + pol->retry_bo->jitter_percent); + printf("};\n"); + + est += sizeof(lws_retry_bo_t); + } + } + + /* + * How about his trust store, it's new to us? + */ + + if (pol->trust.store) { + a = trustmap; + while (a) { + if (a->orig == (const char *)pol->trust.store) + break; + + a = a->next; + } + + if (!a) { + + /* it's new to us... */ + + a = malloc(sizeof(*a)); + if (!a) + goto bail; + a->next = trustmap; + a->offset = 0; /* don't care, just track seen */ + a->orig = (const char *)pol->trust.store; + trustmap = a; + + /* + * Have a look through his x.509 stack... + * any that're new to us? + */ + + for (n = 0; n < pol->trust.store->count; n++) { + if (!pol->trust.store->ssx509[n]) + continue; + a1 = certmap; + while (a1) { + if (a1->orig == (const char *)pol->trust.store->ssx509[n]) + break; + a1 = a1->next; + } + + if (!a1) { + /* + * This x.509 cert is new to us... + * let's capture the DER + */ + + a1 = malloc(sizeof(*a1)); + if (!a1) + goto bail; + a1->next = certmap; + a1->offset = 0; /* don't care, just track seen */ + a1->orig = (const char *)pol->trust.store->ssx509[n]; + certmap = a1; + + printf("static const uint8_t _ss_der_%s[] = {\n", + purify_csymbol(pol->trust.store->ssx509[n]->vhost_name, + buf, sizeof(buf))); + + for (m = 0; m < (int)pol->trust.store->ssx509[n]->ca_der_len; m++) { + if ((m & 7) == 0) + printf("\t/* 0x%3x */ ", m); + + printf("0x%02X, ", pol->trust.store->ssx509[n]->ca_der[m]); + if ((m & 7) == 7) + printf("\n"); + } + + printf("\n};\nstatic const lws_ss_x509_t _ss_x509_%s = {\n", + purify_csymbol(pol->trust.store->ssx509[n]->vhost_name, + buf, sizeof(buf))); + printf("\t.vhost_name = \"%s\",\n", pol->trust.store->ssx509[n]->vhost_name); + printf("\t.ca_der = _ss_der_%s,\n", + purify_csymbol(pol->trust.store->ssx509[n]->vhost_name, + buf, sizeof(buf))); + printf("\t.ca_der_len = %zu,\n", pol->trust.store->ssx509[n]->ca_der_len); + printf("};\n"); + + est += sizeof(lws_ss_x509_t) + pol->trust.store->ssx509[n]->ca_der_len; + } + + } + + + printf("static const lws_ss_trust_store_t _ss_ts_%s = {\n", + purify_csymbol(pol->trust.store->name, + buf, sizeof(buf))); + + printf("\t.name = \"%s\",\n", pol->trust.store->name); + printf("\t.ssx509 = {\n"); + + for (n = pol->trust.store->count - 1; n >= 0 ; n--) + printf("\t\t&_ss_x509_%s,\n", + pol->trust.store->ssx509[n]->vhost_name); + + printf("\t}\n};\n"); + + est += sizeof(lws_ss_trust_store_t); + + } + } + + pol = pol->next; + } + + + + /* + * The streamtypes + */ + + pol = lws_ss_policy_get(context); + + printf("\nstatic const lws_ss_policy_t "); + prev[0] = '\0'; + + while (pol) { + + est += sizeof(*pol); + + lws_snprintf(curr, sizeof(curr), "_ssp_%s", + purify_csymbol(pol->streamtype, buf, sizeof(buf))); + printf("%s = {\n", curr); + + + if (prev[0]) + printf("\t.next = (void *)&%s,\n", prev); + + printf("\t.streamtype = \"%s\",\n", pol->streamtype); + if (pol->endpoint) + printf("\t.endpoint = \"%s\",\n", pol->endpoint); + if (pol->rideshare_streamtype) + printf("\t.rideshare_streamtype = \"%s\",\n", + pol->rideshare_streamtype); + if (pol->payload_fmt) + printf("\t.payload_fmt = \"%s\",\n", + pol->payload_fmt); + if (pol->socks5_proxy) + printf("\t.socks5_proxy = \"%s\",\n", + pol->socks5_proxy); + + { + lws_ss_metadata_t *nv = pol->metadata, *last = NULL; + + while (nv) { + last = nv; + nv = nv->next; + } + if (pol->metadata) + printf("\t.metadata = (void *)&_md_%s_%s,\n", + purify_csymbol(pol->streamtype, buf, sizeof(buf)), + purify_csymbol(last->name, buf1, sizeof(buf1))); + } + + + switch (pol->protocol) { + case LWSSSP_H1: + case LWSSSP_H2: + case LWSSSP_WS: + + printf("\t.u = {\n\t\t.http = {\n"); + + if (pol->u.http.method) + printf("\t\t\t.method = \"%s\",\n", + pol->u.http.method); + if (pol->u.http.url) + printf("\t\t\t.url = \"%s\",\n", + pol->u.http.url); + if (pol->u.http.multipart_name) + printf("\t\t\t.multipart_name = \"%s\",\n", + pol->u.http.multipart_name); + if (pol->u.http.multipart_filename) + printf("\t\t\t.multipart_filename = \"%s\",\n", + pol->u.http.multipart_filename); + if (pol->u.http.multipart_content_type) + printf("\t\t\t.multipart_content_type = \"%s\",\n", + pol->u.http.multipart_content_type); + if (pol->u.http.auth_preamble) + printf("\t\t\t.auth_preamble = \"%s\",\n", + pol->u.http.auth_preamble); + + if (pol->u.http.blob_header[0]) { + printf("\t\t\t.blob_header = {\n"); + for (n = 0; n < (int)LWS_ARRAY_SIZE(pol->u.http.blob_header); n++) + if (pol->u.http.blob_header[n]) + printf("\t\t\t\t\"%s\",\n", + pol->u.http.blob_header[n]); + + printf("\t\t\t},\n"); + } + + if (pol->protocol == LWSSSP_WS) { + printf("\t\t\t.u = {\n\t\t\t\t.ws = {\n"); + if (pol->u.http.u.ws.subprotocol) + printf("\t\t\t\t\t.subprotocol = \"%s\",\n", + pol->u.http.u.ws.subprotocol); + printf("\t\t\t\t\t.binary = %u\n", pol->u.http.u.ws.binary); + printf("\t\t\t\t}\n\t\t\t},\n"); + } + + if (pol->u.http.resp_expect) + printf("\t\t\t.resp_expect = %u,\n", pol->u.http.resp_expect); + if (pol->u.http.fail_redirect) + printf("\t\t\t.fail_redirect = %u,\n", pol->u.http.fail_redirect); + + printf("\t\t}\n\t},\n"); + + break; + case LWSSSP_MQTT: + + printf("\t.u = {\n\t\t.mqtt = {\n"); + + if (pol->u.mqtt.topic) + printf("\t\t\t.topic = \"%s\",\n", + pol->u.mqtt.topic); + if (pol->u.mqtt.subscribe) + printf("\t\t\t.subscribe = \"%s\",\n", + pol->u.mqtt.subscribe); + if (pol->u.mqtt.will_topic) + printf("\t\t\t.will_topic = \"%s\",\n", + pol->u.mqtt.will_topic); + if (pol->u.mqtt.will_message) + printf("\t\t\t.will_message = \"%s\",\n", + pol->u.mqtt.will_message); + + if (pol->u.mqtt.keep_alive) + printf("\t\t\t.keep_alive = %u,\n", + pol->u.mqtt.keep_alive); + if (pol->u.mqtt.qos) + printf("\t\t\t.qos = %u,\n", + pol->u.mqtt.qos); + if (pol->u.mqtt.clean_start) + printf("\t\t\t.clean_start = %u,\n", + pol->u.mqtt.clean_start); + if (pol->u.mqtt.will_qos) + printf("\t\t\t.will_qos = %u,\n", + pol->u.mqtt.will_qos); + if (pol->u.mqtt.will_retain) + printf("\t\t\t.will_retain = %u,\n", + pol->u.mqtt.will_retain); + + printf("\t\t}\n\t},\n"); + + break; + default: + lwsl_err("%s: unknown ss protocol index %d\n", __func__, + pol->protocol); + goto bail; + } + +#if 0 + const lws_ss_trust_store_t *trust_store; /**< CA certs needed for conn + validation, only set between policy parsing and vhost creation */ +#endif + + if (pol->retry_bo) { + a = rbomap; + while (a) { + if (a->orig == (const char *)pol->retry_bo) + break; + + a = a->next; + } + if (!a) + goto bail; + + printf("\t.retry_bo = &_rbo_%zu,\n", a->offset); + } + + if (pol->timeout_ms) + printf("\t.timeout_ms = %u,\n", pol->timeout_ms); + if (pol->flags) + printf("\t.flags = 0x%x,\n", pol->flags); + if (pol->port) + printf("\t.port = %u,\n", pol->port); + if (pol->metadata_count) + printf("\t.metadata_count = %u,\n", pol->metadata_count); + printf("\t.protocol = %u,\n", pol->protocol); + if (pol->client_cert) + printf("\t.client_cert = %u,\n", pol->client_cert); + + if (pol->trust.store) + printf("\t.trust = {.store = &_ss_ts_%s},\n", + purify_csymbol(pol->trust.store->name, + buf, sizeof(buf))); + + + printf("}"); + if (pol->next) + printf(",\n"); + + lws_strncpy(prev, curr, sizeof(prev)); + + lastpol = pol; + + pol = pol->next; + } + + printf(";\n"); + if (lastpol) + printf("#define _ss_static_policy_entry _ssp_%s\n", + purify_csymbol(lastpol->streamtype, buf, sizeof(buf))); + + est += last_offset; + + printf("/* estimated footprint %zu (when sizeof void * = %zu) */\n", + est, sizeof(void *)); + + lws_ss_policy_parse_abandon(context); + bad = 0; + +bail: + + + lws_context_destroy(context); + + lwsl_user("Completed: %s\n", bad ? "failed" : "OK"); + + return bad; +} diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-policy2c/README.md libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-policy2c/README.md --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-policy2c/README.md 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-policy2c/README.md 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,49 @@ +# lws minimal secure streams policy2c + +This application parses a JSON policy passed on stdin and emits the +equivalent of it in C structs ready for compilation. + +This is useful in the case your platform doesn't use a dynamic JSON +policy and is space-constrained, you can still form and maintain the +policy in JSON, but with this utility convert it into compileable C. + +**Notice** this depends on LWS_ROLE_H1, LWS_ROLE_H2, LWS_ROLE_WS and +LWS_ROLE_MQTT build of lws, since it has to be able to work with any kind +of policy content. + +## build + +``` + $ cmake . && make +``` + +## usage + +Commandline option|Meaning +---|--- +-d |Debug verbosity in decimal, eg, -d15 + +``` +$ cat mypolicy.json | lws-minimal-secure-streams-policy2c + +(on stdout) + +static const uint32_t _rbo_bo_0[] = { + 1000, 2000, 3000, 5000, 10000, +}; +static const lws_retry_bo_t _rbo_0 = { + .retry_ms_table = _rbo_bo_0, + .retry_ms_table_count = 5, + .conceal_count = 5, + .secs_since_valid_ping = 30, + .secs_since_valid_hangup = 35, + .jitter_percent = 20, +}; +static const uint8_t _ss_der_amazon_root_ca_1[] = { + /* 0x 0 */ 0x30, 0x82, 0x03, 0x41, 0x30, 0x82, 0x02, 0x29, + /* 0x 8 */ 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x13, 0x06, + /* 0x 10 */ 0x6C, 0x9F, 0xCF, 0x99, 0xBF, 0x8C, 0x0A, 0x39, + /* 0x 18 */ 0xE2, 0xF0, 0x78, 0x8A, 0x43, 0xE6, 0x96, 0x36, + /* 0x 20 */ 0x5B, 0xCA, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, +... +``` diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-post/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-post/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-post/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-post/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,49 @@ +project(lws-minimal-secure-streams-post C) +cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) +include(CheckCSourceCompiles) +include(LwsCheckRequirements) + +set(SAMP lws-minimal-secure-streams-post) + +set(requirements 1) +require_lws_config(LWS_ROLE_H1 1 requirements) +require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 requirements) +require_lws_config(LWS_WITH_SYS_STATE 1 requirements) + +if (requirements) + add_executable(${SAMP} minimal-secure-streams-post.c) + + if (LWS_CTEST_INTERNET_AVAILABLE) + add_test(NAME sspost-warmcat COMMAND lws-minimal-secure-streams-post) + set_tests_properties(sspost-warmcat + PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/secure-streams/minimal-secure-streams-post + TIMEOUT 20) + endif() + + if (websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) + add_dependencies(${SAMP} websockets_shared) + else() + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) + endif() + + CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\ni#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)\n return 0;\n #else\n fail\n #endif\n return 0;\n}\n" HAS_LWS_WITH_SECURE_STREAMS_PROXY_API) + + if (HAS_LWS_WITH_SECURE_STREAMS_PROXY_API OR LWS_WITH_SECURE_STREAMS_PROXY_API) + add_compile_options(-DLWS_SS_USE_SSPC) + + add_executable(${SAMP}-client minimal-secure-streams-post.c) + if (websockets_shared) + target_link_libraries(${SAMP}-client websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) + add_dependencies(${SAMP}-client websockets_shared) + else() + target_link_libraries(${SAMP}-client websockets ${LIBWEBSOCKETS_DEP_LIBS}) + endif() + endif() + +endif() diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-post/minimal-secure-streams-post.c libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-post/minimal-secure-streams-post.c --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-post/minimal-secure-streams-post.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-post/minimal-secure-streams-post.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,611 @@ +/* + * lws-minimal-secure-streams-post + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * + * This demonstrates a minimal http client using secure streams api. + * + * It visits https://warmcat.com/ and receives the html page there. + * + * This example is built two different ways from the same source... one includes + * the policy everything needed to fulfil the stream directly. The other -client + * variant has no policy itself and some other minor init changes, and connects + * to the -proxy example to actually get the connection done. + * + * In the -client build case, the example does not even init the tls libraries + * since the proxy part will take care of all that. + */ + +#include +#include +#include +#include + +/* + * uncomment to force network traffic through 127.0.0.1:1080 + * + * On your local machine, you can run a SOCKS5 proxy like this + * + * $ ssh -N -D 0.0.0.0:1080 localhost -v + * + * If enabled, this also fetches a remote policy that also + * specifies that all traffic should go through the remote + * proxy. + */ +// #define VIA_LOCALHOST_SOCKS + +static int interrupted, bad = 1, force_cpd_fail_portal, + force_cpd_fail_no_internet; +static unsigned int timeout_ms = 3000; +static lws_state_notify_link_t nl; + +static const char * const postbody = + "--boundary\r\n" + "Content-Disposition: form-data; name=\"text\"\r\n" + "\r\n" + "value1\r\n" + "--boundary\r\n" + "Content-Disposition: form-data; " + "name=\"field2\"; filename=\"example.txt\"\r\n" + "\r\n" + "value2\r\n" + "00-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "01-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "02-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "03-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "04-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "05-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "06-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "07-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "08-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "09-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "0a-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "0b-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "0c-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "0d-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "0e-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "0f-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "10-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "11-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "12-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "13-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "14-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "15-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "16-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "17-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "18-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "19-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "1a-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "1b-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "1c-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "1d-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "1e-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "1f-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "20-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "21-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "22-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "23-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "24-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "25-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "26-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "27-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "28-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "29-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "2a-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "2b-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "2c-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "2d-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "2e-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "2f-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "30-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "31-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "32-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "33-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "34-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "35-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "36-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "37-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "38-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "39-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "3a-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "3b-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "3c-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "3d-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "3e-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "3f-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "40-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "41-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "42-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "43-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "44-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "45-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "46-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "47-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "48-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "49-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "4a-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "4b-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "4c-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "4d-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "4e-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "4f-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n" + "--boundary--\r\n"; + +/* + * If the -proxy app is fulfilling our connection, then we don't need to have + * the policy in the client. + * + * When we build with LWS_SS_USE_SSPC, the apis hook up to a proxy process over + * a Unix Domain Socket. To test that, you need to separately run the + * ./lws-minimal-secure-streams-proxy test app on the same machine. + */ + +#if !defined(LWS_SS_USE_SSPC) +static const char * const default_ss_policy = + "{" + "\"release\":" "\"01234567\"," + "\"product\":" "\"myproduct\"," + "\"schema-version\":" "1," +#if defined(VIA_LOCALHOST_SOCKS) + "\"via-socks5\":" "\"127.0.0.1:1080\"," +#endif + + "\"retry\": [" /* named backoff / retry strategies */ + "{\"default\": {" + "\"backoff\": [" "1000," + "2000," + "3000," + "5000," + "10000" + "]," + "\"conceal\":" "5," + "\"jitterpc\":" "20," + "\"svalidping\":" "30," + "\"svalidhup\":" "35" + "}}" + "]," + "\"certs\": [" /* named individual certificates in BASE64 DER */ + /* + * Let's Encrypt certs for warmcat.com / libwebsockets.org + * + * We fetch the real policy from there using SS and switch to + * using that. + */ + "{\"isrg_root_x1\": \"" /* ISRG ROOT X1 */ + "MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw" + "TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh" + "cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4" + "WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu" + "ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY" + "MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc" + "h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+" + "0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U" + "A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW" + "T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH" + "B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC" + "B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv" + "KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn" + "OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn" + "jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw" + "qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI" + "rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV" + "HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq" + "hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL" + "ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ" + "3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK" + "NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5" + "ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur" + "TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC" + "jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc" + "oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq" + "4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA" + "mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d" + "emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=" + "\"}," + "{\"LEX3_isrg_root_x1\": \"" /* LE X3 signed by ISRG X1 root */ + "MIIFjTCCA3WgAwIBAgIRANOxciY0IzLc9AUoUSrsnGowDQYJKoZIhvcNAQELBQAw" + "TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh" + "cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTYxMDA2MTU0MzU1" + "WhcNMjExMDA2MTU0MzU1WjBKMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg" + "RW5jcnlwdDEjMCEGA1UEAxMaTGV0J3MgRW5jcnlwdCBBdXRob3JpdHkgWDMwggEi" + "MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCc0wzwWuUuR7dyXTeDs2hjMOrX" + "NSYZJeG9vjXxcJIvt7hLQQWrqZ41CFjssSrEaIcLo+N15Obzp2JxunmBYB/XkZqf" + "89B4Z3HIaQ6Vkc/+5pnpYDxIzH7KTXcSJJ1HG1rrueweNwAcnKx7pwXqzkrrvUHl" + "Npi5y/1tPJZo3yMqQpAMhnRnyH+lmrhSYRQTP2XpgofL2/oOVvaGifOFP5eGr7Dc" + "Gu9rDZUWfcQroGWymQQ2dYBrrErzG5BJeC+ilk8qICUpBMZ0wNAxzY8xOJUWuqgz" + "uEPxsR/DMH+ieTETPS02+OP88jNquTkxxa/EjQ0dZBYzqvqEKbbUC8DYfcOTAgMB" + "AAGjggFnMIIBYzAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADBU" + "BgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEBATAwMC4GCCsGAQUFBwIB" + "FiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQub3JnMB0GA1UdDgQWBBSo" + "SmpjBH3duubRObemRWXv86jsoTAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8vY3Js" + "LnJvb3QteDEubGV0c2VuY3J5cHQub3JnMHIGCCsGAQUFBwEBBGYwZDAwBggrBgEF" + "BQcwAYYkaHR0cDovL29jc3Aucm9vdC14MS5sZXRzZW5jcnlwdC5vcmcvMDAGCCsG" + "AQUFBzAChiRodHRwOi8vY2VydC5yb290LXgxLmxldHNlbmNyeXB0Lm9yZy8wHwYD" + "VR0jBBgwFoAUebRZ5nu25eQBc4AIiMgaWPbpm24wDQYJKoZIhvcNAQELBQADggIB" + "ABnPdSA0LTqmRf/Q1eaM2jLonG4bQdEnqOJQ8nCqxOeTRrToEKtwT++36gTSlBGx" + "A/5dut82jJQ2jxN8RI8L9QFXrWi4xXnA2EqA10yjHiR6H9cj6MFiOnb5In1eWsRM" + "UM2v3e9tNsCAgBukPHAg1lQh07rvFKm/Bz9BCjaxorALINUfZ9DD64j2igLIxle2" + "DPxW8dI/F2loHMjXZjqG8RkqZUdoxtID5+90FgsGIfkMpqgRS05f4zPbCEHqCXl1" + "eO5HyELTgcVlLXXQDgAWnRzut1hFJeczY1tjQQno6f6s+nMydLN26WuU4s3UYvOu" + "OsUxRlJu7TSRHqDC3lSE5XggVkzdaPkuKGQbGpny+01/47hfXXNB7HntWNZ6N2Vw" + "p7G6OfY+YQrZwIaQmhrIqJZuigsrbe3W+gdn5ykE9+Ky0VgVUsfxo52mwFYs1JKY" + "2PGDuWx8M6DlS6qQkvHaRUo0FMd8TsSlbF0/v965qGFKhSDeQoMpYnwcmQilRh/0" + "ayLThlHLN81gSkJjVrPI0Y8xCVPB4twb1PFUd2fPM3sA1tJ83sZ5v8vgFv2yofKR" + "PB0t6JzUA81mSqM3kxl5e+IZwhYAyO0OTg3/fs8HqGTNKd9BqoUwSRBzp06JMg5b" + "rUCGwbCUDI0mxadJ3Bz4WxR6fyNpBK2yAinWEsikxqEt" + "\"}" + "]," + "\"trust_stores\": [" /* named cert chains */ + "{" + "\"name\": \"le_via_isrg\"," + "\"stack\": [" + "\"isrg_root_x1\"," + "\"LEX3_isrg_root_x1\"" + "]" + "}" + "]," + "\"s\": [" + /* + * "fetch_policy" decides from where the real policy + * will be fetched, if present. Otherwise the initial + * policy is treated as the whole, hardcoded, policy. + */ + "{\"fetch_policy\": {" + "\"endpoint\":" "\"warmcat.com\"," + "\"port\":" "443," + "\"protocol\":" "\"h1\"," + "\"http_method\":" "\"GET\"," +#if defined(VIA_LOCALHOST_SOCKS) + "\"http_url\":" "\"policy/minimal-proxy-socks.json\"," +#else + "\"http_url\":" "\"policy/minimal-proxy.json\"," +#endif + "\"tls\":" "true," + "\"opportunistic\":" "true," + "\"retry\":" "\"default\"," + "\"tls_trust_store\":" "\"le_via_isrg\"" + "}},{" + /* + * "captive_portal_detect" describes + * what to do in order to check if the path to + * the Internet is being interrupted by a + * captive portal. If there's a larger policy + * fetched from elsewhere, it should also include + * this since it needs to be done at least after + * every DHCP acquisition + */ + "\"captive_portal_detect\": {" + "\"endpoint\": \"connectivitycheck.android.com\"," + "\"http_url\": \"generate_204\"," + "\"port\": 80," + "\"protocol\": \"h1\"," + "\"http_method\": \"GET\"," + "\"opportunistic\": true," + "\"http_expect\": 204," + "\"http_fail_redirect\": true" + "}}" + "]}" +; + +#endif + +typedef struct myss { + struct lws_ss_handle *ss; + void *opaque_data; + /* ... application specific state ... */ + lws_sorted_usec_list_t sul; + + size_t pos; + size_t len; +} myss_t; + +#if !defined(LWS_SS_USE_SSPC) + +static const char *canned_root_token_payload = + "grant_type=refresh_token" + "&refresh_token=Atzr|IwEBIJedGXjDqsU_vMxykqOMg" + "SHfYe3CPcedueWEMWSDMaDnEmiW8RlR1Kns7Cb4B-TOSnqp7ifVsY4BMY2B8tpHfO39XP" + "zfu9HapGjTR458IyHX44FE71pWJkGZ79uVBpljP4sazJuk8XS3Oe_yLnm_DIO6fU1nU3Y" + "0flYmsOiOAQE_gRk_pdlmEtHnpMA-9rLw3mkY5L89Ty9kUygBsiFaYatouROhbsTn8-jW" + "k1zZLUDpT6ICtBXSnrCIg0pUbZevPFhTwdXd6eX-u4rq0W-XaDvPWFO7au-iPb4Zk5eZE" + "iX6sissYrtNmuEXc2uHu7MnQO1hHCaTdIO2CANVumf-PHSD8xseamyh04sLV5JgFzY45S" + "KvKMajiUZuLkMokOx86rjC2Hdkx5DO7G-dbG1ufBDG-N79pFMSs7Ck5pc283IdLoJkCQc" + "AGvTX8o8I29QqkcGou-9TKhOJmpX8As94T61ok0UqqEKPJ7RhfQHHYdCtsdwxgvfVr9qI" + "xL_hDCcTho8opCVX-6QhJHl6SQFlTw13" + "&client_id=" + "amzn1.application-oa2-client.4823334c434b4190a2b5a42c07938a2d"; + +#endif + +/* secure streams payload interface */ + +static int +myss_rx(void *userobj, const uint8_t *buf, size_t len, int flags) +{ +// myss_t *m = (myss_t *)userobj; + + lwsl_user("%s: len %d, flags: %d\n", __func__, (int)len, flags); + lwsl_hexdump_info(buf, len); + + /* + * If we received the whole message, for our example it means + * we are done. + */ + if (flags & LWSSS_FLAG_EOM) { + bad = 0; + interrupted = 1; + } + + return 0; +} + +static int +myss_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, size_t *len, + int *flags) +{ + myss_t *m = (myss_t *)userobj; + + if (m->pos == m->len) + return LWSSSSRET_TX_DONT_SEND; + + if (m->len - m->pos < *len) + *len = m->len - m->pos; + + *flags = 0; + if (!m->pos) + *flags |= LWSSS_FLAG_SOM; + + memcpy(buf, postbody + m->pos, *len); + + m->pos += *len; + if (m->pos == m->len) + *flags |= LWSSS_FLAG_EOM; + else + lws_ss_request_tx(m->ss); + + lwsl_notice("%s: write %d flags %d\n", __func__, (int)*len, (int)*flags); + + return 0; +} + +static int +myss_state(void *userobj, void *sh, lws_ss_constate_t state, + lws_ss_tx_ordinal_t ack) +{ + myss_t *m = (myss_t *)userobj; + + lwsl_user("%s: h %p, %s, ord 0x%x\n", __func__, m->ss, + lws_ss_state_name(state), (unsigned int)ack); + + switch (state) { + case LWSSSCS_CREATING: + + /* + * CREATING is only coming after we have asked the upstream + * proxy to create the stream and it has been allowed. + */ + + lws_ss_set_metadata(m->ss, "ctype", + "multipart/form-data;boundary=\"boundary\"", + 39); + + /* provide a hint about the payload size */ + m->pos = 0; + m->len = strlen(postbody); + lws_ss_request_tx_len(m->ss, (unsigned long)strlen(postbody)); + break; + case LWSSSCS_CONNECTED: + lws_ss_request_tx(m->ss); + break; + case LWSSSCS_ALL_RETRIES_FAILED: + /* if we're out of retries, we want to close the app and FAIL */ + interrupted = 1; + break; + case LWSSSCS_QOS_ACK_REMOTE: + lwsl_notice("%s: LWSSSCS_QOS_ACK_REMOTE\n", __func__); + break; + + case LWSSSCS_TIMEOUT: + lwsl_notice("%s: LWSSSCS_TIMEOUT\n", __func__); + break; + default: + break; + } + + return 0; +} + +static int +app_system_state_nf(lws_state_manager_t *mgr, lws_state_notify_link_t *link, + int current, int target) +{ + struct lws_context *context = lws_system_context_from_system_mgr(mgr); +#if !defined(LWS_SS_USE_SSPC) + + lws_system_blob_t *ab = lws_system_get_blob(context, + LWS_SYSBLOB_TYPE_AUTH, 1 /* AUTH_IDX_ROOT */); + size_t size; +#endif + + /* + * For the things we care about, let's notice if we are trying to get + * past them when we haven't solved them yet, and make the system + * state wait while we trigger the dependent action. + */ + switch (target) { + +#if !defined(LWS_SS_USE_SSPC) + + case LWS_SYSTATE_REGISTERED: + size = lws_system_blob_get_size(ab); + if (size) + break; + + /* let's register our canned root token so auth can use it */ + lws_system_blob_direct_set(ab, + (const uint8_t *)canned_root_token_payload, + strlen(canned_root_token_payload)); + break; + +#endif + + case LWS_SYSTATE_OPERATIONAL: + if (current == LWS_SYSTATE_OPERATIONAL) { + lws_ss_info_t ssi; + + /* We're making an outgoing secure stream ourselves */ + + memset(&ssi, 0, sizeof(ssi)); + ssi.handle_offset = offsetof(myss_t, ss); + ssi.opaque_user_data_offset = offsetof(myss_t, + opaque_data); + ssi.rx = myss_rx; + ssi.tx = myss_tx; + ssi.state = myss_state; + ssi.user_alloc = sizeof(myss_t); + ssi.streamtype = "minpost"; + + if (lws_ss_create(context, 0, &ssi, NULL, NULL, + NULL, NULL)) { + lwsl_err("%s: failed to create secure stream\n", + __func__); + return -1; + } + } + break; + } + + return 0; +} + +static lws_state_notify_link_t * const app_notifier_list[] = { + &nl, NULL +}; + +static void +sigint_handler(int sig) +{ + interrupted = 1; +} + +int main(int argc, const char **argv) +{ + struct lws_context_creation_info info; + struct lws_context *context; + const char *p; + int n = 0; + + signal(SIGINT, sigint_handler); + + memset(&info, 0, sizeof info); + lws_cmdline_option_handle_builtin(argc, argv, &info); + + lwsl_user("LWS secure streams test client [-d]\n"); + + /* these options are mutually exclusive if given */ + + if (lws_cmdline_option(argc, argv, "--force-portal")) + force_cpd_fail_portal = 1; + + if (lws_cmdline_option(argc, argv, "--force-no-internet")) + force_cpd_fail_no_internet = 1; + + if ((p = lws_cmdline_option(argc, argv, "--timeout_ms"))) + timeout_ms = atoi(p); + + info.fd_limit_per_thread = 1 + 6 + 1; + info.port = CONTEXT_PORT_NO_LISTEN; +#if defined(LWS_SS_USE_SSPC) + info.protocols = lws_sspc_protocols; + { + const char *p; + + /* connect to ssproxy via UDS by default, else via + * tcp connection to this port */ + if ((p = lws_cmdline_option(argc, argv, "-p"))) + info.ss_proxy_port = atoi(p); + + /* UDS "proxy.ss.lws" in abstract namespace, else this socket + * path; when -p given this can specify the network interface + * to bind to */ + if ((p = lws_cmdline_option(argc, argv, "-i"))) + info.ss_proxy_bind = p; + + /* if -p given, -a specifies the proxy address to connect to */ + if ((p = lws_cmdline_option(argc, argv, "-a"))) + info.ss_proxy_address = p; + } +#else + info.pss_policies_json = default_ss_policy; + info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | + LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; +#endif +#if defined(LWS_WITH_DETAILED_LATENCY) + info.detailed_latency_cb = lws_det_lat_plot_cb; + info.detailed_latency_filepath = "/tmp/lws-latency-ssproxy"; +#endif + + /* integrate us with lws system state management when context created */ + + nl.name = "app"; + nl.notify_cb = app_system_state_nf; + info.register_notifier_list = app_notifier_list; + + /* create the context */ + + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + return 1; + } + +#if !defined(LWS_SS_USE_SSPC) + /* + * If we're being a proxied client, the proxy does all this + */ + + /* + * Set the related lws_system blobs + * + * ...direct_set() sets a pointer, so the thing pointed to has to have + * a suitable lifetime, eg, something that already exists on the heap or + * a const string in .rodata like this + */ + + lws_system_blob_direct_set(lws_system_get_blob(context, + LWS_SYSBLOB_TYPE_DEVICE_SERIAL, 0), + (const uint8_t *)"SN12345678", 10); + lws_system_blob_direct_set(lws_system_get_blob(context, + LWS_SYSBLOB_TYPE_DEVICE_FW_VERSION, 0), + (const uint8_t *)"v0.01", 5); + + /* + * ..._heap_append() appends to a buflist kind of arrangement on heap, + * just one block is fine, otherwise it will concatenate the fragments + * in the order they were appended (and take care of freeing them at + * context destroy time). ..._heap_empty() is also available to remove + * everything that was already allocated. + * + * Here we use _heap_append() just so it's tested as well as direct set. + */ + + lws_system_blob_heap_append(lws_system_get_blob(context, + LWS_SYSBLOB_TYPE_DEVICE_TYPE, 0), + (const uint8_t *)"spacerocket", 11); +#endif + + /* the event loop */ + + while (n >= 0 && !interrupted) + n = lws_service(context, 0); + + lws_context_destroy(context); + + lwsl_user("Completed: %s\n", bad ? "failed" : "OK"); + + return bad; +} diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-post/README.md libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-post/README.md --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-post/README.md 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-post/README.md 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,66 @@ +# lws minimal secure streams + +The application goes to https://warmcat.com and reads index.html there. + +It does it using Secure Streams... the main code in minimal-secure-streams.c +just sets up the context and opens a secure stream of type "mintest". + +The handler for state changes and payloads for "mintest" is in ss-myss.c + +The information about how a "mintest" stream should connect and the +protocol it uses is kept separated in policy-database.c + +## build + +``` + $ cmake . && make +``` + +## usage + +Commandline option|Meaning +---|--- +-d |Debug verbosity in decimal, eg, -d15 +-f| Force connecting to the wrong endpoint to check backoff retry flow +-p| Run as proxy server for clients to connect to over unix domain socket +--force-portal|Force the SS Captive Portal Detection to feel it's behind a portal +--force-no-internet|Force the SS Captive Portal Detection to feel it can't reach the internet + +``` +[2019/08/12 07:16:11:0045] USR: LWS minimal secure streams [-d] [-f] +[2019/08/12 07:16:12:6102] USR: myss_state: LWSSSCS_CREATING, ord 0x0 +[2019/08/12 07:16:12:6107] USR: myss_state: LWSSSCS_POLL, ord 0x0 +[2019/08/12 07:16:12:6117] N: lws_ss_client_connect: connecting h1get warmcat.com / +[2019/08/12 07:16:12:6118] USR: myss_state: LWSSSCS_CONNECTING, ord 0x0 +[2019/08/12 07:16:13:4171] USR: myss_state: LWSSSCS_CONNECTED, ord 0x0 +[2019/08/12 07:16:13:4222] USR: myss_rx: len 1024, flags: 1 +[2019/08/12 07:16:13:4243] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4244] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4244] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4245] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4246] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4247] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4252] USR: myss_rx: len 1015, flags: 0 +[2019/08/12 07:16:13:4264] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4265] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4266] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4267] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4268] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4268] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4269] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4270] USR: myss_rx: len 1015, flags: 0 +[2019/08/12 07:16:13:4278] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4279] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4280] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4281] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4282] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4283] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4283] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4284] USR: myss_rx: len 1015, flags: 0 +[2019/08/12 07:16:13:4287] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4288] USR: myss_rx: len 947, flags: 0 +[2019/08/12 07:16:13:4293] USR: myss_rx: len 0, flags: 2 +[2019/08/12 07:16:13:4399] USR: myss_state: LWSSSCS_DISCONNECTED, ord 0x0 +[2019/08/12 07:16:13:4761] USR: myss_state: LWSSSCS_DESTROYING, ord 0x0 +[2019/08/12 07:16:13:4781] USR: Completed: OK +``` diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-proxy/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-proxy/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-proxy/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-proxy/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,80 +1,28 @@ +project(lws-minimal-secure-streams-proxy C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-secure-streams-proxy) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) require_lws_config(LWS_WITH_SECURE_STREAMS_PROXY_API 1 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 requirements) +require_lws_config(LWS_WITH_SYS_STATE 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-proxy/main.c libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-proxy/main.c --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-proxy/main.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-proxy/main.c 2020-12-01 17:40:26.000000000 +0000 @@ -133,8 +133,18 @@ "]" "}" "]," - "\"s\": [" - "{\"fetch_policy\": {" + "\"s\": [{" + "\"captive_portal_detect\": {" + "\"endpoint\": \"connectivitycheck.android.com\"," + "\"http_url\": \"generate_204\"," + "\"port\": 80," + "\"protocol\": \"h1\"," + "\"http_method\": \"GET\"," + "\"opportunistic\": true," + "\"http_expect\": 204," + "\"http_fail_redirect\": true" + "}," + "\"fetch_policy\": {" "\"endpoint\":" "\"warmcat.com\"," "\"port\":" "443," "\"protocol\":" "\"h1\"," diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-seq/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-seq/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-seq/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-seq/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,79 +1,27 @@ +project(lws-minimal-secure-streams-seq C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-secure-streams-seq) set(SRCS minimal-secure-streams.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) +require_lws_config(LWS_WITH_SEQUENCER 1 requirements) require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-server/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-server/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-server/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-server/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,28 @@ +project(lws-minimal-secure-streams-server C) +cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) +include(CheckCSourceCompiles) +include(LwsCheckRequirements) + +set(SAMP lws-minimal-secure-streams-server) +set(SRCS main.c ss-client.c ss-server.c) + +set(requirements 1) +require_lws_config(LWS_ROLE_H1 1 requirements) +require_lws_config(LWS_WITH_CLIENT 1 requirements) +require_lws_config(LWS_WITH_SERVER 1 requirements) +require_lws_config(LWS_WITH_SYS_SMD 1 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 requirements) + +if (requirements) + add_executable(${SAMP} ${SRCS}) + + if (websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) + add_dependencies(${SAMP} websockets_shared) + else() + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) + endif() +endif() diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-server/main.c libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-server/main.c --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-server/main.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-server/main.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,336 @@ +/* + * lws-minimal-secure-streams-server + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + */ + +#include +#include +#include + +extern const lws_ss_info_t ssi_client, ssi_server; + +static struct lws_context *context; +int interrupted, bad = 1, multipart; +static const char * const default_ss_policy = + "{" + "\"release\":" "\"01234567\"," + "\"product\":" "\"myproduct\"," + "\"schema-version\":" "1," + "\"retry\": [" /* named backoff / retry strategies */ + "{\"default\": {" + "\"backoff\": [" "1000," + "2000," + "3000," + "5000," + "10000" + "]," + "\"conceal\":" "5," + "\"jitterpc\":" "20," + "\"svalidping\":" "300," + "\"svalidhup\":" "310" + "}}" + "]," + "\"certs\": [" /* named individual certificates in BASE64 DER */ + /* + * Need to be in order from root cert... notice sometimes as + * with Let's Encrypt there are multiple possible validation + * paths, all the pieces for one validation path must be + * given, excluding the server cert itself. Let's Encrypt + * intermediate is signed by their ISRG Root CA but also is + * cross-signed by an IdenTrust intermediate that's widely + * deployed in browsers. We use the ISRG path because that + * way we can skip the extra IdenTrust root cert. + */ + "{\"isrg_root_x1\": \"" /* ISRG ROOT X1 */ + "MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw" + "TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh" + "cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4" + "WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu" + "ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY" + "MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc" + "h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+" + "0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U" + "A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW" + "T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH" + "B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC" + "B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv" + "KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn" + "OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn" + "jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw" + "qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI" + "rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV" + "HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq" + "hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL" + "ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ" + "3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK" + "NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5" + "ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur" + "TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC" + "jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc" + "oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq" + "4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA" + "mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d" + "emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=" + "\"}," + "{\"LEX3_isrg_root_x1\": \"" /* LE X3 signed by ISRG X1 root */ + "MIIFjTCCA3WgAwIBAgIRANOxciY0IzLc9AUoUSrsnGowDQYJKoZIhvcNAQELBQAw" + "TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh" + "cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTYxMDA2MTU0MzU1" + "WhcNMjExMDA2MTU0MzU1WjBKMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg" + "RW5jcnlwdDEjMCEGA1UEAxMaTGV0J3MgRW5jcnlwdCBBdXRob3JpdHkgWDMwggEi" + "MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCc0wzwWuUuR7dyXTeDs2hjMOrX" + "NSYZJeG9vjXxcJIvt7hLQQWrqZ41CFjssSrEaIcLo+N15Obzp2JxunmBYB/XkZqf" + "89B4Z3HIaQ6Vkc/+5pnpYDxIzH7KTXcSJJ1HG1rrueweNwAcnKx7pwXqzkrrvUHl" + "Npi5y/1tPJZo3yMqQpAMhnRnyH+lmrhSYRQTP2XpgofL2/oOVvaGifOFP5eGr7Dc" + "Gu9rDZUWfcQroGWymQQ2dYBrrErzG5BJeC+ilk8qICUpBMZ0wNAxzY8xOJUWuqgz" + "uEPxsR/DMH+ieTETPS02+OP88jNquTkxxa/EjQ0dZBYzqvqEKbbUC8DYfcOTAgMB" + "AAGjggFnMIIBYzAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADBU" + "BgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEBATAwMC4GCCsGAQUFBwIB" + "FiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQub3JnMB0GA1UdDgQWBBSo" + "SmpjBH3duubRObemRWXv86jsoTAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8vY3Js" + "LnJvb3QteDEubGV0c2VuY3J5cHQub3JnMHIGCCsGAQUFBwEBBGYwZDAwBggrBgEF" + "BQcwAYYkaHR0cDovL29jc3Aucm9vdC14MS5sZXRzZW5jcnlwdC5vcmcvMDAGCCsG" + "AQUFBzAChiRodHRwOi8vY2VydC5yb290LXgxLmxldHNlbmNyeXB0Lm9yZy8wHwYD" + "VR0jBBgwFoAUebRZ5nu25eQBc4AIiMgaWPbpm24wDQYJKoZIhvcNAQELBQADggIB" + "ABnPdSA0LTqmRf/Q1eaM2jLonG4bQdEnqOJQ8nCqxOeTRrToEKtwT++36gTSlBGx" + "A/5dut82jJQ2jxN8RI8L9QFXrWi4xXnA2EqA10yjHiR6H9cj6MFiOnb5In1eWsRM" + "UM2v3e9tNsCAgBukPHAg1lQh07rvFKm/Bz9BCjaxorALINUfZ9DD64j2igLIxle2" + "DPxW8dI/F2loHMjXZjqG8RkqZUdoxtID5+90FgsGIfkMpqgRS05f4zPbCEHqCXl1" + "eO5HyELTgcVlLXXQDgAWnRzut1hFJeczY1tjQQno6f6s+nMydLN26WuU4s3UYvOu" + "OsUxRlJu7TSRHqDC3lSE5XggVkzdaPkuKGQbGpny+01/47hfXXNB7HntWNZ6N2Vw" + "p7G6OfY+YQrZwIaQmhrIqJZuigsrbe3W+gdn5ykE9+Ky0VgVUsfxo52mwFYs1JKY" + "2PGDuWx8M6DlS6qQkvHaRUo0FMd8TsSlbF0/v965qGFKhSDeQoMpYnwcmQilRh/0" + "ayLThlHLN81gSkJjVrPI0Y8xCVPB4twb1PFUd2fPM3sA1tJ83sZ5v8vgFv2yofKR" + "PB0t6JzUA81mSqM3kxl5e+IZwhYAyO0OTg3/fs8HqGTNKd9BqoUwSRBzp06JMg5b" + "rUCGwbCUDI0mxadJ3Bz4WxR6fyNpBK2yAinWEsikxqEt" + "\"}," + /* + * a selfsigned cert for localhost for 100 years + */ + "{\"self_localhost\": \"" + "MIIF5jCCA86gAwIBAgIJANq50IuwPFKgMA0GCSqGSIb3DQEBCwUAMIGGMQswCQYD" + "VQQGEwJHQjEQMA4GA1UECAwHRXJld2hvbjETMBEGA1UEBwwKQWxsIGFyb3VuZDEb" + "MBkGA1UECgwSbGlid2Vic29ja2V0cy10ZXN0MRIwEAYDVQQDDAlsb2NhbGhvc3Qx" + "HzAdBgkqhkiG9w0BCQEWEG5vbmVAaW52YWxpZC5vcmcwIBcNMTgwMzIwMDQxNjA3" + "WhgPMjExODAyMjQwNDE2MDdaMIGGMQswCQYDVQQGEwJHQjEQMA4GA1UECAwHRXJl" + "d2hvbjETMBEGA1UEBwwKQWxsIGFyb3VuZDEbMBkGA1UECgwSbGlid2Vic29ja2V0" + "cy10ZXN0MRIwEAYDVQQDDAlsb2NhbGhvc3QxHzAdBgkqhkiG9w0BCQEWEG5vbmVA" + "aW52YWxpZC5vcmcwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCjYtuW" + "aICCY0tJPubxpIgIL+WWmz/fmK8IQr11Wtee6/IUyUlo5I602mq1qcLhT/kmpoR8" + "Di3DAmHKnSWdPWtn1BtXLErLlUiHgZDrZWInmEBjKM1DZf+CvNGZ+EzPgBv5nTek" + "LWcfI5ZZtoGuIP1Dl/IkNDw8zFz4cpiMe/BFGemyxdHhLrKHSm8Eo+nT734tItnH" + "KT/m6DSU0xlZ13d6ehLRm7/+Nx47M3XMTRH5qKP/7TTE2s0U6+M0tsGI2zpRi+m6" + "jzhNyMBTJ1u58qAe3ZW5/+YAiuZYAB6n5bhUp4oFuB5wYbcBywVR8ujInpF8buWQ" + "Ujy5N8pSNp7szdYsnLJpvAd0sibrNPjC0FQCNrpNjgJmIK3+mKk4kXX7ZTwefoAz" + "TK4l2pHNuC53QVc/EF++GBLAxmvCDq9ZpMIYi7OmzkkAKKC9Ue6Ef217LFQCFIBK" + "Izv9cgi9fwPMLhrKleoVRNsecBsCP569WgJXhUnwf2lon4fEZr3+vRuc9shfqnV0" + "nPN1IMSnzXCast7I2fiuRXdIz96KjlGQpP4XfNVA+RGL7aMnWOFIaVrKWLzAtgzo" + "GMTvP/AuehKXncBJhYtW0ltTioVx+5yTYSAZWl+IssmXjefxJqYi2/7QWmv1QC9p" + "sNcjTMaBQLN03T1Qelbs7Y27sxdEnNUth4kI+wIDAQABo1MwUTAdBgNVHQ4EFgQU" + "9mYU23tW2zsomkKTAXarjr2vjuswHwYDVR0jBBgwFoAU9mYU23tW2zsomkKTAXar" + "jr2vjuswDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEANjIBMrow" + "YNCbhAJdP7dhlhT2RUFRdeRUJD0IxrH/hkvb6myHHnK8nOYezFPjUlmRKUgNEDuA" + "xbnXZzPdCRNV9V2mShbXvCyiDY7WCQE2Bn44z26O0uWVk+7DNNLH9BnkwUtOnM9P" + "wtmD9phWexm4q2GnTsiL6Ul6cy0QlTJWKVLEUQQ6yda582e23J1AXqtqFcpfoE34" + "H3afEiGy882b+ZBiwkeV+oq6XVF8sFyr9zYrv9CvWTYlkpTQfLTZSsgPdEHYVcjv" + "xQ2D+XyDR0aRLRlvxUa9dHGFHLICG34Juq5Ai6lM1EsoD8HSsJpMcmrH7MWw2cKk" + "ujC3rMdFTtte83wF1uuF4FjUC72+SmcQN7A386BC/nk2TTsJawTDzqwOu/VdZv2g" + "1WpTHlumlClZeP+G/jkSyDwqNnTu1aodDmUa4xZodfhP1HWPwUKFcq8oQr148QYA" + "AOlbUOJQU7QwRWd1VbnwhDtQWXC92A2w1n/xkZSR1BM/NUSDhkBSUU1WjMbWg6Gg" + "mnIZLRerQCu1Oozr87rOQqQakPkyt8BUSNK3K42j2qcfhAONdRl8Hq8Qs5pupy+s" + "8sdCGDlwR3JNCMv6u48OK87F4mcIxhkSefFJUFII25pCGN5WtE4p5l+9cnO1GrIX" + "e2Hl/7M0c/lbZ4FvXgARlex2rkgS0Ka06HE=" + "\"}," + /* + * the private key for above + */ + "{\"self_localhost_key\": \"" + "MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQCjYtuWaICCY0tJ" + "PubxpIgIL+WWmz/fmK8IQr11Wtee6/IUyUlo5I602mq1qcLhT/kmpoR8Di3DAmHK" + "nSWdPWtn1BtXLErLlUiHgZDrZWInmEBjKM1DZf+CvNGZ+EzPgBv5nTekLWcfI5ZZ" + "toGuIP1Dl/IkNDw8zFz4cpiMe/BFGemyxdHhLrKHSm8Eo+nT734tItnHKT/m6DSU" + "0xlZ13d6ehLRm7/+Nx47M3XMTRH5qKP/7TTE2s0U6+M0tsGI2zpRi+m6jzhNyMBT" + "J1u58qAe3ZW5/+YAiuZYAB6n5bhUp4oFuB5wYbcBywVR8ujInpF8buWQUjy5N8pS" + "Np7szdYsnLJpvAd0sibrNPjC0FQCNrpNjgJmIK3+mKk4kXX7ZTwefoAzTK4l2pHN" + "uC53QVc/EF++GBLAxmvCDq9ZpMIYi7OmzkkAKKC9Ue6Ef217LFQCFIBKIzv9cgi9" + "fwPMLhrKleoVRNsecBsCP569WgJXhUnwf2lon4fEZr3+vRuc9shfqnV0nPN1IMSn" + "zXCast7I2fiuRXdIz96KjlGQpP4XfNVA+RGL7aMnWOFIaVrKWLzAtgzoGMTvP/Au" + "ehKXncBJhYtW0ltTioVx+5yTYSAZWl+IssmXjefxJqYi2/7QWmv1QC9psNcjTMaB" + "QLN03T1Qelbs7Y27sxdEnNUth4kI+wIDAQABAoICAFWe8MQZb37k2gdAV3Y6aq8f" + "qokKQqbCNLd3giGFwYkezHXoJfg6Di7oZxNcKyw35LFEghkgtQqErQqo35VPIoH+" + "vXUpWOjnCmM4muFA9/cX6mYMc8TmJsg0ewLdBCOZVw+wPABlaqz+0UOiSMMftpk9" + "fz9JwGd8ERyBsT+tk3Qi6D0vPZVsC1KqxxL/cwIFd3Hf2ZBtJXe0KBn1pktWht5A" + "Kqx9mld2Ovl7NjgiC1Fx9r+fZw/iOabFFwQA4dr+R8mEMK/7bd4VXfQ1o/QGGbMT" + "G+ulFrsiDyP+rBIAaGC0i7gDjLAIBQeDhP409ZhswIEc/GBtODU372a2CQK/u4Q/" + "HBQvuBtKFNkGUooLgCCbFxzgNUGc83GB/6IwbEM7R5uXqsFiE71LpmroDyjKTlQ8" + "YZkpIcLNVLw0usoGYHFm2rvCyEVlfsE3Ub8cFyTFk50SeOcF2QL2xzKmmbZEpXgl" + "xBHR0hjgon0IKJDGfor4bHO7Nt+1Ece8u2oTEKvpz5aIn44OeC5mApRGy83/0bvs" + "esnWjDE/bGpoT8qFuy+0urDEPNId44XcJm1IRIlG56ErxC3l0s11wrIpTmXXckqw" + "zFR9s2z7f0zjeyxqZg4NTPI7wkM3M8BXlvp2GTBIeoxrWB4V3YArwu8QF80QBgVz" + "mgHl24nTg00UH1OjZsABAoIBAQDOxftSDbSqGytcWqPYP3SZHAWDA0O4ACEM+eCw" + "au9ASutl0IDlNDMJ8nC2ph25BMe5hHDWp2cGQJog7pZ/3qQogQho2gUniKDifN77" + "40QdykllTzTVROqmP8+efreIvqlzHmuqaGfGs5oTkZaWj5su+B+bT+9rIwZcwfs5" + "YRINhQRx17qa++xh5mfE25c+M9fiIBTiNSo4lTxWMBShnK8xrGaMEmN7W0qTMbFH" + "PgQz5FcxRjCCqwHilwNBeLDTp/ZECEB7y34khVh531mBE2mNzSVIQcGZP1I/DvXj" + "W7UUNdgFwii/GW+6M0uUDy23UVQpbFzcV8o1C2nZc4Fb4zwBAoIBAQDKSJkFwwuR" + "naVJS6WxOKjX8MCu9/cKPnwBv2mmI2jgGxHTw5sr3ahmF5eTb8Zo19BowytN+tr6" + "2ZFoIBA9Ubc9esEAU8l3fggdfM82cuR9sGcfQVoCh8tMg6BP8IBLOmbSUhN3PG2m" + "39I802u0fFNVQCJKhx1m1MFFLOu7lVcDS9JN+oYVPb6MDfBLm5jOiPuYkFZ4gH79" + "J7gXI0/YKhaJ7yXthYVkdrSF6Eooer4RZgma62Dd1VNzSq3JBo6rYjF7Lvd+RwDC" + "R1thHrmf/IXplxpNVkoMVxtzbrrbgnC25QmvRYc0rlS/kvM4yQhMH3eA7IycDZMp" + "Y+0xm7I7jTT7AoIBAGKzKIMDXdCxBWKhNYJ8z7hiItNl1IZZMW2TPUiY0rl6yaCh" + "BVXjM9W0r07QPnHZsUiByqb743adkbTUjmxdJzjaVtxN7ZXwZvOVrY7I7fPWYnCE" + "fXCr4+IVpZI/ZHZWpGX6CGSgT6EOjCZ5IUufIvEpqVSmtF8MqfXO9o9uIYLokrWQ" + "x1dBl5UnuTLDqw8bChq7O5y6yfuWaOWvL7nxI8NvSsfj4y635gIa/0dFeBYZEfHI" + "UlGdNVomwXwYEzgE/c19ruIowX7HU/NgxMWTMZhpazlxgesXybel+YNcfDQ4e3RM" + "OMz3ZFiaMaJsGGNf4++d9TmMgk4Ns6oDs6Tb9AECggEBAJYzd+SOYo26iBu3nw3L" + "65uEeh6xou8pXH0Tu4gQrPQTRZZ/nT3iNgOwqu1gRuxcq7TOjt41UdqIKO8vN7/A" + "aJavCpaKoIMowy/aGCbvAvjNPpU3unU8jdl/t08EXs79S5IKPcgAx87sTTi7KDN5" + "SYt4tr2uPEe53NTXuSatilG5QCyExIELOuzWAMKzg7CAiIlNS9foWeLyVkBgCQ6S" + "me/L8ta+mUDy37K6vC34jh9vK9yrwF6X44ItRoOJafCaVfGI+175q/eWcqTX4q+I" + "G4tKls4sL4mgOJLq+ra50aYMxbcuommctPMXU6CrrYyQpPTHMNVDQy2ttFdsq9iK" + "TncCggEBAMmt/8yvPflS+xv3kg/ZBvR9JB1In2n3rUCYYD47ReKFqJ03Vmq5C9nY" + "56s9w7OUO8perBXlJYmKZQhO4293lvxZD2Iq4NcZbVSCMoHAUzhzY3brdgtSIxa2" + "gGveGAezZ38qKIU26dkz7deECY4vrsRkwhpTW0LGVCpjcQoaKvymAoCmAs8V2oMr" + "Ziw1YQ9uOUoWwOqm1wZqmVcOXvPIS2gWAs3fQlWjH9hkcQTMsUaXQDOD0aqkSY3E" + "NqOvbCV1/oUpRi3076khCoAXI1bKSn/AvR3KDP14B5toHI/F5OTSEiGhhHesgRrs" + "fBrpEY1IATtPq1taBZZogRqI3rOkkPk=" + "\"}" + "]," + "\"trust_stores\": [" /* named cert chains */ + "{" + "\"name\": \"le_via_isrg\"," + "\"stack\": [" + "\"isrg_root_x1\"," + "\"LEX3_isrg_root_x1\"" + "]" + "}" + "]," + "\"s\": [" + /* + * Client streamtypes + */ + + "{\"mintest\": {" + "\"endpoint\":" "\"warmcat.com\"," + "\"port\":" "443," + "\"protocol\":" "\"h2\"," + "\"http_method\":" "\"GET\"," + "\"http_url\":" "\"index.html\"," + "\"tls\":" "true," + "\"retry\":" "\"default\"," + "\"tls_trust_store\":" "\"le_via_isrg\"" + "}}," + + /* + * This streamtype represents an h2 server listening on :7681, + * using a 100-y self-signed tls cert + */ + + "{\"myserver\": {" + /* if given, "endpoint" is network if to bind to */ + "\"server\":" "true," + "\"port\":" "7681," + "\"protocol\":" "\"h1\"," + "\"metadata\": [{" + "\"mime\": \"Content-Type:\"," + "\"method\": \"\"," + "\"path\": \"\"" + "}]," + "\"tls\":" "true," + /* + * A ws server is an http server, if you give a + * ws_subprotocol here it's understood we also serve + * that ove ws or wss according to tls + */ + "\"ws_subprotocol\":" "\"mywsprotocol\"," + "\"server_cert\":" "\"self_localhost\"," + "\"server_key\":" "\"self_localhost_key\"" + "}}," + + "]" + "}" +; + +static int +smd_cb(void *opaque, lws_smd_class_t c, lws_usec_t ts, void *buf, size_t len) +{ + if ((c & LWSSMDCL_SYSTEM_STATE) && + !lws_json_simple_strcmp(buf, len, "\"state\":", "OPERATIONAL")) { + + /* create the secure streams */ + + lwsl_notice("%s: creating server stream\n", __func__); + + if (lws_ss_create(context, 0, &ssi_server, NULL, NULL, + NULL, NULL)) { + lwsl_err("%s: failed to create secure stream\n", + __func__); + return -1; + } +#if 0 + lwsl_notice("%s: creating client stream\n", __func__); + + if (lws_ss_create(context, 0, &ssi_client, NULL, NULL, + NULL, NULL)) { + lwsl_err("%s: failed to create secure stream\n", + __func__); + return -1; + } +#endif + } + + return 0; +} + +static void +sigint_handler(int sig) +{ + interrupted = 1; +} + +int main(int argc, const char **argv) +{ + struct lws_context_creation_info info; + int n = 0; + + signal(SIGINT, sigint_handler); + + memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ + lws_cmdline_option_handle_builtin(argc, argv, &info); + + if (lws_cmdline_option(argc, argv, "-m")) + multipart = 1; + + lwsl_user("LWS Secure Streams Server\n"); + + info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | + LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + info.fd_limit_per_thread = 1 + 6 + 1; + info.pss_policies_json = default_ss_policy; + info.port = CONTEXT_PORT_NO_LISTEN; + info.early_smd_cb = smd_cb; + info.early_smd_class_filter = LWSSMDCL_SYSTEM_STATE; + + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + return 1; + } + + /* the event loop */ + + while (n >= 0 && !interrupted) + n = lws_service(context, 0); + + bad = 0; + + lws_context_destroy(context); + lwsl_user("Completed: %s\n", bad ? "failed" : "OK"); + + return bad; +} diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-server/README.md libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-server/README.md --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-server/README.md 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-server/README.md 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,72 @@ +# lws minimal secure streams server + +The application sets up a tls + ws server on https://localhost:7681 + +It does it using Secure Streams... information about how the server should +operate is held in JSON policy in main.c + +Visiting the server in a modern browser will fetch some html + JS, the JS will +create a ws link back to the server and the server will spam an incrementing +number that is displayed in the browser every 100ms. + +The app also has a SS client that works, but it's disabled by default since +we're interested in server. + +## build + +``` + $ cmake . && make +``` + +## usage + +Commandline option|Meaning +---|--- +-d |Debug verbosity in decimal, eg, -d15 + +``` +[2020/07/27 10:51:04:8994] U: LWS Secure Streams Server +[2020/07/27 10:51:04:9440] N: LWS: 4.0.99-v4.0.0-245-ge6eb4417a, loglevel 1031 +[2020/07/27 10:51:04:9444] N: NET CLI SRV H1 H2 WS MQTT SS-JSON-POL SSPROX ASYNC_DNS IPv6-absent +[2020/07/27 10:51:05:1685] N: lws_adopt_descriptor_vhost2: wsi 0x5317d30, vhost system ss_handle (nil) +[2020/07/27 10:51:05:1753] N: lws_adopt_descriptor_vhost2: wsi 0x53182c0, vhost system ss_handle (nil) +[2020/07/27 10:51:05:2129] N: lws_ss_policy_parser_cb: server 'self_localhost' keep 52 0x5318cc0 +[2020/07/27 10:51:05:2134] N: lws_ss_policy_parser_cb: server 'self_localhost_key' keep 53 0x5318cf8 +[2020/07/27 10:51:05:2192] N: lws_ss_policy_ref_trust_store: le_via_isrg trust store initial 'isrg_root_x1' +[2020/07/27 10:51:05:7804] N: smd_cb: creating server stream +[2020/07/27 10:51:05:7851] N: Vhost 'myserver' using TLS mode +[2020/07/27 10:51:05:8660] N: SSL ECDH curve 'prime256v1' +[2020/07/27 10:51:06:1035] N: vhost myserver: cert expiry: 729599d +[2020/07/27 10:51:06:1039] N: lws_ss_create: created server myserver +[2020/07/27 10:51:11:8650] N: lws_adopt_descriptor_vhost2: wsi 0x5b046e0, vhost myserver ss_handle 0x56e2be0 +[2020/07/27 10:51:11:8672] U: myss_srv_state: 0x5b52f60 LWSSSCS_CREATING, ord 0x0 +[2020/07/27 10:51:11:8693] U: myss_srv_state: 0x5b52f60 LWSSSCS_CONNECTING, ord 0x0 +[2020/07/27 10:51:11:8696] U: myss_srv_state: 0x5b52f60 LWSSSCS_CONNECTED, ord 0x0 +[2020/07/27 10:51:11:9743] U: myss_srv_state: 0x5ba2bd0 LWSSSCS_CREATING, ord 0x0 +[2020/07/27 10:51:11:9747] U: myss_srv_state: 0x5ba2bd0 LWSSSCS_CONNECTING, ord 0x0 +[2020/07/27 10:51:11:9747] U: myss_srv_state: 0x5ba2bd0 LWSSSCS_CONNECTED, ord 0x0 +[2020/07/27 10:51:12:0192] U: myss_srv_state: 0x5bad0a0 LWSSSCS_CREATING, ord 0x0 +[2020/07/27 10:51:12:0193] U: myss_srv_state: 0x5bad0a0 LWSSSCS_CONNECTING, ord 0x0 +[2020/07/27 10:51:12:0194] U: myss_srv_state: 0x5bad0a0 LWSSSCS_CONNECTED, ord 0x0 +[2020/07/27 10:51:12:0306] N: secstream_h1: LWS_CALLBACK_HTTP +[2020/07/27 10:51:12:0329] U: myss_srv_state: 0x5bad0a0 LWSSSCS_SERVER_TXN, ord 0x0 +[2020/07/27 10:51:12:0481] N: lws_h2_ws_handshake: Server SS 0x5ba2bd0 .wsi 0x5ba27b0 switching to ws protocol +[2020/07/27 10:51:12:0484] U: myss_srv_state: 0x5ba2bd0 LWSSSCS_SERVER_UPGRADE, ord 0x0 +[2020/07/27 10:51:12:0541] U: myss_srv_state: 0x5ba2bd0 LWSSSCS_CONNECTED, ord 0x0 +[2020/07/27 10:51:12:1222] U: myss_srv_state: 0x5bd1100 LWSSSCS_CREATING, ord 0x0 +[2020/07/27 10:51:12:1222] U: myss_srv_state: 0x5bd1100 LWSSSCS_CONNECTING, ord 0x0 +[2020/07/27 10:51:12:1223] U: myss_srv_state: 0x5bd1100 LWSSSCS_CONNECTED, ord 0x0 +[2020/07/27 10:51:12:1242] N: lws_h2_ws_handshake: Server SS 0x5bd1100 .wsi 0x5bd0ce0 switching to ws protocol +[2020/07/27 10:51:12:1243] U: myss_srv_state: 0x5bd1100 LWSSSCS_SERVER_UPGRADE, ord 0x0 +[2020/07/27 10:51:12:1246] U: myss_srv_state: 0x5bd1100 LWSSSCS_CONNECTED, ord 0x0 +^C[2020/07/27 10:51:15:2809] U: myss_srv_state: 0x5bad0a0 LWSSSCS_DISCONNECTED, ord 0x0 +[2020/07/27 10:51:15:2838] U: myss_srv_state: 0x5bad0a0 LWSSSCS_DESTROYING, ord 0x0 +[2020/07/27 10:51:15:2938] U: myss_srv_state: 0x5ba2bd0 LWSSSCS_DISCONNECTED, ord 0x0 +[2020/07/27 10:51:15:2946] U: myss_srv_state: 0x5ba2bd0 LWSSSCS_DESTROYING, ord 0x0 +[2020/07/27 10:51:15:2952] U: myss_srv_state: 0x5bd1100 LWSSSCS_DISCONNECTED, ord 0x0 +[2020/07/27 10:51:15:2953] U: myss_srv_state: 0x5bd1100 LWSSSCS_DESTROYING, ord 0x0 +[2020/07/27 10:51:15:2960] U: myss_srv_state: 0x5b52f60 LWSSSCS_DISCONNECTED, ord 0x0 +[2020/07/27 10:51:15:2961] U: myss_srv_state: 0x5b52f60 LWSSSCS_DESTROYING, ord 0x0 +[2020/07/27 10:51:15:3042] U: myss_srv_state: 0x56e2be0 LWSSSCS_DESTROYING, ord 0x0 +[2020/07/27 10:51:15:3378] U: Completed: OK +``` diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-server/ss-client.c libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-server/ss-client.c --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-server/ss-client.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-server/ss-client.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,86 @@ +/* + * lws-minimal-secure-streams-server + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + */ + +#include + +extern int interrupted, bad; + +typedef struct myss { + struct lws_ss_handle *ss; + void *opaque_data; + /* ... application specific state ... */ + lws_sorted_usec_list_t sul; + + int count; +} myss_t; + +/* secure streams payload interface */ + +static int +myss_rx(void *userobj, const uint8_t *buf, size_t len, int flags) +{ +// myss_t *m = (myss_t *)userobj; + + lwsl_user("%s: len %d, flags: %d\n", __func__, (int)len, flags); + lwsl_hexdump_info(buf, len); + + /* + * If we received the whole message, for our example it means + * we are done. + */ + if (flags & LWSSS_FLAG_EOM) { + bad = 0; + interrupted = 1; + } + + return 0; +} + +static int +myss_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, size_t *len, + int *flags) +{ + //myss_t *m = (myss_t *)userobj; + + return LWSSSSRET_TX_DONT_SEND; /* don't want to write */ +} + +static int +myss_state(void *userobj, void *sh, lws_ss_constate_t state, + lws_ss_tx_ordinal_t ack) +{ + myss_t *m = (myss_t *)userobj; + + lwsl_user("%s: %p %s, ord 0x%x\n", __func__, m->ss, + lws_ss_state_name(state), (unsigned int)ack); + + switch (state) { + case LWSSSCS_CREATING: + lws_ss_request_tx(m->ss); + break; + case LWSSSCS_ALL_RETRIES_FAILED: + /* if we're out of retries, we want to close the app and FAIL */ + interrupted = 1; + break; + default: + break; + } + + return 0; +} + +const lws_ss_info_t ssi_client = { + .handle_offset = offsetof(myss_t, ss), + .opaque_user_data_offset = offsetof(myss_t, opaque_data), + .streamtype = "mintest", + .rx = myss_rx, + .tx = myss_tx, + .state = myss_state, + .user_alloc = sizeof(myss_t), +}; diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-server/ss-server.c libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-server/ss-server.c --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-server/ss-server.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-server/ss-server.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,235 @@ +/* + * lws-minimal-secure-streams-server + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + */ + +#include +#include + +extern int interrupted, bad, multipart; + +static const char *html = + /* normally we serve this... */ + "" + "Hello from the web server
" + "

" + "", + +*multipart_html = + /* + * If you use -m commandline switch we send this instead, as + * multipart/form-data + */ + "--aBoundaryString\r\n" + "Content-Disposition: form-data; name=\"myFile\"; filename=\"xxx.txt\"\r\n" + "Content-Type: text/plain\r\n" + "\r\n" + "The file contents\r\n" + "--aBoundaryString\r\n" + "Content-Disposition: form-data; name=\"myField\"\r\n" + "\r\n" + "(data)\r\n" + "--aBoundaryString--\r\n"; + + +typedef struct myss { + struct lws_ss_handle *ss; + void *opaque_data; + /* ... application specific state ... */ + + lws_sorted_usec_list_t sul; + int count; + char upgraded; + +} myss_srv_t; + +/* + * This is the Secure Streams Server RX and TX for HTTP(S) + */ + +static int +myss_srv_rx(void *userobj, const uint8_t *buf, size_t len, int flags) +{ +// myss_srv_t *m = (myss_srv_t *)userobj; + + lwsl_user("%s: len %d, flags: %d\n", __func__, (int)len, flags); + lwsl_hexdump_info(buf, len); + + /* + * If we received the whole message, for our example it means + * we are done. + */ + if (flags & LWSSS_FLAG_EOM) { + bad = 0; + interrupted = 1; + } + + return 0; +} + +static int +myss_srv_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, size_t *len, + int *flags) +{ + myss_srv_t *m = (myss_srv_t *)userobj; + const char *send = html; + + if (m->upgraded) + return LWSSSSRET_TX_DONT_SEND; + + if (multipart) + send = multipart_html; + + *flags = LWSSS_FLAG_SOM | LWSSS_FLAG_EOM; + + lws_strncpy((char *)buf, send, *len); + *len = strlen(send); + + return 0; +} + +/* + * This is the Secure Streams Server RX and TX for WS(S)... when we get a + * state that the underlying connection upgraded protocol, we switch the stream + * rx and tx handlers to here. + */ + +static int +myss_ws_rx(void *userobj, const uint8_t *buf, size_t len, int flags) +{ +// myss_srv_t *m = (myss_srv_t *)userobj; + + lwsl_user("%s: len %d, flags: %d\n", __func__, (int)len, flags); + lwsl_hexdump_info(buf, len); + + /* + * If we received the whole message, for our example it means + * we are done. + */ + if (flags & LWSSS_FLAG_EOM) { + bad = 0; + interrupted = 1; + } + + return 0; +} + +/* this is the callback that mediates sending the incrementing number */ + +static void +spam_sul_cb(struct lws_sorted_usec_list *sul) +{ + myss_srv_t *m = lws_container_of(sul, myss_srv_t, sul); + + lws_ss_request_tx(m->ss); + + lws_sul_schedule(lws_ss_get_context(m->ss), 0, &m->sul, spam_sul_cb, + 100 * LWS_US_PER_MS); +} + +static int +myss_ws_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, size_t *len, + int *flags) +{ + myss_srv_t *m = (myss_srv_t *)userobj; + + *flags = LWSSS_FLAG_SOM | LWSSS_FLAG_EOM; + + *len = lws_snprintf((char *)buf, *len, "hello from ws %d", m->count++); + + lws_sul_schedule(lws_ss_get_context(m->ss), 0, &m->sul, spam_sul_cb, + 100 * LWS_US_PER_MS); + + return 0; +} + +static int +myss_srv_state(void *userobj, void *sh, lws_ss_constate_t state, + lws_ss_tx_ordinal_t ack) +{ + myss_srv_t *m = (myss_srv_t *)userobj; + + lwsl_user("%s: %p %s, ord 0x%x\n", __func__, m->ss, + lws_ss_state_name(state), (unsigned int)ack); + + switch (state) { + case LWSSSCS_DISCONNECTED: + lws_sul_cancel(&m->sul); + break; + case LWSSSCS_CREATING: + lws_ss_request_tx(m->ss); + break; + case LWSSSCS_ALL_RETRIES_FAILED: + /* if we're out of retries, we want to close the app and FAIL */ + interrupted = 1; + break; + + case LWSSSCS_SERVER_TXN: + /* + * The underlying protocol started a transaction, let's + * describe how we want to complete it. We can defer this until + * later, eg, after we have consumed any rx that's coming with + * the client's transaction initiation phase, but in this + * example we know what we want to do already. + * + * We do want to ack the transaction... + */ + lws_ss_server_ack(m->ss, 0); + /* + * ... it's going to be either text/html or multipart ... + */ + if (multipart) + lws_ss_set_metadata(m->ss, "mime", + "multipart/form-data; boundary=aBoundaryString", 45); + else + lws_ss_set_metadata(m->ss, "mime", "text/html", 9); + /* + * ...it's going to be whatever size it is (and request tx) + */ + lws_ss_request_tx_len(m->ss, (unsigned long) + (multipart ? strlen(multipart_html) : + strlen(html))); + break; + + case LWSSSCS_SERVER_UPGRADE: + + /* + * This is sent when the underlying protocol has experienced + * an upgrade, eg, http->ws... it's a one-way upgrade on this + * stream, change the handlers to deal with the kind of + * messages we send on ws + */ + + m->upgraded = 1; + lws_ss_change_handlers(m->ss, myss_ws_rx, myss_ws_tx, NULL); + lws_ss_request_tx(m->ss); /* we want to start sending numbers */ + break; + default: + break; + } + + return 0; +} + +const lws_ss_info_t ssi_server = { + .handle_offset = offsetof(myss_srv_t, ss), + .opaque_user_data_offset = offsetof(myss_srv_t, opaque_data), + .streamtype = "myserver", + .rx = myss_srv_rx, + .tx = myss_srv_tx, + .state = myss_srv_state, + .user_alloc = sizeof(myss_srv_t), +}; diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-server-raw/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-server-raw/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-server-raw/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-server-raw/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,27 @@ +project(lws-minimal-secure-streams-server-raw C) +cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) +include(CheckCSourceCompiles) +include(LwsCheckRequirements) + +set(SAMP lws-minimal-secure-streams-server-raw) +set(SRCS main.c ss-server.c) + +set(requirements 1) +require_lws_config(LWS_ROLE_H1 1 requirements) +require_lws_config(LWS_WITH_SERVER 1 requirements) +require_lws_config(LWS_WITH_SYS_SMD 1 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 requirements) + +if (requirements) + add_executable(${SAMP} ${SRCS}) + + if (websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) + add_dependencies(${SAMP} websockets_shared) + else() + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) + endif() +endif() diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-server-raw/main.c libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-server-raw/main.c --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-server-raw/main.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-server-raw/main.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,104 @@ +/* + * lws-minimal-secure-streams-server + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + */ + +#include +#include +#include + +extern const lws_ss_info_t ssi_client, ssi_server; + +static struct lws_context *context; +int interrupted, bad = 1; +static const char * const default_ss_policy = + "{" + "\"release\":" "\"01234567\"," + "\"product\":" "\"myproduct\"," + "\"schema-version\":" "1," + "\"s\": [" + + /* + * This streamtype represents a raw server listening on :7681, + * without tls + */ + + "{\"myrawserver\": {" + /* if given, "endpoint" is network if to bind to */ + "\"server\":" "true," + "\"port\":" "7681," + "\"protocol\":" "\"raw\"" + "}}" + + "]" + "}" +; + +static int +smd_cb(void *opaque, lws_smd_class_t c, lws_usec_t ts, void *buf, size_t len) +{ + if ((c & LWSSMDCL_SYSTEM_STATE) && + !lws_json_simple_strcmp(buf, len, "\"state\":", "OPERATIONAL")) { + + /* create the secure streams */ + + lwsl_notice("%s: creating server stream\n", __func__); + + if (lws_ss_create(context, 0, &ssi_server, NULL, NULL, + NULL, NULL)) { + lwsl_err("%s: failed to create secure stream\n", + __func__); + return -1; + } + } + + return 0; +} + +static void +sigint_handler(int sig) +{ + interrupted = 1; +} + +int main(int argc, const char **argv) +{ + struct lws_context_creation_info info; + int n = 0; + + signal(SIGINT, sigint_handler); + + memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ + lws_cmdline_option_handle_builtin(argc, argv, &info); + lwsl_user("LWS Secure Streams Server Raw\n"); + + info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | + LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + info.fd_limit_per_thread = 1 + 6 + 1; + info.pss_policies_json = default_ss_policy; + info.port = CONTEXT_PORT_NO_LISTEN; + info.early_smd_cb = smd_cb; + info.early_smd_class_filter = LWSSMDCL_SYSTEM_STATE; + + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + return 1; + } + + /* the event loop */ + + while (n >= 0 && !interrupted) + n = lws_service(context, 0); + + bad = 0; + + lws_context_destroy(context); + lwsl_user("Completed: %s\n", bad ? "failed" : "OK"); + + return bad; +} diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-server-raw/README.md libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-server-raw/README.md --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-server-raw/README.md 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-server-raw/README.md 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,54 @@ +# lws minimal secure streams server raw + +The application sets up a raw tcp server on localhost:7681 + +It does it using Secure Streams... information about how the server should +operate is held in JSON policy in main.c + +Connecting to the server using `echo "hello" | nc --no-shutdown 127.0.0.1 7681` +will send "hello" which is hexdumped to console by the rx function, then +will receive an incrementing message at 100ms intervals. + +Note there are two incomaptible versions of netcat around, this is from Fedora's +nmap-ncat, the --no-shutdown is needed to stop it hanging up itself after it +has sent its stdin. + +## build + +``` + $ cmake . && make +``` + +## usage + +Commandline option|Meaning +---|--- +-d |Debug verbosity in decimal, eg, -d15 + +``` +[2020/07/28 10:25:54:6747] U: LWS Secure Streams Server Raw +[2020/07/28 10:25:54:7194] N: LWS: 4.0.99-v4.0.0-247-g58be599aa, loglevel 1031 +[2020/07/28 10:25:54:7198] N: NET CLI SRV H1 H2 WS MQTT SS-JSON-POL SSPROX ASYNC_DNS IPv6-absent +[2020/07/28 10:25:54:9376] N: lws_adopt_descriptor_vhost2: wsi 0x5317d30, vhost system ss_handle (nil) +[2020/07/28 10:25:54:9442] N: lws_adopt_descriptor_vhost2: wsi 0x53182c0, vhost system ss_handle (nil) +[2020/07/28 10:25:54:9920] N: smd_cb: creating server stream +[2020/07/28 10:25:54:9963] N: lws_ss_create: created server myrawserver +[2020/07/28 10:26:00:1065] N: secstream_raw: RAW_ADOPT +[2020/07/28 10:26:00:1068] N: lws_adopt_descriptor_vhost2: wsi 0x531a6b0, vhost myrawserver ss_handle 0x5319ac0 +[2020/07/28 10:26:00:1088] U: myss_raw_state: 0x531aad0 LWSSSCS_CREATING, ord 0x0 +[2020/07/28 10:26:00:1094] U: myss_raw_state: 0x531aad0 LWSSSCS_CONNECTING, ord 0x0 +[2020/07/28 10:26:00:1096] U: myss_raw_state: 0x531aad0 LWSSSCS_CONNECTED, ord 0x0 +[2020/07/28 10:26:00:1172] U: myss_raw_rx: len 6, flags: 0 +[2020/07/28 10:26:02:8516] U: myss_raw_state: 0x531aad0 LWSSSCS_DISCONNECTED, ord 0x0 +[2020/07/28 10:26:02:8545] U: myss_raw_state: 0x531aad0 LWSSSCS_DESTROYING, ord 0x0 +^C[2020/07/28 10:26:04:9608] U: myss_raw_state: 0x5319ac0 LWSSSCS_DESTROYING, ord 0x0 +[2020/07/28 10:26:04:9723] U: Completed: OK +``` + +``` +$ echo "hello" | nc --no-shutdown 127.0.0.1 7681 +hello from raw 0 +hello from raw 1 +hello from raw 2 +... +``` diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-server-raw/ss-server.c libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-server-raw/ss-server.c --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-server-raw/ss-server.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-server-raw/ss-server.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,111 @@ +/* + * lws-minimal-secure-streams-server + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + */ + +#include +#include + +extern int interrupted, bad; + +typedef struct myss { + struct lws_ss_handle *ss; + void *opaque_data; + /* ... application specific state ... */ + + lws_sorted_usec_list_t sul; + int count; + char upgraded; + +} myss_srv_t; + +/* + * This is the Secure Streams Server RX and TX + */ + +static int +myss_raw_rx(void *userobj, const uint8_t *buf, size_t len, int flags) +{ +// myss_srv_t *m = (myss_srv_t *)userobj; + + lwsl_user("%s: len %d, flags: %d\n", __func__, (int)len, flags); + lwsl_hexdump_info(buf, len); + + /* + * If we received the whole message, for our example it means + * we are done. + */ + if (flags & LWSSS_FLAG_EOM) { + bad = 0; + interrupted = 1; + } + + return 0; +} + +/* this is the callback that mediates sending the incrementing number */ + +static void +spam_sul_cb(struct lws_sorted_usec_list *sul) +{ + myss_srv_t *m = lws_container_of(sul, myss_srv_t, sul); + + lws_ss_request_tx(m->ss); + + lws_sul_schedule(lws_ss_get_context(m->ss), 0, &m->sul, spam_sul_cb, + 100 * LWS_US_PER_MS); +} + +static int +myss_raw_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, size_t *len, + int *flags) +{ + myss_srv_t *m = (myss_srv_t *)userobj; + + *flags = LWSSS_FLAG_SOM | LWSSS_FLAG_EOM; + + *len = lws_snprintf((char *)buf, *len, "hello from raw %d\n", m->count++); + + lws_sul_schedule(lws_ss_get_context(m->ss), 0, &m->sul, spam_sul_cb, + 100 * LWS_US_PER_MS); + + return 0; +} + +static int +myss_raw_state(void *userobj, void *sh, lws_ss_constate_t state, + lws_ss_tx_ordinal_t ack) +{ + myss_srv_t *m = (myss_srv_t *)userobj; + + lwsl_user("%s: %p %s, ord 0x%x\n", __func__, m->ss, + lws_ss_state_name(state), (unsigned int)ack); + + switch (state) { + case LWSSSCS_DISCONNECTED: + lws_sul_cancel(&m->sul); + break; + case LWSSSCS_CONNECTED: + lws_ss_request_tx(m->ss); + break; + + default: + break; + } + + return 0; +} + +const lws_ss_info_t ssi_server = { + .handle_offset = offsetof(myss_srv_t, ss), + .opaque_user_data_offset = offsetof(myss_srv_t, opaque_data), + .streamtype = "myrawserver", + .rx = myss_raw_rx, + .tx = myss_raw_tx, + .state = myss_raw_state, + .user_alloc = sizeof(myss_srv_t), +}; diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-sink/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-sink/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-sink/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-sink/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,79 +0,0 @@ -cmake_minimum_required(VERSION 2.8) -include(CheckCSourceCompiles) - -set(SAMP lws-minimal-secure-streams-sink) -set(SRCS main.c) - -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - - -set(requirements 1) -require_lws_config(LWS_ROLE_H1 1 requirements) -require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) -require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) - -if (requirements) - add_executable(${SAMP} ${SRCS}) - - if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) - add_dependencies(${SAMP} websockets_shared) - else() - target_link_libraries(${SAMP} websockets) - endif() -endif() diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-sink/main.c libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-sink/main.c --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-sink/main.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-sink/main.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,288 +0,0 @@ -/* - * lws-minimal-secure-streams-sink - * - * Written in 2010-2020 by Andy Green - * - * This file is made available under the Creative Commons CC0 1.0 - * Universal Public Domain Dedication. - */ - -#include -#include -#include - -static int interrupted, bad = 1; -static const char * const default_ss_policy = - "{" - "\"release\":" "\"01234567\"," - "\"product\":" "\"myproduct\"," - "\"schema-version\":" "1," - "\"retry\": [" /* named backoff / retry strategies */ - "{\"default\": {" - "\"backoff\": [" "1000," - "2000," - "3000," - "5000," - "10000" - "]," - "\"conceal\":" "5," - "\"jitterpc\":" "20," - "\"svalidping\":" "300," - "\"svalidhup\":" "310" - "}}" - "]," - "\"certs\": [" /* named individual certificates in BASE64 DER */ - /* - * Need to be in order from root cert... notice sometimes as - * with Let's Encrypt there are multiple possible validation - * paths, all the pieces for one validation path must be - * given, excluding the server cert itself. Let's Encrypt - * intermediate is signed by their ISRG Root CA but also is - * cross-signed by an IdenTrust intermediate that's widely - * deployed in browsers. We use the ISRG path because that - * way we can skip the extra IdenTrust root cert. - */ - "{\"isrg_root_x1\": \"" /* ISRG ROOT X1 */ - "MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw" - "TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh" - "cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4" - "WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu" - "ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY" - "MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc" - "h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+" - "0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U" - "A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW" - "T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH" - "B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC" - "B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv" - "KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn" - "OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn" - "jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw" - "qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI" - "rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV" - "HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq" - "hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL" - "ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ" - "3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK" - "NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5" - "ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur" - "TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC" - "jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc" - "oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq" - "4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA" - "mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d" - "emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=" - "\"}," - "{\"LEX3_isrg_root_x1\": \"" /* LE X3 signed by ISRG X1 root */ - "MIIFjTCCA3WgAwIBAgIRANOxciY0IzLc9AUoUSrsnGowDQYJKoZIhvcNAQELBQAw" - "TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh" - "cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTYxMDA2MTU0MzU1" - "WhcNMjExMDA2MTU0MzU1WjBKMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg" - "RW5jcnlwdDEjMCEGA1UEAxMaTGV0J3MgRW5jcnlwdCBBdXRob3JpdHkgWDMwggEi" - "MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCc0wzwWuUuR7dyXTeDs2hjMOrX" - "NSYZJeG9vjXxcJIvt7hLQQWrqZ41CFjssSrEaIcLo+N15Obzp2JxunmBYB/XkZqf" - "89B4Z3HIaQ6Vkc/+5pnpYDxIzH7KTXcSJJ1HG1rrueweNwAcnKx7pwXqzkrrvUHl" - "Npi5y/1tPJZo3yMqQpAMhnRnyH+lmrhSYRQTP2XpgofL2/oOVvaGifOFP5eGr7Dc" - "Gu9rDZUWfcQroGWymQQ2dYBrrErzG5BJeC+ilk8qICUpBMZ0wNAxzY8xOJUWuqgz" - "uEPxsR/DMH+ieTETPS02+OP88jNquTkxxa/EjQ0dZBYzqvqEKbbUC8DYfcOTAgMB" - "AAGjggFnMIIBYzAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADBU" - "BgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEBATAwMC4GCCsGAQUFBwIB" - "FiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQub3JnMB0GA1UdDgQWBBSo" - "SmpjBH3duubRObemRWXv86jsoTAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8vY3Js" - "LnJvb3QteDEubGV0c2VuY3J5cHQub3JnMHIGCCsGAQUFBwEBBGYwZDAwBggrBgEF" - "BQcwAYYkaHR0cDovL29jc3Aucm9vdC14MS5sZXRzZW5jcnlwdC5vcmcvMDAGCCsG" - "AQUFBzAChiRodHRwOi8vY2VydC5yb290LXgxLmxldHNlbmNyeXB0Lm9yZy8wHwYD" - "VR0jBBgwFoAUebRZ5nu25eQBc4AIiMgaWPbpm24wDQYJKoZIhvcNAQELBQADggIB" - "ABnPdSA0LTqmRf/Q1eaM2jLonG4bQdEnqOJQ8nCqxOeTRrToEKtwT++36gTSlBGx" - "A/5dut82jJQ2jxN8RI8L9QFXrWi4xXnA2EqA10yjHiR6H9cj6MFiOnb5In1eWsRM" - "UM2v3e9tNsCAgBukPHAg1lQh07rvFKm/Bz9BCjaxorALINUfZ9DD64j2igLIxle2" - "DPxW8dI/F2loHMjXZjqG8RkqZUdoxtID5+90FgsGIfkMpqgRS05f4zPbCEHqCXl1" - "eO5HyELTgcVlLXXQDgAWnRzut1hFJeczY1tjQQno6f6s+nMydLN26WuU4s3UYvOu" - "OsUxRlJu7TSRHqDC3lSE5XggVkzdaPkuKGQbGpny+01/47hfXXNB7HntWNZ6N2Vw" - "p7G6OfY+YQrZwIaQmhrIqJZuigsrbe3W+gdn5ykE9+Ky0VgVUsfxo52mwFYs1JKY" - "2PGDuWx8M6DlS6qQkvHaRUo0FMd8TsSlbF0/v965qGFKhSDeQoMpYnwcmQilRh/0" - "ayLThlHLN81gSkJjVrPI0Y8xCVPB4twb1PFUd2fPM3sA1tJ83sZ5v8vgFv2yofKR" - "PB0t6JzUA81mSqM3kxl5e+IZwhYAyO0OTg3/fs8HqGTNKd9BqoUwSRBzp06JMg5b" - "rUCGwbCUDI0mxadJ3Bz4WxR6fyNpBK2yAinWEsikxqEt" - "\"}" - "]," - "\"trust_stores\": [" /* named cert chains */ - "{" - "\"name\": \"le_via_isrg\"," - "\"stack\": [" - "\"isrg_root_x1\"," - "\"LEX3_isrg_root_x1\"" - "]" - "}" - "]," - "\"s\": [" /* the supported stream types */ - "{\"\": {" - "\"endpoint\":" "\"warmcat.com\"," - "\"port\":" "443," - "\"protocol\":" "\"h2\"," - "\"http_method\":" "\"GET\"," - "\"http_url\":" "\"index.html\"," - "\"plugins\":" "[]," - "\"tls\":" "true," - "\"nailed_up\":" "true," - "\"long_poll\":" "true," - "\"retry\":" "\"default\"," - "\"tls_trust_store\":" "\"le_via_isrg\"" - "}}" - "]" - "}" -; - -typedef struct myss { - struct lws_ss_handle *ss; - void *opaque_data; - /* ... application specific state ... */ - lws_sorted_usec_list_t sul; - - int count; -} myss_t; - -/* secure streams payload interface */ - -static int -myss_rx(void *userobj, const uint8_t *buf, size_t len, int flags) -{ -// myss_t *m = (myss_t *)userobj; - - lwsl_user("%s: len %d, flags: %d\n", __func__, (int)len, flags); - lwsl_hexdump_info(buf, len); - - /* - * If we received the whole message, for our example it means - * we are done. - */ - if (flags & LWSSS_FLAG_EOM) { - bad = 0; - interrupted = 1; - } - - return 0; -} - -static int -myss_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, size_t *len, - int *flags) -{ - //myss_t *m = (myss_t *)userobj; - - return 0; -} - -static int -myss_state(void *userobj, void *sh, lws_ss_constate_t state, - lws_ss_tx_ordinal_t ack) -{ - myss_t *m = (myss_t *)userobj; - - lwsl_user("%s: %s, ord 0x%x\n", __func__, lws_ss_state_name(state), - (unsigned int)ack); - - switch (state) { - case LWSSSCS_CREATING: - lws_ss_request_tx(m->ss); - break; - case LWSSSCS_ALL_RETRIES_FAILED: - /* if we're out of retries, we want to close the app and FAIL */ - interrupted = 1; - break; - default: - break; - } - - return 0; -} - -static void -sigint_handler(int sig) -{ - interrupted = 1; -} - -int main(int argc, const char **argv) -{ - struct lws_context_creation_info info; - struct lws_context *context; - int n = 0; - - signal(SIGINT, sigint_handler); - - memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ - lws_cmdline_option_handle_builtin(argc, argv, &info); - lwsl_user("LWS secure streams [-d] [-f] [-p] [--h1post]\n"); - - info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | - LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; - info.fd_limit_per_thread = 1 + 6 + 1; - info.pss_policies_json = default_ss_policy; - info.port = CONTEXT_PORT_NO_LISTEN; - - context = lws_create_context(&info); - if (!context) { - lwsl_err("lws init failed\n"); - return 1; - } - - // puts(default_ss_policy); - - if (lws_cmdline_option(argc, argv, "-p")) { - - /* we are being the proxy */ - -#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) - if (lws_ss_proxy_create(context, NULL, 0)) { - lwsl_err("%s: failed to create ss proxy\n", __func__); - goto bail; - } - lwsl_notice("%s: secure streams proxy mode\n", __func__); -#else - lwsl_err("%s: needs cmake LWS_WITH_SECURE_STREAMS_PROXY_API\n", - __func__); -#endif - } else { - lws_ss_info_t ssi; - - /* We're making an outgoing secure stream ourselves */ - - memset(&ssi, 0, sizeof(ssi)); - ssi.handle_offset = offsetof(myss_t, ss); - ssi.opaque_user_data_offset = offsetof(myss_t, opaque_data); - ssi.rx = myss_rx; - ssi.tx = myss_tx; - ssi.state = myss_state; - ssi.user_alloc = sizeof(myss_t); - - /* requested to fail (to check backoff)? */ - if (lws_cmdline_option(argc, argv, "-f")) - ssi.streamtype = "mintest-fail"; - else - /* request to check h1 POST */ - if (lws_cmdline_option(argc, argv, "--h1post")) - ssi.streamtype = "minpost"; - else - /* default to h1 GET */ - ssi.streamtype = "mintest"; - - if (lws_ss_create(context, 0, &ssi, NULL, NULL, NULL, NULL)) { - lwsl_err("%s: failed to create secure stream\n", - __func__); - goto bail; - } - } - - /* the event loop */ - - while (n >= 0 && !interrupted) - n = lws_service(context, 0); - -bail: - - lws_context_destroy(context); - lwsl_user("Completed: %s\n", bad ? "failed" : "OK"); - - return bad; -} diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-sink/README.md libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-sink/README.md --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-sink/README.md 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-sink/README.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,64 +0,0 @@ -# lws minimal secure streams - -The application goes to https://warmcat.com and reads index.html there. - -It does it using Secure Streams... the main code in minimal-secure-streams.c -just sets up the context and opens a secure stream of type "mintest". - -The handler for state changes and payloads for "mintest" is in ss-myss.c - -The information about how a "mintest" stream should connect and the -protocol it uses is kept separated in policy-database.c - -## build - -``` - $ cmake . && make -``` - -## usage - -Commandline option|Meaning ----|--- --d |Debug verbosity in decimal, eg, -d15 --f| Force connecting to the wrong endpoint to check backoff retry flow --p| Run as proxy server for clients to connect to over unix domain socket - -``` -[2019/08/12 07:16:11:0045] USR: LWS minimal secure streams [-d] [-f] -[2019/08/12 07:16:12:6102] USR: myss_state: LWSSSCS_CREATING, ord 0x0 -[2019/08/12 07:16:12:6107] USR: myss_state: LWSSSCS_POLL, ord 0x0 -[2019/08/12 07:16:12:6117] N: lws_ss_client_connect: connecting h1get warmcat.com / -[2019/08/12 07:16:12:6118] USR: myss_state: LWSSSCS_CONNECTING, ord 0x0 -[2019/08/12 07:16:13:4171] USR: myss_state: LWSSSCS_CONNECTED, ord 0x0 -[2019/08/12 07:16:13:4222] USR: myss_rx: len 1024, flags: 1 -[2019/08/12 07:16:13:4243] USR: myss_rx: len 1024, flags: 0 -[2019/08/12 07:16:13:4244] USR: myss_rx: len 1024, flags: 0 -[2019/08/12 07:16:13:4244] USR: myss_rx: len 1024, flags: 0 -[2019/08/12 07:16:13:4245] USR: myss_rx: len 1024, flags: 0 -[2019/08/12 07:16:13:4246] USR: myss_rx: len 1024, flags: 0 -[2019/08/12 07:16:13:4247] USR: myss_rx: len 1024, flags: 0 -[2019/08/12 07:16:13:4252] USR: myss_rx: len 1015, flags: 0 -[2019/08/12 07:16:13:4264] USR: myss_rx: len 1024, flags: 0 -[2019/08/12 07:16:13:4265] USR: myss_rx: len 1024, flags: 0 -[2019/08/12 07:16:13:4266] USR: myss_rx: len 1024, flags: 0 -[2019/08/12 07:16:13:4267] USR: myss_rx: len 1024, flags: 0 -[2019/08/12 07:16:13:4268] USR: myss_rx: len 1024, flags: 0 -[2019/08/12 07:16:13:4268] USR: myss_rx: len 1024, flags: 0 -[2019/08/12 07:16:13:4269] USR: myss_rx: len 1024, flags: 0 -[2019/08/12 07:16:13:4270] USR: myss_rx: len 1015, flags: 0 -[2019/08/12 07:16:13:4278] USR: myss_rx: len 1024, flags: 0 -[2019/08/12 07:16:13:4279] USR: myss_rx: len 1024, flags: 0 -[2019/08/12 07:16:13:4280] USR: myss_rx: len 1024, flags: 0 -[2019/08/12 07:16:13:4281] USR: myss_rx: len 1024, flags: 0 -[2019/08/12 07:16:13:4282] USR: myss_rx: len 1024, flags: 0 -[2019/08/12 07:16:13:4283] USR: myss_rx: len 1024, flags: 0 -[2019/08/12 07:16:13:4283] USR: myss_rx: len 1024, flags: 0 -[2019/08/12 07:16:13:4284] USR: myss_rx: len 1015, flags: 0 -[2019/08/12 07:16:13:4287] USR: myss_rx: len 1024, flags: 0 -[2019/08/12 07:16:13:4288] USR: myss_rx: len 947, flags: 0 -[2019/08/12 07:16:13:4293] USR: myss_rx: len 0, flags: 2 -[2019/08/12 07:16:13:4399] USR: myss_state: LWSSSCS_DISCONNECTED, ord 0x0 -[2019/08/12 07:16:13:4761] USR: myss_state: LWSSSCS_DESTROYING, ord 0x0 -[2019/08/12 07:16:13:4781] USR: Completed: OK -``` diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-smd/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-smd/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-smd/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-smd/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,48 @@ +project(lws-minimal-secure-streams-smd C) +cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) +include(CheckCSourceCompiles) +include(LwsCheckRequirements) + +set(requirements 1) +require_lws_config(LWS_ROLE_H1 1 requirements) +require_lws_config(LWS_WITH_CLIENT 1 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) +require_lws_config(LWS_WITH_SYS_SMD 1 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 requirements) +require_lws_config(LWS_WITH_SYS_STATE 1 requirements) + +if (requirements) + add_executable(${PROJECT_NAME} minimal-secure-streams-smd.c) + + if (LWS_CTEST_INTERNET_AVAILABLE) + add_test(NAME ss-smd COMMAND lws-minimal-secure-streams-smd) + set_tests_properties(ss-smd + PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/secure-streams/minimal-secure-streams-smd + TIMEOUT 10) + endif() + + if (websockets_shared) + target_link_libraries(${PROJECT_NAME} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) + add_dependencies(${PROJECT_NAME} websockets_shared) + else() + target_link_libraries(${PROJECT_NAME} websockets ${LIBWEBSOCKETS_DEP_LIBS}) + endif() + + CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\ni#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)\n return 0;\n #else\n fail\n #endif\n return 0;\n}\n" HAS_LWS_WITH_SECURE_STREAMS_PROXY_API) + + if (HAS_LWS_WITH_SECURE_STREAMS_PROXY_API OR LWS_WITH_SECURE_STREAMS_PROXY_API) + add_compile_options(-DLWS_SS_USE_SSPC) + + add_executable(${PROJECT_NAME}-client minimal-secure-streams-smd.c) + if (websockets_shared) + target_link_libraries(${PROJECT_NAME}-client websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) + add_dependencies(${PROJECT_NAME}-client websockets_shared) + else() + target_link_libraries(${PROJECT_NAME}-client websockets ${LIBWEBSOCKETS_DEP_LIBS}) + endif() + endif() + +endif() diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-smd/minimal-secure-streams-smd.c libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-smd/minimal-secure-streams-smd.c --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-smd/minimal-secure-streams-smd.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-smd/minimal-secure-streams-smd.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,319 @@ +/* + * lws-minimal-secure-streams-smd + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * + * This demonstrates a minimal http client using secure streams to access the + * SMD api. + */ + +#include +#include +#include + +static int interrupted, bad = 1, count_p1, count_p2, count_tx; +static lws_sorted_usec_list_t sul_timeout; + +/* + * If the -proxy app is fulfilling our connection, then we don't need to have + * the policy in the client. + * + * When we build with LWS_SS_USE_SSPC, the apis hook up to a proxy process over + * a Unix Domain Socket. To test that, you need to separately run the + * ./lws-minimal-secure-streams-proxy test app on the same machine. + */ + +#if !defined(LWS_SS_USE_SSPC) +static const char * const default_ss_policy = + "{" + "\"schema-version\":1," + "\"s\": [" + "{" + /* + * "captive_portal_detect" describes + * what to do in order to check if the path to + * the Internet is being interrupted by a + * captive portal. If there's a larger policy + * fetched from elsewhere, it should also include + * this since it needs to be done at least after + * every DHCP acquisition + */ + "\"captive_portal_detect\": {" + "\"endpoint\": \"connectivitycheck.android.com\"," + "\"http_url\": \"generate_204\"," + "\"port\": 80," + "\"protocol\": \"h1\"," + "\"http_method\": \"GET\"," + "\"opportunistic\": true," + "\"http_expect\": 204," + "\"http_fail_redirect\": true" + "}" + "}" + "]" + "}" +; + +#endif + +typedef struct myss { + struct lws_ss_handle *ss; + void *opaque_data; + /* ... application specific state ... */ + lws_sorted_usec_list_t sul; + char alternate; +} myss_t; + + +/* secure streams payload interface */ + +static int +myss_rx(void *userobj, const uint8_t *buf, size_t len, int flags) +{ +// myss_t *m = (myss_t *)userobj; + + lwsl_notice("%s: len %d, flags: %d\n", __func__, (int)len, flags); + lwsl_hexdump_notice(buf, len); + + count_p1++; + + return 0; +} + +static void +sul_tx_periodic_cb(lws_sorted_usec_list_t *sul) +{ + myss_t *m = lws_container_of(sul, myss_t, sul); + + lwsl_notice("%s: requesting TX\n", __func__); + lws_ss_request_tx(m->ss); +} + +static int +myss_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, size_t *len, + int *flags) +{ + myss_t *m = (myss_t *)userobj; + + lwsl_notice("%s: sending SS smd\n", __func__); + + /* + * The SS RX isn't going to see INTERACTION messages, because its class + * filter doesn't accept INTERACTION class messages. The direct + * participant we also set up for the test will see them though. + * + * Let's alternate between sending NETWORK class smd messages and + * INTERACTION so we can test both rx paths + */ + + m->alternate++; + lws_ser_wu64be(buf, (m->alternate & 1) ? LWSSMDCL_NETWORK : LWSSMDCL_INTERACTION); + lws_ser_wu64be(buf + 8, 0); /* valgrind notices uninitialized if left */ + + if (m->alternate == 4) { + /* + * after a few, let's request a CPD check + */ + *len = LWS_SMD_SS_RX_HEADER_LEN + + lws_snprintf((char *)buf + LWS_SMD_SS_RX_HEADER_LEN, *len, + "{\"trigger\": \"cpdcheck\", \"src\":\"SS-test\"}"); + } else + + *len = LWS_SMD_SS_RX_HEADER_LEN + + lws_snprintf((char *)buf + LWS_SMD_SS_RX_HEADER_LEN, *len, + (m->alternate & 1) ? "{\"class\":\"NETWORK\"}" : + "{\"class\":\"INTERACTION\"}"); + + *flags = LWSSS_FLAG_SOM | LWSSS_FLAG_EOM; + + count_tx++; + + lws_sul_schedule(lws_ss_get_context(m->ss), 0, &m->sul, + sul_tx_periodic_cb, 250 * LWS_US_PER_MS); + + return 0; +} + +static int +myss_state(void *userobj, void *h_src, lws_ss_constate_t state, + lws_ss_tx_ordinal_t ack) +{ + myss_t *m = (myss_t *)userobj; + + if (state == LWSSSCS_DESTROYING) { + lws_sul_cancel(&m->sul); + return 0; + } + + if (state == LWSSSCS_CONNECTED) { + lwsl_notice("%s: CONNECTED\n", __func__); + lws_sul_schedule(lws_ss_get_context(m->ss), 0, &m->sul, + sul_tx_periodic_cb, 1); + return 0; + } + + return 0; +} + +static const lws_ss_info_t ssi_lws_smd = { + .handle_offset = offsetof(myss_t, ss), + .opaque_user_data_offset = offsetof(myss_t, opaque_data), + .rx = myss_rx, + .tx = myss_tx, + .state = myss_state, + .user_alloc = sizeof(myss_t), + .streamtype = LWS_SMD_STREAMTYPENAME, + .manual_initial_tx_credit = LWSSMDCL_SYSTEM_STATE | + LWSSMDCL_NETWORK, +}; + +/* for comparison, this is a non-SS lws_smd participant */ + +static int +direct_smd_cb(void *opaque, lws_smd_class_t _class, lws_usec_t timestamp, + void *buf, size_t len) +{ + struct lws_context **pctx = (struct lws_context **)opaque; + + lwsl_notice("%s: class: 0x%x, ts: %llu\n", __func__, _class, + (unsigned long long)timestamp); + lwsl_hexdump_notice(buf, len); + + count_p2++; + + if (_class != LWSSMDCL_SYSTEM_STATE) + return 0; + + if (!lws_json_simple_strcmp(buf, len, "\"state\":", "OPERATIONAL")) { + +#if !defined(LWS_SS_USE_SSPC) + /* + * Let's trigger a CPD check, just as a test. SS can't see it + * anyway since it doesn't listen for NETWORK but the direct / + * local participant will see it and the result + * + * This process doesn't run the smd / captive portal action + * when it's a client of the SS proxy. SMD has to be passed + * via the SS _lws_smd proxied connection in that case. + */ + (void)lws_smd_msg_printf(*pctx, LWSSMDCL_NETWORK, + "{\"trigger\": \"cpdcheck\", \"src\":\"direct-test\"}"); +#endif + + /* + * Create the SS link to lws_smd... notice in ssi_lws_smd + * above, we tell this link to use a class filter that excludes + * NETWORK messages. + */ + + if (lws_ss_create(*pctx, 0, &ssi_lws_smd, NULL, NULL, NULL, NULL)) { + lwsl_err("%s: failed to create secure stream\n", + __func__); + + return -1; + } + } + + return 0; +} + + +static void +sul_timeout_cb(lws_sorted_usec_list_t *sul) +{ + interrupted = 1; +} + + +static void +sigint_handler(int sig) +{ + interrupted = 1; +} + +int main(int argc, const char **argv) +{ + struct lws_context_creation_info info; + struct lws_context *context; + + signal(SIGINT, sigint_handler); + + memset(&info, 0, sizeof info); + lws_cmdline_option_handle_builtin(argc, argv, &info); + + lwsl_user("LWS Secure Streams SMD test client [-d]\n"); + + info.fd_limit_per_thread = 1 + 6 + 1; + info.port = CONTEXT_PORT_NO_LISTEN; +#if !defined(LWS_SS_USE_SSPC) + info.pss_policies_json = default_ss_policy; +#else + info.protocols = lws_sspc_protocols; +#endif + info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | + LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + + info.early_smd_cb = direct_smd_cb; + info.early_smd_class_filter = 0xffffffff; + info.early_smd_opaque = &context; + + /* create the context */ + + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + return 1; + } + +#if defined(LWS_SS_USE_SSPC) + if (!lws_create_vhost(context, &info)) { + lwsl_err("%s: failed to create default vhost\n", __func__); + goto bail; + } +#endif + + /* set up the test timeout */ + + lws_sul_schedule(context, 0, &sul_timeout, sul_timeout_cb, + 4 * LWS_US_PER_SEC); + + /* the event loop */ + + while (lws_service(context, 0) >= 0 && !interrupted) + ; + + /* compare what happened with what we expect */ + +#if defined(LWS_SS_USE_SSPC) + /* if SSPC + * + * - the SS _lws_smd link does not enable INTERACTION class, so doesn't + * see these messages (count_p1 is half count_tx) + * + * - the direct smd participant sees local state, but it doesn't send + * any local CPD request, since as a client it doesn't do CPD + * directly (count_p2 -= 1 compared to non-SSPC) + * + * - one CPD trigger is sent on the proxied SS link (countp1 += 1) + */ + if (count_p1 >= 6 && count_p2 >= 11 && count_tx >= 12) +#else + /* if not SSPC, then we can see direct smd activity */ + if (count_p1 >= 2 && count_p2 >= 15 && count_tx >= 5) +#endif + bad = 0; + + lwsl_notice("%d %d %d\n", count_p1, count_p2, count_tx); + +#if defined(LWS_SS_USE_SSPC) +bail: +#endif + lws_context_destroy(context); + + lwsl_user("Completed: %s\n", bad ? "failed" : "OK"); + + return bad; +} diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-smd/README.md libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-smd/README.md --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-smd/README.md 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-smd/README.md 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,126 @@ +# lws minimal secure streams SMD + +This application creates a Secure Stream link to LWS SMD, System +Message Distribution. + +The SS is able to receive system messages matching a specified +class filter, and issue system messages also using SS payload +semantics. + +Both a direct api lws_smd participant and an SS based one are instantiated. +They both filter on system messages. + +When the Secure Stream is created, it asks to send using normal the SS api. +In the SS tx callback, it prepares a header and then send a NETWORK class +message. + +Numbers of messages received each way and sent is compared after 2s and the +test exits with a success or a fail. + +### Building and testing + +Build with + + -DLWS_WITH_SECURE_STREAMS=1 + -DLWS_WITH_SECURE_STREAMS_PROXY_API=1 + -DLWS_WITH_MINIMAL_EXAMPLES=1 + +The run ./bin/lws-minimal-secure-streams-smd alone (local SS and direct SMD tests) +and after run ./bin/lws-minimal-secure-streams-proxy in one console and +./bin-lws-minimal-secure-streams-smd-client in the other (SS proxy tests) + +### What's going on in the -client test + +The -client build version contains the test logic as usual, but outsources the +policy and smd_ server part to the Secure Streams Proxy. + + - start lws-minimal-secure-streams-proxy first + + - start lws-minimal-secure-streams-smd-client + +1) When the client starts, we waits to hear the client state is OPERATIONAL in +a direct smd participant callback. When it is, he creates a Secure Stream of +streamtype "_lws_smd", creating a local SS handle. + +2) The SS creation request is proxied to the SS proxy process over Unix Domain +Sockets. There it creates a Secure Stream object proxyside, and registers as +an SMD participant... this smd-related behaviour is tied to the special +streamtype name "_lws_smd". The SMD registration uses a class mask passed to +the proxy in the tx credit field of the serialization. + +3) SMD messages that pass the class mask filter are proxied back to the client +over the connection. + +4) SMD messages created at the client are passed to the proxy and added to the +proxy's SMD queue, if the same connection's class mask accepts the message then +it will be proxied back to the client same as other messages. + +The minimal example produces a variety of messages on the SS link, including +CPD detect trigger. The SS link is set up to only accept messages of classes +LWSSMDCL_SYSTEM_STATE and LWSSMDCL_NETWORK, INTERACTION type messages are +not accepted. + +## build + +``` + $ cmake . && make +``` + +## usage + +Commandline option|Meaning +---|--- +-d |Debug verbosity in decimal, eg, -d15 + +``` +$ ./bin/lws-minimal-secure-streams-smd -d 1151 +[2020/06/18 21:44:54:5148] U: LWS Secure Streams SMD test client [-d] +[2020/06/18 21:44:54:5601] I: Initial logging level 1151 +[2020/06/18 21:44:54:5605] I: Libwebsockets version: 4.0.99-v4.0.0-174-ga8a2eb954 v4.0.0-174-ga8a2eb954 +[2020/06/18 21:44:54:5607] I: IPV6 not compiled in +... +[2020/06/18 21:44:54:7906] D: _lws_state_transition: system: changed 11 'AUTH2' -> 12 'OPERATIONAL' +[2020/06/18 21:44:54:7906] D: _realloc: size 81: lws_smd_msg_alloc +[2020/06/18 21:44:54:7907] I: lws_cancel_service +[2020/06/18 21:44:54:7912] I: lws_state_transition_steps: CONTEXT_CREATED -> OPERATIONAL +[2020/06/18 21:44:54:7919] N: myss_tx: sending SS smd +[2020/06/18 21:44:54:7940] D: _realloc: size 84: lws_smd_msg_alloc +[2020/06/18 21:44:54:7944] I: lws_cancel_service +[2020/06/18 21:44:54:7966] D: direct_smd_cb: class: 0x2, ts: 3139600721554 +[2020/06/18 21:44:54:7972] D: +[2020/06/18 21:44:54:7990] D: 0000: 7B 22 73 74 61 74 65 22 3A 22 49 4E 49 54 49 41 {"state":"INITIA +[2020/06/18 21:44:54:7998] D: 0010: 4C 49 5A 45 44 22 7D LIZED"} +[2020/06/18 21:44:54:8001] D: +[2020/06/18 21:44:54:8016] I: myss_rx: len 39, flags: 3 +[2020/06/18 21:44:54:8018] I: +[2020/06/18 21:44:54:8021] I: 0000: 00 00 00 00 00 00 00 02 00 00 02 DA FE C9 26 92 ..............&. +[2020/06/18 21:44:54:8022] I: 0010: 7B 22 73 74 61 74 65 22 3A 22 49 4E 49 54 49 41 {"state":"INITIA +[2020/06/18 21:44:54:8023] I: 0020: 4C 49 5A 45 44 22 7D LIZED"} +[2020/06/18 21:44:54:8023] I: +[2020/06/18 21:44:54:8029] D: direct_smd_cb: class: 0x2, ts: 3139600724243 +[2020/06/18 21:44:54:8029] D: +[2020/06/18 21:44:54:8030] D: 0000: 7B 22 73 74 61 74 65 22 3A 22 49 46 41 43 45 5F {"state":"IFACE_ +[2020/06/18 21:44:54:8031] D: 0010: 43 4F 4C 44 50 4C 55 47 22 7D COLDPLUG"} +[2020/06/18 21:44:54:8032] D: +... +[2020/06/18 21:44:54:8112] D: direct_smd_cb: class: 0x4, ts: 3139600732952 +[2020/06/18 21:44:54:8112] D: +[2020/06/18 21:44:54:8114] D: 0000: 7B 22 73 6F 6D 74 68 69 6E 67 22 3A 22 6E 6F 74 {"somthing":"not +[2020/06/18 21:44:54:8115] D: 0010: 73 65 65 6E 62 79 73 73 72 78 22 7D seenbyssrx"} +[2020/06/18 21:44:54:8115] D: +[2020/06/18 21:44:57:5823] I: 11 12 1 +[2020/06/18 21:44:57:5838] I: lws_context_destroy: ctx 0x4f61db0 +[2020/06/18 21:44:57:5849] D: _lws_state_transition: system: changed 12 'OPERATIONAL' -> 13 'POLICY_INVALID' +[2020/06/18 21:44:57:5851] D: _realloc: size 84: lws_smd_msg_alloc +[2020/06/18 21:44:57:5853] I: lws_cancel_service +[2020/06/18 21:44:57:5871] I: lws_destroy_event_pipe +[2020/06/18 21:44:57:5906] I: lws_pt_destroy: pt destroyed +[2020/06/18 21:44:57:5913] I: lws_context_destroy2: ctx 0x4f61db0 +[2020/06/18 21:44:57:5936] D: lwsac_free: head (nil) +[2020/06/18 21:44:57:5947] D: 0x455970: post vh listl +[2020/06/18 21:44:57:5950] D: 0x455970: post pdl +[2020/06/18 21:44:57:5961] D: 0x455970: baggage +[2020/06/18 21:44:57:5968] D: 0x455970: post dc2 +[2020/06/18 21:44:57:6010] D: lws_context_destroy3: ctx 0x4f61db0 freed +[2020/06/18 21:44:57:6014] U: Completed: OK +``` \ No newline at end of file diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,26 @@ +project(lws-minimal-secure-streams-staticpolicy C) +cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) +include(CheckCSourceCompiles) +include(LwsCheckRequirements) + +set(SAMP lws-minimal-secure-streams-staticpolicy) + +set(requirements 1) +require_lws_config(LWS_ROLE_H1 1 requirements) +require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 1 requirements) + +if (requirements) + add_executable(${SAMP} minimal-secure-streams.c) + + if (websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) + add_dependencies(${SAMP} websockets_shared) + else() + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) + endif() + +endif() diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/minimal-secure-streams.c libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/minimal-secure-streams.c --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/minimal-secure-streams.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/minimal-secure-streams.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,291 @@ +/* + * lws-minimal-secure-streams + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * + * This demonstrates a minimal http client using secure streams api. + * + * It visits https://warmcat.com/ and receives the html page there. + * + * This example is built two different ways from the same source... one includes + * the policy everything needed to fulfil the stream directly. The other -client + * variant has no policy itself and some other minor init changes, and connects + * to the -proxy example to actually get the connection done. + * + * In the -client build case, the example does not even init the tls libraries + * since the proxy part will take care of all that. + */ + +#include +#include +#include + +static int interrupted, bad = 1, force_cpd_fail_portal, + force_cpd_fail_no_internet; +static lws_state_notify_link_t nl; + +/* + * This is example builds with a static policy autogenerated from a JSON + * policy... + */ +#include "static-policy.h" + + +typedef struct myss { + struct lws_ss_handle *ss; + void *opaque_data; + /* ... application specific state ... */ + lws_sorted_usec_list_t sul; +} myss_t; + +static const char *canned_root_token_payload = + "grant_type=refresh_token" + "&refresh_token=Atzr|IwEBIJedGXjDqsU_vMxykqOMg" + "SHfYe3CPcedueWEMWSDMaDnEmiW8RlR1Kns7Cb4B-TOSnqp7ifVsY4BMY2B8tpHfO39XP" + "zfu9HapGjTR458IyHX44FE71pWJkGZ79uVBpljP4sazJuk8XS3Oe_yLnm_DIO6fU1nU3Y" + "0flYmsOiOAQE_gRk_pdlmEtHnpMA-9rLw3mkY5L89Ty9kUygBsiFaYatouROhbsTn8-jW" + "k1zZLUDpT6ICtBXSnrCIg0pUbZevPFhTwdXd6eX-u4rq0W-XaDvPWFO7au-iPb4Zk5eZE" + "iX6sissYrtNmuEXc2uHu7MnQO1hHCaTdIO2CANVumf-PHSD8xseamyh04sLV5JgFzY45S" + "KvKMajiUZuLkMokOx86rjC2Hdkx5DO7G-dbG1ufBDG-N79pFMSs7Ck5pc283IdLoJkCQc" + "AGvTX8o8I29QqkcGou-9TKhOJmpX8As94T61ok0UqqEKPJ7RhfQHHYdCtsdwxgvfVr9qI" + "xL_hDCcTho8opCVX-6QhJHl6SQFlTw13" + "&client_id=" + "amzn1.application-oa2-client.4823334c434b4190a2b5a42c07938a2d"; + +/* secure streams payload interface */ + +static int +myss_rx(void *userobj, const uint8_t *buf, size_t len, int flags) +{ +// myss_t *m = (myss_t *)userobj; + + lwsl_user("%s: len %d, flags: %d\n", __func__, (int)len, flags); + lwsl_hexdump_info(buf, len); + + /* + * If we received the whole message, for our example it means + * we are done. + */ + if (flags & LWSSS_FLAG_EOM) { + bad = 0; + interrupted = 1; + } + + return 0; +} + +static int +myss_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, size_t *len, + int *flags) +{ + //myss_t *m = (myss_t *)userobj; + + return 0; +} + +static int +myss_state(void *userobj, void *sh, lws_ss_constate_t state, + lws_ss_tx_ordinal_t ack) +{ + myss_t *m = (myss_t *)userobj; + + lwsl_user("%s: %s, ord 0x%x\n", __func__, lws_ss_state_name(state), + (unsigned int)ack); + + switch (state) { + case LWSSSCS_CREATING: + lws_ss_set_metadata(m->ss, "uptag", "myuptag123", 10); + lws_ss_set_metadata(m->ss, "ctype", "myctype", 7); + lws_ss_client_connect(m->ss); + break; + case LWSSSCS_ALL_RETRIES_FAILED: + /* if we're out of retries, we want to close the app and FAIL */ + interrupted = 1; + break; + case LWSSSCS_QOS_ACK_REMOTE: + lwsl_notice("%s: LWSSSCS_QOS_ACK_REMOTE\n", __func__); + break; + default: + break; + } + + return 0; +} + +static int +app_system_state_nf(lws_state_manager_t *mgr, lws_state_notify_link_t *link, + int current, int target) +{ + struct lws_context *context = lws_system_context_from_system_mgr(mgr); + lws_system_blob_t *ab = lws_system_get_blob(context, + LWS_SYSBLOB_TYPE_AUTH, 1 /* AUTH_IDX_ROOT */); + size_t size; + + /* + * For the things we care about, let's notice if we are trying to get + * past them when we haven't solved them yet, and make the system + * state wait while we trigger the dependent action. + */ + switch (target) { + + case LWS_SYSTATE_REGISTERED: + size = lws_system_blob_get_size(ab); + if (size) + break; + + /* let's register our canned root token so auth can use it */ + lws_system_blob_direct_set(ab, + (const uint8_t *)canned_root_token_payload, + strlen(canned_root_token_payload)); + break; + + case LWS_SYSTATE_OPERATIONAL: + if (current == LWS_SYSTATE_OPERATIONAL) { + lws_ss_info_t ssi; + + /* We're making an outgoing secure stream ourselves */ + + memset(&ssi, 0, sizeof(ssi)); + ssi.handle_offset = offsetof(myss_t, ss); + ssi.opaque_user_data_offset = offsetof(myss_t, + opaque_data); + ssi.rx = myss_rx; + ssi.tx = myss_tx; + ssi.state = myss_state; + ssi.user_alloc = sizeof(myss_t); + ssi.streamtype = "mintest"; + + if (lws_ss_create(context, 0, &ssi, NULL, NULL, + NULL, NULL)) { + lwsl_err("%s: failed to create secure stream\n", + __func__); + return -1; + } + } + break; + } + + return 0; +} + +static lws_state_notify_link_t * const app_notifier_list[] = { + &nl, NULL +}; + +static void +sigint_handler(int sig) +{ + interrupted = 1; +} + +int main(int argc, const char **argv) +{ + struct lws_context_creation_info info; + struct lws_context *context; + int n = 0; + + signal(SIGINT, sigint_handler); + + memset(&info, 0, sizeof info); + lws_cmdline_option_handle_builtin(argc, argv, &info); + + lwsl_user("LWS secure streams static policy test client [-d]\n"); + + /* these options are mutually exclusive if given */ + + if (lws_cmdline_option(argc, argv, "--force-portal")) + force_cpd_fail_portal = 1; + + if (lws_cmdline_option(argc, argv, "--force-no-internet")) + force_cpd_fail_no_internet = 1; + + info.fd_limit_per_thread = 1 + 6 + 1; + info.port = CONTEXT_PORT_NO_LISTEN; +#if defined(LWS_SS_USE_SSPC) + info.protocols = lws_sspc_protocols; + { + const char *p; + + /* connect to ssproxy via UDS by default, else via + * tcp connection to this port */ + if ((p = lws_cmdline_option(argc, argv, "-p"))) + info.ss_proxy_port = atoi(p); + + /* UDS "proxy.ss.lws" in abstract namespace, else this socket + * path; when -p given this can specify the network interface + * to bind to */ + if ((p = lws_cmdline_option(argc, argv, "-i"))) + info.ss_proxy_bind = p; + + /* if -p given, -a specifies the proxy address to connect to */ + if ((p = lws_cmdline_option(argc, argv, "-a"))) + info.ss_proxy_address = p; + } +#else + info.pss_policies = &_ss_static_policy_entry; + info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | + LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; +#endif +#if defined(LWS_WITH_DETAILED_LATENCY) + info.detailed_latency_cb = lws_det_lat_plot_cb; + info.detailed_latency_filepath = "/tmp/lws-latency-ssproxy"; +#endif + + /* integrate us with lws system state management when context created */ + + nl.name = "app"; + nl.notify_cb = app_system_state_nf; + info.register_notifier_list = app_notifier_list; + + /* create the context */ + + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + return 1; + } + + /* + * Set the related lws_system blobs + * + * ...direct_set() sets a pointer, so the thing pointed to has to have + * a suitable lifetime, eg, something that already exists on the heap or + * a const string in .rodata like this + */ + + lws_system_blob_direct_set(lws_system_get_blob(context, + LWS_SYSBLOB_TYPE_DEVICE_SERIAL, 0), + (const uint8_t *)"SN12345678", 10); + lws_system_blob_direct_set(lws_system_get_blob(context, + LWS_SYSBLOB_TYPE_DEVICE_FW_VERSION, 0), + (const uint8_t *)"v0.01", 5); + + /* + * ..._heap_append() appends to a buflist kind of arrangement on heap, + * just one block is fine, otherwise it will concatenate the fragments + * in the order they were appended (and take care of freeing them at + * context destroy time). ..._heap_empty() is also available to remove + * everything that was already allocated. + * + * Here we use _heap_append() just so it's tested as well as direct set. + */ + + lws_system_blob_heap_append(lws_system_get_blob(context, + LWS_SYSBLOB_TYPE_DEVICE_TYPE, 0), + (const uint8_t *)"spacerocket", 11); + + /* the event loop */ + + while (n >= 0 && !interrupted) + n = lws_service(context, 0); + + lws_context_destroy(context); + + lwsl_user("Completed: %s\n", bad ? "failed" : "OK"); + + return bad; +} diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/README.md libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/README.md --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/README.md 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/README.md 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,61 @@ +# lws minimal secure streams static policy + +The application goes to https://warmcat.com and reads index.html there. + +It does it using a static Secure Streams policy generated from JSON by +policy2c example. + +## build + +``` + $ cmake . && make +``` + +## usage + +Commandline option|Meaning +---|--- +-d |Debug verbosity in decimal, eg, -d15 + +``` +$ ./lws-minimal-secure-streams-staticpolicy +[2020/03/26 15:49:12:6640] U: LWS secure streams static policy test client [-d] +[2020/03/26 15:49:12:7067] N: lws_create_context: using ss proxy bind '(null)', port 0, ads '(null)' +[2020/03/26 15:49:12:7567] N: lws_tls_client_create_vhost_context: using mem client CA cert 914 +[2020/03/26 15:49:12:7597] N: lws_tls_client_create_vhost_context: using mem client CA cert 1011 +[2020/03/26 15:49:12:7603] N: lws_tls_client_create_vhost_context: using mem client CA cert 1425 +[2020/03/26 15:49:12:7605] N: lws_tls_client_create_vhost_context: using mem client CA cert 1011 +[2020/03/26 15:49:12:9713] N: lws_system_cpd_set: setting CPD result OK +[2020/03/26 15:49:13:9625] N: ss_api_amazon_auth_rx: acquired 588-byte api.amazon.com auth token, exp 3600s +[2020/03/26 15:49:13:9747] U: myss_state: LWSSSCS_CREATING, ord 0x0 +[2020/03/26 15:49:13:9774] U: myss_state: LWSSSCS_CONNECTING, ord 0x0 +[2020/03/26 15:49:14:1897] U: myss_state: LWSSSCS_CONNECTED, ord 0x0 +[2020/03/26 15:49:14:1926] U: myss_rx: len 1520, flags: 1 +[2020/03/26 15:49:14:1945] U: myss_rx: len 1520, flags: 0 +[2020/03/26 15:49:14:1946] U: myss_rx: len 1520, flags: 0 +[2020/03/26 15:49:14:1947] U: myss_rx: len 1520, flags: 0 +[2020/03/26 15:49:14:1948] U: myss_rx: len 1520, flags: 0 +[2020/03/26 15:49:14:1949] U: myss_rx: len 583, flags: 0 +[2020/03/26 15:49:14:2087] U: myss_rx: len 1520, flags: 0 +[2020/03/26 15:49:14:2089] U: myss_rx: len 1520, flags: 0 +[2020/03/26 15:49:14:2090] U: myss_rx: len 1520, flags: 0 +[2020/03/26 15:49:14:2091] U: myss_rx: len 1520, flags: 0 +[2020/03/26 15:49:14:2092] U: myss_rx: len 1520, flags: 0 +[2020/03/26 15:49:14:2093] U: myss_rx: len 583, flags: 0 +[2020/03/26 15:49:14:2109] U: myss_rx: len 1520, flags: 0 +[2020/03/26 15:49:14:2110] U: myss_rx: len 1520, flags: 0 +[2020/03/26 15:49:14:2111] U: myss_rx: len 1520, flags: 0 +[2020/03/26 15:49:14:2112] U: myss_rx: len 1520, flags: 0 +[2020/03/26 15:49:14:2113] U: myss_rx: len 1520, flags: 0 +[2020/03/26 15:49:14:2114] U: myss_rx: len 583, flags: 0 +[2020/03/26 15:49:14:2135] U: myss_rx: len 1520, flags: 0 +[2020/03/26 15:49:14:2136] U: myss_rx: len 1358, flags: 0 +[2020/03/26 15:49:14:2136] U: myss_rx: len 0, flags: 2 +[2020/03/26 15:49:14:2138] U: myss_state: LWSSSCS_QOS_ACK_REMOTE, ord 0x0 +[2020/03/26 15:49:14:2139] N: myss_state: LWSSSCS_QOS_ACK_REMOTE +[2020/03/26 15:49:14:2170] U: myss_state: LWSSSCS_DISCONNECTED, ord 0x0 +[2020/03/26 15:49:14:2192] U: myss_state: LWSSSCS_DESTROYING, ord 0x0 +[2020/03/26 15:49:14:2265] E: lws_context_destroy3 +[2020/03/26 15:49:14:2282] U: Completed: OK + +``` diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/static-policy.h libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/static-policy.h --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/static-policy.h 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/static-policy.h 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,1513 @@ +/* + * Autogenerated from the following JSON policy + */ + +#if 0 +{ + "release": "01234567", + "product": "myproduct", + "schema-version": 1, + "retry": [{ + "default": { + "backoff": [1000, 2000, 3000, 5000, 10000], + "conceal": 5, + "jitterpc": 20, + "svalidping": 30, + "svalidhup": 35 + } + }], + "certs": [{ + "isrg_root_x1": "MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygch77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6UA5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sWT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyHB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UCB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUvKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWnOlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTnjh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbwqHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CIrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkqhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZLubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KKNFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7UrTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdCjNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVcoyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPAmRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57demyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=" + }, { + "LEX3_isrg_root_x1": "MIIFjTCCA3WgAwIBAgIRANOxciY0IzLc9AUoUSrsnGowDQYJKoZIhvcNAQELBQAwTzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTYxMDA2MTU0MzU1WhcNMjExMDA2MTU0MzU1WjBKMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3MgRW5jcnlwdDEjMCEGA1UEAxMaTGV0J3MgRW5jcnlwdCBBdXRob3JpdHkgWDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCc0wzwWuUuR7dyXTeDs2hjMOrXNSYZJeG9vjXxcJIvt7hLQQWrqZ41CFjssSrEaIcLo+N15Obzp2JxunmBYB/XkZqf89B4Z3HIaQ6Vkc/+5pnpYDxIzH7KTXcSJJ1HG1rrueweNwAcnKx7pwXqzkrrvUHlNpi5y/1tPJZo3yMqQpAMhnRnyH+lmrhSYRQTP2XpgofL2/oOVvaGifOFP5eGr7DcGu9rDZUWfcQroGWymQQ2dYBrrErzG5BJeC+ilk8qICUpBMZ0wNAxzY8xOJUWuqgzuEPxsR/DMH+ieTETPS02+OP88jNquTkxxa/EjQ0dZBYzqvqEKbbUC8DYfcOTAgMBAAGjggFnMIIBYzAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEBATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQub3JnMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8vY3JsLnJvb3QteDEubGV0c2VuY3J5cHQub3JnMHIGCCsGAQUFBwEBBGYwZDAwBggrBgEFBQcwAYYkaHR0cDovL29jc3Aucm9vdC14MS5sZXRzZW5jcnlwdC5vcmcvMDAGCCsGAQUFBzAChiRodHRwOi8vY2VydC5yb290LXgxLmxldHNlbmNyeXB0Lm9yZy8wHwYDVR0jBBgwFoAUebRZ5nu25eQBc4AIiMgaWPbpm24wDQYJKoZIhvcNAQELBQADggIBABnPdSA0LTqmRf/Q1eaM2jLonG4bQdEnqOJQ8nCqxOeTRrToEKtwT++36gTSlBGxA/5dut82jJQ2jxN8RI8L9QFXrWi4xXnA2EqA10yjHiR6H9cj6MFiOnb5In1eWsRMUM2v3e9tNsCAgBukPHAg1lQh07rvFKm/Bz9BCjaxorALINUfZ9DD64j2igLIxle2DPxW8dI/F2loHMjXZjqG8RkqZUdoxtID5+90FgsGIfkMpqgRS05f4zPbCEHqCXl1eO5HyELTgcVlLXXQDgAWnRzut1hFJeczY1tjQQno6f6s+nMydLN26WuU4s3UYvOuOsUxRlJu7TSRHqDC3lSE5XggVkzdaPkuKGQbGpny+01/47hfXXNB7HntWNZ6N2Vwp7G6OfY+YQrZwIaQmhrIqJZuigsrbe3W+gdn5ykE9+Ky0VgVUsfxo52mwFYs1JKY2PGDuWx8M6DlS6qQkvHaRUo0FMd8TsSlbF0/v965qGFKhSDeQoMpYnwcmQilRh/0ayLThlHLN81gSkJjVrPI0Y8xCVPB4twb1PFUd2fPM3sA1tJ83sZ5v8vgFv2yofKRPB0t6JzUA81mSqM3kxl5e+IZwhYAyO0OTg3/fs8HqGTNKd9BqoUwSRBzp06JMg5brUCGwbCUDI0mxadJ3Bz4WxR6fyNpBK2yAinWEsikxqEt" + }, { + "amazon_root_ca_1": "MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsFADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXjca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qwIFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQmjgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUAA4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDIU5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUsN+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vvo/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpyrqXRfboQnoZsG4q5WTP468SQvvG5" + }, { + "digicert_global_root_g2": "MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQq2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5WztCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQvIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NGFdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ918rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTepLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTflMrY=" + }, { + "digicert_global_ca_g2": "MIIEizCCA3OgAwIBAgIQDI7gyQ1qiRWIBAYe4kH5rzANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjAeFw0xMzA4MDExMjAwMDBaFw0yODA4MDExMjAwMDBaMEQxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxHjAcBgNVBAMTFURpZ2lDZXJ0IEdsb2JhbCBDQSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANNIfL7zBYZdW9UvhU5L4IatFaxhz1uvPmoKR/uadpFgC4przc/cV35gmAvkVNlW7SHMArZagV+Xau4CLyMnuG3UsOcGAngLH1ypmTb+u6wbBfpXzYEQQGfWMItYNdSWYb7QjHqXnxr5IuYUL6nG6AEfq/gmD6yOTSwyOR2Bm40cZbIc22GoiS9g5+vCShjEbyrpEJIJ7RfRACvmfe8EiRROM6GyD5eHn7OgzS+8LOy4g2gxPR/VSpAQGQuBldYpdlH5NnbQtwl6OErXb4y/E3w57bqukPyV93t4CTZedJMeJfD/1K2uaGvG/w/VNfFVbkhJ+Pi474j48V4Rd6rfArMCAwEAAaOCAVowggFWMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMHsGA1UdHwR0MHIwN6A1oDOGMWh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RHMi5jcmwwN6A1oDOGMWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RHMi5jcmwwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwHQYDVR0OBBYEFCRuKy3QapJRUSVpAaqaR6aJ50AgMB8GA1UdIwQYMBaAFE4iVCAYlebjbuYP+vq5Eu0GF485MA0GCSqGSIb3DQEBCwUAA4IBAQALOYSR+ZfrqoGvhOlaOJL84mxZvzbIRacxAxHhBsCsMsdaVSnaT0AC9aHesO3ewPj2dZ12uYf+QYB6z13jAMZbAuabeGLJ3LhimnftiQjXS8X9Q9ViIyfEBFltcT8jW+rZ8uckJ2/0lYDblizkVIvP6hnZf1WZUXoOLRg9eFhSvGNoVwvdRLNXSmDmyHBwW4coatc7TlJFGa8kBpJIERqLrqwYElesA8u49L3KJg6nwd3jM+/AVTANlVlOnAM2BvjAjxSZnE0qnsHhfTuvcqdFuhOWKU4Z0BqYBvQ3lBetoxi6PrABDJXWKTUgNX31EGDk92hiHuwZ4STyhxGs6QiA" + }, { + "starfield_services_root_ca": "MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkdiEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6" + }, { + "starfield_class_2_ca": "MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJlxy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q=" + }], + "trust_stores": [{ + "name": "le_via_isrg", + "stack": ["isrg_root_x1", "LEX3_isrg_root_x1"] + }, { + "name": "api_amazon_com", + "stack": ["digicert_global_ca_g2", "digicert_global_root_g2"] + }, { + "name": "avs_via_starfield", + "stack": ["starfield_class_2_ca", "starfield_services_root_ca"] + }, { + "name": "mqtt_amz_iot", + "stack": ["amazon_root_ca_1", "starfield_class_2_ca", "starfield_services_root_ca"] + }], + "s": [{ + "api_amazon_com_auth": { + "endpoint": "api.amazon.com", + "port": 443, + "protocol": "h1", + "http_method": "POST", + "http_url": "auth/o2/token", + "plugins": [], + "opportunistic": true, + "tls": true, + "h2q_oflow_txcr": true, + "http_www_form_urlencoded": true, + "http_no_content_length": true, + "retry": "default", + "tls_trust_store": "api_amazon_com" + } + }, { + "avs_event": { + "endpoint": "alexa.na.gateway.devices.a2z.com", + "port": 443, + "protocol": "h2", + "http_method": "GET", + "http_url": "v20160207/directives", + "h2q_oflow_txcr": true, + "http_auth_header": "authorization:", + "http_auth_preamble": "Bearer ", + "http_no_content_length": true, + "nailed_up": true, + "long_poll": true, + "retry": "default", + "plugins": [], + "tls": true, + "tls_trust_store": "avs_via_starfield" + } + }, { + "avs_metadata": { + "endpoint": "alexa.na.gateway.devices.a2z.com", + "port": 443, + "protocol": "h2", + "http_method": "POST", + "http_url": "v20160207/events", + "opportunistic": true, + "h2q_oflow_txcr": true, + "http_auth_header": "authorization:", + "http_auth_preamble": "Bearer ", + "http_multipart_name": "metadata", + "http_mime_content_type": "application/json; charset=UTF-8", + "http_no_content_length": true, + "rideshare": "avs_audio", + "retry": "default", + "plugins": [], + "tls": true, + "tls_trust_store": "avs_via_starfield" + } + }, { + "avs_audio": { + "endpoint": "alexa.na.gateway.devices.a2z.com", + "port": 443, + "protocol": "h2", + "http_method": "POST", + "http_url": "v20160207/events", + "plugins": [], + "tls": true, + "h2q_oflow_txcr": true, + "http_auth_header": "authorization:", + "http_auth_preamble": "Bearer ", + "http_multipart_name": "audio", + "http_mime_content_type": "application/octet-stream", + "http_no_content_length": true, + "retry": "default", + "tls_trust_store": "avs_via_starfield" + } + }, { + "mintest": { + "endpoint": "warmcat.com", + "port": 443, + "protocol": "h1", + "http_method": "GET", + "http_url": "index.html?uptag=${uptag}", + "http_dsn_header": "x-dsn:", + "http_fwv_header": "x-fw-version:", + "http_devtype_header": "x-devtype:", + "metadata": [{ + "uptag": "X-Upload-Tag:" + }, { + "ctype": "Content-Type:" + }, { + "xctype": "X-Content-Type:" + }], + "plugins": [], + "tls": true, + "opportunistic": true, + "retry": "default", + "tls_trust_store": "le_via_isrg" + } + }, { + "h2longpolltest": { + "endpoint": "warmcat.com", + "port": 443, + "protocol": "h2", + "http_method": "GET", + "http_url": "index.html", + "plugins": [], + "tls": true, + "nailed_up": true, + "long_poll": true, + "retry": "default", + "tls_trust_store": "le_via_isrg" + } + }, { + "mintest-fail": { + "endpoint": "warmcat.com", + "port": 22, + "protocol": "h1", + "http_method": "GET", + "http_url": "index.html", + "plugins": [], + "tls": true, + "opportunistic": true, + "retry": "default", + "tls_trust_store": "le_via_isrg" + } + }, { + "minpost": { + "endpoint": "warmcat.com", + "port": 443, + "protocol": "h1", + "http_method": "POST", + "http_url": "testserver/formtest", + "plugins": [], + "tls": true, + "opportunistic": true, + "retry": "default", + "tls_trust_store": "le_via_isrg" + } + }, { + "mqtt_test": { + "endpoint": "a1ygonr3im5cv2-ats.iot.us-west-2.amazonaws.com", + "port": 443, + "tls": true, + "client_cert": 0, + "tls_trust_store": "mqtt_amz_iot", + "protocol": "mqtt", + "mqtt_topic": "test/topic0", + "mqtt_subscribe": "test/topic0", + "mqtt_qos": 0, + "retry": "default" + } + }, { + "mqtt_test1": { + "endpoint": "a1ygonr3im5cv2-ats.iot.us-west-2.amazonaws.com", + "port": 443, + "tls": true, + "client_cert": 0, + "tls_trust_store": "mqtt_amz_iot", + "protocol": "mqtt", + "mqtt_topic": "test/topic1", + "mqtt_subscribe": "test/topic1", + "mqtt_qos": 1, + "retry": "default" + } + }, { + "captive_portal_detect": { + "endpoint": "connectivitycheck.android.com", + "port": 80, + "protocol": "h1", + "http_method": "GET", + "http_url": "generate_204", + "opportunistic": true, + "http_expect": 204, + "http_fail_redirect": true + } + } + ] +} + + + + + Original JSON size: 15493 +#endif + +static const uint32_t _rbo_bo_0[] = { + 1000, 2000, 3000, 5000, 10000, +}; +static const lws_retry_bo_t _rbo_0 = { + .retry_ms_table = _rbo_bo_0, + .retry_ms_table_count = 5, + .conceal_count = 5, + .secs_since_valid_ping = 30, + .secs_since_valid_hangup = 35, + .jitter_percent = 20, +}; +static const uint8_t _ss_der_amazon_root_ca_1[] = { + /* 0x 0 */ 0x30, 0x82, 0x03, 0x41, 0x30, 0x82, 0x02, 0x29, + /* 0x 8 */ 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x13, 0x06, + /* 0x 10 */ 0x6C, 0x9F, 0xCF, 0x99, 0xBF, 0x8C, 0x0A, 0x39, + /* 0x 18 */ 0xE2, 0xF0, 0x78, 0x8A, 0x43, 0xE6, 0x96, 0x36, + /* 0x 20 */ 0x5B, 0xCA, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + /* 0x 28 */ 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, + /* 0x 30 */ 0x00, 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, + /* 0x 38 */ 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + /* 0x 40 */ 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, + /* 0x 48 */ 0x0A, 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + /* 0x 50 */ 0x6E, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, + /* 0x 58 */ 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, + /* 0x 60 */ 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + /* 0x 68 */ 0x43, 0x41, 0x20, 0x31, 0x30, 0x1E, 0x17, 0x0D, + /* 0x 70 */ 0x31, 0x35, 0x30, 0x35, 0x32, 0x36, 0x30, 0x30, + /* 0x 78 */ 0x30, 0x30, 0x30, 0x30, 0x5A, 0x17, 0x0D, 0x33, + /* 0x 80 */ 0x38, 0x30, 0x31, 0x31, 0x37, 0x30, 0x30, 0x30, + /* 0x 88 */ 0x30, 0x30, 0x30, 0x5A, 0x30, 0x39, 0x31, 0x0B, + /* 0x 90 */ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + /* 0x 98 */ 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, + /* 0x a0 */ 0x03, 0x55, 0x04, 0x0A, 0x13, 0x06, 0x41, 0x6D, + /* 0x a8 */ 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + /* 0x b0 */ 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, + /* 0x b8 */ 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x20, 0x52, 0x6F, + /* 0x c0 */ 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x30, + /* 0x c8 */ 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, + /* 0x d0 */ 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, + /* 0x d8 */ 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, + /* 0x e0 */ 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, + /* 0x e8 */ 0xB2, 0x78, 0x80, 0x71, 0xCA, 0x78, 0xD5, 0xE3, + /* 0x f0 */ 0x71, 0xAF, 0x47, 0x80, 0x50, 0x74, 0x7D, 0x6E, + /* 0x f8 */ 0xD8, 0xD7, 0x88, 0x76, 0xF4, 0x99, 0x68, 0xF7, + /* 0x100 */ 0x58, 0x21, 0x60, 0xF9, 0x74, 0x84, 0x01, 0x2F, + /* 0x108 */ 0xAC, 0x02, 0x2D, 0x86, 0xD3, 0xA0, 0x43, 0x7A, + /* 0x110 */ 0x4E, 0xB2, 0xA4, 0xD0, 0x36, 0xBA, 0x01, 0xBE, + /* 0x118 */ 0x8D, 0xDB, 0x48, 0xC8, 0x07, 0x17, 0x36, 0x4C, + /* 0x120 */ 0xF4, 0xEE, 0x88, 0x23, 0xC7, 0x3E, 0xEB, 0x37, + /* 0x128 */ 0xF5, 0xB5, 0x19, 0xF8, 0x49, 0x68, 0xB0, 0xDE, + /* 0x130 */ 0xD7, 0xB9, 0x76, 0x38, 0x1D, 0x61, 0x9E, 0xA4, + /* 0x138 */ 0xFE, 0x82, 0x36, 0xA5, 0xE5, 0x4A, 0x56, 0xE4, + /* 0x140 */ 0x45, 0xE1, 0xF9, 0xFD, 0xB4, 0x16, 0xFA, 0x74, + /* 0x148 */ 0xDA, 0x9C, 0x9B, 0x35, 0x39, 0x2F, 0xFA, 0xB0, + /* 0x150 */ 0x20, 0x50, 0x06, 0x6C, 0x7A, 0xD0, 0x80, 0xB2, + /* 0x158 */ 0xA6, 0xF9, 0xAF, 0xEC, 0x47, 0x19, 0x8F, 0x50, + /* 0x160 */ 0x38, 0x07, 0xDC, 0xA2, 0x87, 0x39, 0x58, 0xF8, + /* 0x168 */ 0xBA, 0xD5, 0xA9, 0xF9, 0x48, 0x67, 0x30, 0x96, + /* 0x170 */ 0xEE, 0x94, 0x78, 0x5E, 0x6F, 0x89, 0xA3, 0x51, + /* 0x178 */ 0xC0, 0x30, 0x86, 0x66, 0xA1, 0x45, 0x66, 0xBA, + /* 0x180 */ 0x54, 0xEB, 0xA3, 0xC3, 0x91, 0xF9, 0x48, 0xDC, + /* 0x188 */ 0xFF, 0xD1, 0xE8, 0x30, 0x2D, 0x7D, 0x2D, 0x74, + /* 0x190 */ 0x70, 0x35, 0xD7, 0x88, 0x24, 0xF7, 0x9E, 0xC4, + /* 0x198 */ 0x59, 0x6E, 0xBB, 0x73, 0x87, 0x17, 0xF2, 0x32, + /* 0x1a0 */ 0x46, 0x28, 0xB8, 0x43, 0xFA, 0xB7, 0x1D, 0xAA, + /* 0x1a8 */ 0xCA, 0xB4, 0xF2, 0x9F, 0x24, 0x0E, 0x2D, 0x4B, + /* 0x1b0 */ 0xF7, 0x71, 0x5C, 0x5E, 0x69, 0xFF, 0xEA, 0x95, + /* 0x1b8 */ 0x02, 0xCB, 0x38, 0x8A, 0xAE, 0x50, 0x38, 0x6F, + /* 0x1c0 */ 0xDB, 0xFB, 0x2D, 0x62, 0x1B, 0xC5, 0xC7, 0x1E, + /* 0x1c8 */ 0x54, 0xE1, 0x77, 0xE0, 0x67, 0xC8, 0x0F, 0x9C, + /* 0x1d0 */ 0x87, 0x23, 0xD6, 0x3F, 0x40, 0x20, 0x7F, 0x20, + /* 0x1d8 */ 0x80, 0xC4, 0x80, 0x4C, 0x3E, 0x3B, 0x24, 0x26, + /* 0x1e0 */ 0x8E, 0x04, 0xAE, 0x6C, 0x9A, 0xC8, 0xAA, 0x0D, + /* 0x1e8 */ 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x42, 0x30, + /* 0x1f0 */ 0x40, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, + /* 0x1f8 */ 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, + /* 0x200 */ 0x01, 0xFF, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, + /* 0x208 */ 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, + /* 0x210 */ 0x01, 0x86, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, + /* 0x218 */ 0x0E, 0x04, 0x16, 0x04, 0x14, 0x84, 0x18, 0xCC, + /* 0x220 */ 0x85, 0x34, 0xEC, 0xBC, 0x0C, 0x94, 0x94, 0x2E, + /* 0x228 */ 0x08, 0x59, 0x9C, 0xC7, 0xB2, 0x10, 0x4E, 0x0A, + /* 0x230 */ 0x08, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, + /* 0x238 */ 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, + /* 0x240 */ 0x03, 0x82, 0x01, 0x01, 0x00, 0x98, 0xF2, 0x37, + /* 0x248 */ 0x5A, 0x41, 0x90, 0xA1, 0x1A, 0xC5, 0x76, 0x51, + /* 0x250 */ 0x28, 0x20, 0x36, 0x23, 0x0E, 0xAE, 0xE6, 0x28, + /* 0x258 */ 0xBB, 0xAA, 0xF8, 0x94, 0xAE, 0x48, 0xA4, 0x30, + /* 0x260 */ 0x7F, 0x1B, 0xFC, 0x24, 0x8D, 0x4B, 0xB4, 0xC8, + /* 0x268 */ 0xA1, 0x97, 0xF6, 0xB6, 0xF1, 0x7A, 0x70, 0xC8, + /* 0x270 */ 0x53, 0x93, 0xCC, 0x08, 0x28, 0xE3, 0x98, 0x25, + /* 0x278 */ 0xCF, 0x23, 0xA4, 0xF9, 0xDE, 0x21, 0xD3, 0x7C, + /* 0x280 */ 0x85, 0x09, 0xAD, 0x4E, 0x9A, 0x75, 0x3A, 0xC2, + /* 0x288 */ 0x0B, 0x6A, 0x89, 0x78, 0x76, 0x44, 0x47, 0x18, + /* 0x290 */ 0x65, 0x6C, 0x8D, 0x41, 0x8E, 0x3B, 0x7F, 0x9A, + /* 0x298 */ 0xCB, 0xF4, 0xB5, 0xA7, 0x50, 0xD7, 0x05, 0x2C, + /* 0x2a0 */ 0x37, 0xE8, 0x03, 0x4B, 0xAD, 0xE9, 0x61, 0xA0, + /* 0x2a8 */ 0x02, 0x6E, 0xF5, 0xF2, 0xF0, 0xC5, 0xB2, 0xED, + /* 0x2b0 */ 0x5B, 0xB7, 0xDC, 0xFA, 0x94, 0x5C, 0x77, 0x9E, + /* 0x2b8 */ 0x13, 0xA5, 0x7F, 0x52, 0xAD, 0x95, 0xF2, 0xF8, + /* 0x2c0 */ 0x93, 0x3B, 0xDE, 0x8B, 0x5C, 0x5B, 0xCA, 0x5A, + /* 0x2c8 */ 0x52, 0x5B, 0x60, 0xAF, 0x14, 0xF7, 0x4B, 0xEF, + /* 0x2d0 */ 0xA3, 0xFB, 0x9F, 0x40, 0x95, 0x6D, 0x31, 0x54, + /* 0x2d8 */ 0xFC, 0x42, 0xD3, 0xC7, 0x46, 0x1F, 0x23, 0xAD, + /* 0x2e0 */ 0xD9, 0x0F, 0x48, 0x70, 0x9A, 0xD9, 0x75, 0x78, + /* 0x2e8 */ 0x71, 0xD1, 0x72, 0x43, 0x34, 0x75, 0x6E, 0x57, + /* 0x2f0 */ 0x59, 0xC2, 0x02, 0x5C, 0x26, 0x60, 0x29, 0xCF, + /* 0x2f8 */ 0x23, 0x19, 0x16, 0x8E, 0x88, 0x43, 0xA5, 0xD4, + /* 0x300 */ 0xE4, 0xCB, 0x08, 0xFB, 0x23, 0x11, 0x43, 0xE8, + /* 0x308 */ 0x43, 0x29, 0x72, 0x62, 0xA1, 0xA9, 0x5D, 0x5E, + /* 0x310 */ 0x08, 0xD4, 0x90, 0xAE, 0xB8, 0xD8, 0xCE, 0x14, + /* 0x318 */ 0xC2, 0xD0, 0x55, 0xF2, 0x86, 0xF6, 0xC4, 0x93, + /* 0x320 */ 0x43, 0x77, 0x66, 0x61, 0xC0, 0xB9, 0xE8, 0x41, + /* 0x328 */ 0xD7, 0x97, 0x78, 0x60, 0x03, 0x6E, 0x4A, 0x72, + /* 0x330 */ 0xAE, 0xA5, 0xD1, 0x7D, 0xBA, 0x10, 0x9E, 0x86, + /* 0x338 */ 0x6C, 0x1B, 0x8A, 0xB9, 0x59, 0x33, 0xF8, 0xEB, + /* 0x340 */ 0xC4, 0x90, 0xBE, 0xF1, 0xB9, +}; +static const lws_ss_x509_t _ss_x509_amazon_root_ca_1 = { + .vhost_name = "amazon_root_ca_1", + .ca_der = _ss_der_amazon_root_ca_1, + .ca_der_len = 837, +}; +static const uint8_t _ss_der_starfield_class_2_ca[] = { + /* 0x 0 */ 0x30, 0x82, 0x04, 0x0F, 0x30, 0x82, 0x02, 0xF7, + /* 0x 8 */ 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, + /* 0x 10 */ 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + /* 0x 18 */ 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, + /* 0x 20 */ 0x68, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + /* 0x 28 */ 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x25, + /* 0x 30 */ 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, + /* 0x 38 */ 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, + /* 0x 40 */ 0x6C, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, + /* 0x 48 */ 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x2C, + /* 0x 50 */ 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x32, 0x30, + /* 0x 58 */ 0x30, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x29, + /* 0x 60 */ 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, 0x6C, + /* 0x 68 */ 0x64, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, + /* 0x 70 */ 0x32, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + /* 0x 78 */ 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, + /* 0x 80 */ 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, + /* 0x 88 */ 0x79, 0x30, 0x1E, 0x17, 0x0D, 0x30, 0x34, 0x30, + /* 0x 90 */ 0x36, 0x32, 0x39, 0x31, 0x37, 0x33, 0x39, 0x31, + /* 0x 98 */ 0x36, 0x5A, 0x17, 0x0D, 0x33, 0x34, 0x30, 0x36, + /* 0x a0 */ 0x32, 0x39, 0x31, 0x37, 0x33, 0x39, 0x31, 0x36, + /* 0x a8 */ 0x5A, 0x30, 0x68, 0x31, 0x0B, 0x30, 0x09, 0x06, + /* 0x b0 */ 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + /* 0x b8 */ 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, + /* 0x c0 */ 0x0A, 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, + /* 0x c8 */ 0x69, 0x65, 0x6C, 0x64, 0x20, 0x54, 0x65, 0x63, + /* 0x d0 */ 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, + /* 0x d8 */ 0x73, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, + /* 0x e0 */ 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x0B, + /* 0x e8 */ 0x13, 0x29, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, + /* 0x f0 */ 0x65, 0x6C, 0x64, 0x20, 0x43, 0x6C, 0x61, 0x73, + /* 0x f8 */ 0x73, 0x20, 0x32, 0x20, 0x43, 0x65, 0x72, 0x74, + /* 0x100 */ 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, + /* 0x108 */ 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, + /* 0x110 */ 0x69, 0x74, 0x79, 0x30, 0x82, 0x01, 0x20, 0x30, + /* 0x118 */ 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, + /* 0x120 */ 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, + /* 0x128 */ 0x01, 0x0D, 0x00, 0x30, 0x82, 0x01, 0x08, 0x02, + /* 0x130 */ 0x82, 0x01, 0x01, 0x00, 0xB7, 0x32, 0xC8, 0xFE, + /* 0x138 */ 0xE9, 0x71, 0xA6, 0x04, 0x85, 0xAD, 0x0C, 0x11, + /* 0x140 */ 0x64, 0xDF, 0xCE, 0x4D, 0xEF, 0xC8, 0x03, 0x18, + /* 0x148 */ 0x87, 0x3F, 0xA1, 0xAB, 0xFB, 0x3C, 0xA6, 0x9F, + /* 0x150 */ 0xF0, 0xC3, 0xA1, 0xDA, 0xD4, 0xD8, 0x6E, 0x2B, + /* 0x158 */ 0x53, 0x90, 0xFB, 0x24, 0xA4, 0x3E, 0x84, 0xF0, + /* 0x160 */ 0x9E, 0xE8, 0x5F, 0xEC, 0xE5, 0x27, 0x44, 0xF5, + /* 0x168 */ 0x28, 0xA6, 0x3F, 0x7B, 0xDE, 0xE0, 0x2A, 0xF0, + /* 0x170 */ 0xC8, 0xAF, 0x53, 0x2F, 0x9E, 0xCA, 0x05, 0x01, + /* 0x178 */ 0x93, 0x1E, 0x8F, 0x66, 0x1C, 0x39, 0xA7, 0x4D, + /* 0x180 */ 0xFA, 0x5A, 0xB6, 0x73, 0x04, 0x25, 0x66, 0xEB, + /* 0x188 */ 0x77, 0x7F, 0xE7, 0x59, 0xC6, 0x4A, 0x99, 0x25, + /* 0x190 */ 0x14, 0x54, 0xEB, 0x26, 0xC7, 0xF3, 0x7F, 0x19, + /* 0x198 */ 0xD5, 0x30, 0x70, 0x8F, 0xAF, 0xB0, 0x46, 0x2A, + /* 0x1a0 */ 0xFF, 0xAD, 0xEB, 0x29, 0xED, 0xD7, 0x9F, 0xAA, + /* 0x1a8 */ 0x04, 0x87, 0xA3, 0xD4, 0xF9, 0x89, 0xA5, 0x34, + /* 0x1b0 */ 0x5F, 0xDB, 0x43, 0x91, 0x82, 0x36, 0xD9, 0x66, + /* 0x1b8 */ 0x3C, 0xB1, 0xB8, 0xB9, 0x82, 0xFD, 0x9C, 0x3A, + /* 0x1c0 */ 0x3E, 0x10, 0xC8, 0x3B, 0xEF, 0x06, 0x65, 0x66, + /* 0x1c8 */ 0x7A, 0x9B, 0x19, 0x18, 0x3D, 0xFF, 0x71, 0x51, + /* 0x1d0 */ 0x3C, 0x30, 0x2E, 0x5F, 0xBE, 0x3D, 0x77, 0x73, + /* 0x1d8 */ 0xB2, 0x5D, 0x06, 0x6C, 0xC3, 0x23, 0x56, 0x9A, + /* 0x1e0 */ 0x2B, 0x85, 0x26, 0x92, 0x1C, 0xA7, 0x02, 0xB3, + /* 0x1e8 */ 0xE4, 0x3F, 0x0D, 0xAF, 0x08, 0x79, 0x82, 0xB8, + /* 0x1f0 */ 0x36, 0x3D, 0xEA, 0x9C, 0xD3, 0x35, 0xB3, 0xBC, + /* 0x1f8 */ 0x69, 0xCA, 0xF5, 0xCC, 0x9D, 0xE8, 0xFD, 0x64, + /* 0x200 */ 0x8D, 0x17, 0x80, 0x33, 0x6E, 0x5E, 0x4A, 0x5D, + /* 0x208 */ 0x99, 0xC9, 0x1E, 0x87, 0xB4, 0x9D, 0x1A, 0xC0, + /* 0x210 */ 0xD5, 0x6E, 0x13, 0x35, 0x23, 0x5E, 0xDF, 0x9B, + /* 0x218 */ 0x5F, 0x3D, 0xEF, 0xD6, 0xF7, 0x76, 0xC2, 0xEA, + /* 0x220 */ 0x3E, 0xBB, 0x78, 0x0D, 0x1C, 0x42, 0x67, 0x6B, + /* 0x228 */ 0x04, 0xD8, 0xF8, 0xD6, 0xDA, 0x6F, 0x8B, 0xF2, + /* 0x230 */ 0x44, 0xA0, 0x01, 0xAB, 0x02, 0x01, 0x03, 0xA3, + /* 0x238 */ 0x81, 0xC5, 0x30, 0x81, 0xC2, 0x30, 0x1D, 0x06, + /* 0x240 */ 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, + /* 0x248 */ 0xBF, 0x5F, 0xB7, 0xD1, 0xCE, 0xDD, 0x1F, 0x86, + /* 0x250 */ 0xF4, 0x5B, 0x55, 0xAC, 0xDC, 0xD7, 0x10, 0xC2, + /* 0x258 */ 0x0E, 0xA9, 0x88, 0xE7, 0x30, 0x81, 0x92, 0x06, + /* 0x260 */ 0x03, 0x55, 0x1D, 0x23, 0x04, 0x81, 0x8A, 0x30, + /* 0x268 */ 0x81, 0x87, 0x80, 0x14, 0xBF, 0x5F, 0xB7, 0xD1, + /* 0x270 */ 0xCE, 0xDD, 0x1F, 0x86, 0xF4, 0x5B, 0x55, 0xAC, + /* 0x278 */ 0xDC, 0xD7, 0x10, 0xC2, 0x0E, 0xA9, 0x88, 0xE7, + /* 0x280 */ 0xA1, 0x6C, 0xA4, 0x6A, 0x30, 0x68, 0x31, 0x0B, + /* 0x288 */ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + /* 0x290 */ 0x02, 0x55, 0x53, 0x31, 0x25, 0x30, 0x23, 0x06, + /* 0x298 */ 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x53, 0x74, + /* 0x2a0 */ 0x61, 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, + /* 0x2a8 */ 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, + /* 0x2b0 */ 0x67, 0x69, 0x65, 0x73, 0x2C, 0x20, 0x49, 0x6E, + /* 0x2b8 */ 0x63, 0x2E, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, + /* 0x2c0 */ 0x55, 0x04, 0x0B, 0x13, 0x29, 0x53, 0x74, 0x61, + /* 0x2c8 */ 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x43, + /* 0x2d0 */ 0x6C, 0x61, 0x73, 0x73, 0x20, 0x32, 0x20, 0x43, + /* 0x2d8 */ 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + /* 0x2e0 */ 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, + /* 0x2e8 */ 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x82, 0x01, + /* 0x2f0 */ 0x00, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, + /* 0x2f8 */ 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, + /* 0x300 */ 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, + /* 0x308 */ 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, + /* 0x310 */ 0x01, 0x01, 0x00, 0x05, 0x9D, 0x3F, 0x88, 0x9D, + /* 0x318 */ 0xD1, 0xC9, 0x1A, 0x55, 0xA1, 0xAC, 0x69, 0xF3, + /* 0x320 */ 0xF3, 0x59, 0xDA, 0x9B, 0x01, 0x87, 0x1A, 0x4F, + /* 0x328 */ 0x57, 0xA9, 0xA1, 0x79, 0x09, 0x2A, 0xDB, 0xF7, + /* 0x330 */ 0x2F, 0xB2, 0x1E, 0xCC, 0xC7, 0x5E, 0x6A, 0xD8, + /* 0x338 */ 0x83, 0x87, 0xA1, 0x97, 0xEF, 0x49, 0x35, 0x3E, + /* 0x340 */ 0x77, 0x06, 0x41, 0x58, 0x62, 0xBF, 0x8E, 0x58, + /* 0x348 */ 0xB8, 0x0A, 0x67, 0x3F, 0xEC, 0xB3, 0xDD, 0x21, + /* 0x350 */ 0x66, 0x1F, 0xC9, 0x54, 0xFA, 0x72, 0xCC, 0x3D, + /* 0x358 */ 0x4C, 0x40, 0xD8, 0x81, 0xAF, 0x77, 0x9E, 0x83, + /* 0x360 */ 0x7A, 0xBB, 0xA2, 0xC7, 0xF5, 0x34, 0x17, 0x8E, + /* 0x368 */ 0xD9, 0x11, 0x40, 0xF4, 0xFC, 0x2C, 0x2A, 0x4D, + /* 0x370 */ 0x15, 0x7F, 0xA7, 0x62, 0x5D, 0x2E, 0x25, 0xD3, + /* 0x378 */ 0x00, 0x0B, 0x20, 0x1A, 0x1D, 0x68, 0xF9, 0x17, + /* 0x380 */ 0xB8, 0xF4, 0xBD, 0x8B, 0xED, 0x28, 0x59, 0xDD, + /* 0x388 */ 0x4D, 0x16, 0x8B, 0x17, 0x83, 0xC8, 0xB2, 0x65, + /* 0x390 */ 0xC7, 0x2D, 0x7A, 0xA5, 0xAA, 0xBC, 0x53, 0x86, + /* 0x398 */ 0x6D, 0xDD, 0x57, 0xA4, 0xCA, 0xF8, 0x20, 0x41, + /* 0x3a0 */ 0x0B, 0x68, 0xF0, 0xF4, 0xFB, 0x74, 0xBE, 0x56, + /* 0x3a8 */ 0x5D, 0x7A, 0x79, 0xF5, 0xF9, 0x1D, 0x85, 0xE3, + /* 0x3b0 */ 0x2D, 0x95, 0xBE, 0xF5, 0x71, 0x90, 0x43, 0xCC, + /* 0x3b8 */ 0x8D, 0x1F, 0x9A, 0x00, 0x0A, 0x87, 0x29, 0xE9, + /* 0x3c0 */ 0x55, 0x22, 0x58, 0x00, 0x23, 0xEA, 0xE3, 0x12, + /* 0x3c8 */ 0x43, 0x29, 0x5B, 0x47, 0x08, 0xDD, 0x8C, 0x41, + /* 0x3d0 */ 0x6A, 0x65, 0x06, 0xA8, 0xE5, 0x21, 0xAA, 0x41, + /* 0x3d8 */ 0xB4, 0x95, 0x21, 0x95, 0xB9, 0x7D, 0xD1, 0x34, + /* 0x3e0 */ 0xAB, 0x13, 0xD6, 0xAD, 0xBC, 0xDC, 0xE2, 0x3D, + /* 0x3e8 */ 0x39, 0xCD, 0xBD, 0x3E, 0x75, 0x70, 0xA1, 0x18, + /* 0x3f0 */ 0x59, 0x03, 0xC9, 0x22, 0xB4, 0x8F, 0x9C, 0xD5, + /* 0x3f8 */ 0x5E, 0x2A, 0xD7, 0xA5, 0xB6, 0xD4, 0x0A, 0x6D, + /* 0x400 */ 0xF8, 0xB7, 0x40, 0x11, 0x46, 0x9A, 0x1F, 0x79, + /* 0x408 */ 0x0E, 0x62, 0xBF, 0x0F, 0x97, 0xEC, 0xE0, 0x2F, + /* 0x410 */ 0x1F, 0x17, 0x94, +}; +static const lws_ss_x509_t _ss_x509_starfield_class_2_ca = { + .vhost_name = "starfield_class_2_ca", + .ca_der = _ss_der_starfield_class_2_ca, + .ca_der_len = 1043, +}; +static const uint8_t _ss_der_starfield_services_root_ca[] = { + /* 0x 0 */ 0x30, 0x82, 0x03, 0xEF, 0x30, 0x82, 0x02, 0xD7, + /* 0x 8 */ 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, + /* 0x 10 */ 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + /* 0x 18 */ 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, + /* 0x 20 */ 0x81, 0x98, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, + /* 0x 28 */ 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, + /* 0x 30 */ 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x08, + /* 0x 38 */ 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, + /* 0x 40 */ 0x61, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, + /* 0x 48 */ 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F, 0x74, + /* 0x 50 */ 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x25, + /* 0x 58 */ 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, + /* 0x 60 */ 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, + /* 0x 68 */ 0x6C, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, + /* 0x 70 */ 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x2C, + /* 0x 78 */ 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3B, 0x30, + /* 0x 80 */ 0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x32, + /* 0x 88 */ 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, 0x6C, + /* 0x 90 */ 0x64, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + /* 0x 98 */ 0x65, 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + /* 0x a0 */ 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + /* 0x a8 */ 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, + /* 0x b0 */ 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, + /* 0x b8 */ 0x47, 0x32, 0x30, 0x1E, 0x17, 0x0D, 0x30, 0x39, + /* 0x c0 */ 0x30, 0x39, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, + /* 0x c8 */ 0x30, 0x30, 0x5A, 0x17, 0x0D, 0x33, 0x37, 0x31, + /* 0x d0 */ 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, + /* 0x d8 */ 0x39, 0x5A, 0x30, 0x81, 0x98, 0x31, 0x0B, 0x30, + /* 0x e0 */ 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + /* 0x e8 */ 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + /* 0x f0 */ 0x55, 0x04, 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, + /* 0x f8 */ 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13, 0x30, 0x11, + /* 0x100 */ 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, + /* 0x108 */ 0x63, 0x6F, 0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, + /* 0x110 */ 0x65, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, + /* 0x118 */ 0x04, 0x0A, 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, + /* 0x120 */ 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x54, 0x65, + /* 0x128 */ 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, + /* 0x130 */ 0x65, 0x73, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, + /* 0x138 */ 0x31, 0x3B, 0x30, 0x39, 0x06, 0x03, 0x55, 0x04, + /* 0x140 */ 0x03, 0x13, 0x32, 0x53, 0x74, 0x61, 0x72, 0x66, + /* 0x148 */ 0x69, 0x65, 0x6C, 0x64, 0x20, 0x53, 0x65, 0x72, + /* 0x150 */ 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x52, 0x6F, + /* 0x158 */ 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, + /* 0x160 */ 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, + /* 0x168 */ 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, + /* 0x170 */ 0x20, 0x2D, 0x20, 0x47, 0x32, 0x30, 0x82, 0x01, + /* 0x178 */ 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, + /* 0x180 */ 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, + /* 0x188 */ 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, + /* 0x190 */ 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xD5, 0x0C, + /* 0x198 */ 0x3A, 0xC4, 0x2A, 0xF9, 0x4E, 0xE2, 0xF5, 0xBE, + /* 0x1a0 */ 0x19, 0x97, 0x5F, 0x8E, 0x88, 0x53, 0xB1, 0x1F, + /* 0x1a8 */ 0x3F, 0xCB, 0xCF, 0x9F, 0x20, 0x13, 0x6D, 0x29, + /* 0x1b0 */ 0x3A, 0xC8, 0x0F, 0x7D, 0x3C, 0xF7, 0x6B, 0x76, + /* 0x1b8 */ 0x38, 0x63, 0xD9, 0x36, 0x60, 0xA8, 0x9B, 0x5E, + /* 0x1c0 */ 0x5C, 0x00, 0x80, 0xB2, 0x2F, 0x59, 0x7F, 0xF6, + /* 0x1c8 */ 0x87, 0xF9, 0x25, 0x43, 0x86, 0xE7, 0x69, 0x1B, + /* 0x1d0 */ 0x52, 0x9A, 0x90, 0xE1, 0x71, 0xE3, 0xD8, 0x2D, + /* 0x1d8 */ 0x0D, 0x4E, 0x6F, 0xF6, 0xC8, 0x49, 0xD9, 0xB6, + /* 0x1e0 */ 0xF3, 0x1A, 0x56, 0xAE, 0x2B, 0xB6, 0x74, 0x14, + /* 0x1e8 */ 0xEB, 0xCF, 0xFB, 0x26, 0xE3, 0x1A, 0xBA, 0x1D, + /* 0x1f0 */ 0x96, 0x2E, 0x6A, 0x3B, 0x58, 0x94, 0x89, 0x47, + /* 0x1f8 */ 0x56, 0xFF, 0x25, 0xA0, 0x93, 0x70, 0x53, 0x83, + /* 0x200 */ 0xDA, 0x84, 0x74, 0x14, 0xC3, 0x67, 0x9E, 0x04, + /* 0x208 */ 0x68, 0x3A, 0xDF, 0x8E, 0x40, 0x5A, 0x1D, 0x4A, + /* 0x210 */ 0x4E, 0xCF, 0x43, 0x91, 0x3B, 0xE7, 0x56, 0xD6, + /* 0x218 */ 0x00, 0x70, 0xCB, 0x52, 0xEE, 0x7B, 0x7D, 0xAE, + /* 0x220 */ 0x3A, 0xE7, 0xBC, 0x31, 0xF9, 0x45, 0xF6, 0xC2, + /* 0x228 */ 0x60, 0xCF, 0x13, 0x59, 0x02, 0x2B, 0x80, 0xCC, + /* 0x230 */ 0x34, 0x47, 0xDF, 0xB9, 0xDE, 0x90, 0x65, 0x6D, + /* 0x238 */ 0x02, 0xCF, 0x2C, 0x91, 0xA6, 0xA6, 0xE7, 0xDE, + /* 0x240 */ 0x85, 0x18, 0x49, 0x7C, 0x66, 0x4E, 0xA3, 0x3A, + /* 0x248 */ 0x6D, 0xA9, 0xB5, 0xEE, 0x34, 0x2E, 0xBA, 0x0D, + /* 0x250 */ 0x03, 0xB8, 0x33, 0xDF, 0x47, 0xEB, 0xB1, 0x6B, + /* 0x258 */ 0x8D, 0x25, 0xD9, 0x9B, 0xCE, 0x81, 0xD1, 0x45, + /* 0x260 */ 0x46, 0x32, 0x96, 0x70, 0x87, 0xDE, 0x02, 0x0E, + /* 0x268 */ 0x49, 0x43, 0x85, 0xB6, 0x6C, 0x73, 0xBB, 0x64, + /* 0x270 */ 0xEA, 0x61, 0x41, 0xAC, 0xC9, 0xD4, 0x54, 0xDF, + /* 0x278 */ 0x87, 0x2F, 0xC7, 0x22, 0xB2, 0x26, 0xCC, 0x9F, + /* 0x280 */ 0x59, 0x54, 0x68, 0x9F, 0xFC, 0xBE, 0x2A, 0x2F, + /* 0x288 */ 0xC4, 0x55, 0x1C, 0x75, 0x40, 0x60, 0x17, 0x85, + /* 0x290 */ 0x02, 0x55, 0x39, 0x8B, 0x7F, 0x05, 0x02, 0x03, + /* 0x298 */ 0x01, 0x00, 0x01, 0xA3, 0x42, 0x30, 0x40, 0x30, + /* 0x2a0 */ 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, + /* 0x2a8 */ 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, + /* 0x2b0 */ 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, + /* 0x2b8 */ 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, + /* 0x2c0 */ 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, + /* 0x2c8 */ 0x16, 0x04, 0x14, 0x9C, 0x5F, 0x00, 0xDF, 0xAA, + /* 0x2d0 */ 0x01, 0xD7, 0x30, 0x2B, 0x38, 0x88, 0xA2, 0xB8, + /* 0x2d8 */ 0x6D, 0x4A, 0x9C, 0xF2, 0x11, 0x91, 0x83, 0x30, + /* 0x2e0 */ 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, + /* 0x2e8 */ 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, + /* 0x2f0 */ 0x01, 0x01, 0x00, 0x4B, 0x36, 0xA6, 0x84, 0x77, + /* 0x2f8 */ 0x69, 0xDD, 0x3B, 0x19, 0x9F, 0x67, 0x23, 0x08, + /* 0x300 */ 0x6F, 0x0E, 0x61, 0xC9, 0xFD, 0x84, 0xDC, 0x5F, + /* 0x308 */ 0xD8, 0x36, 0x81, 0xCD, 0xD8, 0x1B, 0x41, 0x2D, + /* 0x310 */ 0x9F, 0x60, 0xDD, 0xC7, 0x1A, 0x68, 0xD9, 0xD1, + /* 0x318 */ 0x6E, 0x86, 0xE1, 0x88, 0x23, 0xCF, 0x13, 0xDE, + /* 0x320 */ 0x43, 0xCF, 0xE2, 0x34, 0xB3, 0x04, 0x9D, 0x1F, + /* 0x328 */ 0x29, 0xD5, 0xBF, 0xF8, 0x5E, 0xC8, 0xD5, 0xC1, + /* 0x330 */ 0xBD, 0xEE, 0x92, 0x6F, 0x32, 0x74, 0xF2, 0x91, + /* 0x338 */ 0x82, 0x2F, 0xBD, 0x82, 0x42, 0x7A, 0xAD, 0x2A, + /* 0x340 */ 0xB7, 0x20, 0x7D, 0x4D, 0xBC, 0x7A, 0x55, 0x12, + /* 0x348 */ 0xC2, 0x15, 0xEA, 0xBD, 0xF7, 0x6A, 0x95, 0x2E, + /* 0x350 */ 0x6C, 0x74, 0x9F, 0xCF, 0x1C, 0xB4, 0xF2, 0xC5, + /* 0x358 */ 0x01, 0xA3, 0x85, 0xD0, 0x72, 0x3E, 0xAD, 0x73, + /* 0x360 */ 0xAB, 0x0B, 0x9B, 0x75, 0x0C, 0x6D, 0x45, 0xB7, + /* 0x368 */ 0x8E, 0x94, 0xAC, 0x96, 0x37, 0xB5, 0xA0, 0xD0, + /* 0x370 */ 0x8F, 0x15, 0x47, 0x0E, 0xE3, 0xE8, 0x83, 0xDD, + /* 0x378 */ 0x8F, 0xFD, 0xEF, 0x41, 0x01, 0x77, 0xCC, 0x27, + /* 0x380 */ 0xA9, 0x62, 0x85, 0x33, 0xF2, 0x37, 0x08, 0xEF, + /* 0x388 */ 0x71, 0xCF, 0x77, 0x06, 0xDE, 0xC8, 0x19, 0x1D, + /* 0x390 */ 0x88, 0x40, 0xCF, 0x7D, 0x46, 0x1D, 0xFF, 0x1E, + /* 0x398 */ 0xC7, 0xE1, 0xCE, 0xFF, 0x23, 0xDB, 0xC6, 0xFA, + /* 0x3a0 */ 0x8D, 0x55, 0x4E, 0xA9, 0x02, 0xE7, 0x47, 0x11, + /* 0x3a8 */ 0x46, 0x3E, 0xF4, 0xFD, 0xBD, 0x7B, 0x29, 0x26, + /* 0x3b0 */ 0xBB, 0xA9, 0x61, 0x62, 0x37, 0x28, 0xB6, 0x2D, + /* 0x3b8 */ 0x2A, 0xF6, 0x10, 0x86, 0x64, 0xC9, 0x70, 0xA7, + /* 0x3c0 */ 0xD2, 0xAD, 0xB7, 0x29, 0x70, 0x79, 0xEA, 0x3C, + /* 0x3c8 */ 0xDA, 0x63, 0x25, 0x9F, 0xFD, 0x68, 0xB7, 0x30, + /* 0x3d0 */ 0xEC, 0x70, 0xFB, 0x75, 0x8A, 0xB7, 0x6D, 0x60, + /* 0x3d8 */ 0x67, 0xB2, 0x1E, 0xC8, 0xB9, 0xE9, 0xD8, 0xA8, + /* 0x3e0 */ 0x6F, 0x02, 0x8B, 0x67, 0x0D, 0x4D, 0x26, 0x57, + /* 0x3e8 */ 0x71, 0xDA, 0x20, 0xFC, 0xC1, 0x4A, 0x50, 0x8D, + /* 0x3f0 */ 0xB1, 0x28, 0xBA, +}; +static const lws_ss_x509_t _ss_x509_starfield_services_root_ca = { + .vhost_name = "starfield_services_root_ca", + .ca_der = _ss_der_starfield_services_root_ca, + .ca_der_len = 1011, +}; +static const lws_ss_trust_store_t _ss_ts_mqtt_amz_iot = { + .name = "mqtt_amz_iot", + .ssx509 = { + &_ss_x509_starfield_services_root_ca, + &_ss_x509_starfield_class_2_ca, + &_ss_x509_amazon_root_ca_1, + } +}; +static const uint8_t _ss_der_isrg_root_x1[] = { + /* 0x 0 */ 0x30, 0x82, 0x05, 0x6B, 0x30, 0x82, 0x03, 0x53, + /* 0x 8 */ 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x11, 0x00, + /* 0x 10 */ 0x82, 0x10, 0xCF, 0xB0, 0xD2, 0x40, 0xE3, 0x59, + /* 0x 18 */ 0x44, 0x63, 0xE0, 0xBB, 0x63, 0x82, 0x8B, 0x00, + /* 0x 20 */ 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + /* 0x 28 */ 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, + /* 0x 30 */ 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + /* 0x 38 */ 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x29, + /* 0x 40 */ 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, + /* 0x 48 */ 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, + /* 0x 50 */ 0x74, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, + /* 0x 58 */ 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, + /* 0x 60 */ 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6F, 0x75, + /* 0x 68 */ 0x70, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, + /* 0x 70 */ 0x04, 0x03, 0x13, 0x0C, 0x49, 0x53, 0x52, 0x47, + /* 0x 78 */ 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, 0x31, + /* 0x 80 */ 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x35, 0x30, 0x36, + /* 0x 88 */ 0x30, 0x34, 0x31, 0x31, 0x30, 0x34, 0x33, 0x38, + /* 0x 90 */ 0x5A, 0x17, 0x0D, 0x33, 0x35, 0x30, 0x36, 0x30, + /* 0x 98 */ 0x34, 0x31, 0x31, 0x30, 0x34, 0x33, 0x38, 0x5A, + /* 0x a0 */ 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, + /* 0x a8 */ 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, + /* 0x b0 */ 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0A, + /* 0x b8 */ 0x13, 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, + /* 0x c0 */ 0x65, 0x74, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, + /* 0x c8 */ 0x69, 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, + /* 0x d0 */ 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6F, + /* 0x d8 */ 0x75, 0x70, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, + /* 0x e0 */ 0x55, 0x04, 0x03, 0x13, 0x0C, 0x49, 0x53, 0x52, + /* 0x e8 */ 0x47, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, + /* 0x f0 */ 0x31, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0D, 0x06, + /* 0x f8 */ 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + /* 0x100 */ 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0F, + /* 0x108 */ 0x00, 0x30, 0x82, 0x02, 0x0A, 0x02, 0x82, 0x02, + /* 0x110 */ 0x01, 0x00, 0xAD, 0xE8, 0x24, 0x73, 0xF4, 0x14, + /* 0x118 */ 0x37, 0xF3, 0x9B, 0x9E, 0x2B, 0x57, 0x28, 0x1C, + /* 0x120 */ 0x87, 0xBE, 0xDC, 0xB7, 0xDF, 0x38, 0x90, 0x8C, + /* 0x128 */ 0x6E, 0x3C, 0xE6, 0x57, 0xA0, 0x78, 0xF7, 0x75, + /* 0x130 */ 0xC2, 0xA2, 0xFE, 0xF5, 0x6A, 0x6E, 0xF6, 0x00, + /* 0x138 */ 0x4F, 0x28, 0xDB, 0xDE, 0x68, 0x86, 0x6C, 0x44, + /* 0x140 */ 0x93, 0xB6, 0xB1, 0x63, 0xFD, 0x14, 0x12, 0x6B, + /* 0x148 */ 0xBF, 0x1F, 0xD2, 0xEA, 0x31, 0x9B, 0x21, 0x7E, + /* 0x150 */ 0xD1, 0x33, 0x3C, 0xBA, 0x48, 0xF5, 0xDD, 0x79, + /* 0x158 */ 0xDF, 0xB3, 0xB8, 0xFF, 0x12, 0xF1, 0x21, 0x9A, + /* 0x160 */ 0x4B, 0xC1, 0x8A, 0x86, 0x71, 0x69, 0x4A, 0x66, + /* 0x168 */ 0x66, 0x6C, 0x8F, 0x7E, 0x3C, 0x70, 0xBF, 0xAD, + /* 0x170 */ 0x29, 0x22, 0x06, 0xF3, 0xE4, 0xC0, 0xE6, 0x80, + /* 0x178 */ 0xAE, 0xE2, 0x4B, 0x8F, 0xB7, 0x99, 0x7E, 0x94, + /* 0x180 */ 0x03, 0x9F, 0xD3, 0x47, 0x97, 0x7C, 0x99, 0x48, + /* 0x188 */ 0x23, 0x53, 0xE8, 0x38, 0xAE, 0x4F, 0x0A, 0x6F, + /* 0x190 */ 0x83, 0x2E, 0xD1, 0x49, 0x57, 0x8C, 0x80, 0x74, + /* 0x198 */ 0xB6, 0xDA, 0x2F, 0xD0, 0x38, 0x8D, 0x7B, 0x03, + /* 0x1a0 */ 0x70, 0x21, 0x1B, 0x75, 0xF2, 0x30, 0x3C, 0xFA, + /* 0x1a8 */ 0x8F, 0xAE, 0xDD, 0xDA, 0x63, 0xAB, 0xEB, 0x16, + /* 0x1b0 */ 0x4F, 0xC2, 0x8E, 0x11, 0x4B, 0x7E, 0xCF, 0x0B, + /* 0x1b8 */ 0xE8, 0xFF, 0xB5, 0x77, 0x2E, 0xF4, 0xB2, 0x7B, + /* 0x1c0 */ 0x4A, 0xE0, 0x4C, 0x12, 0x25, 0x0C, 0x70, 0x8D, + /* 0x1c8 */ 0x03, 0x29, 0xA0, 0xE1, 0x53, 0x24, 0xEC, 0x13, + /* 0x1d0 */ 0xD9, 0xEE, 0x19, 0xBF, 0x10, 0xB3, 0x4A, 0x8C, + /* 0x1d8 */ 0x3F, 0x89, 0xA3, 0x61, 0x51, 0xDE, 0xAC, 0x87, + /* 0x1e0 */ 0x07, 0x94, 0xF4, 0x63, 0x71, 0xEC, 0x2E, 0xE2, + /* 0x1e8 */ 0x6F, 0x5B, 0x98, 0x81, 0xE1, 0x89, 0x5C, 0x34, + /* 0x1f0 */ 0x79, 0x6C, 0x76, 0xEF, 0x3B, 0x90, 0x62, 0x79, + /* 0x1f8 */ 0xE6, 0xDB, 0xA4, 0x9A, 0x2F, 0x26, 0xC5, 0xD0, + /* 0x200 */ 0x10, 0xE1, 0x0E, 0xDE, 0xD9, 0x10, 0x8E, 0x16, + /* 0x208 */ 0xFB, 0xB7, 0xF7, 0xA8, 0xF7, 0xC7, 0xE5, 0x02, + /* 0x210 */ 0x07, 0x98, 0x8F, 0x36, 0x08, 0x95, 0xE7, 0xE2, + /* 0x218 */ 0x37, 0x96, 0x0D, 0x36, 0x75, 0x9E, 0xFB, 0x0E, + /* 0x220 */ 0x72, 0xB1, 0x1D, 0x9B, 0xBC, 0x03, 0xF9, 0x49, + /* 0x228 */ 0x05, 0xD8, 0x81, 0xDD, 0x05, 0xB4, 0x2A, 0xD6, + /* 0x230 */ 0x41, 0xE9, 0xAC, 0x01, 0x76, 0x95, 0x0A, 0x0F, + /* 0x238 */ 0xD8, 0xDF, 0xD5, 0xBD, 0x12, 0x1F, 0x35, 0x2F, + /* 0x240 */ 0x28, 0x17, 0x6C, 0xD2, 0x98, 0xC1, 0xA8, 0x09, + /* 0x248 */ 0x64, 0x77, 0x6E, 0x47, 0x37, 0xBA, 0xCE, 0xAC, + /* 0x250 */ 0x59, 0x5E, 0x68, 0x9D, 0x7F, 0x72, 0xD6, 0x89, + /* 0x258 */ 0xC5, 0x06, 0x41, 0x29, 0x3E, 0x59, 0x3E, 0xDD, + /* 0x260 */ 0x26, 0xF5, 0x24, 0xC9, 0x11, 0xA7, 0x5A, 0xA3, + /* 0x268 */ 0x4C, 0x40, 0x1F, 0x46, 0xA1, 0x99, 0xB5, 0xA7, + /* 0x270 */ 0x3A, 0x51, 0x6E, 0x86, 0x3B, 0x9E, 0x7D, 0x72, + /* 0x278 */ 0xA7, 0x12, 0x05, 0x78, 0x59, 0xED, 0x3E, 0x51, + /* 0x280 */ 0x78, 0x15, 0x0B, 0x03, 0x8F, 0x8D, 0xD0, 0x2F, + /* 0x288 */ 0x05, 0xB2, 0x3E, 0x7B, 0x4A, 0x1C, 0x4B, 0x73, + /* 0x290 */ 0x05, 0x12, 0xFC, 0xC6, 0xEA, 0xE0, 0x50, 0x13, + /* 0x298 */ 0x7C, 0x43, 0x93, 0x74, 0xB3, 0xCA, 0x74, 0xE7, + /* 0x2a0 */ 0x8E, 0x1F, 0x01, 0x08, 0xD0, 0x30, 0xD4, 0x5B, + /* 0x2a8 */ 0x71, 0x36, 0xB4, 0x07, 0xBA, 0xC1, 0x30, 0x30, + /* 0x2b0 */ 0x5C, 0x48, 0xB7, 0x82, 0x3B, 0x98, 0xA6, 0x7D, + /* 0x2b8 */ 0x60, 0x8A, 0xA2, 0xA3, 0x29, 0x82, 0xCC, 0xBA, + /* 0x2c0 */ 0xBD, 0x83, 0x04, 0x1B, 0xA2, 0x83, 0x03, 0x41, + /* 0x2c8 */ 0xA1, 0xD6, 0x05, 0xF1, 0x1B, 0xC2, 0xB6, 0xF0, + /* 0x2d0 */ 0xA8, 0x7C, 0x86, 0x3B, 0x46, 0xA8, 0x48, 0x2A, + /* 0x2d8 */ 0x88, 0xDC, 0x76, 0x9A, 0x76, 0xBF, 0x1F, 0x6A, + /* 0x2e0 */ 0xA5, 0x3D, 0x19, 0x8F, 0xEB, 0x38, 0xF3, 0x64, + /* 0x2e8 */ 0xDE, 0xC8, 0x2B, 0x0D, 0x0A, 0x28, 0xFF, 0xF7, + /* 0x2f0 */ 0xDB, 0xE2, 0x15, 0x42, 0xD4, 0x22, 0xD0, 0x27, + /* 0x2f8 */ 0x5D, 0xE1, 0x79, 0xFE, 0x18, 0xE7, 0x70, 0x88, + /* 0x300 */ 0xAD, 0x4E, 0xE6, 0xD9, 0x8B, 0x3A, 0xC6, 0xDD, + /* 0x308 */ 0x27, 0x51, 0x6E, 0xFF, 0xBC, 0x64, 0xF5, 0x33, + /* 0x310 */ 0x43, 0x4F, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, + /* 0x318 */ 0x42, 0x30, 0x40, 0x30, 0x0E, 0x06, 0x03, 0x55, + /* 0x320 */ 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, + /* 0x328 */ 0x02, 0x01, 0x06, 0x30, 0x0F, 0x06, 0x03, 0x55, + /* 0x330 */ 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, + /* 0x338 */ 0x03, 0x01, 0x01, 0xFF, 0x30, 0x1D, 0x06, 0x03, + /* 0x340 */ 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x79, + /* 0x348 */ 0xB4, 0x59, 0xE6, 0x7B, 0xB6, 0xE5, 0xE4, 0x01, + /* 0x350 */ 0x73, 0x80, 0x08, 0x88, 0xC8, 0x1A, 0x58, 0xF6, + /* 0x358 */ 0xE9, 0x9B, 0x6E, 0x30, 0x0D, 0x06, 0x09, 0x2A, + /* 0x360 */ 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, + /* 0x368 */ 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x55, + /* 0x370 */ 0x1F, 0x58, 0xA9, 0xBC, 0xB2, 0xA8, 0x50, 0xD0, + /* 0x378 */ 0x0C, 0xB1, 0xD8, 0x1A, 0x69, 0x20, 0x27, 0x29, + /* 0x380 */ 0x08, 0xAC, 0x61, 0x75, 0x5C, 0x8A, 0x6E, 0xF8, + /* 0x388 */ 0x82, 0xE5, 0x69, 0x2F, 0xD5, 0xF6, 0x56, 0x4B, + /* 0x390 */ 0xB9, 0xB8, 0x73, 0x10, 0x59, 0xD3, 0x21, 0x97, + /* 0x398 */ 0x7E, 0xE7, 0x4C, 0x71, 0xFB, 0xB2, 0xD2, 0x60, + /* 0x3a0 */ 0xAD, 0x39, 0xA8, 0x0B, 0xEA, 0x17, 0x21, 0x56, + /* 0x3a8 */ 0x85, 0xF1, 0x50, 0x0E, 0x59, 0xEB, 0xCE, 0xE0, + /* 0x3b0 */ 0x59, 0xE9, 0xBA, 0xC9, 0x15, 0xEF, 0x86, 0x9D, + /* 0x3b8 */ 0x8F, 0x84, 0x80, 0xF6, 0xE4, 0xE9, 0x91, 0x90, + /* 0x3c0 */ 0xDC, 0x17, 0x9B, 0x62, 0x1B, 0x45, 0xF0, 0x66, + /* 0x3c8 */ 0x95, 0xD2, 0x7C, 0x6F, 0xC2, 0xEA, 0x3B, 0xEF, + /* 0x3d0 */ 0x1F, 0xCF, 0xCB, 0xD6, 0xAE, 0x27, 0xF1, 0xA9, + /* 0x3d8 */ 0xB0, 0xC8, 0xAE, 0xFD, 0x7D, 0x7E, 0x9A, 0xFA, + /* 0x3e0 */ 0x22, 0x04, 0xEB, 0xFF, 0xD9, 0x7F, 0xEA, 0x91, + /* 0x3e8 */ 0x2B, 0x22, 0xB1, 0x17, 0x0E, 0x8F, 0xF2, 0x8A, + /* 0x3f0 */ 0x34, 0x5B, 0x58, 0xD8, 0xFC, 0x01, 0xC9, 0x54, + /* 0x3f8 */ 0xB9, 0xB8, 0x26, 0xCC, 0x8A, 0x88, 0x33, 0x89, + /* 0x400 */ 0x4C, 0x2D, 0x84, 0x3C, 0x82, 0xDF, 0xEE, 0x96, + /* 0x408 */ 0x57, 0x05, 0xBA, 0x2C, 0xBB, 0xF7, 0xC4, 0xB7, + /* 0x410 */ 0xC7, 0x4E, 0x3B, 0x82, 0xBE, 0x31, 0xC8, 0x22, + /* 0x418 */ 0x73, 0x73, 0x92, 0xD1, 0xC2, 0x80, 0xA4, 0x39, + /* 0x420 */ 0x39, 0x10, 0x33, 0x23, 0x82, 0x4C, 0x3C, 0x9F, + /* 0x428 */ 0x86, 0xB2, 0x55, 0x98, 0x1D, 0xBE, 0x29, 0x86, + /* 0x430 */ 0x8C, 0x22, 0x9B, 0x9E, 0xE2, 0x6B, 0x3B, 0x57, + /* 0x438 */ 0x3A, 0x82, 0x70, 0x4D, 0xDC, 0x09, 0xC7, 0x89, + /* 0x440 */ 0xCB, 0x0A, 0x07, 0x4D, 0x6C, 0xE8, 0x5D, 0x8E, + /* 0x448 */ 0xC9, 0xEF, 0xCE, 0xAB, 0xC7, 0xBB, 0xB5, 0x2B, + /* 0x450 */ 0x4E, 0x45, 0xD6, 0x4A, 0xD0, 0x26, 0xCC, 0xE5, + /* 0x458 */ 0x72, 0xCA, 0x08, 0x6A, 0xA5, 0x95, 0xE3, 0x15, + /* 0x460 */ 0xA1, 0xF7, 0xA4, 0xED, 0xC9, 0x2C, 0x5F, 0xA5, + /* 0x468 */ 0xFB, 0xFF, 0xAC, 0x28, 0x02, 0x2E, 0xBE, 0xD7, + /* 0x470 */ 0x7B, 0xBB, 0xE3, 0x71, 0x7B, 0x90, 0x16, 0xD3, + /* 0x478 */ 0x07, 0x5E, 0x46, 0x53, 0x7C, 0x37, 0x07, 0x42, + /* 0x480 */ 0x8C, 0xD3, 0xC4, 0x96, 0x9C, 0xD5, 0x99, 0xB5, + /* 0x488 */ 0x2A, 0xE0, 0x95, 0x1A, 0x80, 0x48, 0xAE, 0x4C, + /* 0x490 */ 0x39, 0x07, 0xCE, 0xCC, 0x47, 0xA4, 0x52, 0x95, + /* 0x498 */ 0x2B, 0xBA, 0xB8, 0xFB, 0xAD, 0xD2, 0x33, 0x53, + /* 0x4a0 */ 0x7D, 0xE5, 0x1D, 0x4D, 0x6D, 0xD5, 0xA1, 0xB1, + /* 0x4a8 */ 0xC7, 0x42, 0x6F, 0xE6, 0x40, 0x27, 0x35, 0x5C, + /* 0x4b0 */ 0xA3, 0x28, 0xB7, 0x07, 0x8D, 0xE7, 0x8D, 0x33, + /* 0x4b8 */ 0x90, 0xE7, 0x23, 0x9F, 0xFB, 0x50, 0x9C, 0x79, + /* 0x4c0 */ 0x6C, 0x46, 0xD5, 0xB4, 0x15, 0xB3, 0x96, 0x6E, + /* 0x4c8 */ 0x7E, 0x9B, 0x0C, 0x96, 0x3A, 0xB8, 0x52, 0x2D, + /* 0x4d0 */ 0x3F, 0xD6, 0x5B, 0xE1, 0xFB, 0x08, 0xC2, 0x84, + /* 0x4d8 */ 0xFE, 0x24, 0xA8, 0xA3, 0x89, 0xDA, 0xAC, 0x6A, + /* 0x4e0 */ 0xE1, 0x18, 0x2A, 0xB1, 0xA8, 0x43, 0x61, 0x5B, + /* 0x4e8 */ 0xD3, 0x1F, 0xDC, 0x3B, 0x8D, 0x76, 0xF2, 0x2D, + /* 0x4f0 */ 0xE8, 0x8D, 0x75, 0xDF, 0x17, 0x33, 0x6C, 0x3D, + /* 0x4f8 */ 0x53, 0xFB, 0x7B, 0xCB, 0x41, 0x5F, 0xFF, 0xDC, + /* 0x500 */ 0xA2, 0xD0, 0x61, 0x38, 0xE1, 0x96, 0xB8, 0xAC, + /* 0x508 */ 0x5D, 0x8B, 0x37, 0xD7, 0x75, 0xD5, 0x33, 0xC0, + /* 0x510 */ 0x99, 0x11, 0xAE, 0x9D, 0x41, 0xC1, 0x72, 0x75, + /* 0x518 */ 0x84, 0xBE, 0x02, 0x41, 0x42, 0x5F, 0x67, 0x24, + /* 0x520 */ 0x48, 0x94, 0xD1, 0x9B, 0x27, 0xBE, 0x07, 0x3F, + /* 0x528 */ 0xB9, 0xB8, 0x4F, 0x81, 0x74, 0x51, 0xE1, 0x7A, + /* 0x530 */ 0xB7, 0xED, 0x9D, 0x23, 0xE2, 0xBE, 0xE0, 0xD5, + /* 0x538 */ 0x28, 0x04, 0x13, 0x3C, 0x31, 0x03, 0x9E, 0xDD, + /* 0x540 */ 0x7A, 0x6C, 0x8F, 0xC6, 0x07, 0x18, 0xC6, 0x7F, + /* 0x548 */ 0xDE, 0x47, 0x8E, 0x3F, 0x28, 0x9E, 0x04, 0x06, + /* 0x550 */ 0xCF, 0xA5, 0x54, 0x34, 0x77, 0xBD, 0xEC, 0x89, + /* 0x558 */ 0x9B, 0xE9, 0x17, 0x43, 0xDF, 0x5B, 0xDB, 0x5F, + /* 0x560 */ 0xFE, 0x8E, 0x1E, 0x57, 0xA2, 0xCD, 0x40, 0x9D, + /* 0x568 */ 0x7E, 0x62, 0x22, 0xDA, 0xDE, 0x18, 0x27, +}; +static const lws_ss_x509_t _ss_x509_isrg_root_x1 = { + .vhost_name = "isrg_root_x1", + .ca_der = _ss_der_isrg_root_x1, + .ca_der_len = 1391, +}; +static const uint8_t _ss_der_LEX3_isrg_root_x1[] = { + /* 0x 0 */ 0x30, 0x82, 0x05, 0x8D, 0x30, 0x82, 0x03, 0x75, + /* 0x 8 */ 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x11, 0x00, + /* 0x 10 */ 0xD3, 0xB1, 0x72, 0x26, 0x34, 0x23, 0x32, 0xDC, + /* 0x 18 */ 0xF4, 0x05, 0x28, 0x51, 0x2A, 0xEC, 0x9C, 0x6A, + /* 0x 20 */ 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + /* 0x 28 */ 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, + /* 0x 30 */ 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + /* 0x 38 */ 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x29, + /* 0x 40 */ 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, + /* 0x 48 */ 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, + /* 0x 50 */ 0x74, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, + /* 0x 58 */ 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, + /* 0x 60 */ 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6F, 0x75, + /* 0x 68 */ 0x70, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, + /* 0x 70 */ 0x04, 0x03, 0x13, 0x0C, 0x49, 0x53, 0x52, 0x47, + /* 0x 78 */ 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, 0x31, + /* 0x 80 */ 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x36, 0x31, 0x30, + /* 0x 88 */ 0x30, 0x36, 0x31, 0x35, 0x34, 0x33, 0x35, 0x35, + /* 0x 90 */ 0x5A, 0x17, 0x0D, 0x32, 0x31, 0x31, 0x30, 0x30, + /* 0x 98 */ 0x36, 0x31, 0x35, 0x34, 0x33, 0x35, 0x35, 0x5A, + /* 0x a0 */ 0x30, 0x4A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, + /* 0x a8 */ 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, + /* 0x b0 */ 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, + /* 0x b8 */ 0x13, 0x0D, 0x4C, 0x65, 0x74, 0x27, 0x73, 0x20, + /* 0x c0 */ 0x45, 0x6E, 0x63, 0x72, 0x79, 0x70, 0x74, 0x31, + /* 0x c8 */ 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x03, + /* 0x d0 */ 0x13, 0x1A, 0x4C, 0x65, 0x74, 0x27, 0x73, 0x20, + /* 0x d8 */ 0x45, 0x6E, 0x63, 0x72, 0x79, 0x70, 0x74, 0x20, + /* 0x e0 */ 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, + /* 0x e8 */ 0x79, 0x20, 0x58, 0x33, 0x30, 0x82, 0x01, 0x22, + /* 0x f0 */ 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + /* 0x f8 */ 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, + /* 0x100 */ 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, + /* 0x108 */ 0x02, 0x82, 0x01, 0x01, 0x00, 0x9C, 0xD3, 0x0C, + /* 0x110 */ 0xF0, 0x5A, 0xE5, 0x2E, 0x47, 0xB7, 0x72, 0x5D, + /* 0x118 */ 0x37, 0x83, 0xB3, 0x68, 0x63, 0x30, 0xEA, 0xD7, + /* 0x120 */ 0x35, 0x26, 0x19, 0x25, 0xE1, 0xBD, 0xBE, 0x35, + /* 0x128 */ 0xF1, 0x70, 0x92, 0x2F, 0xB7, 0xB8, 0x4B, 0x41, + /* 0x130 */ 0x05, 0xAB, 0xA9, 0x9E, 0x35, 0x08, 0x58, 0xEC, + /* 0x138 */ 0xB1, 0x2A, 0xC4, 0x68, 0x87, 0x0B, 0xA3, 0xE3, + /* 0x140 */ 0x75, 0xE4, 0xE6, 0xF3, 0xA7, 0x62, 0x71, 0xBA, + /* 0x148 */ 0x79, 0x81, 0x60, 0x1F, 0xD7, 0x91, 0x9A, 0x9F, + /* 0x150 */ 0xF3, 0xD0, 0x78, 0x67, 0x71, 0xC8, 0x69, 0x0E, + /* 0x158 */ 0x95, 0x91, 0xCF, 0xFE, 0xE6, 0x99, 0xE9, 0x60, + /* 0x160 */ 0x3C, 0x48, 0xCC, 0x7E, 0xCA, 0x4D, 0x77, 0x12, + /* 0x168 */ 0x24, 0x9D, 0x47, 0x1B, 0x5A, 0xEB, 0xB9, 0xEC, + /* 0x170 */ 0x1E, 0x37, 0x00, 0x1C, 0x9C, 0xAC, 0x7B, 0xA7, + /* 0x178 */ 0x05, 0xEA, 0xCE, 0x4A, 0xEB, 0xBD, 0x41, 0xE5, + /* 0x180 */ 0x36, 0x98, 0xB9, 0xCB, 0xFD, 0x6D, 0x3C, 0x96, + /* 0x188 */ 0x68, 0xDF, 0x23, 0x2A, 0x42, 0x90, 0x0C, 0x86, + /* 0x190 */ 0x74, 0x67, 0xC8, 0x7F, 0xA5, 0x9A, 0xB8, 0x52, + /* 0x198 */ 0x61, 0x14, 0x13, 0x3F, 0x65, 0xE9, 0x82, 0x87, + /* 0x1a0 */ 0xCB, 0xDB, 0xFA, 0x0E, 0x56, 0xF6, 0x86, 0x89, + /* 0x1a8 */ 0xF3, 0x85, 0x3F, 0x97, 0x86, 0xAF, 0xB0, 0xDC, + /* 0x1b0 */ 0x1A, 0xEF, 0x6B, 0x0D, 0x95, 0x16, 0x7D, 0xC4, + /* 0x1b8 */ 0x2B, 0xA0, 0x65, 0xB2, 0x99, 0x04, 0x36, 0x75, + /* 0x1c0 */ 0x80, 0x6B, 0xAC, 0x4A, 0xF3, 0x1B, 0x90, 0x49, + /* 0x1c8 */ 0x78, 0x2F, 0xA2, 0x96, 0x4F, 0x2A, 0x20, 0x25, + /* 0x1d0 */ 0x29, 0x04, 0xC6, 0x74, 0xC0, 0xD0, 0x31, 0xCD, + /* 0x1d8 */ 0x8F, 0x31, 0x38, 0x95, 0x16, 0xBA, 0xA8, 0x33, + /* 0x1e0 */ 0xB8, 0x43, 0xF1, 0xB1, 0x1F, 0xC3, 0x30, 0x7F, + /* 0x1e8 */ 0xA2, 0x79, 0x31, 0x13, 0x3D, 0x2D, 0x36, 0xF8, + /* 0x1f0 */ 0xE3, 0xFC, 0xF2, 0x33, 0x6A, 0xB9, 0x39, 0x31, + /* 0x1f8 */ 0xC5, 0xAF, 0xC4, 0x8D, 0x0D, 0x1D, 0x64, 0x16, + /* 0x200 */ 0x33, 0xAA, 0xFA, 0x84, 0x29, 0xB6, 0xD4, 0x0B, + /* 0x208 */ 0xC0, 0xD8, 0x7D, 0xC3, 0x93, 0x02, 0x03, 0x01, + /* 0x210 */ 0x00, 0x01, 0xA3, 0x82, 0x01, 0x67, 0x30, 0x82, + /* 0x218 */ 0x01, 0x63, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, + /* 0x220 */ 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, + /* 0x228 */ 0x01, 0x86, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1D, + /* 0x230 */ 0x13, 0x01, 0x01, 0xFF, 0x04, 0x08, 0x30, 0x06, + /* 0x238 */ 0x01, 0x01, 0xFF, 0x02, 0x01, 0x00, 0x30, 0x54, + /* 0x240 */ 0x06, 0x03, 0x55, 0x1D, 0x20, 0x04, 0x4D, 0x30, + /* 0x248 */ 0x4B, 0x30, 0x08, 0x06, 0x06, 0x67, 0x81, 0x0C, + /* 0x250 */ 0x01, 0x02, 0x01, 0x30, 0x3F, 0x06, 0x0B, 0x2B, + /* 0x258 */ 0x06, 0x01, 0x04, 0x01, 0x82, 0xDF, 0x13, 0x01, + /* 0x260 */ 0x01, 0x01, 0x30, 0x30, 0x30, 0x2E, 0x06, 0x08, + /* 0x268 */ 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, + /* 0x270 */ 0x16, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, + /* 0x278 */ 0x2F, 0x63, 0x70, 0x73, 0x2E, 0x72, 0x6F, 0x6F, + /* 0x280 */ 0x74, 0x2D, 0x78, 0x31, 0x2E, 0x6C, 0x65, 0x74, + /* 0x288 */ 0x73, 0x65, 0x6E, 0x63, 0x72, 0x79, 0x70, 0x74, + /* 0x290 */ 0x2E, 0x6F, 0x72, 0x67, 0x30, 0x1D, 0x06, 0x03, + /* 0x298 */ 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0xA8, + /* 0x2a0 */ 0x4A, 0x6A, 0x63, 0x04, 0x7D, 0xDD, 0xBA, 0xE6, + /* 0x2a8 */ 0xD1, 0x39, 0xB7, 0xA6, 0x45, 0x65, 0xEF, 0xF3, + /* 0x2b0 */ 0xA8, 0xEC, 0xA1, 0x30, 0x33, 0x06, 0x03, 0x55, + /* 0x2b8 */ 0x1D, 0x1F, 0x04, 0x2C, 0x30, 0x2A, 0x30, 0x28, + /* 0x2c0 */ 0xA0, 0x26, 0xA0, 0x24, 0x86, 0x22, 0x68, 0x74, + /* 0x2c8 */ 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x63, 0x72, 0x6C, + /* 0x2d0 */ 0x2E, 0x72, 0x6F, 0x6F, 0x74, 0x2D, 0x78, 0x31, + /* 0x2d8 */ 0x2E, 0x6C, 0x65, 0x74, 0x73, 0x65, 0x6E, 0x63, + /* 0x2e0 */ 0x72, 0x79, 0x70, 0x74, 0x2E, 0x6F, 0x72, 0x67, + /* 0x2e8 */ 0x30, 0x72, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, + /* 0x2f0 */ 0x05, 0x07, 0x01, 0x01, 0x04, 0x66, 0x30, 0x64, + /* 0x2f8 */ 0x30, 0x30, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, + /* 0x300 */ 0x05, 0x07, 0x30, 0x01, 0x86, 0x24, 0x68, 0x74, + /* 0x308 */ 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x6F, 0x63, 0x73, + /* 0x310 */ 0x70, 0x2E, 0x72, 0x6F, 0x6F, 0x74, 0x2D, 0x78, + /* 0x318 */ 0x31, 0x2E, 0x6C, 0x65, 0x74, 0x73, 0x65, 0x6E, + /* 0x320 */ 0x63, 0x72, 0x79, 0x70, 0x74, 0x2E, 0x6F, 0x72, + /* 0x328 */ 0x67, 0x2F, 0x30, 0x30, 0x06, 0x08, 0x2B, 0x06, + /* 0x330 */ 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x24, + /* 0x338 */ 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x63, + /* 0x340 */ 0x65, 0x72, 0x74, 0x2E, 0x72, 0x6F, 0x6F, 0x74, + /* 0x348 */ 0x2D, 0x78, 0x31, 0x2E, 0x6C, 0x65, 0x74, 0x73, + /* 0x350 */ 0x65, 0x6E, 0x63, 0x72, 0x79, 0x70, 0x74, 0x2E, + /* 0x358 */ 0x6F, 0x72, 0x67, 0x2F, 0x30, 0x1F, 0x06, 0x03, + /* 0x360 */ 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, + /* 0x368 */ 0x14, 0x79, 0xB4, 0x59, 0xE6, 0x7B, 0xB6, 0xE5, + /* 0x370 */ 0xE4, 0x01, 0x73, 0x80, 0x08, 0x88, 0xC8, 0x1A, + /* 0x378 */ 0x58, 0xF6, 0xE9, 0x9B, 0x6E, 0x30, 0x0D, 0x06, + /* 0x380 */ 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + /* 0x388 */ 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, + /* 0x390 */ 0x00, 0x19, 0xCF, 0x75, 0x20, 0x34, 0x2D, 0x3A, + /* 0x398 */ 0xA6, 0x45, 0xFF, 0xD0, 0xD5, 0xE6, 0x8C, 0xDA, + /* 0x3a0 */ 0x32, 0xE8, 0x9C, 0x6E, 0x1B, 0x41, 0xD1, 0x27, + /* 0x3a8 */ 0xA8, 0xE2, 0x50, 0xF2, 0x70, 0xAA, 0xC4, 0xE7, + /* 0x3b0 */ 0x93, 0x46, 0xB4, 0xE8, 0x10, 0xAB, 0x70, 0x4F, + /* 0x3b8 */ 0xEF, 0xB7, 0xEA, 0x04, 0xD2, 0x94, 0x11, 0xB1, + /* 0x3c0 */ 0x03, 0xFE, 0x5D, 0xBA, 0xDF, 0x36, 0x8C, 0x94, + /* 0x3c8 */ 0x36, 0x8F, 0x13, 0x7C, 0x44, 0x8F, 0x0B, 0xF5, + /* 0x3d0 */ 0x01, 0x57, 0xAD, 0x68, 0xB8, 0xC5, 0x79, 0xC0, + /* 0x3d8 */ 0xD8, 0x4A, 0x80, 0xD7, 0x4C, 0xA3, 0x1E, 0x24, + /* 0x3e0 */ 0x7A, 0x1F, 0xD7, 0x23, 0xE8, 0xC1, 0x62, 0x3A, + /* 0x3e8 */ 0x76, 0xF9, 0x22, 0x7D, 0x5E, 0x5A, 0xC4, 0x4C, + /* 0x3f0 */ 0x50, 0xCD, 0xAF, 0xDD, 0xEF, 0x6D, 0x36, 0xC0, + /* 0x3f8 */ 0x80, 0x80, 0x1B, 0xA4, 0x3C, 0x70, 0x20, 0xD6, + /* 0x400 */ 0x54, 0x21, 0xD3, 0xBA, 0xEF, 0x14, 0xA9, 0xBF, + /* 0x408 */ 0x07, 0x3F, 0x41, 0x0A, 0x36, 0xB1, 0xA2, 0xB0, + /* 0x410 */ 0x0B, 0x20, 0xD5, 0x1F, 0x67, 0xD0, 0xC3, 0xEB, + /* 0x418 */ 0x88, 0xF6, 0x8A, 0x02, 0xC8, 0xC6, 0x57, 0xB6, + /* 0x420 */ 0x0C, 0xFC, 0x56, 0xF1, 0xD2, 0x3F, 0x17, 0x69, + /* 0x428 */ 0x68, 0x1C, 0xC8, 0xD7, 0x66, 0x3A, 0x86, 0xF1, + /* 0x430 */ 0x19, 0x2A, 0x65, 0x47, 0x68, 0xC6, 0xD2, 0x03, + /* 0x438 */ 0xE7, 0xEF, 0x74, 0x16, 0x0B, 0x06, 0x21, 0xF9, + /* 0x440 */ 0x0C, 0xA6, 0xA8, 0x11, 0x4B, 0x4E, 0x5F, 0xE3, + /* 0x448 */ 0x33, 0xDB, 0x08, 0x41, 0xEA, 0x09, 0x79, 0x75, + /* 0x450 */ 0x78, 0xEE, 0x47, 0xC8, 0x42, 0xD3, 0x81, 0xC5, + /* 0x458 */ 0x65, 0x2D, 0x75, 0xD0, 0x0E, 0x00, 0x16, 0x9D, + /* 0x460 */ 0x1C, 0xEE, 0xB7, 0x58, 0x45, 0x25, 0xE7, 0x33, + /* 0x468 */ 0x63, 0x5B, 0x63, 0x41, 0x09, 0xE8, 0xE9, 0xFE, + /* 0x470 */ 0xAC, 0xFA, 0x73, 0x32, 0x74, 0xB3, 0x76, 0xE9, + /* 0x478 */ 0x6B, 0x94, 0xE2, 0xCD, 0xD4, 0x62, 0xF3, 0xAE, + /* 0x480 */ 0x3A, 0xC5, 0x31, 0x46, 0x52, 0x6E, 0xED, 0x34, + /* 0x488 */ 0x91, 0x1E, 0xA0, 0xC2, 0xDE, 0x54, 0x84, 0xE5, + /* 0x490 */ 0x78, 0x20, 0x56, 0x4C, 0xDD, 0x68, 0xF9, 0x2E, + /* 0x498 */ 0x28, 0x64, 0x1B, 0x1A, 0x99, 0xF2, 0xFB, 0x4D, + /* 0x4a0 */ 0x7F, 0xE3, 0xB8, 0x5F, 0x5D, 0x73, 0x41, 0xEC, + /* 0x4a8 */ 0x79, 0xED, 0x58, 0xD6, 0x7A, 0x37, 0x65, 0x70, + /* 0x4b0 */ 0xA7, 0xB1, 0xBA, 0x39, 0xF6, 0x3E, 0x61, 0x0A, + /* 0x4b8 */ 0xD9, 0xC0, 0x86, 0x90, 0x9A, 0x1A, 0xC8, 0xA8, + /* 0x4c0 */ 0x96, 0x6E, 0x8A, 0x0B, 0x2B, 0x6D, 0xED, 0xD6, + /* 0x4c8 */ 0xFA, 0x07, 0x67, 0xE7, 0x29, 0x04, 0xF7, 0xE2, + /* 0x4d0 */ 0xB2, 0xD1, 0x58, 0x15, 0x52, 0xC7, 0xF1, 0xA3, + /* 0x4d8 */ 0x9D, 0xA6, 0xC0, 0x56, 0x2C, 0xD4, 0x92, 0x98, + /* 0x4e0 */ 0xD8, 0xF1, 0x83, 0xB9, 0x6C, 0x7C, 0x33, 0xA0, + /* 0x4e8 */ 0xE5, 0x4B, 0xAA, 0x90, 0x92, 0xF1, 0xDA, 0x45, + /* 0x4f0 */ 0x4A, 0x34, 0x14, 0xC7, 0x7C, 0x4E, 0xC4, 0xA5, + /* 0x4f8 */ 0x6C, 0x5D, 0x3F, 0xBF, 0xDE, 0xB9, 0xA8, 0x61, + /* 0x500 */ 0x4A, 0x85, 0x20, 0xDE, 0x42, 0x83, 0x29, 0x62, + /* 0x508 */ 0x7C, 0x1C, 0x99, 0x08, 0xA5, 0x46, 0x1F, 0xF4, + /* 0x510 */ 0x6B, 0x22, 0xD3, 0x86, 0x51, 0xCB, 0x37, 0xCD, + /* 0x518 */ 0x60, 0x4A, 0x42, 0x63, 0x56, 0xB3, 0xC8, 0xD1, + /* 0x520 */ 0x8F, 0x31, 0x09, 0x53, 0xC1, 0xE2, 0xDC, 0x1B, + /* 0x528 */ 0xD4, 0xF1, 0x54, 0x77, 0x67, 0xCF, 0x33, 0x7B, + /* 0x530 */ 0x00, 0xD6, 0xD2, 0x7C, 0xDE, 0xC6, 0x79, 0xBF, + /* 0x538 */ 0xCB, 0xE0, 0x16, 0xFD, 0xB2, 0xA1, 0xF2, 0x91, + /* 0x540 */ 0x3C, 0x1D, 0x2D, 0xE8, 0x9C, 0xD4, 0x03, 0xCD, + /* 0x548 */ 0x66, 0x4A, 0xA3, 0x37, 0x93, 0x19, 0x79, 0x7B, + /* 0x550 */ 0xE2, 0x19, 0xC2, 0x16, 0x00, 0xC8, 0xED, 0x0E, + /* 0x558 */ 0x4E, 0x0D, 0xFF, 0x7E, 0xCF, 0x07, 0xA8, 0x64, + /* 0x560 */ 0xCD, 0x29, 0xDF, 0x41, 0xAA, 0x85, 0x30, 0x49, + /* 0x568 */ 0x10, 0x73, 0xA7, 0x4E, 0x89, 0x32, 0x0E, 0x5B, + /* 0x570 */ 0xAD, 0x40, 0x86, 0xC1, 0xB0, 0x94, 0x0C, 0x8D, + /* 0x578 */ 0x26, 0xC5, 0xA7, 0x49, 0xDC, 0x1C, 0xF8, 0x5B, + /* 0x580 */ 0x14, 0x7A, 0x7F, 0x23, 0x69, 0x04, 0xAD, 0xB2, + /* 0x588 */ 0x02, 0x29, 0xD6, 0x12, 0xC8, 0xA4, 0xC6, 0xA1, + /* 0x590 */ 0x2D, +}; +static const lws_ss_x509_t _ss_x509_LEX3_isrg_root_x1 = { + .vhost_name = "LEX3_isrg_root_x1", + .ca_der = _ss_der_LEX3_isrg_root_x1, + .ca_der_len = 1425, +}; +static const lws_ss_trust_store_t _ss_ts_le_via_isrg = { + .name = "le_via_isrg", + .ssx509 = { + &_ss_x509_LEX3_isrg_root_x1, + &_ss_x509_isrg_root_x1, + } +}; + +static const lws_ss_metadata_t _md_mintest_xctype = { + .name = "xctype", + .value = (void *)"X-Content-Type:", + .length = 0, +}, +_md_mintest_ctype = { + .next = (void *)&_md_mintest_xctype, + .name = "ctype", + .value = (void *)"Content-Type:", + .length = 1, +}, +_md_mintest_uptag = { + .next = (void *)&_md_mintest_ctype, + .name = "uptag", + .value = (void *)"X-Upload-Tag:", + .length = 2, +}; + +static const lws_ss_trust_store_t _ss_ts_avs_via_starfield = { + .name = "avs_via_starfield", + .ssx509 = { + &_ss_x509_starfield_services_root_ca, + &_ss_x509_starfield_class_2_ca, + } +}; +static const uint8_t _ss_der_digicert_global_ca_g2[] = { + /* 0x 0 */ 0x30, 0x82, 0x04, 0x8B, 0x30, 0x82, 0x03, 0x73, + /* 0x 8 */ 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x0C, + /* 0x 10 */ 0x8E, 0xE0, 0xC9, 0x0D, 0x6A, 0x89, 0x15, 0x88, + /* 0x 18 */ 0x04, 0x06, 0x1E, 0xE2, 0x41, 0xF9, 0xAF, 0x30, + /* 0x 20 */ 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, + /* 0x 28 */ 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x61, + /* 0x 30 */ 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + /* 0x 38 */ 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, + /* 0x 40 */ 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0C, + /* 0x 48 */ 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + /* 0x 50 */ 0x20, 0x49, 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, + /* 0x 58 */ 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x10, 0x77, + /* 0x 60 */ 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, + /* 0x 68 */ 0x65, 0x72, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, + /* 0x 70 */ 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, + /* 0x 78 */ 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, + /* 0x 80 */ 0x72, 0x74, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + /* 0x 88 */ 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, + /* 0x 90 */ 0x32, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x33, 0x30, + /* 0x 98 */ 0x38, 0x30, 0x31, 0x31, 0x32, 0x30, 0x30, 0x30, + /* 0x a0 */ 0x30, 0x5A, 0x17, 0x0D, 0x32, 0x38, 0x30, 0x38, + /* 0x a8 */ 0x30, 0x31, 0x31, 0x32, 0x30, 0x30, 0x30, 0x30, + /* 0x b0 */ 0x5A, 0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, + /* 0x b8 */ 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + /* 0x c0 */ 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, + /* 0x c8 */ 0x0A, 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, + /* 0x d0 */ 0x65, 0x72, 0x74, 0x20, 0x49, 0x6E, 0x63, 0x31, + /* 0x d8 */ 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x03, + /* 0x e0 */ 0x13, 0x15, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, + /* 0x e8 */ 0x72, 0x74, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + /* 0x f0 */ 0x6C, 0x20, 0x43, 0x41, 0x20, 0x47, 0x32, 0x30, + /* 0x f8 */ 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, + /* 0x100 */ 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, + /* 0x108 */ 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, + /* 0x110 */ 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, + /* 0x118 */ 0xD3, 0x48, 0x7C, 0xBE, 0xF3, 0x05, 0x86, 0x5D, + /* 0x120 */ 0x5B, 0xD5, 0x2F, 0x85, 0x4E, 0x4B, 0xE0, 0x86, + /* 0x128 */ 0xAD, 0x15, 0xAC, 0x61, 0xCF, 0x5B, 0xAF, 0x3E, + /* 0x130 */ 0x6A, 0x0A, 0x47, 0xFB, 0x9A, 0x76, 0x91, 0x60, + /* 0x138 */ 0x0B, 0x8A, 0x6B, 0xCD, 0xCF, 0xDC, 0x57, 0x7E, + /* 0x140 */ 0x60, 0x98, 0x0B, 0xE4, 0x54, 0xD9, 0x56, 0xED, + /* 0x148 */ 0x21, 0xCC, 0x02, 0xB6, 0x5A, 0x81, 0x5F, 0x97, + /* 0x150 */ 0x6A, 0xEE, 0x02, 0x2F, 0x23, 0x27, 0xB8, 0x6D, + /* 0x158 */ 0xD4, 0xB0, 0xE7, 0x06, 0x02, 0x78, 0x0B, 0x1F, + /* 0x160 */ 0x5C, 0xA9, 0x99, 0x36, 0xFE, 0xBB, 0xAC, 0x1B, + /* 0x168 */ 0x05, 0xFA, 0x57, 0xCD, 0x81, 0x10, 0x40, 0x67, + /* 0x170 */ 0xD6, 0x30, 0x8B, 0x58, 0x35, 0xD4, 0x96, 0x61, + /* 0x178 */ 0xBE, 0xD0, 0x8C, 0x7A, 0x97, 0x9F, 0x1A, 0xF9, + /* 0x180 */ 0x22, 0xE6, 0x14, 0x2F, 0xA9, 0xC6, 0xE8, 0x01, + /* 0x188 */ 0x1F, 0xAB, 0xF8, 0x26, 0x0F, 0xAC, 0x8E, 0x4D, + /* 0x190 */ 0x2C, 0x32, 0x39, 0x1D, 0x81, 0x9B, 0x8D, 0x1C, + /* 0x198 */ 0x65, 0xB2, 0x1C, 0xDB, 0x61, 0xA8, 0x89, 0x2F, + /* 0x1a0 */ 0x60, 0xE7, 0xEB, 0xC2, 0x4A, 0x18, 0xC4, 0x6F, + /* 0x1a8 */ 0x2A, 0xE9, 0x10, 0x92, 0x09, 0xED, 0x17, 0xD1, + /* 0x1b0 */ 0x00, 0x2B, 0xE6, 0x7D, 0xEF, 0x04, 0x89, 0x14, + /* 0x1b8 */ 0x4E, 0x33, 0xA1, 0xB2, 0x0F, 0x97, 0x87, 0x9F, + /* 0x1c0 */ 0xB3, 0xA0, 0xCD, 0x2F, 0xBC, 0x2C, 0xEC, 0xB8, + /* 0x1c8 */ 0x83, 0x68, 0x31, 0x3D, 0x1F, 0xD5, 0x4A, 0x90, + /* 0x1d0 */ 0x10, 0x19, 0x0B, 0x81, 0x95, 0xD6, 0x29, 0x76, + /* 0x1d8 */ 0x51, 0xF9, 0x36, 0x76, 0xD0, 0xB7, 0x09, 0x7A, + /* 0x1e0 */ 0x38, 0x4A, 0xD7, 0x6F, 0x8C, 0xBF, 0x13, 0x7C, + /* 0x1e8 */ 0x39, 0xED, 0xBA, 0xAE, 0x90, 0xFC, 0x95, 0xF7, + /* 0x1f0 */ 0x7B, 0x78, 0x09, 0x36, 0x5E, 0x74, 0x93, 0x1E, + /* 0x1f8 */ 0x25, 0xF0, 0xFF, 0xD4, 0xAD, 0xAE, 0x68, 0x6B, + /* 0x200 */ 0xC6, 0xFF, 0x0F, 0xD5, 0x35, 0xF1, 0x55, 0x6E, + /* 0x208 */ 0x48, 0x49, 0xF8, 0xF8, 0xB8, 0xEF, 0x88, 0xF8, + /* 0x210 */ 0xF1, 0x5E, 0x11, 0x77, 0xAA, 0xDF, 0x02, 0xB3, + /* 0x218 */ 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, + /* 0x220 */ 0x5A, 0x30, 0x82, 0x01, 0x56, 0x30, 0x12, 0x06, + /* 0x228 */ 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, + /* 0x230 */ 0x08, 0x30, 0x06, 0x01, 0x01, 0xFF, 0x02, 0x01, + /* 0x238 */ 0x00, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, + /* 0x240 */ 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x01, + /* 0x248 */ 0x86, 0x30, 0x34, 0x06, 0x08, 0x2B, 0x06, 0x01, + /* 0x250 */ 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x28, 0x30, + /* 0x258 */ 0x26, 0x30, 0x24, 0x06, 0x08, 0x2B, 0x06, 0x01, + /* 0x260 */ 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x18, 0x68, + /* 0x268 */ 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x6F, 0x63, + /* 0x270 */ 0x73, 0x70, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, + /* 0x278 */ 0x65, 0x72, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x30, + /* 0x280 */ 0x7B, 0x06, 0x03, 0x55, 0x1D, 0x1F, 0x04, 0x74, + /* 0x288 */ 0x30, 0x72, 0x30, 0x37, 0xA0, 0x35, 0xA0, 0x33, + /* 0x290 */ 0x86, 0x31, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, + /* 0x298 */ 0x2F, 0x63, 0x72, 0x6C, 0x34, 0x2E, 0x64, 0x69, + /* 0x2a0 */ 0x67, 0x69, 0x63, 0x65, 0x72, 0x74, 0x2E, 0x63, + /* 0x2a8 */ 0x6F, 0x6D, 0x2F, 0x44, 0x69, 0x67, 0x69, 0x43, + /* 0x2b0 */ 0x65, 0x72, 0x74, 0x47, 0x6C, 0x6F, 0x62, 0x61, + /* 0x2b8 */ 0x6C, 0x52, 0x6F, 0x6F, 0x74, 0x47, 0x32, 0x2E, + /* 0x2c0 */ 0x63, 0x72, 0x6C, 0x30, 0x37, 0xA0, 0x35, 0xA0, + /* 0x2c8 */ 0x33, 0x86, 0x31, 0x68, 0x74, 0x74, 0x70, 0x3A, + /* 0x2d0 */ 0x2F, 0x2F, 0x63, 0x72, 0x6C, 0x33, 0x2E, 0x64, + /* 0x2d8 */ 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, 0x74, 0x2E, + /* 0x2e0 */ 0x63, 0x6F, 0x6D, 0x2F, 0x44, 0x69, 0x67, 0x69, + /* 0x2e8 */ 0x43, 0x65, 0x72, 0x74, 0x47, 0x6C, 0x6F, 0x62, + /* 0x2f0 */ 0x61, 0x6C, 0x52, 0x6F, 0x6F, 0x74, 0x47, 0x32, + /* 0x2f8 */ 0x2E, 0x63, 0x72, 0x6C, 0x30, 0x3D, 0x06, 0x03, + /* 0x300 */ 0x55, 0x1D, 0x20, 0x04, 0x36, 0x30, 0x34, 0x30, + /* 0x308 */ 0x32, 0x06, 0x04, 0x55, 0x1D, 0x20, 0x00, 0x30, + /* 0x310 */ 0x2A, 0x30, 0x28, 0x06, 0x08, 0x2B, 0x06, 0x01, + /* 0x318 */ 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x1C, 0x68, + /* 0x320 */ 0x74, 0x74, 0x70, 0x73, 0x3A, 0x2F, 0x2F, 0x77, + /* 0x328 */ 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, + /* 0x330 */ 0x65, 0x72, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, + /* 0x338 */ 0x43, 0x50, 0x53, 0x30, 0x1D, 0x06, 0x03, 0x55, + /* 0x340 */ 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x24, 0x6E, + /* 0x348 */ 0x2B, 0x2D, 0xD0, 0x6A, 0x92, 0x51, 0x51, 0x25, + /* 0x350 */ 0x69, 0x01, 0xAA, 0x9A, 0x47, 0xA6, 0x89, 0xE7, + /* 0x358 */ 0x40, 0x20, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, + /* 0x360 */ 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x4E, + /* 0x368 */ 0x22, 0x54, 0x20, 0x18, 0x95, 0xE6, 0xE3, 0x6E, + /* 0x370 */ 0xE6, 0x0F, 0xFA, 0xFA, 0xB9, 0x12, 0xED, 0x06, + /* 0x378 */ 0x17, 0x8F, 0x39, 0x30, 0x0D, 0x06, 0x09, 0x2A, + /* 0x380 */ 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, + /* 0x388 */ 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x0B, + /* 0x390 */ 0x39, 0x84, 0x91, 0xF9, 0x97, 0xEB, 0xAA, 0x81, + /* 0x398 */ 0xAF, 0x84, 0xE9, 0x5A, 0x38, 0x92, 0xFC, 0xE2, + /* 0x3a0 */ 0x6C, 0x59, 0xBF, 0x36, 0xC8, 0x45, 0xA7, 0x31, + /* 0x3a8 */ 0x03, 0x11, 0xE1, 0x06, 0xC0, 0xAC, 0x32, 0xC7, + /* 0x3b0 */ 0x5A, 0x55, 0x29, 0xDA, 0x4F, 0x40, 0x02, 0xF5, + /* 0x3b8 */ 0xA1, 0xDE, 0xB0, 0xED, 0xDE, 0xC0, 0xF8, 0xF6, + /* 0x3c0 */ 0x75, 0x9D, 0x76, 0xB9, 0x87, 0xFE, 0x41, 0x80, + /* 0x3c8 */ 0x7A, 0xCF, 0x5D, 0xE3, 0x00, 0xC6, 0x5B, 0x02, + /* 0x3d0 */ 0xE6, 0x9B, 0x78, 0x62, 0xC9, 0xDC, 0xB8, 0x62, + /* 0x3d8 */ 0x9A, 0x77, 0xED, 0x89, 0x08, 0xD7, 0x4B, 0xC5, + /* 0x3e0 */ 0xFD, 0x43, 0xD5, 0x62, 0x23, 0x27, 0xC4, 0x04, + /* 0x3e8 */ 0x59, 0x6D, 0x71, 0x3F, 0x23, 0x5B, 0xEA, 0xD9, + /* 0x3f0 */ 0xF2, 0xE7, 0x24, 0x27, 0x6F, 0xF4, 0x95, 0x80, + /* 0x3f8 */ 0xDB, 0x96, 0x2C, 0xE4, 0x54, 0x8B, 0xCF, 0xEA, + /* 0x400 */ 0x19, 0xD9, 0x7F, 0x55, 0x99, 0x51, 0x7A, 0x0E, + /* 0x408 */ 0x2D, 0x18, 0x3D, 0x78, 0x58, 0x52, 0xBC, 0x63, + /* 0x410 */ 0x68, 0x57, 0x0B, 0xDD, 0x44, 0xB3, 0x57, 0x4A, + /* 0x418 */ 0x60, 0xE6, 0xC8, 0x70, 0x70, 0x5B, 0x87, 0x28, + /* 0x420 */ 0x6A, 0xD7, 0x3B, 0x4E, 0x52, 0x45, 0x19, 0xAF, + /* 0x428 */ 0x24, 0x06, 0x92, 0x48, 0x11, 0x1A, 0x8B, 0xAE, + /* 0x430 */ 0xAC, 0x18, 0x12, 0x57, 0xAC, 0x03, 0xCB, 0xB8, + /* 0x438 */ 0xF4, 0xBD, 0xCA, 0x26, 0x0E, 0xA7, 0xC1, 0xDD, + /* 0x440 */ 0xE3, 0x33, 0xEF, 0xC0, 0x55, 0x30, 0x0D, 0x95, + /* 0x448 */ 0x59, 0x4E, 0x9C, 0x03, 0x36, 0x06, 0xF8, 0xC0, + /* 0x450 */ 0x8F, 0x14, 0x99, 0x9C, 0x4D, 0x2A, 0x9E, 0xC1, + /* 0x458 */ 0xE1, 0x7D, 0x3B, 0xAF, 0x72, 0xA7, 0x45, 0xBA, + /* 0x460 */ 0x13, 0x96, 0x29, 0x4E, 0x19, 0xD0, 0x1A, 0x98, + /* 0x468 */ 0x06, 0xF4, 0x37, 0x94, 0x17, 0xAD, 0xA3, 0x18, + /* 0x470 */ 0xBA, 0x3E, 0xB0, 0x01, 0x0C, 0x95, 0xD6, 0x29, + /* 0x478 */ 0x35, 0x20, 0x35, 0x7D, 0xF5, 0x10, 0x60, 0xE4, + /* 0x480 */ 0xF7, 0x68, 0x62, 0x1E, 0xEC, 0x19, 0xE1, 0x24, + /* 0x488 */ 0xF2, 0x87, 0x11, 0xAC, 0xE9, 0x08, 0x80, +}; +static const lws_ss_x509_t _ss_x509_digicert_global_ca_g2 = { + .vhost_name = "digicert_global_ca_g2", + .ca_der = _ss_der_digicert_global_ca_g2, + .ca_der_len = 1167, +}; +static const uint8_t _ss_der_digicert_global_root_g2[] = { + /* 0x 0 */ 0x30, 0x82, 0x03, 0x8E, 0x30, 0x82, 0x02, 0x76, + /* 0x 8 */ 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x03, + /* 0x 10 */ 0x3A, 0xF1, 0xE6, 0xA7, 0x11, 0xA9, 0xA0, 0xBB, + /* 0x 18 */ 0x28, 0x64, 0xB1, 0x1D, 0x09, 0xFA, 0xE5, 0x30, + /* 0x 20 */ 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, + /* 0x 28 */ 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x61, + /* 0x 30 */ 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + /* 0x 38 */ 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, + /* 0x 40 */ 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0C, + /* 0x 48 */ 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + /* 0x 50 */ 0x20, 0x49, 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, + /* 0x 58 */ 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x10, 0x77, + /* 0x 60 */ 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, + /* 0x 68 */ 0x65, 0x72, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, + /* 0x 70 */ 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, + /* 0x 78 */ 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, + /* 0x 80 */ 0x72, 0x74, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + /* 0x 88 */ 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, + /* 0x 90 */ 0x32, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x33, 0x30, + /* 0x 98 */ 0x38, 0x30, 0x31, 0x31, 0x32, 0x30, 0x30, 0x30, + /* 0x a0 */ 0x30, 0x5A, 0x17, 0x0D, 0x33, 0x38, 0x30, 0x31, + /* 0x a8 */ 0x31, 0x35, 0x31, 0x32, 0x30, 0x30, 0x30, 0x30, + /* 0x b0 */ 0x5A, 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, + /* 0x b8 */ 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + /* 0x c0 */ 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, + /* 0x c8 */ 0x0A, 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, + /* 0x d0 */ 0x65, 0x72, 0x74, 0x20, 0x49, 0x6E, 0x63, 0x31, + /* 0x d8 */ 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, + /* 0x e0 */ 0x13, 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, + /* 0x e8 */ 0x67, 0x69, 0x63, 0x65, 0x72, 0x74, 0x2E, 0x63, + /* 0x f0 */ 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, + /* 0x f8 */ 0x55, 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, + /* 0x100 */ 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x47, 0x6C, + /* 0x108 */ 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, + /* 0x110 */ 0x74, 0x20, 0x47, 0x32, 0x30, 0x82, 0x01, 0x22, + /* 0x118 */ 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + /* 0x120 */ 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, + /* 0x128 */ 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, + /* 0x130 */ 0x02, 0x82, 0x01, 0x01, 0x00, 0xBB, 0x37, 0xCD, + /* 0x138 */ 0x34, 0xDC, 0x7B, 0x6B, 0xC9, 0xB2, 0x68, 0x90, + /* 0x140 */ 0xAD, 0x4A, 0x75, 0xFF, 0x46, 0xBA, 0x21, 0x0A, + /* 0x148 */ 0x08, 0x8D, 0xF5, 0x19, 0x54, 0xC9, 0xFB, 0x88, + /* 0x150 */ 0xDB, 0xF3, 0xAE, 0xF2, 0x3A, 0x89, 0x91, 0x3C, + /* 0x158 */ 0x7A, 0xE6, 0xAB, 0x06, 0x1A, 0x6B, 0xCF, 0xAC, + /* 0x160 */ 0x2D, 0xE8, 0x5E, 0x09, 0x24, 0x44, 0xBA, 0x62, + /* 0x168 */ 0x9A, 0x7E, 0xD6, 0xA3, 0xA8, 0x7E, 0xE0, 0x54, + /* 0x170 */ 0x75, 0x20, 0x05, 0xAC, 0x50, 0xB7, 0x9C, 0x63, + /* 0x178 */ 0x1A, 0x6C, 0x30, 0xDC, 0xDA, 0x1F, 0x19, 0xB1, + /* 0x180 */ 0xD7, 0x1E, 0xDE, 0xFD, 0xD7, 0xE0, 0xCB, 0x94, + /* 0x188 */ 0x83, 0x37, 0xAE, 0xEC, 0x1F, 0x43, 0x4E, 0xDD, + /* 0x190 */ 0x7B, 0x2C, 0xD2, 0xBD, 0x2E, 0xA5, 0x2F, 0xE4, + /* 0x198 */ 0xA9, 0xB8, 0xAD, 0x3A, 0xD4, 0x99, 0xA4, 0xB6, + /* 0x1a0 */ 0x25, 0xE9, 0x9B, 0x6B, 0x00, 0x60, 0x92, 0x60, + /* 0x1a8 */ 0xFF, 0x4F, 0x21, 0x49, 0x18, 0xF7, 0x67, 0x90, + /* 0x1b0 */ 0xAB, 0x61, 0x06, 0x9C, 0x8F, 0xF2, 0xBA, 0xE9, + /* 0x1b8 */ 0xB4, 0xE9, 0x92, 0x32, 0x6B, 0xB5, 0xF3, 0x57, + /* 0x1c0 */ 0xE8, 0x5D, 0x1B, 0xCD, 0x8C, 0x1D, 0xAB, 0x95, + /* 0x1c8 */ 0x04, 0x95, 0x49, 0xF3, 0x35, 0x2D, 0x96, 0xE3, + /* 0x1d0 */ 0x49, 0x6D, 0xDD, 0x77, 0xE3, 0xFB, 0x49, 0x4B, + /* 0x1d8 */ 0xB4, 0xAC, 0x55, 0x07, 0xA9, 0x8F, 0x95, 0xB3, + /* 0x1e0 */ 0xB4, 0x23, 0xBB, 0x4C, 0x6D, 0x45, 0xF0, 0xF6, + /* 0x1e8 */ 0xA9, 0xB2, 0x95, 0x30, 0xB4, 0xFD, 0x4C, 0x55, + /* 0x1f0 */ 0x8C, 0x27, 0x4A, 0x57, 0x14, 0x7C, 0x82, 0x9D, + /* 0x1f8 */ 0xCD, 0x73, 0x92, 0xD3, 0x16, 0x4A, 0x06, 0x0C, + /* 0x200 */ 0x8C, 0x50, 0xD1, 0x8F, 0x1E, 0x09, 0xBE, 0x17, + /* 0x208 */ 0xA1, 0xE6, 0x21, 0xCA, 0xFD, 0x83, 0xE5, 0x10, + /* 0x210 */ 0xBC, 0x83, 0xA5, 0x0A, 0xC4, 0x67, 0x28, 0xF6, + /* 0x218 */ 0x73, 0x14, 0x14, 0x3D, 0x46, 0x76, 0xC3, 0x87, + /* 0x220 */ 0x14, 0x89, 0x21, 0x34, 0x4D, 0xAF, 0x0F, 0x45, + /* 0x228 */ 0x0C, 0xA6, 0x49, 0xA1, 0xBA, 0xBB, 0x9C, 0xC5, + /* 0x230 */ 0xB1, 0x33, 0x83, 0x29, 0x85, 0x02, 0x03, 0x01, + /* 0x238 */ 0x00, 0x01, 0xA3, 0x42, 0x30, 0x40, 0x30, 0x0F, + /* 0x240 */ 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, + /* 0x248 */ 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, + /* 0x250 */ 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, + /* 0x258 */ 0xFF, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, + /* 0x260 */ 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, + /* 0x268 */ 0x04, 0x14, 0x4E, 0x22, 0x54, 0x20, 0x18, 0x95, + /* 0x270 */ 0xE6, 0xE3, 0x6E, 0xE6, 0x0F, 0xFA, 0xFA, 0xB9, + /* 0x278 */ 0x12, 0xED, 0x06, 0x17, 0x8F, 0x39, 0x30, 0x0D, + /* 0x280 */ 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + /* 0x288 */ 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x01, + /* 0x290 */ 0x01, 0x00, 0x60, 0x67, 0x28, 0x94, 0x6F, 0x0E, + /* 0x298 */ 0x48, 0x63, 0xEB, 0x31, 0xDD, 0xEA, 0x67, 0x18, + /* 0x2a0 */ 0xD5, 0x89, 0x7D, 0x3C, 0xC5, 0x8B, 0x4A, 0x7F, + /* 0x2a8 */ 0xE9, 0xBE, 0xDB, 0x2B, 0x17, 0xDF, 0xB0, 0x5F, + /* 0x2b0 */ 0x73, 0x77, 0x2A, 0x32, 0x13, 0x39, 0x81, 0x67, + /* 0x2b8 */ 0x42, 0x84, 0x23, 0xF2, 0x45, 0x67, 0x35, 0xEC, + /* 0x2c0 */ 0x88, 0xBF, 0xF8, 0x8F, 0xB0, 0x61, 0x0C, 0x34, + /* 0x2c8 */ 0xA4, 0xAE, 0x20, 0x4C, 0x84, 0xC6, 0xDB, 0xF8, + /* 0x2d0 */ 0x35, 0xE1, 0x76, 0xD9, 0xDF, 0xA6, 0x42, 0xBB, + /* 0x2d8 */ 0xC7, 0x44, 0x08, 0x86, 0x7F, 0x36, 0x74, 0x24, + /* 0x2e0 */ 0x5A, 0xDA, 0x6C, 0x0D, 0x14, 0x59, 0x35, 0xBD, + /* 0x2e8 */ 0xF2, 0x49, 0xDD, 0xB6, 0x1F, 0xC9, 0xB3, 0x0D, + /* 0x2f0 */ 0x47, 0x2A, 0x3D, 0x99, 0x2F, 0xBB, 0x5C, 0xBB, + /* 0x2f8 */ 0xB5, 0xD4, 0x20, 0xE1, 0x99, 0x5F, 0x53, 0x46, + /* 0x300 */ 0x15, 0xDB, 0x68, 0x9B, 0xF0, 0xF3, 0x30, 0xD5, + /* 0x308 */ 0x3E, 0x31, 0xE2, 0x8D, 0x84, 0x9E, 0xE3, 0x8A, + /* 0x310 */ 0xDA, 0xDA, 0x96, 0x3E, 0x35, 0x13, 0xA5, 0x5F, + /* 0x318 */ 0xF0, 0xF9, 0x70, 0x50, 0x70, 0x47, 0x41, 0x11, + /* 0x320 */ 0x57, 0x19, 0x4E, 0xC0, 0x8F, 0xAE, 0x06, 0xC4, + /* 0x328 */ 0x95, 0x13, 0x17, 0x2F, 0x1B, 0x25, 0x9F, 0x75, + /* 0x330 */ 0xF2, 0xB1, 0x8E, 0x99, 0xA1, 0x6F, 0x13, 0xB1, + /* 0x338 */ 0x41, 0x71, 0xFE, 0x88, 0x2A, 0xC8, 0x4F, 0x10, + /* 0x340 */ 0x20, 0x55, 0xD7, 0xF3, 0x14, 0x45, 0xE5, 0xE0, + /* 0x348 */ 0x44, 0xF4, 0xEA, 0x87, 0x95, 0x32, 0x93, 0x0E, + /* 0x350 */ 0xFE, 0x53, 0x46, 0xFA, 0x2C, 0x9D, 0xFF, 0x8B, + /* 0x358 */ 0x22, 0xB9, 0x4B, 0xD9, 0x09, 0x45, 0xA4, 0xDE, + /* 0x360 */ 0xA4, 0xB8, 0x9A, 0x58, 0xDD, 0x1B, 0x7D, 0x52, + /* 0x368 */ 0x9F, 0x8E, 0x59, 0x43, 0x88, 0x81, 0xA4, 0x9E, + /* 0x370 */ 0x26, 0xD5, 0x6F, 0xAD, 0xDD, 0x0D, 0xC6, 0x37, + /* 0x378 */ 0x7D, 0xED, 0x03, 0x92, 0x1B, 0xE5, 0x77, 0x5F, + /* 0x380 */ 0x76, 0xEE, 0x3C, 0x8D, 0xC4, 0x5D, 0x56, 0x5B, + /* 0x388 */ 0xA2, 0xD9, 0x66, 0x6E, 0xB3, 0x35, 0x37, 0xE5, + /* 0x390 */ 0x32, 0xB6, +}; +static const lws_ss_x509_t _ss_x509_digicert_global_root_g2 = { + .vhost_name = "digicert_global_root_g2", + .ca_der = _ss_der_digicert_global_root_g2, + .ca_der_len = 914, +}; +static const lws_ss_trust_store_t _ss_ts_api_amazon_com = { + .name = "api_amazon_com", + .ssx509 = { + &_ss_x509_digicert_global_root_g2, + &_ss_x509_digicert_global_ca_g2, + } +}; + +static const lws_ss_policy_t _ssp_captive_portal_detect = { + .streamtype = "captive_portal_detect", + .endpoint = "connectivitycheck.android.com", + .u = { + .http = { + .method = "GET", + .url = "generate_204", + .resp_expect = 204, + .fail_redirect = 1, + } + }, + .flags = 0x1, + .port = 80, + .protocol = 0, +}, +_ssp_mqtt_test1 = { + .next = (void *)&_ssp_captive_portal_detect, + .streamtype = "mqtt_test1", + .endpoint = "a1ygonr3im5cv2-ats.iot.us-west-2.amazonaws.com", + .u = { + .mqtt = { + .topic = "test/topic1", + .subscribe = "test/topic1", + .qos = 1, + } + }, + .retry_bo = &_rbo_0, + .flags = 0x10, + .port = 443, + .protocol = 3, + .client_cert = 1, + .trust = {.store = &_ss_ts_mqtt_amz_iot}, +}, +_ssp_mqtt_test = { + .next = (void *)&_ssp_mqtt_test1, + .streamtype = "mqtt_test", + .endpoint = "a1ygonr3im5cv2-ats.iot.us-west-2.amazonaws.com", + .u = { + .mqtt = { + .topic = "test/topic0", + .subscribe = "test/topic0", + } + }, + .retry_bo = &_rbo_0, + .flags = 0x10, + .port = 443, + .protocol = 3, + .client_cert = 1, + .trust = {.store = &_ss_ts_mqtt_amz_iot}, +}, +_ssp_minpost = { + .next = (void *)&_ssp_mqtt_test, + .streamtype = "minpost", + .endpoint = "warmcat.com", + .u = { + .http = { + .method = "POST", + .url = "testserver/formtest", + } + }, + .retry_bo = &_rbo_0, + .flags = 0x11, + .port = 443, + .protocol = 0, + .trust = {.store = &_ss_ts_le_via_isrg}, +}, +_ssp_mintest_fail = { + .next = (void *)&_ssp_minpost, + .streamtype = "mintest-fail", + .endpoint = "warmcat.com", + .u = { + .http = { + .method = "GET", + .url = "index.html", + } + }, + .retry_bo = &_rbo_0, + .flags = 0x11, + .port = 22, + .protocol = 0, + .trust = {.store = &_ss_ts_le_via_isrg}, +}, +_ssp_h2longpolltest = { + .next = (void *)&_ssp_mintest_fail, + .streamtype = "h2longpolltest", + .endpoint = "warmcat.com", + .u = { + .http = { + .method = "GET", + .url = "index.html", + } + }, + .retry_bo = &_rbo_0, + .flags = 0x32, + .port = 443, + .protocol = 1, + .trust = {.store = &_ss_ts_le_via_isrg}, +}, +_ssp_mintest = { + .next = (void *)&_ssp_h2longpolltest, + .streamtype = "mintest", + .endpoint = "warmcat.com", + .metadata = (void *)&_md_mintest_uptag, + .u = { + .http = { + .method = "GET", + .url = "index.html?uptag=${uptag}", + } + }, + .retry_bo = &_rbo_0, + .flags = 0x11, + .port = 443, + .metadata_count = 3, + .protocol = 0, + .trust = {.store = &_ss_ts_le_via_isrg}, +}, +_ssp_avs_audio = { + .next = (void *)&_ssp_mintest, + .streamtype = "avs_audio", + .endpoint = "alexa.na.gateway.devices.a2z.com", + .u = { + .http = { + .method = "POST", + .url = "v20160207/events", + .multipart_name = "audio", + .multipart_content_type = "application/octet-stream", + .auth_preamble = "Bearer ", + .blob_header = { + "authorization:", + }, + } + }, + .retry_bo = &_rbo_0, + .flags = 0xa90, + .port = 443, + .protocol = 1, + .trust = {.store = &_ss_ts_avs_via_starfield}, +}, +_ssp_avs_metadata = { + .next = (void *)&_ssp_avs_audio, + .streamtype = "avs_metadata", + .endpoint = "alexa.na.gateway.devices.a2z.com", + .rideshare_streamtype = "avs_audio", + .u = { + .http = { + .method = "POST", + .url = "v20160207/events", + .multipart_name = "metadata", + .multipart_content_type = "application/json; charset=UTF-8", + .auth_preamble = "Bearer ", + .blob_header = { + "authorization:", + }, + } + }, + .retry_bo = &_rbo_0, + .flags = 0xa91, + .port = 443, + .protocol = 1, + .trust = {.store = &_ss_ts_avs_via_starfield}, +}, +_ssp_avs_event = { + .next = (void *)&_ssp_avs_metadata, + .streamtype = "avs_event", + .endpoint = "alexa.na.gateway.devices.a2z.com", + .u = { + .http = { + .method = "GET", + .url = "v20160207/directives", + .auth_preamble = "Bearer ", + .blob_header = { + "authorization:", + }, + } + }, + .retry_bo = &_rbo_0, + .flags = 0x2b2, + .port = 443, + .protocol = 1, + .trust = {.store = &_ss_ts_avs_via_starfield}, +}, +_ssp_api_amazon_com_auth = { + .next = (void *)&_ssp_avs_event, + .streamtype = "api_amazon_com_auth", + .endpoint = "api.amazon.com", + .u = { + .http = { + .method = "POST", + .url = "auth/o2/token", + } + }, + .retry_bo = &_rbo_0, + .flags = 0x1291, + .port = 443, + .protocol = 0, + .trust = {.store = &_ss_ts_api_amazon_com}, +}; +#define _ss_static_policy_entry _ssp_api_amazon_com_auth +/* estimated footprint 10720 (when sizeof void * = 8) */ diff -Nru libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/static-policy.json libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/static-policy.json --- libwebsockets-4.0.20/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/static-policy.json 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/static-policy.json 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,218 @@ +{ + "release": "01234567", + "product": "myproduct", + "schema-version": 1, + "retry": [{ + "default": { + "backoff": [1000, 2000, 3000, 5000, 10000], + "conceal": 5, + "jitterpc": 20, + "svalidping": 30, + "svalidhup": 35 + } + }], + "certs": [{ + "isrg_root_x1": "MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygch77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6UA5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sWT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyHB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UCB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUvKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWnOlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTnjh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbwqHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CIrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkqhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZLubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KKNFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7UrTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdCjNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVcoyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPAmRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57demyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=" + }, { + "LEX3_isrg_root_x1": "MIIFjTCCA3WgAwIBAgIRANOxciY0IzLc9AUoUSrsnGowDQYJKoZIhvcNAQELBQAwTzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTYxMDA2MTU0MzU1WhcNMjExMDA2MTU0MzU1WjBKMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3MgRW5jcnlwdDEjMCEGA1UEAxMaTGV0J3MgRW5jcnlwdCBBdXRob3JpdHkgWDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCc0wzwWuUuR7dyXTeDs2hjMOrXNSYZJeG9vjXxcJIvt7hLQQWrqZ41CFjssSrEaIcLo+N15Obzp2JxunmBYB/XkZqf89B4Z3HIaQ6Vkc/+5pnpYDxIzH7KTXcSJJ1HG1rrueweNwAcnKx7pwXqzkrrvUHlNpi5y/1tPJZo3yMqQpAMhnRnyH+lmrhSYRQTP2XpgofL2/oOVvaGifOFP5eGr7DcGu9rDZUWfcQroGWymQQ2dYBrrErzG5BJeC+ilk8qICUpBMZ0wNAxzY8xOJUWuqgzuEPxsR/DMH+ieTETPS02+OP88jNquTkxxa/EjQ0dZBYzqvqEKbbUC8DYfcOTAgMBAAGjggFnMIIBYzAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEBATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQub3JnMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8vY3JsLnJvb3QteDEubGV0c2VuY3J5cHQub3JnMHIGCCsGAQUFBwEBBGYwZDAwBggrBgEFBQcwAYYkaHR0cDovL29jc3Aucm9vdC14MS5sZXRzZW5jcnlwdC5vcmcvMDAGCCsGAQUFBzAChiRodHRwOi8vY2VydC5yb290LXgxLmxldHNlbmNyeXB0Lm9yZy8wHwYDVR0jBBgwFoAUebRZ5nu25eQBc4AIiMgaWPbpm24wDQYJKoZIhvcNAQELBQADggIBABnPdSA0LTqmRf/Q1eaM2jLonG4bQdEnqOJQ8nCqxOeTRrToEKtwT++36gTSlBGxA/5dut82jJQ2jxN8RI8L9QFXrWi4xXnA2EqA10yjHiR6H9cj6MFiOnb5In1eWsRMUM2v3e9tNsCAgBukPHAg1lQh07rvFKm/Bz9BCjaxorALINUfZ9DD64j2igLIxle2DPxW8dI/F2loHMjXZjqG8RkqZUdoxtID5+90FgsGIfkMpqgRS05f4zPbCEHqCXl1eO5HyELTgcVlLXXQDgAWnRzut1hFJeczY1tjQQno6f6s+nMydLN26WuU4s3UYvOuOsUxRlJu7TSRHqDC3lSE5XggVkzdaPkuKGQbGpny+01/47hfXXNB7HntWNZ6N2Vwp7G6OfY+YQrZwIaQmhrIqJZuigsrbe3W+gdn5ykE9+Ky0VgVUsfxo52mwFYs1JKY2PGDuWx8M6DlS6qQkvHaRUo0FMd8TsSlbF0/v965qGFKhSDeQoMpYnwcmQilRh/0ayLThlHLN81gSkJjVrPI0Y8xCVPB4twb1PFUd2fPM3sA1tJ83sZ5v8vgFv2yofKRPB0t6JzUA81mSqM3kxl5e+IZwhYAyO0OTg3/fs8HqGTNKd9BqoUwSRBzp06JMg5brUCGwbCUDI0mxadJ3Bz4WxR6fyNpBK2yAinWEsikxqEt" + }, { + "amazon_root_ca_1": "MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsFADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXjca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qwIFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQmjgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUAA4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDIU5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUsN+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vvo/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpyrqXRfboQnoZsG4q5WTP468SQvvG5" + }, { + "digicert_global_root_g2": "MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQq2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5WztCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQvIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NGFdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ918rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTepLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTflMrY=" + }, { + "digicert_global_ca_g2": "MIIEizCCA3OgAwIBAgIQDI7gyQ1qiRWIBAYe4kH5rzANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjAeFw0xMzA4MDExMjAwMDBaFw0yODA4MDExMjAwMDBaMEQxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxHjAcBgNVBAMTFURpZ2lDZXJ0IEdsb2JhbCBDQSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANNIfL7zBYZdW9UvhU5L4IatFaxhz1uvPmoKR/uadpFgC4przc/cV35gmAvkVNlW7SHMArZagV+Xau4CLyMnuG3UsOcGAngLH1ypmTb+u6wbBfpXzYEQQGfWMItYNdSWYb7QjHqXnxr5IuYUL6nG6AEfq/gmD6yOTSwyOR2Bm40cZbIc22GoiS9g5+vCShjEbyrpEJIJ7RfRACvmfe8EiRROM6GyD5eHn7OgzS+8LOy4g2gxPR/VSpAQGQuBldYpdlH5NnbQtwl6OErXb4y/E3w57bqukPyV93t4CTZedJMeJfD/1K2uaGvG/w/VNfFVbkhJ+Pi474j48V4Rd6rfArMCAwEAAaOCAVowggFWMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMHsGA1UdHwR0MHIwN6A1oDOGMWh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RHMi5jcmwwN6A1oDOGMWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RHMi5jcmwwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwHQYDVR0OBBYEFCRuKy3QapJRUSVpAaqaR6aJ50AgMB8GA1UdIwQYMBaAFE4iVCAYlebjbuYP+vq5Eu0GF485MA0GCSqGSIb3DQEBCwUAA4IBAQALOYSR+ZfrqoGvhOlaOJL84mxZvzbIRacxAxHhBsCsMsdaVSnaT0AC9aHesO3ewPj2dZ12uYf+QYB6z13jAMZbAuabeGLJ3LhimnftiQjXS8X9Q9ViIyfEBFltcT8jW+rZ8uckJ2/0lYDblizkVIvP6hnZf1WZUXoOLRg9eFhSvGNoVwvdRLNXSmDmyHBwW4coatc7TlJFGa8kBpJIERqLrqwYElesA8u49L3KJg6nwd3jM+/AVTANlVlOnAM2BvjAjxSZnE0qnsHhfTuvcqdFuhOWKU4Z0BqYBvQ3lBetoxi6PrABDJXWKTUgNX31EGDk92hiHuwZ4STyhxGs6QiA" + }, { + "starfield_services_root_ca": "MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkdiEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6" + }, { + "starfield_class_2_ca": "MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJlxy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q=" + }], + "trust_stores": [{ + "name": "le_via_isrg", + "stack": ["isrg_root_x1", "LEX3_isrg_root_x1"] + }, { + "name": "api_amazon_com", + "stack": ["digicert_global_ca_g2", "digicert_global_root_g2"] + }, { + "name": "avs_via_starfield", + "stack": ["starfield_class_2_ca", "starfield_services_root_ca"] + }, { + "name": "mqtt_amz_iot", + "stack": ["amazon_root_ca_1", "starfield_class_2_ca", "starfield_services_root_ca"] + }], + "s": [{ + "api_amazon_com_auth": { + "endpoint": "api.amazon.com", + "port": 443, + "protocol": "h1", + "http_method": "POST", + "http_url": "auth/o2/token", + "plugins": [], + "opportunistic": true, + "tls": true, + "h2q_oflow_txcr": true, + "http_www_form_urlencoded": true, + "http_no_content_length": true, + "retry": "default", + "tls_trust_store": "api_amazon_com" + } + }, { + "avs_event": { + "endpoint": "alexa.na.gateway.devices.a2z.com", + "port": 443, + "protocol": "h2", + "http_method": "GET", + "http_url": "v20160207/directives", + "h2q_oflow_txcr": true, + "http_auth_header": "authorization:", + "http_auth_preamble": "Bearer ", + "http_no_content_length": true, + "nailed_up": true, + "long_poll": true, + "retry": "default", + "plugins": [], + "tls": true, + "tls_trust_store": "avs_via_starfield" + } + }, { + "avs_metadata": { + "endpoint": "alexa.na.gateway.devices.a2z.com", + "port": 443, + "protocol": "h2", + "http_method": "POST", + "http_url": "v20160207/events", + "opportunistic": true, + "h2q_oflow_txcr": true, + "http_auth_header": "authorization:", + "http_auth_preamble": "Bearer ", + "http_multipart_name": "metadata", + "http_mime_content_type": "application/json; charset=UTF-8", + "http_no_content_length": true, + "rideshare": "avs_audio", + "retry": "default", + "plugins": [], + "tls": true, + "tls_trust_store": "avs_via_starfield" + } + }, { + "avs_audio": { + "endpoint": "alexa.na.gateway.devices.a2z.com", + "port": 443, + "protocol": "h2", + "http_method": "POST", + "http_url": "v20160207/events", + "plugins": [], + "tls": true, + "h2q_oflow_txcr": true, + "http_auth_header": "authorization:", + "http_auth_preamble": "Bearer ", + "http_multipart_name": "audio", + "http_mime_content_type": "application/octet-stream", + "http_no_content_length": true, + "retry": "default", + "tls_trust_store": "avs_via_starfield" + } + }, { + "mintest": { + "endpoint": "warmcat.com", + "port": 443, + "protocol": "h1", + "http_method": "GET", + "http_url": "index.html?uptag=${uptag}", + "http_dsn_header": "x-dsn:", + "http_fwv_header": "x-fw-version:", + "http_devtype_header": "x-devtype:", + "metadata": [{ + "uptag": "X-Upload-Tag:" + }, { + "ctype": "Content-Type:" + }, { + "xctype": "X-Content-Type:" + }], + "plugins": [], + "tls": true, + "opportunistic": true, + "retry": "default", + "tls_trust_store": "le_via_isrg" + } + }, { + "h2longpolltest": { + "endpoint": "warmcat.com", + "port": 443, + "protocol": "h2", + "http_method": "GET", + "http_url": "index.html", + "plugins": [], + "tls": true, + "nailed_up": true, + "long_poll": true, + "retry": "default", + "tls_trust_store": "le_via_isrg" + } + }, { + "mintest-fail": { + "endpoint": "warmcat.com", + "port": 22, + "protocol": "h1", + "http_method": "GET", + "http_url": "index.html", + "plugins": [], + "tls": true, + "opportunistic": true, + "retry": "default", + "tls_trust_store": "le_via_isrg" + } + }, { + "minpost": { + "endpoint": "warmcat.com", + "port": 443, + "protocol": "h1", + "http_method": "POST", + "http_url": "testserver/formtest", + "plugins": [], + "tls": true, + "opportunistic": true, + "retry": "default", + "tls_trust_store": "le_via_isrg" + } + }, { + "mqtt_test": { + "endpoint": "a1ygonr3im5cv2-ats.iot.us-west-2.amazonaws.com", + "port": 443, + "tls": true, + "client_cert": 0, + "tls_trust_store": "mqtt_amz_iot", + "protocol": "mqtt", + "mqtt_topic": "test/topic0", + "mqtt_subscribe": "test/topic0", + "mqtt_qos": 0, + "retry": "default" + } + }, { + "mqtt_test1": { + "endpoint": "a1ygonr3im5cv2-ats.iot.us-west-2.amazonaws.com", + "port": 443, + "tls": true, + "client_cert": 0, + "tls_trust_store": "mqtt_amz_iot", + "protocol": "mqtt", + "mqtt_topic": "test/topic1", + "mqtt_subscribe": "test/topic1", + "mqtt_qos": 1, + "retry": "default" + } + }, { + "captive_portal_detect": { + "endpoint": "connectivitycheck.android.com", + "port": 80, + "protocol": "h1", + "http_method": "GET", + "http_url": "generate_204", + "opportunistic": true, + "http_expect": 204, + "http_fail_redirect": true + } + } + ] +} + + diff -Nru libwebsockets-4.0.20/minimal-examples/selftests-library.sh libwebsockets-4.1.6/minimal-examples/selftests-library.sh --- libwebsockets-4.0.20/minimal-examples/selftests-library.sh 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/selftests-library.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,110 +0,0 @@ -#!/bin/bash - -if [ -z "$1" -o -z "$2" ] ; then - echo "required args missing" - exit 1 -fi - -IDX=$3 -TOT=$4 -MYTEST=`echo $0 | sed "s/\/[^\/]*\$//g" |sed "s/.*\///g"` -mkdir -p $2/$MYTEST -rm -f $2/$MYTEST/*.log $2/$MYTEST/*.result -FAILS=0 -WHICH=$IDX -SPID= -SCRIPT_DIR=`dirname $0` -SCRIPT_DIR=`readlink -f $SCRIPT_DIR` -LOGPATH=$2 - -feedback() { - if [ "$2" != "$4" ] ; then - FAILS=$(( $FAILS + 1 )) - echo -n -e "\e[31m" - fi - T=" --- killed --- " - if [ ! -z "`cat $LOGPATH/$MYTEST/$3.time`" ] ; then - T="`cat $LOGPATH/$MYTEST/$3.time | grep real | sed "s/.*\ //g"`" - T="$T `cat $LOGPATH/$MYTEST/$3.time | grep user | sed "s/.*\ //g"`" - T="$T `cat $LOGPATH/$MYTEST/$3.time | grep sys | sed "s/.*\ //g"`" - fi - printf "%-35s [ %3s/%3s ]: %3s : %8s : %s\n" $1 $WHICH $TOT $2 "$T" $3 - if [ "$2" != "0" ] ; then - echo -n -e "\e[0m" - fi - WHICH=$(( $WHICH + 1)) -} - -spawn() { - if [ ! -z "$1" ] ; then - if [ `ps $1 | wc -l` -eq 2 ]; then -# echo "prerequisite still up" - return 0 - fi - fi - - QQ=`pwd` - cd $SCRIPT_DIR - cd $2 - $3 $4 $5 > $LOGPATH/$MYTEST/serverside.log 2> $LOGPATH/$MYTEST/serverside.log & - SPID=$! - cd $QQ - sleep 0.5s -# echo "launched prerequisite $SPID" -} - -_dotest() { - EXPRES=0 - if [ ! -z "$4" ] ; then - EXPRES=$4 - fi - T=$3 -# echo "$1/lws-$MYTEST $5 $6 $7 $8 $9 ${10} ${11} ${12} ${13} ${14}" - ( - { - /usr/bin/time -p /usr/bin/valgrind -q $1/lws-$MYTEST $5 $6 $7 $8 $9 ${10} ${11} ${12} ${13} ${14} > $2/$MYTEST/$T.log 2> $2/$MYTEST/$T.log ; - echo $? > $2/$MYTEST/$T.result - } 2> $2/$MYTEST/$T.time >/dev/null - ) >/dev/null 2> /dev/null & - W=$! - WT=0 - while [ $WT -le 820 ] ; do - kill -0 $W 2>/dev/null - if [ $? -ne 0 ] ; then - WT=10000 - else - if [ $WT -ge 800 ] ; then - WT=10000 - kill $W 2>/dev/null - wait $W 2>/dev/null - fi - fi - sleep 0.1s - WT=$(( $WT + 1 )) - done - - R=254 - if [ -e $2/$MYTEST/$T.result ] ; then - R=`cat $2/$MYTEST/$T.result` - cat $2/$MYTEST/$T.log | tail -n 3 > $2/$MYTEST/$T.time - if [ $R -ne $EXPRES ] ; then - pwd - echo Expected result $EXPRES but got $R - echo - cat $2/$MYTEST/$T.log - echo - fi - fi - - feedback $MYTEST $R $T $EXPRES -} - -dotest() -{ - _dotest $1 $2 $3 0 "$4" "$5" "$6" "$7" "$8" "$9" "${10}" "${11}" "${12}" "${13}" -} - -dofailtest() -{ - _dotest $1 $2 $3 1 $4 $5 $6 $7 $8 $9 ${10} ${11} ${12} ${13} -} diff -Nru libwebsockets-4.0.20/minimal-examples/selftests.sh libwebsockets-4.1.6/minimal-examples/selftests.sh --- libwebsockets-4.0.20/minimal-examples/selftests.sh 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/selftests.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ -#!/bin/bash -# -# run this from your build dir having configured -# -DLWS_WITH_MINIMAL_EXAMPLES=1 to get all the examples -# that apply built into ./bin -# -# Eg, -# -# build $ ../minimal-examples/selftests.sh - -echo -echo "----------------------------------------------" -echo "------- tests: lws minimal example selftests" -echo - -LOGGING_PATH=/tmp/logs - -# for mebedtls, we need the CA certs in ./build where we run from - -cp ../minimal-examples/http-client/minimal-http-client-multi/warmcat.com.cer . -cp ../minimal-examples/http-client/minimal-http-client-post/libwebsockets.org.cer . - -MINEX=`dirname $0` -MINEX=`realpath $MINEX` -TESTS=0 -for i in `find $MINEX -name selftest.sh` ; do - BN=`echo -n "$i" | sed "s/\/[^\/]*\$//g" | sed "s/.*\///g"` - if [ -e `pwd`/bin/lws-$BN ] ; then - C=`cat $i | grep COUNT_TESTS= | cut -d= -f2` - TESTS=$(( $TESTS + $C )) - fi -done - -FAILS=0 -WH=1 - -for i in `find $MINEX -name selftest.sh` ; do - BN=`echo -n "$i" | sed "s/\/[^\/]*\$//g" | sed "s/.*\///g"` - if [ -e `pwd`/bin/lws-$BN ] ; then - C=`cat $i | grep COUNT_TESTS= | cut -d= -f2` - sh $i `pwd`/bin $LOGGING_PATH $WH $TESTS $MINEX - FAILS=$(( $FAILS + $? )) - - L=`ps fax | grep lws- | cut -d' ' -f2` - kill $L 2>/dev/null - kill -9 $L 2>/dev/null - wait $L 2>/dev/null - - WH=$(( $WH + $C )) - fi -done - -if [ $FAILS -eq 0 ] ; then - echo "All $TESTS passed" - exit 0 -else - echo "Failed: $FAILS / $TESTS" - exit 1 -fi - - diff -Nru libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,69 +1,14 @@ -project(lws-minimal-ws-client-ping) +project(lws-minimal-ws-client-ping C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckIncludeFile) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-client) set(SRCS minimal-ws-client.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_WS 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) @@ -72,9 +17,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client/libwebsockets.org.cer libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client/libwebsockets.org.cer --- libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client/libwebsockets.org.cer 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client/libwebsockets.org.cer 2020-12-01 17:40:26.000000000 +0000 @@ -56,3 +56,24 @@ PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6 KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg== -----END CERTIFICATE----- + -----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow +PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD +Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O +rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq +OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b +xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw +7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD +aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG +SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 +ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr +AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz +R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 +JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo +Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +-----END CERTIFICATE----- + diff -Nru libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client/minimal-ws-client.c libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client/minimal-ws-client.c --- libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client/minimal-ws-client.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client/minimal-ws-client.c 2020-12-01 17:40:26.000000000 +0000 @@ -13,7 +13,6 @@ #include #include #include -#include /* * This represents your object that "contains" the client connection and has @@ -164,7 +163,7 @@ info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ info.protocols = protocols; -#if defined(LWS_WITH_MBEDTLS) +#if defined(LWS_WITH_MBEDTLS) || defined(USE_WOLFSSL) /* * OpenSSL uses the system trust store. mbedTLS has to be told which * CA to trust explicitly. diff -Nru libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-binance/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-binance/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-binance/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-binance/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,26 @@ +project(lws-minimal-ws-client-binance C) +cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) +include(CheckIncludeFile) +include(CheckCSourceCompiles) +include(LwsCheckRequirements) + +set(SAMP lws-minimal-ws-client-binance) +set(SRCS main.c) + +set(requirements 1) +require_lws_config(LWS_ROLE_WS 1 requirements) +require_lws_config(LWS_WITH_CLIENT 1 requirements) +require_lws_config(LWS_WITHOUT_EXTENSIONS 0 requirements) + +if (requirements) + add_executable(${SAMP} ${SRCS}) + + if (websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) + add_dependencies(${SAMP} websockets_shared) + else() + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) + endif() +endif() diff -Nru libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-binance/main.c libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-binance/main.c --- libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-binance/main.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-binance/main.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,380 @@ +/* + * lws-minimal-ws-client-binance + * + * Written in 2010-2020 by Andy Green + * Kutoga + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * This demonstrates a ws client that connects to binance ws server efficiently + */ + +#include +#include +#include +#include + +typedef struct range { + lws_usec_t sum; + lws_usec_t lowest; + lws_usec_t highest; + + int samples; +} range_t; + +/* + * This represents your object that "contains" the client connection and has + * the client connection bound to it + */ + +static struct my_conn { + lws_sorted_usec_list_t sul; /* schedule connection retry */ + lws_sorted_usec_list_t sul_hz; /* 1hz summary */ + + range_t e_lat_range; + range_t price_range; + + struct lws *wsi; /* related wsi if any */ + uint16_t retry_count; /* count of consequetive retries */ +} mco; + +static struct lws_context *context; +static int interrupted; + +#if defined(LWS_WITH_MBEDTLS) || defined(USE_WOLFSSL) +/* + * OpenSSL uses the system trust store. mbedTLS / WolfSSL have to be told which + * CA to trust explicitly. + */ +static const char * const ca_pem_digicert_global_root = + "-----BEGIN CERTIFICATE-----\n" + "MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh\n" + "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" + "d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\n" + "QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT\n" + "MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n" + "b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG\n" + "9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB\n" + "CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97\n" + "nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt\n" + "43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P\n" + "T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4\n" + "gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO\n" + "BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR\n" + "TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw\n" + "DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr\n" + "hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg\n" + "06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF\n" + "PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls\n" + "YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk\n" + "CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=\n" + "-----END CERTIFICATE-----\n"; +#endif + +/* + * The retry and backoff policy we want to use for our client connections + */ + +static const uint32_t backoff_ms[] = { 1000, 2000, 3000, 4000, 5000 }; + +static const lws_retry_bo_t retry = { + .retry_ms_table = backoff_ms, + .retry_ms_table_count = LWS_ARRAY_SIZE(backoff_ms), + .conceal_count = LWS_ARRAY_SIZE(backoff_ms), + + .secs_since_valid_ping = 400, /* force PINGs after secs idle */ + .secs_since_valid_hangup = 400, /* hangup after secs idle */ + + .jitter_percent = 0, +}; + +/* + * If we don't enable permessage-deflate ws extension, during times when there + * are many ws messages per second the server coalesces them inside a smaller + * number of larger ssl records, for >100 mps typically >2048 records. + * + * This is a problem, because the coalesced record cannot be send nor decrypted + * until the last part of the record is received, meaning additional latency + * for the earlier members of the coalesced record that have just been sitting + * there waiting for the last one to go out and be decrypted. + * + * permessage-deflate reduces the data size before the tls layer, for >100mps + * reducing the colesced records to ~1.2KB. + */ + +static const struct lws_extension extensions[] = { + { + "permessage-deflate", + lws_extension_callback_pm_deflate, + "permessage-deflate" + "; client_no_context_takeover" + "; client_max_window_bits" + }, + { NULL, NULL, NULL /* terminator */ } +}; +/* + * Scheduled sul callback that starts the connection attempt + */ + +static void +connect_client(lws_sorted_usec_list_t *sul) +{ + struct my_conn *mco = lws_container_of(sul, struct my_conn, sul); + struct lws_client_connect_info i; + + memset(&i, 0, sizeof(i)); + + i.context = context; + i.port = 443; + i.address = "fstream.binance.com"; + i.path = "/stream?" + "streams=btcusdt@depth@0ms/btcusdt@bookTicker/btcusdt@aggTrade"; + i.host = i.address; + i.origin = i.address; + i.ssl_connection = LCCSCF_USE_SSL | LCCSCF_PRIORITIZE_READS; + i.protocol = NULL; + i.local_protocol_name = "lws-minimal-client"; + i.pwsi = &mco->wsi; + i.retry_and_idle_policy = &retry; + i.userdata = mco; + + if (!lws_client_connect_via_info(&i)) + /* + * Failed... schedule a retry... we can't use the _retry_wsi() + * convenience wrapper api here because no valid wsi at this + * point. + */ + if (lws_retry_sul_schedule(context, 0, sul, &retry, + connect_client, &mco->retry_count)) { + lwsl_err("%s: connection attempts exhausted\n", __func__); + interrupted = 1; + } +} + +static void +range_reset(range_t *r) +{ + r->sum = r->highest = 0; + r->lowest = 999999999999ull; + r->samples = 0; +} + +static uint64_t +get_us_timeofday(void) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + + return ((lws_usec_t)tv.tv_sec * LWS_US_PER_SEC) + tv.tv_usec; +} + +static void +sul_hz_cb(lws_sorted_usec_list_t *sul) +{ + struct my_conn *mco = lws_container_of(sul, struct my_conn, sul_hz); + + /* + * We are called once a second to dump statistics on the connection + */ + + lws_sul_schedule(lws_get_context(mco->wsi), 0, &mco->sul_hz, + sul_hz_cb, LWS_US_PER_SEC); + + if (mco->price_range.samples) + lwsl_notice("%s: price: min: %llu¢, max: %llu¢, avg: %llu¢, " + "(%d prices/s)\n", + __func__, + (unsigned long long)mco->price_range.lowest, + (unsigned long long)mco->price_range.highest, + (unsigned long long)(mco->price_range.sum / mco->price_range.samples), + mco->price_range.samples); + if (mco->e_lat_range.samples) + lwsl_notice("%s: elatency: min: %llums, max: %llums, " + "avg: %llums, (%d msg/s)\n", __func__, + (unsigned long long)mco->e_lat_range.lowest / 1000, + (unsigned long long)mco->e_lat_range.highest / 1000, + (unsigned long long)(mco->e_lat_range.sum / + mco->e_lat_range.samples) / 1000, + mco->e_lat_range.samples); + + range_reset(&mco->e_lat_range); + range_reset(&mco->price_range); +} + +static uint64_t +pennies(const char *s) +{ + uint64_t price = (uint64_t)atoll(s) * 100; + + s = strchr(s, '.'); + + if (s && isdigit(s[1]) && isdigit(s[2])) + price += (10 * (s[1] - '0')) + (s[2] - '0'); + + return price; +} + +static int +callback_minimal(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) +{ + struct my_conn *mco = (struct my_conn *)user; + lws_usec_t latency_us, now_us, price; + char numbuf[16]; + const char *p; + size_t alen; + + switch (reason) { + + case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: + lwsl_err("CLIENT_CONNECTION_ERROR: %s\n", + in ? (char *)in : "(null)"); + goto do_retry; + break; + + case LWS_CALLBACK_CLIENT_RECEIVE: + /* + * The messages are a few 100 bytes of JSON each + */ + + // lwsl_hexdump_notice(in, len); + + now_us = get_us_timeofday(); + + p = lws_json_simple_find((const char *)in, len, + "\"depthUpdate\"", &alen); + /* + * Only the JSON with depthUpdate init has the numbers we care + * about as well + */ + if (!p) + break; + + p = lws_json_simple_find((const char *)in, len, "\"E\":", &alen); + if (!p) { + lwsl_err("%s: no E JSON\n", __func__); + break; + } + lws_strnncpy(numbuf, p, alen, sizeof(numbuf)); + latency_us = now_us - + ((lws_usec_t)atoll(numbuf) * LWS_US_PER_MS); + + if (latency_us < mco->e_lat_range.lowest) + mco->e_lat_range.lowest = latency_us; + if (latency_us > mco->e_lat_range.highest) + mco->e_lat_range.highest = latency_us; + + mco->e_lat_range.sum += latency_us; + mco->e_lat_range.samples++; + + p = lws_json_simple_find((const char *)in, len, + "\"a\":[[\"", &alen); + if (p) { + lws_strnncpy(numbuf, p, alen, sizeof(numbuf)); + price = pennies(numbuf); + + if (price < mco->price_range.lowest) + mco->price_range.lowest = price; + if (price > mco->price_range.highest) + mco->price_range.highest = price; + + mco->price_range.sum += price; + mco->price_range.samples++; + } + break; + + case LWS_CALLBACK_CLIENT_ESTABLISHED: + lwsl_user("%s: established\n", __func__); + lws_sul_schedule(lws_get_context(wsi), 0, &mco->sul_hz, + sul_hz_cb, LWS_US_PER_SEC); + mco->wsi = wsi; + range_reset(&mco->e_lat_range); + range_reset(&mco->price_range); + break; + + case LWS_CALLBACK_CLIENT_CLOSED: + goto do_retry; + + default: + break; + } + + return lws_callback_http_dummy(wsi, reason, user, in, len); + +do_retry: + /* + * retry the connection to keep it nailed up + * + * For this example, we try to conceal any problem for one set of + * backoff retries and then exit the app. + * + * If you set retry.conceal_count to be larger than the number of + * elements in the backoff table, it will never give up and keep + * retrying at the last backoff delay plus the random jitter amount. + */ + if (lws_retry_sul_schedule_retry_wsi(wsi, &mco->sul, connect_client, + &mco->retry_count)) { + lwsl_err("%s: connection attempts exhausted\n", __func__); + interrupted = 1; + } + + return 0; +} + +static const struct lws_protocols protocols[] = { + { "lws-minimal-client", callback_minimal, 0, 0, }, + { NULL, NULL, 0, 0 } +}; + +static void +sigint_handler(int sig) +{ + interrupted = 1; +} + +int main(int argc, const char **argv) +{ + struct lws_context_creation_info info; + int n = 0; + + signal(SIGINT, sigint_handler); + memset(&info, 0, sizeof info); + lws_cmdline_option_handle_builtin(argc, argv, &info); + + lwsl_user("LWS minimal binance client\n"); + + info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ + info.protocols = protocols; + info.fd_limit_per_thread = 1 + 1 + 1; + info.extensions = extensions; + +#if defined(LWS_WITH_MBEDTLS) || defined(USE_WOLFSSL) + /* + * OpenSSL uses the system trust store. mbedTLS / WolfSSL have to be + * told which CA to trust explicitly. + */ + info.client_ssl_ca_mem = ca_pem_digicert_global_root; + info.client_ssl_ca_mem_len = strlen(ca_pem_digicert_global_root); +#endif + + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + return 1; + } + + /* schedule the first client connection attempt to happen immediately */ + lws_sul_schedule(context, 0, &mco.sul, connect_client, 1); + + while (n >= 0 && !interrupted) + n = lws_service(context, 0); + + lws_context_destroy(context); + lwsl_user("Completed\n"); + + return 0; +} + diff -Nru libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-binance/README.md libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-binance/README.md --- libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-binance/README.md 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-binance/README.md 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,67 @@ +# lws minimal ws client binance + +This connects to the binance ws server and monitors transactions with +an eye on low latency. + +Latency seems to be associated with server-side coalescing at tls +layer, and the coalescing at server side seems somewhat correlated to number +of transactions per second, which seems to cause increased packet sizes from the +server as a reaction. The relationship is more complex probably according to what +actually happens at the server backend, but it seems to be broadly related +reliably. + +Typically when showing low latency at ~70msg/s, the messages on the wire are +eg, ~70 byte packets containing small tls records + +10:14:40.682293 IP ec2-54-249-113-172.ap-northeast-1.compute.amazonaws.com.https > constance.42952: Flags [P.], seq 50846:50927, ack 1, win 11, options [nop,nop,TS val 366445630 ecr 3893437035], length 81 + +under pressure from increased messages per second, the tls records increase above 2KB + +08:06:02.825160 IP ec2-54-249-113-172.ap-northeast-1.compute.amazonaws.com.https > constance.42688: Flags [.], seq 512319:513643, ack 1, win 11, options [nop,nop,TS val 3990208942 ecr 3885719233], length 1324 +08:06:02.825290 IP constance.42688 > ec2-54-249-113-172.ap-northeast-1.compute.amazonaws.com.https: Flags [.], ack 513643, win 14248, options [nop,nop,TS val 3885719479 ecr 3990208942], length 0 +08:06:02.891646 IP ec2-54-249-113-172.ap-northeast-1.compute.amazonaws.com.https > constance.42688: Flags [.], seq 513643:516291, ack 1, win 11, options [nop,nop,TS val 3990209006 ecr 3885719296], length 2648 + +The larger the packets, the longer the first item in the packet had to +wait before it was sent, and a tls record cannot be authenticated until +all of it has been received. + +The example circumvents this somewhat by using `permessage_deflate`, which reduces +the packet size before tls by applying compression, making even coalesced packets +smaller, and a new option for adjusting how lws manages conflicting requirements to +clear pending rx and allow interleaved tx, `LCCSCF_PRIORITIZE_READS` that causes the +stream to prioritize handling any pending rx, not just pending at ssl layer, in one +event loop trip. + +## build + +Lws must have been built with `LWS_ROLE_WS=1` and `LWS_WITHOUT_EXTENSIONS=0` + +``` + $ cmake . && make +``` + +## Commandline Options + +Option|Meaning +---|--- +-d|Set logging verbosity + +## usage + +``` +$ ./bin/lws-minimal-ws-client-binance +[2020/08/23 10:22:49:3003] U: LWS minimal binance client +[2020/08/23 10:22:49:3005] N: LWS: 4.0.99-v4.1.0-rc2-4-g3cf133aef, loglevel 1031 +[2020/08/23 10:22:49:3005] N: NET CLI SRV H1 H2 WS MQTT SS-JSON-POL SSPROX ASYNC_DNS IPv6-absent +[2020/08/23 10:22:50:8243] N: checking client ext permessage-deflate +[2020/08/23 10:22:50:8244] N: instantiating client ext permessage-deflate +[2020/08/23 10:22:50:8244] U: callback_minimal: established +[2020/08/23 10:22:51:8244] N: sul_hz_cb: price: min: 1160284¢, max: 1163794¢, avg: 1160516¢, (150 prices/s) +[2020/08/23 10:22:51:8245] N: sul_hz_cb: elatency: min: 112ms, max: 547ms, avg: 259ms, (155 msg/s) +[2020/08/23 10:22:52:8244] N: sul_hz_cb: price: min: 1160287¢, max: 1178845¢, avg: 1160897¢, (112 prices/s) +[2020/08/23 10:22:52:8245] N: sul_hz_cb: elatency: min: 111ms, max: 226ms, avg: 152ms, (134 msg/s) +[2020/08/23 10:22:53:8247] N: sul_hz_cb: price: min: 1160287¢, max: 1168005¢, avg: 1160806¢, (86 prices/s) +[2020/08/23 10:22:53:8248] N: sul_hz_cb: elatency: min: 112ms, max: 476ms, avg: 287ms, (101 msg/s) +[2020/08/23 10:22:54:8247] N: sul_hz_cb: price: min: 1160284¢, max: 1162780¢, avg: 1160698¢, (71 prices/s) +... +``` diff -Nru libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-echo/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-echo/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-echo/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-echo/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,68 +1,13 @@ -project(lws-minimal-ws-client-echo) +project(lws-minimal-ws-client-echo C) cmake_minimum_required(VERSION 2.8.9) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-client-echo) set(SRCS minimal-ws-client-echo.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_WS 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) @@ -72,9 +17,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-echo/protocol_lws_minimal_client_echo.c libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-echo/protocol_lws_minimal_client_echo.c --- libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-echo/protocol_lws_minimal_client_echo.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-echo/protocol_lws_minimal_client_echo.c 2020-12-01 17:40:26.000000000 +0000 @@ -43,6 +43,8 @@ struct lws_vhost *vhost; struct lws *client_wsi; + lws_sorted_usec_list_t sul; + int *interrupted; int *options; const char **url; @@ -51,9 +53,11 @@ int *port; }; -static int -connect_client(struct vhd_minimal_client_echo *vhd) +static void +sul_connect_attempt(struct lws_sorted_usec_list *sul) { + struct vhd_minimal_client_echo *vhd = + lws_container_of(sul, struct vhd_minimal_client_echo, sul); struct lws_client_connect_info i; char host[128]; @@ -77,7 +81,9 @@ lwsl_user("connecting to %s:%d/%s\n", i.address, i.port, i.path); - return !lws_client_connect_via_info(&i); + if (!lws_client_connect_via_info(&i)) + lws_sul_schedule(vhd->context, 0, &vhd->sul, + sul_connect_attempt, 10 * LWS_US_PER_SEC); } static void @@ -90,13 +96,6 @@ msg->len = 0; } -static void -schedule_callback(struct lws *wsi, int reason, int secs) -{ - lws_timed_callback_vh_protocol(lws_get_vhost(wsi), - lws_get_protocol(wsi), reason, secs); -} - static int callback_minimal_client_echo(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) @@ -142,8 +141,11 @@ (const struct lws_protocol_vhost_options *)in, "iface")->value; - if (connect_client(vhd)) - schedule_callback(wsi, LWS_CALLBACK_USER, 1); + sul_connect_attempt(&vhd->sul); + break; + + case LWS_CALLBACK_PROTOCOL_DESTROY: + lws_sul_cancel(&vhd->sul); break; case LWS_CALLBACK_CLIENT_ESTABLISHED: @@ -250,32 +252,18 @@ lwsl_err("CLIENT_CONNECTION_ERROR: %s\n", in ? (char *)in : "(null)"); vhd->client_wsi = NULL; - //schedule_callback(wsi, LWS_CALLBACK_USER, 1); - //if (*vhd->options & 1) { - if (!*vhd->interrupted) - *vhd->interrupted = 3; - lws_cancel_service(lws_get_context(wsi)); - //} + if (!*vhd->interrupted) + *vhd->interrupted = 3; + lws_cancel_service(lws_get_context(wsi)); break; case LWS_CALLBACK_CLIENT_CLOSED: lwsl_user("LWS_CALLBACK_CLIENT_CLOSED\n"); lws_ring_destroy(pss->ring); vhd->client_wsi = NULL; - // schedule_callback(wsi, LWS_CALLBACK_USER, 1); - //if (*vhd->options & 1) { - if (!*vhd->interrupted) - *vhd->interrupted = 1 + pss->completed; - lws_cancel_service(lws_get_context(wsi)); - // } - break; - - /* rate-limited client connect retries */ - - case LWS_CALLBACK_USER: - lwsl_notice("%s: LWS_CALLBACK_USER\n", __func__); - if (connect_client(vhd)) - schedule_callback(wsi, LWS_CALLBACK_USER, 1); + if (!*vhd->interrupted) + *vhd->interrupted = 1 + pss->completed; + lws_cancel_service(lws_get_context(wsi)); break; default: @@ -293,36 +281,3 @@ 1024, \ 0, NULL, 0 \ } - -#if !defined (LWS_PLUGIN_STATIC) - -/* boilerplate needed if we are built as a dynamic plugin */ - -static const struct lws_protocols protocols[] = { - LWS_PLUGIN_PROTOCOL_MINIMAL_CLIENT_ECHO -}; - -int -init_protocol_minimal_client_echo(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } - - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} - -int -destroy_protocol_minimal_client_echo(struct lws_context *context) -{ - return 0; -} -#endif diff -Nru libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-ping/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-ping/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-ping/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-ping/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,79 +1,14 @@ -project(lws-minimal-ws-client-ping) +project(lws-minimal-ws-client-ping C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckIncludeFile) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-client-ping) set(SRCS minimal-ws-client-ping.c) -MACRO(require_pthreads result) - CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) - if (NOT LWS_HAVE_PTHREAD_H) - if (LWS_WITH_MINIMAL_EXAMPLES) - set(result 0) - else() - message(FATAL_ERROR "threading support requires pthreads") - endif() - endif() -ENDMACRO() -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_pthreads(requirements) require_lws_config(LWS_ROLE_WS 1 requirements) @@ -83,9 +18,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared pthread) - add_dependencies(${SAMP} websockets_shared pthread) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) + add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets pthread) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-ping/libwebsockets.org.cer libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-ping/libwebsockets.org.cer --- libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-ping/libwebsockets.org.cer 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-ping/libwebsockets.org.cer 2020-12-01 17:40:26.000000000 +0000 @@ -56,3 +56,24 @@ PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6 KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg== -----END CERTIFICATE----- + -----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow +PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD +Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O +rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq +OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b +xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw +7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD +aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG +SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 +ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr +AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz +R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 +JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo +Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +-----END CERTIFICATE----- + diff -Nru libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-ping/minimal-ws-client-ping.c libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-ping/minimal-ws-client-ping.c --- libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-ping/minimal-ws-client-ping.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-ping/minimal-ws-client-ping.c 2020-12-01 17:40:26.000000000 +0000 @@ -14,6 +14,12 @@ #include #include #include +#if defined(WIN32) +#define HAVE_STRUCT_TIMESPEC +#if defined(pid_t) +#undef pid_t +#endif +#endif #include static struct lws_context *context; @@ -117,7 +123,7 @@ info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ info.protocols = protocols; -#if defined(LWS_WITH_MBEDTLS) +#if defined(LWS_WITH_MBEDTLS) || defined(USE_WOLFSSL) /* * OpenSSL uses the system trust store. mbedTLS has to be told which * CA to trust explicitly. diff -Nru libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,68 +1,13 @@ -project(lws-minimal-ws-client-pmd-bulk) +project(lws-minimal-ws-client-pmd-bulk C) cmake_minimum_required(VERSION 2.8.9) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-client-pmd-bulk) set(SRCS minimal-ws-client-pmd-bulk.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_WS 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) @@ -72,9 +17,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/protocol_lws_minimal_pmd_bulk.c libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/protocol_lws_minimal_pmd_bulk.c --- libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/protocol_lws_minimal_pmd_bulk.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/protocol_lws_minimal_pmd_bulk.c 2020-12-01 17:40:26.000000000 +0000 @@ -65,6 +65,8 @@ struct lws_vhost *vhost; struct lws *client_wsi; + lws_sorted_usec_list_t sul; + int *interrupted; int *options; }; @@ -78,9 +80,11 @@ return *r; } -static int -connect_client(struct vhd_minimal_pmd_bulk *vhd) +static void +sul_connect_attempt(struct lws_sorted_usec_list *sul) { + struct vhd_minimal_pmd_bulk *vhd = + lws_container_of(sul, struct vhd_minimal_pmd_bulk, sul); struct lws_client_connect_info i; memset(&i, 0, sizeof(i)); @@ -96,14 +100,9 @@ i.protocol = "lws-minimal-pmd-bulk"; i.pwsi = &vhd->client_wsi; - return !lws_client_connect_via_info(&i); -} - -static void -schedule_callback(struct lws *wsi, int reason, int secs) -{ - lws_timed_callback_vh_protocol(lws_get_vhost(wsi), - lws_get_protocol(wsi), reason, secs); + if (!lws_client_connect_via_info(&i)) + lws_sul_schedule(vhd->context, 0, &vhd->sul, + sul_connect_attempt, 10 * LWS_US_PER_SEC); } static int @@ -138,8 +137,11 @@ (const struct lws_protocol_vhost_options *)in, "options")->value; - if (connect_client(vhd)) - schedule_callback(wsi, LWS_CALLBACK_USER, 1); + sul_connect_attempt(&vhd->sul); + break; + + case LWS_CALLBACK_PROTOCOL_DESTROY: + lws_sul_cancel(&vhd->sul); break; case LWS_CALLBACK_CLIENT_ESTABLISHED: @@ -181,14 +183,14 @@ if (s > (size_t)n) s = n; memcpy(p, &redundant_string[m], s); - pss->position_tx += s; + pss->position_tx += (int)s; p += s; - n -= s; + n -= (int)s; } } else { pss->position_tx += n; while (n--) - *p++ = rng(&pss->rng_tx); + *p++ = (uint8_t)rng(&pss->rng_tx); } n = lws_ptr_diff(p, start); @@ -227,13 +229,13 @@ lwsl_user("echo'd data doesn't match\n"); return -1; } - pss->position_rx += s; + pss->position_rx += (int)s; in = ((unsigned char *)in) + s; len -= s; } } else { p = (uint8_t *)in; - pss->position_rx += len; + pss->position_rx += (int)len; while (len--) if (*p++ != (uint8_t)rng(&pss->rng_rx)) { lwsl_user("echo'd data doesn't match\n"); @@ -253,20 +255,14 @@ lwsl_err("CLIENT_CONNECTION_ERROR: %s\n", in ? (char *)in : "(null)"); vhd->client_wsi = NULL; - schedule_callback(wsi, LWS_CALLBACK_USER, 1); + lws_sul_schedule(vhd->context, 0, &vhd->sul, + sul_connect_attempt, LWS_US_PER_SEC); break; case LWS_CALLBACK_CLIENT_CLOSED: vhd->client_wsi = NULL; - schedule_callback(wsi, LWS_CALLBACK_USER, 1); - break; - - /* rate-limited client connect retries */ - - case LWS_CALLBACK_USER: - lwsl_notice("%s: LWS_CALLBACK_USER\n", __func__); - if (connect_client(vhd)) - schedule_callback(wsi, LWS_CALLBACK_USER, 1); + lws_sul_schedule(vhd->context, 0, &vhd->sul, + sul_connect_attempt, LWS_US_PER_SEC); break; default: @@ -284,36 +280,3 @@ 4096, \ 0, NULL, 0 \ } - -#if !defined (LWS_PLUGIN_STATIC) - -/* boilerplate needed if we are built as a dynamic plugin */ - -static const struct lws_protocols protocols[] = { - LWS_PLUGIN_PROTOCOL_MINIMAL_PMD_BULK -}; - -int -init_protocol_minimal_pmd_bulk(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } - - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} - -int -destroy_protocol_minimal_pmd_bulk(struct lws_context *context) -{ - return 0; -} -#endif diff -Nru libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-rx/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-rx/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-rx/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-rx/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,79 +1,32 @@ -project(lws-minimal-ws-client-rx) +project(lws-minimal-ws-client-rx C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-client-rx) set(SRCS minimal-ws-client.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_WS 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) + if (LWS_CTEST_INTERNET_AVAILABLE) + add_test(NAME ws-client-rx-warmcat COMMAND lws-minimal-ws-client-rx -t) + set_tests_properties(ws-client-rx-warmcat + PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/ws-client/minimal-ws-client-rx + TIMEOUT 20) + + endif() if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() -endif() \ No newline at end of file +endif() diff -Nru libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-rx/libwebsockets.org.cer libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-rx/libwebsockets.org.cer --- libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-rx/libwebsockets.org.cer 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-rx/libwebsockets.org.cer 2020-12-01 17:40:26.000000000 +0000 @@ -56,3 +56,24 @@ PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6 KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg== -----END CERTIFICATE----- + -----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow +PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD +Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O +rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq +OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b +xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw +7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD +aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG +SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 +ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr +AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz +R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 +JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo +Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +-----END CERTIFICATE----- + diff -Nru libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-rx/minimal-ws-client.c libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-rx/minimal-ws-client.c --- libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-rx/minimal-ws-client.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-rx/minimal-ws-client.c 2020-12-01 17:40:26.000000000 +0000 @@ -99,7 +99,9 @@ info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ info.protocols = protocols; -#if defined(LWS_WITH_MBEDTLS) + info.timeout_secs = 10; + info.connect_timeout_secs = 30; +#if defined(LWS_WITH_MBEDTLS) || defined(USE_WOLFSSL) /* * OpenSSL uses the system trust store. mbedTLS has to be told which * CA to trust explicitly. diff -Nru libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-rx/selftest.sh libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-rx/selftest.sh --- libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-rx/selftest.sh 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-rx/selftest.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -#!/bin/bash -# -# $1: path to minimal example binaries... -# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 -# that will be ./bin from your build dir -# -# $2: path for logs and results. The results will go -# in a subdir named after the directory this script -# is in -# -# $3: offset for test index count -# -# $4: total test count -# -# $5: path to ./minimal-examples dir in lws -# -# Test return code 0: OK, 254: timed out, other: error indication - -. $5/selftests-library.sh - -COUNT_TESTS=1 - -dotest $1 $2 warmcat -t - -exit $FAILS diff -Nru libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-spam/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-spam/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-spam/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-spam/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,79 +1,14 @@ -project(lws-minimal-ws-client-spam) +project(lws-minimal-ws-client-spam C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckIncludeFile) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-client-spam) set(SRCS minimal-ws-client-spam.c) -MACRO(require_pthreads result) - CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) - if (NOT LWS_HAVE_PTHREAD_H) - if (LWS_WITH_MINIMAL_EXAMPLES) - set(result 0) - else() - message(FATAL_ERROR "threading support requires pthreads") - endif() - endif() -ENDMACRO() -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_pthreads(requirements) require_lws_config(LWS_ROLE_WS 1 requirements) @@ -81,11 +16,58 @@ if (requirements) add_executable(${SAMP} ${SRCS}) + # + # instantiate the server per sai builder instance, they are running in the same + # machine context in parallel so they can tread on each other otherwise + # + set(PORT_WCS_SRV "7620") + if ("$ENV{SAI_INSTANCE_IDX}" STREQUAL "0") + set(PORT_WCS_SRV 7621) + endif() + if ("$ENV{SAI_INSTANCE_IDX}" STREQUAL "1") + set(PORT_WCS_SRV 7622) + endif() + if ("$ENV{SAI_INSTANCE_IDX}" STREQUAL "2") + set(PORT_WCS_SRV 7623) + endif() + if ("$ENV{SAI_INSTANCE_IDX}" STREQUAL "3") + set(PORT_WCS_SRV 7624) + endif() + +# hack +if (WIN32) +else() + +if (LWS_WITH_SERVER) +if (WIN32) + add_test(NAME st_wcs_srv COMMAND cmd.exe /c start /b $ -s --port ${PORT_WCS_SRV}) + add_test(NAME ki_wcs_srv COMMAND taskkill /F /IM $ /T) +else() + add_test(NAME st_wcs_srv COMMAND + ${CMAKE_SOURCE_DIR}/scripts/ctest-background.sh + wcs_srv $ + -r ${CMAKE_SOURCE_DIR}/destdir/usr/local/share/libwebsockets-test-server/ + -s --port ${PORT_WCS_SRV} --ignore-sigterm) + add_test(NAME ki_wcs_srv COMMAND + ${CMAKE_SOURCE_DIR}/scripts/ctest-background-kill.sh + wcs_srv $ --port ${PORT_WCS_SRV}) +endif() + + set_tests_properties(st_wcs_srv PROPERTIES WORKING_DIRECTORY . FIXTURES_SETUP wcs_srv TIMEOUT 800) + set_tests_properties(ki_wcs_srv PROPERTIES FIXTURES_CLEANUP wcs_srv) + + add_test(NAME ws-client-spam COMMAND lws-minimal-ws-client-spam --server localhost --port ${PORT_WCS_SRV} -l 32 -c 3) + set_tests_properties(ws-client-spam PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/ws-client/minimal-ws-client-spam + FIXTURES_REQUIRED "wcs_srv" + TIMEOUT 40) +endif() +endif() if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared pthread) - add_dependencies(${SAMP} websockets_shared pthread) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) + add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets pthread) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-spam/libwebsockets.org.cer libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-spam/libwebsockets.org.cer --- libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-spam/libwebsockets.org.cer 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-spam/libwebsockets.org.cer 2020-12-01 17:40:26.000000000 +0000 @@ -56,3 +56,24 @@ PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6 KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg== -----END CERTIFICATE----- + -----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow +PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD +Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O +rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq +OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b +xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw +7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD +aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG +SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 +ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr +AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz +R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 +JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo +Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +-----END CERTIFICATE----- + diff -Nru libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-spam/minimal-ws-client-spam.c libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-spam/minimal-ws-client-spam.c --- libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-spam/minimal-ws-client-spam.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-spam/minimal-ws-client-spam.c 2020-12-01 17:40:26.000000000 +0000 @@ -13,6 +13,12 @@ #include #include #include +#if defined(WIN32) +#define HAVE_STRUCT_TIMESPEC +#if defined(pid_t) +#undef pid_t +#endif +#endif #include enum { @@ -64,6 +70,7 @@ clients[idx].state = CLIENT_CONNECTING; tries++; + lwsl_notice("%s: connection %s:%d\n", __func__, i.address, i.port); if (!lws_client_connect_via_info(&i)) { clients[idx].wsi = NULL; clients[idx].state = CLIENT_IDLE; @@ -199,7 +206,7 @@ info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ info.protocols = protocols; -#if defined(LWS_WITH_MBEDTLS) +#if defined(LWS_WITH_MBEDTLS) || defined(USE_WOLFSSL) /* * OpenSSL uses the system trust store. mbedTLS has to be told which * CA to trust explicitly. @@ -252,6 +259,8 @@ while (n >= 0 && !interrupted) n = lws_service(context, 0); + lwsl_notice("%s: exiting service loop\n", __func__); + lws_context_destroy(context); if (tries == limit && closed == tries) { diff -Nru libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-spam/selftest.sh libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-spam/selftest.sh --- libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-spam/selftest.sh 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-spam/selftest.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -#!/bin/bash -# -# $1: path to minimal example binaries... -# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 -# that will be ./bin from your build dir -# -# $2: path for logs and results. The results will go -# in a subdir named after the directory this script -# is in -# -# $3: offset for test index count -# -# $4: total test count -# -# $5: path to ./minimal-examples dir in lws -# -# Test return code 0: OK, 254: timed out, other: error indication - -. $5/selftests-library.sh - -COUNT_TESTS=1 - -dotest $1 $2 warmcat - -exit $FAILS - diff -Nru libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-tx/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-tx/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-tx/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-tx/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,79 +1,14 @@ -project(lws-minimal-ws-client-tx) +project(lws-minimal-ws-client-tx C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckIncludeFile) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-client-tx) set(SRCS minimal-ws-client.c) -MACRO(require_pthreads result) - CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) - if (NOT LWS_HAVE_PTHREAD_H) - if (LWS_WITH_MINIMAL_EXAMPLES) - set(result 0) - else() - message(FATAL_ERROR "threading support requires pthreads") - endif() - endif() -ENDMACRO() -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_pthreads(requirements) require_lws_config(LWS_ROLE_WS 1 requirements) @@ -83,9 +18,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared pthread) - add_dependencies(${SAMP} websockets_shared pthread) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) + add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets pthread) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() \ No newline at end of file diff -Nru libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-tx/minimal-ws-client.c libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-tx/minimal-ws-client.c --- libwebsockets-4.0.20/minimal-examples/ws-client/minimal-ws-client-tx/minimal-ws-client.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-client/minimal-ws-client-tx/minimal-ws-client.c 2020-12-01 17:40:26.000000000 +0000 @@ -21,6 +21,12 @@ #include #include #include +#if defined(WIN32) +#define HAVE_STRUCT_TIMESPEC +#if defined(pid_t) +#undef pid_t +#endif +#endif #include static int interrupted; @@ -38,6 +44,8 @@ const struct lws_protocols *protocol; pthread_t pthread_spam[2]; + lws_sorted_usec_list_t sul; + pthread_mutex_t lock_ring; /* serialize access to the ring buffer */ struct lws_ring *ring; /* ringbuffer holding unsent messages */ uint32_t tail; @@ -70,7 +78,11 @@ struct per_vhost_data__minimal *vhd = (struct per_vhost_data__minimal *)d; struct msg amsg; - int len = 128, index = 1, n; + int len = 128, index = 1, n, whoami = 0; + + for (n = 0; n < (int)LWS_ARRAY_SIZE(vhd->pthread_spam); n++) + if (pthread_equal(pthread_self(), vhd->pthread_spam[n])) + whoami = n + 1; do { /* don't generate output if client not connected */ @@ -92,10 +104,9 @@ goto wait_unlock; } n = lws_snprintf((char *)amsg.payload + LWS_PRE, len, - "tid: %p, msg: %d", - (void *)pthread_self(), index++); + "tid: %d, msg: %d", whoami, index++); amsg.len = n; - n = lws_ring_insert(vhd->ring, &amsg, 1); + n = (int)lws_ring_insert(vhd->ring, &amsg, 1); if (n != 1) { __minimal_destroy_message(&amsg); lwsl_user("dropping!\n"); @@ -114,16 +125,19 @@ } while (!vhd->finished); - lwsl_notice("thread_spam %p exiting\n", (void *)pthread_self()); + lwsl_notice("thread_spam %d exiting\n", whoami); pthread_exit(NULL); return NULL; } -static int -connect_client(struct per_vhost_data__minimal *vhd) +static void +sul_connect_attempt(struct lws_sorted_usec_list *sul) { + struct per_vhost_data__minimal *vhd = + lws_container_of(sul, struct per_vhost_data__minimal, sul); + vhd->i.context = vhd->context; vhd->i.port = 7681; vhd->i.address = "localhost"; @@ -135,7 +149,9 @@ vhd->i.protocol = "lws-minimal-broker"; vhd->i.pwsi = &vhd->client_wsi; - return !lws_client_connect_via_info(&vhd->i); + if (!lws_client_connect_via_info(&vhd->i)) + lws_sul_schedule(vhd->context, 0, &vhd->sul, + sul_connect_attempt, 10 * LWS_US_PER_SEC); } static int @@ -179,21 +195,19 @@ goto init_fail; } - if (connect_client(vhd)) - lws_timed_callback_vh_protocol(vhd->vhost, - vhd->protocol, LWS_CALLBACK_USER, 1); + sul_connect_attempt(&vhd->sul); break; case LWS_CALLBACK_PROTOCOL_DESTROY: init_fail: vhd->finished = 1; for (n = 0; n < (int)LWS_ARRAY_SIZE(vhd->pthread_spam); n++) - if (vhd->pthread_spam[n]) - pthread_join(vhd->pthread_spam[n], &retval); + pthread_join(vhd->pthread_spam[n], &retval); if (vhd->ring) lws_ring_destroy(vhd->ring); + lws_sul_cancel(&vhd->sul); pthread_mutex_destroy(&vhd->lock_ring); return r; @@ -202,8 +216,8 @@ lwsl_err("CLIENT_CONNECTION_ERROR: %s\n", in ? (char *)in : "(null)"); vhd->client_wsi = NULL; - lws_timed_callback_vh_protocol(vhd->vhost, - vhd->protocol, LWS_CALLBACK_USER, 1); + lws_sul_schedule(vhd->context, 0, &vhd->sul, + sul_connect_attempt, LWS_US_PER_SEC); break; /* --- client callbacks --- */ @@ -242,8 +256,8 @@ case LWS_CALLBACK_CLIENT_CLOSED: vhd->client_wsi = NULL; vhd->established = 0; - lws_timed_callback_vh_protocol(vhd->vhost, vhd->protocol, - LWS_CALLBACK_USER, 1); + lws_sul_schedule(vhd->context, 0, &vhd->sul, + sul_connect_attempt, LWS_US_PER_SEC); break; case LWS_CALLBACK_EVENT_WAIT_CANCELLED: @@ -259,16 +273,6 @@ lws_callback_on_writable(vhd->client_wsi); break; - /* rate-limited client connect retries */ - - case LWS_CALLBACK_USER: - lwsl_notice("%s: LWS_CALLBACK_USER\n", __func__); - if (connect_client(vhd)) - lws_timed_callback_vh_protocol(vhd->vhost, - vhd->protocol, - LWS_CALLBACK_USER, 1); - break; - default: break; } diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-broker/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-broker/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-broker/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-broker/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,67 +1,13 @@ -project(lws-minimal-ws-broker) +project(lws-minimal-ws-broker C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-broker) set(SRCS minimal-ws-broker.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() set(requirements 1) require_lws_config(LWS_ROLE_WS 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) @@ -70,9 +16,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() \ No newline at end of file diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-broker/protocol_lws_minimal.c libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-broker/protocol_lws_minimal.c --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-broker/protocol_lws_minimal.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-broker/protocol_lws_minimal.c 2020-12-01 17:40:26.000000000 +0000 @@ -215,36 +215,3 @@ 128, \ 0, NULL, 0 \ } - -#if !defined (LWS_PLUGIN_STATIC) - -/* boilerplate needed if we are built as a dynamic plugin */ - -static const struct lws_protocols protocols[] = { - LWS_PLUGIN_PROTOCOL_MINIMAL -}; - -int -init_protocol_minimal(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } - - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} - -int -destroy_protocol_minimal(struct lws_context *context) -{ - return 0; -} -#endif diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,68 +1,13 @@ -project(lws-minimal-ws-server) +project(lws-minimal-ws-server C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-server) set(SRCS minimal-ws-server.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_WS 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) @@ -71,9 +16,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() \ No newline at end of file diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server/minimal-ws-server.c libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server/minimal-ws-server.c --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server/minimal-ws-server.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server/minimal-ws-server.c 2020-12-01 17:40:26.000000000 +0000 @@ -85,16 +85,17 @@ info.mounts = &mount; info.protocols = protocols; info.vhost_name = "localhost"; - info.ws_ping_pong_interval = 10; info.options = LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; +#if defined(LWS_WITH_TLS) if (lws_cmdline_option(argc, argv, "-s")) { lwsl_user("Server using TLS\n"); info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; info.ssl_cert_filepath = "localhost-100y.cert"; info.ssl_private_key_filepath = "localhost-100y.key"; } +#endif if (lws_cmdline_option(argc, argv, "-h")) info.options |= LWS_SERVER_OPTION_VHOST_UPG_STRICT_HOST_CHECK; diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server/protocol_lws_minimal.c libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server/protocol_lws_minimal.c --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server/protocol_lws_minimal.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server/protocol_lws_minimal.c 2020-12-01 17:40:26.000000000 +0000 @@ -152,36 +152,3 @@ 128, \ 0, NULL, 0 \ } - -#if !defined (LWS_PLUGIN_STATIC) - -/* boilerplate needed if we are built as a dynamic plugin */ - -static const struct lws_protocols protocols[] = { - LWS_PLUGIN_PROTOCOL_MINIMAL -}; - -int -init_protocol_minimal(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } - - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} - -int -destroy_protocol_minimal(struct lws_context *context) -{ - return 0; -} -#endif diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-echo/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-echo/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-echo/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-echo/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,68 +1,13 @@ -project(lws-minimal-ws-server-echo) +project(lws-minimal-ws-server-echo C) cmake_minimum_required(VERSION 2.8.9) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-server-echo) set(SRCS minimal-ws-server-echo.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_WS 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) @@ -72,9 +17,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-echo/protocol_lws_minimal_server_echo.c libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-echo/protocol_lws_minimal_server_echo.c --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-echo/protocol_lws_minimal_server_echo.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-echo/protocol_lws_minimal_server_echo.c 2020-12-01 17:40:26.000000000 +0000 @@ -230,36 +230,3 @@ 1024, \ 0, NULL, 0 \ } - -#if !defined (LWS_PLUGIN_STATIC) - -/* boilerplate needed if we are built as a dynamic plugin */ - -static const struct lws_protocols protocols[] = { - LWS_PLUGIN_PROTOCOL_MINIMAL_SERVER_ECHO -}; - -int -init_protocol_minimal_server_echo(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } - - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} - -int -destroy_protocol_minimal_server_echo(struct lws_context *context) -{ - return 0; -} -#endif diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-pmd/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-pmd/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-pmd/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-pmd/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,68 +1,13 @@ -project(lws-minimal-ws-server-pmd) +project(lws-minimal-ws-server-pmd C) cmake_minimum_required(VERSION 2.8.9) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-server-pmd) set(SRCS minimal-ws-server-pmd.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_WS 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) @@ -72,9 +17,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-pmd/protocol_lws_minimal.c libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-pmd/protocol_lws_minimal.c --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-pmd/protocol_lws_minimal.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-pmd/protocol_lws_minimal.c 2020-12-01 17:40:26.000000000 +0000 @@ -158,36 +158,3 @@ 128, \ 0, NULL, 0 \ } - -#if !defined (LWS_PLUGIN_STATIC) - -/* boilerplate needed if we are built as a dynamic plugin */ - -static const struct lws_protocols protocols[] = { - LWS_PLUGIN_PROTOCOL_MINIMAL -}; - -int -init_protocol_minimal(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } - - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} - -int -destroy_protocol_minimal(struct lws_context *context) -{ - return 0; -} -#endif diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,68 +1,13 @@ -project(lws-minimal-ws-server-pmd-bulk) +project(lws-minimal-ws-server-pmd-bulk C) cmake_minimum_required(VERSION 2.8.9) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-server-pmd-bulk) set(SRCS minimal-ws-server-pmd-bulk.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_WS 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) @@ -72,9 +17,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/protocol_lws_minimal_pmd_bulk.c libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/protocol_lws_minimal_pmd_bulk.c --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/protocol_lws_minimal_pmd_bulk.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/protocol_lws_minimal_pmd_bulk.c 2020-12-01 17:40:26.000000000 +0000 @@ -147,14 +147,14 @@ if (s > (size_t)n) s = n; memcpy(p, &redundant_string[m], s); - pss->position_tx += s; + pss->position_tx += (int)s; p += s; - n -= s; + n -= (int)s; } } else { pss->position_tx += n; while (n--) - *p++ = rng(&pss->rng_tx); + *p++ = (uint8_t)rng(&pss->rng_tx); } n = lws_ptr_diff(p, start); @@ -172,7 +172,7 @@ lwsl_user("LWS_CALLBACK_RECEIVE: %4d (pss->pos=%d, rpp %5d, last %d)\n", (int)len, (int)pss->position_rx, (int)lws_remaining_packet_payload(wsi), lws_is_final_fragment(wsi)); - olen = len; + olen = (int)len; if (*vhd->options & 1) { while (len) { @@ -185,13 +185,13 @@ lwsl_user("echo'd data doesn't match\n"); return -1; } - pss->position_rx += s; + pss->position_rx += (int)s; in = ((char *)in) + s; len -= s; } } else { p = (uint8_t *)in; - pss->position_rx += len; + pss->position_rx += (int)len; while (len--) { if (*p++ != (uint8_t)rng(&pss->rng_rx)) { lwsl_user("echo'd data doesn't match: 0x%02X 0x%02X (%d)\n", @@ -221,36 +221,3 @@ 4096, \ 0, NULL, 0 \ } - -#if !defined (LWS_PLUGIN_STATIC) - -/* boilerplate needed if we are built as a dynamic plugin */ - -static const struct lws_protocols protocols[] = { - LWS_PLUGIN_PROTOCOL_MINIMAL_PMD_BULK -}; - -int -init_protocol_minimal_pmd_bulk(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } - - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} - -int -destroy_protocol_minimal_pmd_bulk(struct lws_context *context) -{ - return 0; -} -#endif diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-pmd-corner/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-pmd-corner/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-pmd-corner/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-pmd-corner/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,68 +1,13 @@ -project(lws-minimal-ws-server-pmd-corner) +project(lws-minimal-ws-server-pmd-corner C) cmake_minimum_required(VERSION 2.8.9) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-server-pmd-corner) set(SRCS minimal-ws-server-pmd-corner.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_WS 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) @@ -72,9 +17,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-pmd-corner/protocol_lws_minimal.c libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-pmd-corner/protocol_lws_minimal.c --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-pmd-corner/protocol_lws_minimal.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-pmd-corner/protocol_lws_minimal.c 2020-12-01 17:40:26.000000000 +0000 @@ -269,36 +269,3 @@ 2048, \ 0, NULL, 0 \ } - -#if !defined (LWS_PLUGIN_STATIC) - -/* boilerplate needed if we are built as a dynamic plugin */ - -static const struct lws_protocols protocols[] = { - LWS_PLUGIN_PROTOCOL_MINIMAL -}; - -int -init_protocol_minimal(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } - - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} - -int -destroy_protocol_minimal(struct lws_context *context) -{ - return 0; -} -#endif diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-ring/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-ring/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-ring/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-ring/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,68 +1,13 @@ -project(lws-minimal-ws-server-ring) +project(lws-minimal-ws-server-ring C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-server-ring) set(SRCS minimal-ws-server-ring.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_WS 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) @@ -71,9 +16,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-ring/protocol_lws_minimal.c libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-ring/protocol_lws_minimal.c --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-ring/protocol_lws_minimal.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-ring/protocol_lws_minimal.c 2020-12-01 17:40:26.000000000 +0000 @@ -55,7 +55,7 @@ { uint32_t oldest_tail = lws_ring_get_oldest_tail(vhd->ring); struct per_session_data__minimal *old_pss = NULL; - int most = 0, before = lws_ring_get_count_waiting_elements(vhd->ring, + int most = 0, before = (int)lws_ring_get_count_waiting_elements(vhd->ring, &oldest_tail), m; /* @@ -111,7 +111,7 @@ * what is the largest number of pending ring elements * for any survivor. */ - m = lws_ring_get_count_waiting_elements(vhd->ring, + m = (int)lws_ring_get_count_waiting_elements(vhd->ring, &((*ppss)->tail)); if (m > most) most = m; @@ -279,36 +279,3 @@ 0, \ 0, NULL, 0 \ } - -#if !defined (LWS_PLUGIN_STATIC) - -/* boilerplate needed if we are built as a dynamic plugin */ - -static const struct lws_protocols protocols[] = { - LWS_PLUGIN_PROTOCOL_MINIMAL -}; - -int -init_protocol_minimal(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } - - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} - -int -destroy_protocol_minimal(struct lws_context *context) -{ - return 0; -} -#endif diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threadpool/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threadpool/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threadpool/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threadpool/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,80 +1,14 @@ -project(lws-minimal-ws-server-threadpool) +project(lws-minimal-ws-server-threadpool C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckIncludeFile) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-server-threadpool) set(SRCS minimal-ws-server-threadpool.c) -MACRO(require_pthreads result) - CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) - if (NOT LWS_HAVE_PTHREAD_H) - if (LWS_WITH_MINIMAL_EXAMPLES) - set(result 0) - else() - message(FATAL_ERROR "threading support requires pthreads") - endif() - endif() -ENDMACRO() - -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_pthreads(requirements) require_lws_config(LWS_ROLE_WS 1 requirements) @@ -85,9 +19,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared pthread) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets pthread) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threadpool/minimal-ws-server-threadpool.c libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threadpool/minimal-ws-server-threadpool.c --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threadpool/minimal-ws-server-threadpool.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threadpool/minimal-ws-server-threadpool.c 2020-12-01 17:40:26.000000000 +0000 @@ -21,6 +21,12 @@ #include #include #include +#if defined(WIN32) +#define HAVE_STRUCT_TIMESPEC +#if defined(pid_t) +#undef pid_t +#endif +#endif #include #define LWS_PLUGIN_STATIC @@ -125,5 +131,7 @@ lws_context_destroy(context); + lwsl_user("%s: exiting cleanly...\n", __func__); + return 0; } diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threadpool/protocol_lws_minimal_threadpool.c libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threadpool/protocol_lws_minimal_threadpool.c --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threadpool/protocol_lws_minimal_threadpool.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threadpool/protocol_lws_minimal_threadpool.c 2020-12-01 17:40:26.000000000 +0000 @@ -34,6 +34,8 @@ struct per_vhost_data__minimal { struct lws_threadpool *tp; + struct lws_context *context; + lws_sorted_usec_list_t sul; const char *config; }; @@ -43,6 +45,10 @@ uint64_t pos, end; }; +#if defined(WIN32) +static void usleep(unsigned long l) { Sleep(l / 1000); } +#endif + /* * Create the private data for the task * @@ -129,6 +135,22 @@ return LWS_TP_RETURN_CHECKING_IN; } + +static void +sul_tp_dump(struct lws_sorted_usec_list *sul) +{ + struct per_vhost_data__minimal *vhd = + lws_container_of(sul, struct per_vhost_data__minimal, sul); + /* + * in debug mode, dump the threadpool stat to the logs once + * a second + */ + lws_threadpool_dump(vhd->tp); + lws_sul_schedule(vhd->context, 0, &vhd->sul, + sul_tp_dump, LWS_US_PER_SEC); +} + + static int callback_minimal(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) @@ -155,6 +177,8 @@ if (!vhd) return 1; + vhd->context = lws_get_context(wsi); + /* recover the pointer to the globals struct */ pvo = lws_pvo_search( (const struct lws_protocol_vhost_options *)in, @@ -175,27 +199,14 @@ if (!vhd->tp) return 1; - lws_timed_callback_vh_protocol(lws_get_vhost(wsi), - lws_get_protocol(wsi), - LWS_CALLBACK_USER, 1); - + lws_sul_schedule(vhd->context, 0, &vhd->sul, + sul_tp_dump, LWS_US_PER_SEC); break; case LWS_CALLBACK_PROTOCOL_DESTROY: lws_threadpool_finish(vhd->tp); lws_threadpool_destroy(vhd->tp); - break; - - case LWS_CALLBACK_USER: - - /* - * in debug mode, dump the threadpool stat to the logs once - * a second - */ - lws_threadpool_dump(vhd->tp); - lws_timed_callback_vh_protocol(lws_get_vhost(wsi), - lws_get_protocol(wsi), - LWS_CALLBACK_USER, 1); + lws_sul_cancel(&vhd->sul); break; case LWS_CALLBACK_ESTABLISHED: @@ -237,7 +248,7 @@ case LWS_CALLBACK_WS_SERVER_DROP_PROTOCOL: lwsl_debug("LWS_CALLBACK_WS_SERVER_DROP_PROTOCOL: %p\n", wsi); - lws_threadpool_dequeue(wsi); + lws_threadpool_dequeue_task(lws_threadpool_get_task_wsi(wsi)); break; case LWS_CALLBACK_SERVER_WRITEABLE: @@ -253,7 +264,10 @@ * private task data. */ - n = lws_threadpool_task_status_wsi(wsi, &task, &_user); + task = lws_threadpool_get_task_wsi(wsi); + if (!task) + break; + n = lws_threadpool_task_status(task, &_user); lwsl_debug("%s: LWS_CALLBACK_SERVER_WRITEABLE: status %d\n", __func__, n); switch(n) { @@ -276,7 +290,7 @@ lws_set_timeout(wsi, PENDING_TIMEOUT_THREADPOOL_TASK, 5); - n = strlen(priv->result + LWS_PRE); + n = (int)strlen(priv->result + LWS_PRE); m = lws_write(wsi, (unsigned char *)priv->result + LWS_PRE, n, LWS_WRITE_TEXT); if (m < n) { @@ -308,36 +322,3 @@ 128, \ 0, NULL, 0 \ } - -#if !defined (LWS_PLUGIN_STATIC) - -/* boilerplate needed if we are built as a dynamic plugin */ - -static const struct lws_protocols protocols[] = { - LWS_PLUGIN_PROTOCOL_MINIMAL -}; - -int -init_protocol_minimal(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } - - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} - -int -destroy_protocol_minimal(struct lws_context *context) -{ - return 0; -} -#endif diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threads/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threads/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threads/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threads/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,80 +1,14 @@ -project(lws-minimal-ws-server-threads) +project(lws-minimal-ws-server-threads C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckIncludeFile) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-server-threads) set(SRCS minimal-ws-server.c) -MACRO(require_pthreads result) - CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) - if (NOT LWS_HAVE_PTHREAD_H) - if (LWS_WITH_MINIMAL_EXAMPLES) - set(result 0) - else() - message(FATAL_ERROR "threading support requires pthreads") - endif() - endif() -ENDMACRO() - -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) if (WIN32) set(requirements 0) @@ -87,9 +21,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared pthread) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets pthread) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threads/minimal-ws-server.c libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threads/minimal-ws-server.c --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threads/minimal-ws-server.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threads/minimal-ws-server.c 2020-12-01 17:40:26.000000000 +0000 @@ -21,6 +21,12 @@ #include #include #include +#if defined(WIN32) +#define HAVE_STRUCT_TIMESPEC +#if defined(pid_t) +#undef pid_t +#endif +#endif #include #define LWS_PLUGIN_STATIC diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threads/protocol_lws_minimal.c libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threads/protocol_lws_minimal.c --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threads/protocol_lws_minimal.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threads/protocol_lws_minimal.c 2020-12-01 17:40:26.000000000 +0000 @@ -83,7 +83,11 @@ struct per_vhost_data__minimal *vhd = (struct per_vhost_data__minimal *)d; struct msg amsg; - int len = 128, index = 1, n; + int len = 128, index = 1, n, whoami = 0; + + for (n = 0; n < (int)LWS_ARRAY_SIZE(vhd->pthread_spam); n++) + if (pthread_equal(pthread_self(), vhd->pthread_spam[n])) + whoami = n + 1; do { /* don't generate output if nobody connected */ @@ -105,8 +109,8 @@ goto wait_unlock; } n = lws_snprintf((char *)amsg.payload + LWS_PRE, len, - "%s: tid: %p, msg: %d", vhd->config, - (void *)pthread_self(), index++); + "%s: tid: %d, msg: %d", vhd->config, + whoami, index++); amsg.len = n; n = lws_ring_insert(vhd->ring, &amsg, 1); if (n != 1) { @@ -127,7 +131,7 @@ } while (!vhd->finished); - lwsl_notice("thread_spam %p exiting\n", (void *)pthread_self()); + lwsl_notice("thread_spam %d exiting\n", whoami); pthread_exit(NULL); @@ -291,36 +295,3 @@ 128, \ 0, NULL, 0 \ } - -#if !defined (LWS_PLUGIN_STATIC) - -/* boilerplate needed if we are built as a dynamic plugin */ - -static const struct lws_protocols protocols[] = { - LWS_PLUGIN_PROTOCOL_MINIMAL -}; - -int -init_protocol_minimal(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } - - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} - -int -destroy_protocol_minimal(struct lws_context *context) -{ - return 0; -} -#endif diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,44 @@ +project(lws-minimal-ws-server-threads-foreign-smp C) +cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) +include(CheckIncludeFile) +include(CheckCSourceCompiles) +include(LwsCheckRequirements) + +set(SAMP lws-minimal-ws-server-threads-foreign-smp) +set(SRCS minimal-ws-server.c) + +set(requirements 1) +require_pthreads(requirements) +require_lws_config(LWS_ROLE_WS 1 requirements) +require_lws_config(LWS_WITH_SERVER 1 requirements) +require_lws_config(LWS_WITH_TLS 1 requirements) +require_lws_config(LWS_WITH_LIBUV 1 requirements) + +CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(LWS_WITH_LIBUV)\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" LWS_WITH_LIBUV) + +if (NOT LWS_WITH_LIBUV) + set(requirements 0) +endif() + + +if (requirements) + add_executable(${SAMP} ${SRCS}) + + find_path(LIBUV_INCLUDE_DIRS NAMES uv.h) + find_library(LIBUV_LIBRARIES NAMES uv) + message("libuv include dir: ${LIBUV_INCLUDE_DIRS}") + message("libuv libraries: ${LIBUV_LIBRARIES}") + include_directories("${LIBUV_INCLUDE_DIRS}") + set(extralibs ${extralibs} ${LIBUV_LIBRARIES}) + + message("Extra libs: ${extralibs}") + + if (websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${extralibs} ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) + add_dependencies(${SAMP} websockets_shared) + else() + target_link_libraries(${SAMP} websockets ${extralibs} ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) + endif() +endif() diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/minimal-ws-server.c libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/minimal-ws-server.c --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/minimal-ws-server.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/minimal-ws-server.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,182 @@ +/* + * lws-minimal-ws-server + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * This demonstrates a minimal ws server that can cooperate with + * other threads cleanly. Two other threads are started, which fill + * a ringbuffer with strings at 10Hz. + * + * The actual work and thread spawning etc are done in the protocol + * implementation in protocol_lws_minimal.c. + * + * To keep it simple, it serves stuff in the subdirectory "./mount-origin" of + * the directory it was started in. + * You can change that by changing mount.origin. + */ + +#include +#include +#include +#if defined(WIN32) +#define HAVE_STRUCT_TIMESPEC +#if defined(pid_t) +#undef pid_t +#endif +#endif +#include +#include + +#define COUNT_THREADS 5 + +#define LWS_PLUGIN_STATIC +#include "protocol_lws_minimal.c" + +static struct lws_protocols protocols[] = { + { "http", lws_callback_http_dummy, 0, 0 }, + LWS_PLUGIN_PROTOCOL_MINIMAL, + { NULL, NULL, 0, 0 } /* terminator */ +}; + +static struct lws_context *context; +static int interrupted; +static uv_loop_t loop[COUNT_THREADS]; + +static const struct lws_http_mount mount = { + /* .mount_next */ NULL, /* linked-list "next" */ + /* .mountpoint */ "/", /* mountpoint URL */ + /* .origin */ "./mount-origin", /* serve from dir */ + /* .def */ "index.html", /* default filename */ + /* .protocol */ NULL, + /* .cgienv */ NULL, + /* .extra_mimetypes */ NULL, + /* .interpret */ NULL, + /* .cgi_timeout */ 0, + /* .cache_max_age */ 0, + /* .auth_mask */ 0, + /* .cache_reusable */ 0, + /* .cache_revalidate */ 0, + /* .cache_intermediaries */ 0, + /* .origin_protocol */ LWSMPRO_FILE, /* files in a dir */ + /* .mountpoint_len */ 1, /* char count */ + /* .basic_auth_login_file */ NULL, +}; + +/* + * This demonstrates how to pass a pointer into a specific protocol handler + * running on a specific vhost. In this case, it's our default vhost and + * we pass the pvo named "config" with the value a const char * "myconfig". + * + * This is the preferred way to pass configuration into a specific vhost + + * protocol instance. + */ + +static const struct lws_protocol_vhost_options pvo_ops = { + NULL, + NULL, + "config", /* pvo name */ + (void *)"myconfig" /* pvo value */ +}; + +static const struct lws_protocol_vhost_options pvo = { + NULL, /* "next" pvo linked-list */ + &pvo_ops, /* "child" pvo linked-list */ + "lws-minimal", /* protocol name we belong to on this vhost */ + "" /* ignored */ +}; + +void *thread_service(void *threadid) +{ + while (lws_service_tsi(context, 0, + (int)(lws_intptr_t)threadid) >= 0 && + !interrupted) + lwsl_notice("%s\n", __func__); + + pthread_exit(NULL); + + return NULL; +} + +void signal_cb(uv_signal_t *watcher, int signum) +{ + int n; + + if (interrupted) + return; + + lwsl_notice("signal_cb: signal %d caught\n", watcher->signum); + interrupted = 1; + uv_signal_stop(watcher); + lws_context_destroy(context); + for (n = 0; n < COUNT_THREADS; n++) + uv_stop(&loop[n]); +} + +int main(int argc, const char **argv) +{ + int n, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE; + uv_signal_t *s, signal_outer[3 * COUNT_THREADS]; + pthread_t pthread_service[COUNT_THREADS]; + struct lws_context_creation_info info; + void *foreign_loops[COUNT_THREADS]; + const char *p; + void *retval; + + if ((p = lws_cmdline_option(argc, argv, "-d"))) + logs = atoi(p); + + lws_set_log_level(logs, NULL); + lwsl_user("LWS minimal ws server + threads + smp | visit http://localhost:7681\n"); + + for (n = 0; n < COUNT_THREADS; n++) { + int m; + + uv_loop_init(&loop[n]); + + for (m = 0; m < 3; m++) { + s = &signal_outer[n * 3 + m]; + uv_signal_init(&loop[n], s); + uv_signal_start(s, signal_cb, SIGINT); + } + + foreign_loops[n] = &loop[n]; + } + + memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ + info.port = 7681; + info.mounts = &mount; + info.pcontext = &context; + info.protocols = protocols; + info.pvo = &pvo; /* per-vhost options */ + info.foreign_loops = foreign_loops; + info.count_threads = COUNT_THREADS; + info.options = LWS_SERVER_OPTION_LIBUV | + LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; + + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + return 1; + } + + lwsl_notice(" Service threads: %d\n", lws_get_count_threads(context)); + + /* start all the service threads */ + + for (n = 0; n < lws_get_count_threads(context); n++) + if (pthread_create(&pthread_service[n], NULL, thread_service, + (void *)(lws_intptr_t)n)) + lwsl_err("Failed to start service thread\n"); + + /* wait for all the service threads to exit */ + + while ((--n) >= 0) + pthread_join(pthread_service[n], &retval); + + lws_context_destroy(context); + + return 0; +} diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/mount-origin/example.js libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/mount-origin/example.js --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/mount-origin/example.js 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/mount-origin/example.js 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,68 @@ +var head = 0, tail = 0, ring = new Array(); + +function get_appropriate_ws_url(extra_url) +{ + var pcol; + var u = document.URL; + + /* + * We open the websocket encrypted if this page came on an + * https:// url itself, otherwise unencrypted + */ + + if (u.substring(0, 5) === "https") { + pcol = "wss://"; + u = u.substr(8); + } else { + pcol = "ws://"; + if (u.substring(0, 4) === "http") + u = u.substr(7); + } + + u = u.split("/"); + + /* + "/xxx" bit is for IE10 workaround */ + + return pcol + u[0] + "/" + extra_url; +} + +function new_ws(urlpath, protocol) +{ + return new WebSocket(urlpath, protocol); +} + +document.addEventListener("DOMContentLoaded", function() { + + var ws = new_ws(get_appropriate_ws_url(""), "lws-minimal"); + try { + ws.onopen = function() { + document.getElementById("r").disabled = 0; + }; + + ws.onmessage =function got_packet(msg) { + var n, s = ""; + + ring[head] = msg.data + "\n"; + head = (head + 1) % 50; + if (tail === head) + tail = (tail + 1) % 50; + + n = tail; + do { + s = s + ring[n]; + n = (n + 1) % 50; + } while (n !== head); + + document.getElementById("r").value = s; + document.getElementById("r").scrollTop = + document.getElementById("r").scrollHeight; + }; + + ws.onclose = function(){ + document.getElementById("r").disabled = 1; + }; + } catch(exception) { + alert("

Error " + exception); + } + +}, false); Binary files /tmp/tmpmec97nsd/m0nuW2sR0N/libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/mount-origin/favicon.ico and /tmp/tmpmec97nsd/q8JCI83EXS/libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/mount-origin/favicon.ico differ diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/mount-origin/index.html libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/mount-origin/index.html --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/mount-origin/index.html 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/mount-origin/index.html 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,19 @@ + + + + + + + +
+ + Minimal ws server threads SMP example.
+ Strings generated by server threads are sent to + all browsers open on this page.
+ The textarea show the last 50 lines received. +
+
+
+ + + diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/mount-origin/libwebsockets.org-logo.svg libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/mount-origin/libwebsockets.org-logo.svg --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/mount-origin/libwebsockets.org-logo.svg 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/mount-origin/libwebsockets.org-logo.svg 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,66 @@ + + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/mount-origin/strict-csp.svg libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/mount-origin/strict-csp.svg --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/mount-origin/strict-csp.svg 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/mount-origin/strict-csp.svg 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/protocol_lws_minimal.c libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/protocol_lws_minimal.c --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/protocol_lws_minimal.c 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/protocol_lws_minimal.c 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,321 @@ +/* + * ws protocol handler plugin for "lws-minimal" demonstrating multithread + * + * Written in 2010-2019 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + */ + +#if !defined (LWS_PLUGIN_STATIC) +#define LWS_DLL +#define LWS_INTERNAL +#include +#endif + +#include +#include + +/* one of these created for each message in the ringbuffer */ + +struct msg { + void *payload; /* is malloc'd */ + size_t len; +}; + +/* + * One of these is created for each client connecting to us. + * + * It is ONLY read or written from the lws service thread context. + */ + +struct per_session_data__minimal { + struct per_session_data__minimal *pss_list; + struct lws *wsi; + uint32_t tail; +}; + +/* + * One of these is created for each vhost our protocol is used with, that + * means it is a shared resource between the SMP threads and must be locked. + */ + +struct per_vhost_data__minimal { + struct lws_context *context; + struct lws_vhost *vhost; + const struct lws_protocols *protocol; + + struct per_session_data__minimal *pss_list; /* linked-list of live pss*/ + pthread_t pthread_spam[2]; + + pthread_mutex_t lock_ring; /* serialize access to the ring buffer */ + struct lws_ring *ring; /* {lock_ring} ringbuffer holding unsent content */ + + const char *config; + char finished; +}; + +#if defined(WIN32) +static void usleep(unsigned long l) { Sleep(l / 1000); } +#endif + +/* + * This runs under both lws service and "spam threads" contexts. + * Access is serialized by vhd->lock_ring. + */ + +static void +__minimal_destroy_message(void *_msg) +{ + struct msg *msg = _msg; + + free(msg->payload); + msg->payload = NULL; + msg->len = 0; +} + +/* + * This runs under the "spam thread" thread context only. + * + * We spawn two threads that generate messages with this. + * + */ + +static void * +thread_spam(void *d) +{ + struct per_vhost_data__minimal *vhd = + (struct per_vhost_data__minimal *)d; + struct msg amsg; + int len = 128, index = 1, n, whoami = 0; + + for (n = 0; n < (int)LWS_ARRAY_SIZE(vhd->pthread_spam); n++) + if (pthread_equal(pthread_self(), vhd->pthread_spam[n])) + whoami = n + 1; + + do { + pthread_mutex_lock(&vhd->lock_ring); /* --------- ring lock { */ + + /* don't generate output if nobody connected */ + if (!vhd->pss_list) + goto wait_unlock; + + /* only create if space in ringbuffer */ + n = (int)lws_ring_get_count_free_elements(vhd->ring); + if (!n) { + // lwsl_user("dropping!\n"); + goto wait_unlock; + } + + amsg.payload = malloc(LWS_PRE + len); + if (!amsg.payload) { + lwsl_user("OOM: dropping\n"); + goto wait_unlock; + } + n = lws_snprintf((char *)amsg.payload + LWS_PRE, len, + "%s: spam tid: %d, msg: %d", vhd->config, + whoami, index++); + amsg.len = n; + n = (int)lws_ring_insert(vhd->ring, &amsg, 1); + if (n != 1) { + __minimal_destroy_message(&amsg); + // lwsl_user("dropping!\n"); + } else + /* + * This will cause a LWS_CALLBACK_EVENT_WAIT_CANCELLED + * in the lws service thread context. + */ + lws_cancel_service(vhd->context); + +wait_unlock: + pthread_mutex_unlock(&vhd->lock_ring); /* } ring lock ------- */ + + usleep(100000); + + } while (!vhd->finished); + + lwsl_notice("thread_spam %d exiting\n", whoami); + + pthread_exit(NULL); + + return NULL; +} + +/* this runs under the lws service thread context only */ + +static int +callback_minimal(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) +{ + struct per_session_data__minimal *pss = + (struct per_session_data__minimal *)user; + struct per_vhost_data__minimal *vhd = + (struct per_vhost_data__minimal *) + lws_protocol_vh_priv_get(lws_get_vhost(wsi), + lws_get_protocol(wsi)); + const struct lws_protocol_vhost_options *pvo; + const struct msg *pmsg; + char temp[LWS_PRE + 256]; + void *retval; + int n, m, r = 0; + + switch (reason) { + case LWS_CALLBACK_PROTOCOL_INIT: + /* create our per-vhost struct */ + vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi), + lws_get_protocol(wsi), + sizeof(struct per_vhost_data__minimal)); + if (!vhd) + return 1; + + pthread_mutex_init(&vhd->lock_ring, NULL); + + /* recover the pointer to the globals struct */ + pvo = lws_pvo_search( + (const struct lws_protocol_vhost_options *)in, + "config"); + if (!pvo || !pvo->value) { + lwsl_err("%s: Can't find \"config\" pvo\n", __func__); + return 1; + } + vhd->config = pvo->value; + + vhd->context = lws_get_context(wsi); + vhd->protocol = lws_get_protocol(wsi); + vhd->vhost = lws_get_vhost(wsi); + + vhd->ring = lws_ring_create(sizeof(struct msg), 8, + __minimal_destroy_message); + if (!vhd->ring) { + lwsl_err("%s: failed to create ring\n", __func__); + return 1; + } + + /* start the content-creating threads */ + + for (n = 0; n < (int)LWS_ARRAY_SIZE(vhd->pthread_spam); n++) + if (pthread_create(&vhd->pthread_spam[n], NULL, + thread_spam, vhd)) { + lwsl_err("thread creation failed\n"); + r = 1; + goto init_fail; + } + break; + + case LWS_CALLBACK_PROTOCOL_DESTROY: +init_fail: + vhd->finished = 1; + for (n = 0; n < (int)LWS_ARRAY_SIZE(vhd->pthread_spam); n++) + pthread_join(vhd->pthread_spam[n], &retval); + + if (vhd->ring) + lws_ring_destroy(vhd->ring); + + pthread_mutex_destroy(&vhd->lock_ring); + break; + + case LWS_CALLBACK_ESTABLISHED: + /* add ourselves to the list of live pss held in the vhd */ + pthread_mutex_lock(&vhd->lock_ring); + lws_ll_fwd_insert(pss, pss_list, vhd->pss_list); + pss->tail = lws_ring_get_oldest_tail(vhd->ring); + pss->wsi = wsi; + pthread_mutex_unlock(&vhd->lock_ring); + break; + + case LWS_CALLBACK_CLOSED: + /* doesn't reference ring */ + pthread_mutex_lock(&vhd->lock_ring); + /* remove our closing pss from the list of live pss */ + lws_ll_fwd_remove(struct per_session_data__minimal, pss_list, + pss, vhd->pss_list); + pthread_mutex_unlock(&vhd->lock_ring); + break; + + case LWS_CALLBACK_SERVER_WRITEABLE: + pthread_mutex_lock(&vhd->lock_ring); /* --------- ring lock { */ + + pmsg = lws_ring_get_element(vhd->ring, &pss->tail); + if (!pmsg) { + pthread_mutex_unlock(&vhd->lock_ring); /* } ring lock ------- */ + + break; + } + + assert(pmsg->payload); + + n = lws_snprintf(temp + LWS_PRE, sizeof(temp) - LWS_PRE, + "svc, %s", + (char *)pmsg->payload + LWS_PRE); + + /* notice we allowed for LWS_PRE in the payload already */ + m = lws_write(wsi, (unsigned char *)temp + LWS_PRE, n, + LWS_WRITE_TEXT); + if (m < n) { + pthread_mutex_unlock(&vhd->lock_ring); /* } ring lock ------- */ + + lwsl_err("ERROR %d writing to ws socket\n", m); + return -1; + } + + lws_ring_consume_and_update_oldest_tail( + vhd->ring, /* lws_ring object */ + struct per_session_data__minimal, /* type of objects with tails */ + &pss->tail, /* tail of guy doing the consuming */ + 1, /* number of payload objects being consumed */ + vhd->pss_list, /* head of list of objects with tails */ + tail, /* member name of tail in objects with tails */ + pss_list /* member name of next object in objects with tails */ + ); + + /* more to do? */ + if (lws_ring_get_element(vhd->ring, &pss->tail)) + /* come back as soon as we can write more */ + lws_callback_on_writable(pss->wsi); + + pthread_mutex_unlock(&vhd->lock_ring); /* } ring lock ------- */ + + break; + + case LWS_CALLBACK_RECEIVE: + break; + + case LWS_CALLBACK_EVENT_WAIT_CANCELLED: + // lwsl_notice("EVENT_WAIT_CANCELLED tsi %d\n", lws_wsi_tsi(wsi)); + if (!vhd) + break; + /* + * When the "spam" threads add a message to the ringbuffer, + * they create this event in the lws service thread context + * using lws_cancel_service(). + * + * We respond by scheduling a writable callback for all + * connected clients. + */ + + pthread_mutex_lock(&vhd->lock_ring); /* --------- ring lock { */ + + lws_start_foreach_llp(struct per_session_data__minimal **, + ppss, vhd->pss_list) { + if (lws_wsi_tsi((*ppss)->wsi) == lws_wsi_tsi(wsi)) + lws_callback_on_writable((*ppss)->wsi); + } lws_end_foreach_llp(ppss, pss_list); + + pthread_mutex_unlock(&vhd->lock_ring); /* } ring lock ------- */ + break; + + default: + break; + } + + return r; +} + +#define LWS_PLUGIN_PROTOCOL_MINIMAL \ + { \ + "lws-minimal", \ + callback_minimal, \ + sizeof(struct per_session_data__minimal), \ + 128, \ + 0, NULL, 0 \ + } diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/README.md libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/README.md --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/README.md 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/README.md 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,39 @@ +# lws minimal ws server (threads) + SMP + +This demonstrates both independent threads creating content as in the +-threads example, multiple service threads as in the http-server-smp +example (but with ws), and using the foreign libuv loop. + +## build + +You must first build libwebsockets itself with cmake `-DLWS_MAX_SMP=8` +or some other number greater than one, as well as `-DLWS_WITH_LIBUV=1` + +``` + $ cmake . && make +``` + +Pthreads is required on your system. + +## usage + +``` + $ ./lws-minimal-ws-server-threads-smp +[2019/01/28 06:59:17:4217] USER: LWS minimal ws server + threads + smp | visit http://localhost:7681 +[2019/01/28 06:59:17:4219] NOTICE: Service threads: 2 +[2019/01/28 06:59:17:4220] NOTICE: LWS_CALLBACK_EVENT_WAIT_CANCELLED in svc tid 0x7fec48af8700 +[2019/01/28 06:59:17:4220] NOTICE: LWS_CALLBACK_EVENT_WAIT_CANCELLED in svc tid 0x7fec48af8700 +... +``` + +Visit http://localhost:7681 on multiple browser windows. You may need to open +4 before the second service thread is used (check "svc tid" in the browser output). + +Two lws service threads are started. + +Two separate asynchronous threads generate strings and add them to a ringbuffer, +signalling all lws service threads to send new entries to all the browser windows. + +This demonstrates how to safely manage asynchronously generated content +and hook it up to the lws service threads. + diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threads-smp/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threads-smp/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threads-smp/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threads-smp/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,80 +1,14 @@ -project(lws-minimal-ws-server-threads-smp) +project(lws-minimal-ws-server-threads-smp C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckIncludeFile) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-server-threads-smp) set(SRCS minimal-ws-server.c) -MACRO(require_pthreads result) - CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) - if (NOT LWS_HAVE_PTHREAD_H) - if (LWS_WITH_MINIMAL_EXAMPLES) - set(result 0) - else() - message(FATAL_ERROR "threading support requires pthreads") - endif() - endif() -ENDMACRO() - -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_pthreads(requirements) require_lws_config(LWS_ROLE_WS 1 requirements) @@ -84,9 +18,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared pthread) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets pthread) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threads-smp/minimal-ws-server.c libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threads-smp/minimal-ws-server.c --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threads-smp/minimal-ws-server.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threads-smp/minimal-ws-server.c 2020-12-01 17:40:26.000000000 +0000 @@ -21,6 +21,12 @@ #include #include #include +#if defined(WIN32) +#define HAVE_STRUCT_TIMESPEC +#if defined(pid_t) +#undef pid_t +#endif +#endif #include #define LWS_PLUGIN_STATIC diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threads-smp/protocol_lws_minimal.c libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threads-smp/protocol_lws_minimal.c --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-threads-smp/protocol_lws_minimal.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-threads-smp/protocol_lws_minimal.c 2020-12-01 17:40:26.000000000 +0000 @@ -83,7 +83,11 @@ struct per_vhost_data__minimal *vhd = (struct per_vhost_data__minimal *)d; struct msg amsg; - int len = 128, index = 1, n; + int len = 128, index = 1, n, whoami = 0; + + for (n = 0; n < (int)LWS_ARRAY_SIZE(vhd->pthread_spam); n++) + if (pthread_equal(pthread_self(), vhd->pthread_spam[n])) + whoami = n + 1; do { /* don't generate output if nobody connected */ @@ -105,10 +109,10 @@ goto wait_unlock; } n = lws_snprintf((char *)amsg.payload + LWS_PRE, len, - "%s: spam tid: %p, msg: %d", vhd->config, - (void *)pthread_self(), index++); + "%s: spam tid: %d, msg: %d", vhd->config, + whoami, index++); amsg.len = n; - n = lws_ring_insert(vhd->ring, &amsg, 1); + n = (int)lws_ring_insert(vhd->ring, &amsg, 1); if (n != 1) { __minimal_destroy_message(&amsg); lwsl_user("dropping!\n"); @@ -127,7 +131,7 @@ } while (!vhd->finished); - lwsl_notice("thread_spam %p exiting\n", (void *)pthread_self()); + lwsl_notice("thread_spam %d exiting\n", whoami); pthread_exit(NULL); @@ -199,8 +203,7 @@ init_fail: vhd->finished = 1; for (n = 0; n < (int)LWS_ARRAY_SIZE(vhd->pthread_spam); n++) - if (vhd->pthread_spam[n]) - pthread_join(vhd->pthread_spam[n], &retval); + pthread_join(vhd->pthread_spam[n], &retval); if (vhd->ring) lws_ring_destroy(vhd->ring); @@ -231,7 +234,7 @@ } n = lws_snprintf(temp + LWS_PRE, sizeof(temp) - LWS_PRE, - "svc tid:%p, %s", (void *)pthread_self(), + "svc, %s", (char *)pmsg->payload + LWS_PRE); /* notice we allowed for LWS_PRE in the payload already */ @@ -265,8 +268,7 @@ break; case LWS_CALLBACK_EVENT_WAIT_CANCELLED: - lwsl_notice("LWS_CALLBACK_EVENT_WAIT_CANCELLED in svc tid %p\n", - (void *)pthread_self()); + lwsl_notice("LWS_CALLBACK_EVENT_WAIT_CANCELLED in svc\n"); if (!vhd) break; /* @@ -298,36 +300,3 @@ 128, \ 0, NULL, 0 \ } - -#if !defined (LWS_PLUGIN_STATIC) - -/* boilerplate needed if we are built as a dynamic plugin */ - -static const struct lws_protocols protocols[] = { - LWS_PLUGIN_PROTOCOL_MINIMAL -}; - -int -init_protocol_minimal(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } - - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} - -int -destroy_protocol_minimal(struct lws_context *context) -{ - return 0; -} -#endif diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-timer/CMakeLists.txt libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-timer/CMakeLists.txt --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-timer/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-timer/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,68 +1,13 @@ -project(lws-minimal-ws-server-timer) +project(lws-minimal-ws-server-timer C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-server-timer) set(SRCS minimal-ws-server.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_WS 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) @@ -71,9 +16,9 @@ add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff -Nru libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-timer/minimal-ws-server.c libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-timer/minimal-ws-server.c --- libwebsockets-4.0.20/minimal-examples/ws-server/minimal-ws-server-timer/minimal-ws-server.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/minimal-examples/ws-server/minimal-ws-server-timer/minimal-ws-server.c 2020-12-01 17:40:26.000000000 +0000 @@ -111,16 +111,17 @@ info.mounts = &mount; info.protocols = protocols; info.vhost_name = "localhost"; - info.ws_ping_pong_interval = 10; info.options = LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; +#if defined(LWS_WITH_TLS) if (lws_cmdline_option(argc, argv, "-s")) { lwsl_user("Server using TLS\n"); info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; info.ssl_cert_filepath = "localhost-100y.cert"; info.ssl_private_key_filepath = "localhost-100y.key"; } +#endif if (lws_cmdline_option(argc, argv, "-h")) info.options |= LWS_SERVER_OPTION_VHOST_UPG_STRICT_HOST_CHECK; diff -Nru libwebsockets-4.0.20/plugins/acme-client/protocol_lws_acme_client.c libwebsockets-4.1.6/plugins/acme-client/protocol_lws_acme_client.c --- libwebsockets-4.0.20/plugins/acme-client/protocol_lws_acme_client.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/acme-client/protocol_lws_acme_client.c 2020-12-01 17:40:26.000000000 +0000 @@ -1196,8 +1196,7 @@ case ACME_STATE_DIRECTORY: ((char *)in)[len] = '\0'; puts(in); - m = (int)(signed char)lejp_parse(&ac->jctx, - (uint8_t *)in, len); + m = lejp_parse(&ac->jctx, (uint8_t *)in, len); if (m < 0 && m != LEJP_CONTINUE) { lwsl_notice("lejp parse failed %d\n", m); goto failed; @@ -1631,28 +1630,17 @@ LWS_PLUGIN_PROTOCOL_LWS_ACME_CLIENT }; -LWS_VISIBLE int -init_protocol_lws_acme_client(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } - - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} - -LWS_VISIBLE int -destroy_protocol_lws_acme_client(struct lws_context *context) -{ - return 0; -} +LWS_VISIBLE const lws_plugin_protocol_t protocol_lws_acme_client = { + .hdr = { + "acme client", + "lws_protocol_plugin", + LWS_PLUGIN_API_MAGIC + }, + + .protocols = protocols, + .count_protocols = LWS_ARRAY_SIZE(protocols), + .extensions = NULL, + .count_extensions = 0, +}; #endif diff -Nru libwebsockets-4.0.20/plugins/CMakeLists.txt libwebsockets-4.1.6/plugins/CMakeLists.txt --- libwebsockets-4.0.20/plugins/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/plugins/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,171 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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_directories(.) + +if (DEFINED LIB_LIST_AT_END) +link_libraries(${LIB_LIST_AT_END}) +endif() + +if (LWS_WITH_PLUGINS AND LWS_WITH_SHARED) + macro(create_plugin PLUGIN_NAME PLUGIN_INCLUDE MAIN_SRC S2 S3) + + set(PLUGIN_SRCS ${MAIN_SRC}) + + if ("${S2}" STREQUAL "") + else() + list(APPEND PLUGIN_SRCS ${S2}) + endif() + if ("${S3}" STREQUAL "") + else() + list(APPEND PLUGIN_SRCS ${S3}) + endif() + + if (WIN32) + list(APPEND PLUGIN_SRCS + ${WIN32_HELPERS_PATH}/getopt.c + ${WIN32_HELPERS_PATH}/getopt_long.c + ${WIN32_HELPERS_PATH}/gettimeofday.c + ) + + list(APPEND PLUGIN_HDR + ${WIN32_HELPERS_PATH}/getopt.h + ${WIN32_HELPERS_PATH}/gettimeofday.h + ) + endif(WIN32) + + source_group("Headers Private" FILES ${PLUGIN_HDR}) + source_group("Sources" FILES ${PLUGIN_SRCS}) + add_library(${PLUGIN_NAME} SHARED ${PLUGIN_SRCS} ${PLUGIN_HDR}) + + foreach(libpath ${LWS_DEP_LIB_PATHS}) + target_link_directories(${TEST_NAME} ${libpath}) + endforeach() + + target_link_libraries(${PLUGIN_NAME} websockets_shared) + add_dependencies(${PLUGIN_NAME} websockets_shared) + + target_include_directories(${PLUGIN_NAME} PRIVATE ${PLUGIN_INCLUDE} ${LWS_LIB_BUILD_INC_PATHS}) + + # Set test app specific defines. + set_property(TARGET ${PLUGIN_NAME} + PROPERTY COMPILE_DEFINITIONS + INSTALL_DATADIR="${CMAKE_INSTALL_PREFIX}/plugins" + ) + + set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +# SET_TARGET_PROPERTIES(${PLUGIN_NAME} +# PROPERTIES COMPILE_FLAGS ${CMAKE_C_FLAGS}) + +# set_target_properties(${PLUGIN_NAME} +# PROPERTIES +# OUTPUT_NAME ${PLUGIN_NAME}) + + list(APPEND PLUGINS_LIST ${PLUGIN_NAME}) + + endmacro() + +if (LWS_ROLE_WS) + create_plugin(protocol_dumb_increment "" + "protocol_dumb_increment.c" "" "") + create_plugin(protocol_lws_mirror "" + "protocol_lws_mirror.c" "" "") + create_plugin(protocol_lws_status "" + "protocol_lws_status.c" "" "") + if (NOT WIN32) + create_plugin(protocol_lws_raw_test "" + "protocol_lws_raw_test.c" "" "") + + if (UNIX AND LWS_HAVE_PTHREAD_H) + create_plugin(protocol_deaddrop "" + "deaddrop/protocol_lws_deaddrop.c" "" "") + endif() + endif() + + if (LWS_WITH_SERVER_STATUS) + create_plugin(protocol_lws_server_status "" + "protocol_lws_server_status.c" "" "") + endif() + + if (NOT LWS_WITHOUT_CLIENT) + create_plugin(protocol_client_loopback_test "" + "protocol_client_loopback_test.c" "" "") + endif() + +endif(LWS_ROLE_WS) + + create_plugin(protocol_post_demo "" + "protocol_post_demo.c" "" "") + +if (LWS_ROLE_RAW_PROXY) + create_plugin(protocol_lws_raw_proxy "" + "raw-proxy/protocol_lws_raw_proxy.c" "" "") +endif() + +if (LWS_WITH_FTS) + create_plugin(protocol_fulltext_demo "" + "protocol_fulltext_demo.c" "" "") +endif() + + +if (LWS_WITH_SSL) + create_plugin(protocol_lws_ssh_base "ssh-base/include" + "ssh-base/sshd.c;ssh-base/telnet.c;ssh-base/kex-25519.c" "ssh-base/crypto/chacha.c;ssh-base/crypto/ed25519.c;ssh-base/crypto/fe25519.c;ssh-base/crypto/ge25519.c;ssh-base/crypto/poly1305.c;ssh-base/crypto/sc25519.c;ssh-base/crypto/smult_curve25519_ref.c" "") + create_plugin(protocol_lws_sshd_demo "ssh-base/include" "protocol_lws_sshd_demo.c" "" "") + + include_directories("${PROJECT_SOURCE_DIR}/plugins/ssh-base/include") +endif() + + + +if (LWS_WITH_ACME) + create_plugin(protocol_lws_acme_client "" + "acme-client/protocol_lws_acme_client.c" "" "") +endif() + +endif(LWS_WITH_PLUGINS AND LWS_WITH_SHARED) + + +# plugins + +if (LWS_WITH_PLUGINS) + install(TARGETS ${PLUGINS_LIST} + PERMISSIONS OWNER_WRITE OWNER_EXECUTE GROUP_EXECUTE WORLD_EXECUTE OWNER_READ GROUP_READ WORLD_READ + DESTINATION share/libwebsockets-test-server/plugins + COMPONENT plugins) + + if (NOT WIN32) + install(FILES deaddrop/assets/index.html;deaddrop/assets/deaddrop.js;deaddrop/assets/deaddrop.css;deaddrop/assets/drop.svg + DESTINATION share/libwebsockets-test-server/deaddrop + COMPONENT plugins) + endif() + + +if (LWS_WITH_SERVER_STATUS) + install(FILES server-status.html;server-status.js;server-status.css;lwsws-logo.png + DESTINATION share/libwebsockets-test-server/server-status + COMPONENT examples) +endif() +endif() diff -Nru libwebsockets-4.0.20/plugins/deaddrop/protocol_lws_deaddrop.c libwebsockets-4.1.6/plugins/deaddrop/protocol_lws_deaddrop.c --- libwebsockets-4.0.20/plugins/deaddrop/protocol_lws_deaddrop.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/deaddrop/protocol_lws_deaddrop.c 2020-12-01 17:40:26.000000000 +0000 @@ -689,28 +689,17 @@ LWS_PLUGIN_PROTOCOL_DEADDROP }; -LWS_VISIBLE int -init_protocol_deaddrop(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } +LWS_VISIBLE const lws_plugin_protocol_t deaddrop = { + .hdr = { + "deaddrop", + "lws_protocol_plugin", + LWS_PLUGIN_API_MAGIC + }, - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} - -LWS_VISIBLE int -destroy_protocol_deaddrop(struct lws_context *context) -{ - return 0; -} + .protocols = protocols, + .count_protocols = LWS_ARRAY_SIZE(protocols), + .extensions = NULL, + .count_extensions = 0, +}; #endif diff -Nru libwebsockets-4.0.20/plugins/generic-sessions/assets/admin-login.html libwebsockets-4.1.6/plugins/generic-sessions/assets/admin-login.html --- libwebsockets-4.0.20/plugins/generic-sessions/assets/admin-login.html 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/generic-sessions/assets/admin-login.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ - -This is an example destination that will appear after successful Admin login. - -This URL cannot be served if you're not logged in as admin. - diff -Nru libwebsockets-4.0.20/plugins/generic-sessions/assets/failed-login.html libwebsockets-4.1.6/plugins/generic-sessions/assets/failed-login.html --- libwebsockets-4.0.20/plugins/generic-sessions/assets/failed-login.html 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/generic-sessions/assets/failed-login.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ - -This is an example destination that will appear after a failed login - diff -Nru libwebsockets-4.0.20/plugins/generic-sessions/assets/index.html libwebsockets-4.1.6/plugins/generic-sessions/assets/index.html --- libwebsockets-4.0.20/plugins/generic-sessions/assets/index.html 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/generic-sessions/assets/index.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - -
-
-
- -
- - This is a demo application for lws generic-sessions.

- It's a simple messageboard.

- What's interesting about it is there is no serverside scripting,
- instead client js makes a wss:// connection back to the server
- and then reacts to JSON from the ws protocol. Sessions stuff is
- handled by lws generic sessions, making the actual
- test application
very small.

- And because it's natively websocket, it's naturally connected
- for dynamic events and easy to maintain. -

- Register / Login at the top right to see and create new messages. -
- -
-
- New message
-
- -
-
-
-
- -
- -
-
- - - - diff -Nru libwebsockets-4.0.20/plugins/generic-sessions/assets/lwsgs.css libwebsockets-4.1.6/plugins/generic-sessions/assets/lwsgs.css --- libwebsockets-4.0.20/plugins/generic-sessions/assets/lwsgs.css 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/generic-sessions/assets/lwsgs.css 1970-01-01 00:00:00.000000000 +0000 @@ -1,134 +0,0 @@ -.body { font-size: 12px } -.gstitle { font-size: 18px } - -.group1 { - vertical-align:middle; - text-align:center; - background:#f0f0e0; - padding:12px; - border-radius:10px; -} -.group2 { - display:none; - vertical-align:middle; - font-size: 22px; - text-align:center; - margin:auto; - align:center; - background-color: rgba(255, 255, 255, 0.8); - padding:12px; - border-radius:10px; -} - -body.seats { - background-image:url(seats.jpg) -} - -div.lwsgs { - z-index: 3; - text-align:right; - background-color: rgba(255, 255, 255, 0.8); -} - -table.lwsgs { - width:100%; - height:100%; - transition: max-height 2s; -} -table.c100 { - text-align:center; - width:100%; -} - -table.r { - vertical-align:top; - text-align:right; -} - -table.l { - vertical-align:top; - text-align:left; -} - -table.fixed { - table-layout: fixed; -} - -td.logo { - vertical-align:top; - text-align:left; - width:200px -} - -td.lwsgs { - vertical-align:top; - float:right; -} - -td.h99 { - height:99%; - vertical-align:middle; -} - -td.c { - margin:auto; - align:center -} - -td.tac { - text-align:center -} - -td.ava { - display:inline-block; - vertical-align:top; - word-wrap:break-word; -} - -iframe.hidden { - display:none; -} - -div.hidden { - display:none; -} - -div.hiddenr { - display:none; - text-align:right; -} - -input { - margin: 2px; - padding: 2px; -} - -input.em { - margin: 4px; - font-weight:bold; -} - -input.wide { - margin: 6px; - padding: 6px; -} - -input.hidden { - display: none; -} - -form.r { - text-align:right; -} - -span.bad { - color: red; -} - -span.small { - font-size:8pt; -} - -.green { - color: green; -} diff -Nru libwebsockets-4.0.20/plugins/generic-sessions/assets/lwsgs.js libwebsockets-4.1.6/plugins/generic-sessions/assets/lwsgs.js --- libwebsockets-4.0.20/plugins/generic-sessions/assets/lwsgs.js 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/generic-sessions/assets/lwsgs.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,627 +0,0 @@ - - -var lwsgs_user = "$lwsgs_user"; -var lwsgs_auth = "$lwsgs_auth"; -var lwsgs_email = "$lwsgs_email"; - -var lwsgs_html = '\ -

\ -\ -
\ -
\ - \ - \ - \ - \ -
\ - \ -
\ - \ -
\ -
\ -\ - \ - \ - \ - \ - \ -'; - -/*-- this came from - -- https://raw.githubusercontent.com/blueimp/JavaScript-MD5/master/js/md5.min.js - -- under MIT license */ -!function(n){"use strict";function t(n,t){var r=(65535&n)+(65535&t),e=(n>>16)+(t>>16)+(r>>16);return e<<16|65535&r}function r(n,t){return n<>>32-t}function e(n,e,o,u,c,f){return t(r(t(t(e,n),t(u,f)),c),o)}function o(n,t,r,o,u,c,f){return e(t&r|~t&o,n,t,u,c,f)}function u(n,t,r,o,u,c,f){return e(t&o|r&~o,n,t,u,c,f)}function c(n,t,r,o,u,c,f){return e(t^r^o,n,t,u,c,f)}function f(n,t,r,o,u,c,f){return e(r^(t|~o),n,t,u,c,f)}function i(n,r){n[r>>5]|=128<>>9<<4)+14]=r;var e,i,a,h,d,l=1732584193,g=-271733879,v=-1732584194,m=271733878;for(e=0;e>5]>>>t%32&255);return r}function h(n){var t,r=[];for(r[(n.length>>2)-1]=void 0,t=0;t>5]|=(255&n.charCodeAt(t/8))<16&&(o=i(o,8*n.length)),r=0;16>r;r+=1)u[r]=909522486^o[r],c[r]=1549556828^o[r];return e=i(u.concat(h(t)),512+8*t.length),a(i(c.concat(e),640))}function g(n){var t,r,e="0123456789abcdef",o="";for(r=0;r>>4&15)+e.charAt(15&t);return o}function v(n){return unescape(encodeURIComponent(n))}function m(n){return d(v(n))}function p(n){return g(m(n))}function s(n,t){return l(v(n),v(t))}function C(n,t){return g(s(n,t))}function A(n,t,r){return t?r?s(t,n):C(t,n):r?m(n):p(n)}"function"==typeof define&&define.amd?define(function(){return A}):"object"==typeof module&&module.exports?module.exports=A:n.md5=A}(this); - -if (lwsgs_user.substring(0, 1) == "$") { - alert("lwsgs.js: lws generic sessions misconfigured and not providing vars"); -} -function lwsgs_san(s) -{ - if (s.search("<") != -1) - return "invalid string"; - - return s; -} - -function lwsgs_update() -{ - var en_login = 1, en_forgot = 1; - - if (document.getElementById('password').value.length && - document.getElementById('password').value.length < 8) - en_login = 0; - - if (!document.getElementById('username').value || - !document.getElementById('password').value) - en_login = 0; - - if (!document.getElementById('username').value || - document.getElementById('password').value) - en_forgot = 0; - - document.getElementById('login').disabled = !en_login; - document.getElementById('forgot').disabled = !en_forgot; - - if (lwsgs_user) - document.getElementById("curuser").innerHTML = lwsgs_san(lwsgs_user); - - if (lwsgs_user === "") - document.getElementById("dlogin").style.display = "inline"; - else - document.getElementById("dlogout").style.display = "inline"; - } - -function lwsgs_open_registration() -{ - document.getElementById("dadmin").style.display = "none"; - document.getElementById("dlogin").style.display = "none"; - document.getElementById("dlogout").style.display = "none"; - document.getElementById("dchange").style.display = "none"; - document.getElementById("dregister").style.display = "inline"; -} - -function lwsgs_cancel_registration() -{ - document.getElementById("dadmin").style.display = "none"; - document.getElementById("dregister").style.display = "none"; - document.getElementById("dchange").style.display = "none"; - - if (lwsgs_user === "") - document.getElementById("dlogin").style.display = "inline"; - else - document.getElementById("dlogout").style.display = "inline"; -} - -function lwsgs_select_change() -{ - document.getElementById("dlogin").style.display = "none"; - document.getElementById("dlogout").style.display = "none"; - document.getElementById("dregister").style.display = "none"; - if (lwsgs_auth & 2) { - document.getElementById("dadmin").style.display = "inline"; - document.getElementById("dchange").style.display = "none"; - } else { - document.getElementById("dadmin").style.display = "none"; - document.getElementById("dchange").style.display = "inline"; - } - - event.preventDefault() -} - -var lwsgs_user_check = '0'; -var lwsgs_email_check = '0'; - -function lwsgs_rupdate() -{ - var en_register = 1, en_forgot = 0, op; - - if (document.getElementById('rpassword').value == - document.getElementById('password2').value) { - if (document.getElementById('rpassword').value.length) - document.getElementById('match').innerHTML = - "\u2713"; - else - document.getElementById('match').innerHTML = ""; - document.getElementById('pw2').style = ""; - } else { - if (document.getElementById('password2').value || - document.getElementById('email').value) { // ie, he is filling in "register" path and cares - document.getElementById('match').innerHTML = - "\u2718 Passwords do not match"; - } else - document.getElementById('match').innerHTML = - "\u2718 Passwords do not match"; - - en_register = 0; - } - - if (document.getElementById('rpassword').value.length && - document.getElementById('rpassword').value.length < 8) { - en_register = 0; - document.getElementById('rpw1').innerHTML = "Need 8 chars"; - } else - if (document.getElementById('rpassword').value.length) - document.getElementById('rpw1').innerHTML = "\u2713"; - else - document.getElementById('rpw1').innerHTML = ""; - - if (!document.getElementById('rpassword').value || - !document.getElementById('password2').value || - !document.getElementById('rusername').value || - !document.getElementById('email').value || - lwsgs_email_check === '1'|| - lwsgs_user_check === '1') - en_register = 0; - - document.getElementById('register').disabled = !en_register; - document.getElementById('rpassword').disabled = lwsgs_user_check === '1'; - document.getElementById('password2').disabled = lwsgs_user_check === '1'; - document.getElementById('email').disabled = lwsgs_user_check === '1'; - - if (lwsgs_user_check === '0') { - var uc = document.getElementById('uchk'); - - if (uc) { - if (document.getElementById('rusername').value) - uc.innerHTML = "\u2713"; - else - uc.innerHTML = ""; - } - } else { - if (document.getElementById('uchk')) - ocument.getElementById('uchk').innerHTML = "\u2718 Already registered"; - en_forgot = 1; - } - - if (lwsgs_email_check === '0') { - var ec = document.getElementById('echk'); - - if (ec) { - if (document.getElementById('email').value) - ec.innerHTML = "\u2713"; - else - ec.innerHTML = ""; - } - } else { - if (document.getElementById('echk')) - document.getElementById('echk').innerHTML = "\u2718 Already registered"; - en_forgot = 1; - } - - if (en_forgot) - document.getElementById('rforgot').style.display = "inline"; - else - document.getElementById('rforgot').style.display = "none"; - - if (lwsgs_user_check === '1') - op = '0.5'; - else - op = '1.0'; - document.getElementById('rpassword').style.opacity = op; - document.getElementById('password2').style.opacity = op; - document.getElementById('email').style.opacity = op; - } - -function lwsgs_cupdate() -{ - var en_change = 1, en_forgot = 1, pwok = 1, op; - - if (lwsgs_auth & 8) { - document.getElementById('ccurpw').style.display = "none"; - document.getElementById('ccurpw_name').style.display = "none"; - } else { - if (!document.getElementById('ccurpw').value || - document.getElementById('ccurpw').value.length < 8) { - en_change = 0; - pwok = 0; - document.getElementById('cuchk').innerHTML = "\u2718"; - } else { - en_forgot = 0; - document.getElementById('cuchk').innerHTML = ""; - } - document.getElementById('ccurpw').style.display = "inline"; - document.getElementById('ccurpw_name').style.display = "inline"; - } - - if (document.getElementById('cpassword').value == - document.getElementById('cpassword2').value) { - if (document.getElementById('cpassword').value.length) - document.getElementById('cmatch').innerHTML = "\u2713"; - else - document.getElementById('cmatch').innerHTML = ""; - document.getElementById('pw2').style = ""; - } else { - if (document.getElementById('cpassword2').value //|| - //document.getElementById('cemail').value - ) { // ie, he is filling in "register" path and cares - document.getElementById('cmatch').innerHTML = - "\u2718 Passwords do not match"; - } else - document.getElementById('cmatch').innerHTML = "\u2718 Passwords do not match"; - - en_change = 0; - } - - if (document.getElementById('cpassword').value.length && - document.getElementById('cpassword').value.length < 8) { - en_change = 0; - document.getElementById('cpw1').innerHTML = "Need 8 chars"; - } else { - var cpw = document.getElementById('cpw1'); - - if (cpw) { - if (document.getElementById('cpassword').value.length) - cpw.innerHTML = "\u2713"; - else - cpw.innerHTML = ""; - } - } - - if (!document.getElementById('cpassword').value || - !document.getElementById('cpassword2').value || - pwok === 0) - en_change = 0; - - if (document.getElementById('showdel').checked) - document.getElementById('delete').style.display = "inline"; - else - document.getElementById('delete').style.display = "none"; - - document.getElementById('change').disabled = !en_change; - document.getElementById('cpassword').disabled = pwok === 0; - document.getElementById('cpassword2').disabled = pwok === 0; - document.getElementById('showdel').disabled = pwok === 0; - document.getElementById('delete').disabled = pwok === 0; - //document.getElementById('cemail').disabled = pwok === 0; - - /* - if (lwsgs_auth & 8) { - document.getElementById('cemail').style.display = "none"; - document.getElementById('cemail_name').style.display = "none"; - } else { - document.getElementById('cemail').style.display = "inline"; - document.getElementById('cemail_name').style.display = "inline"; - if (lwsgs_email_check === '0' && - document.getElementById('cemail').value != lwsgs_email) { - if (document.getElementById('cemail').value) - document.getElementById('cechk').innerHTML = "\u2713"; - else - document.getElementById('cechk').innerHTML = ""; - } else { - document.getElementById('cechk').innerHTML = "\u2718 Already registered"; - en_forgot = 1; - } - } */ - - if (lwsgs_auth & 8) - en_forgot = 0; - - if (en_forgot) - document.getElementById('cforgot').style.display = "inline"; - else - document.getElementById('cforgot').style.display = "none"; - - if (pwok === 0) - op = '0.5'; - else - op = '1.0'; - document.getElementById('cpassword').style.opacity = op; - document.getElementById('cpassword2').style.opacity = op; - // document.getElementById('cemail').style.opacity = op; - } - -function lwsgs_check_user() -{ - var xmlHttp = new XMLHttpRequest(); - xmlHttp.onreadystatechange = function() { - if (xmlHttp.readyState === 4 && xmlHttp.status === 200) { - lwsgs_user_check = xmlHttp.responseText; - lwsgs_rupdate(); - } - } - xmlHttp.open("GET", "lwsgs-check?username="+document.getElementById('rusername').value, true); - xmlHttp.send(null); -} - -function lwsgs_check_email(id) -{ - var xmlHttp = new XMLHttpRequest(); - xmlHttp.onreadystatechange = function() { - if (xmlHttp.readyState === 4 && xmlHttp.status === 200) { - lwsgs_email_check = xmlHttp.responseText; - lwsgs_rupdate(); - } - } - xmlHttp.open("GET", "lwsgs-check?email="+document.getElementById(id).value, true); - xmlHttp.send(null); -} - -function rupdate_user() -{ - lwsgs_rupdate(); - lwsgs_check_user(); -} - -function rupdate_email() -{ - lwsgs_rupdate(); - lwsgs_check_email('email'); -} - -function cupdate_email() -{ - lwsgs_cupdate(); - lwsgs_check_email('cemail'); -} - - -function lwsgs_initial() -{ - document.getElementById('lwsgs').innerHTML = lwsgs_html; - - if (lwsgs_user) { - document.getElementById("curuser").innerHTML = - "currently logged in as " + lwsgs_san(lwsgs_user) + "
"; - - document.getElementById("ccuruser").innerHTML = - "Login settings for " + - lwsgs_san(lwsgs_user) + "
"; - } - - document.getElementById('username').oninput = lwsgs_update; - document.getElementById('username').onchange = lwsgs_update; - document.getElementById('password').oninput = lwsgs_update; - document.getElementById('password').onchange = lwsgs_update; - document.getElementById('doreg').onclick = lwsgs_open_registration; - document.getElementById('clink').onclick = lwsgs_select_change; - document.getElementById('cancel').onclick =lwsgs_cancel_registration; - document.getElementById('cancel2').onclick =lwsgs_cancel_registration; - document.getElementById('rpassword').oninput = lwsgs_rupdate; - document.getElementById('password2').oninput = lwsgs_rupdate; - document.getElementById('rusername').oninput = rupdate_user; - document.getElementById('email').oninput = rupdate_email; - document.getElementById('ccurpw').oninput = lwsgs_cupdate; - document.getElementById('cpassword').oninput = lwsgs_cupdate; - document.getElementById('cpassword2').oninput = lwsgs_cupdate; - - document.getElementById('showdel').onchange = lwsgs_cupdate; - - if (lwsgs_email) - document.getElementById('grav').innerHTML = - ""; - //if (lwsgs_email) - //document.getElementById('cemail').placeholder = lwsgs_email; - document.getElementById('cusername').value = lwsgs_user; - lwsgs_update(); - lwsgs_cupdate(); -} - -window.addEventListener("load", function() { - lwsgs_initial(); - document.getElementById("nolog").style.display = !!lwsgs_user ? "none" : "inline-block"; - document.getElementById("logged").style.display = !lwsgs_user ? "none" : "inline-block"; - - document.getElementById("msg").onkeyup = mupd; - document.getElementById("msg").onchange = mupd; - - var ws; - - function mb_format(s) - { - var r = "", n, wos = 0; - - for (n = 0; n < s.length; n++) { - if (s[n] == ' ') - wos = 0; - else { - wos++; - if (wos === 40) { - wos = 0; - r = r + ' '; - } - } - if (s[n] == '<') { - r = r + "<"; - continue; - } - if (s[n] == '\n') { - r = r + "
"; - continue; - } - - r = r + s[n]; - } - - return r; - } - - function add_div(n, m) - { - var q = document.getElementById(n); - var d = new Date(m.time * 1000); - - q.innerHTML = "
" + - "
" + - "" + lwsgs_san(m.username) + "
" + - "" + d.toDateString() + - "
" + d.toTimeString() + "

" + - "IP: " + lwsgs_san(m.ip) + - "
" + - mb_format(m.content) + - "

" + q.innerHTML; - } - - function get_appropriate_ws_url() - { - var pcol; - var u = document.URL; - - if (u.substring(0, 5) == "https") { - pcol = "wss://"; - u = u.substr(8); - } else { - pcol = "ws://"; - if (u.substring(0, 4) == "http") - u = u.substr(7); - } - u = u.split('/'); - - return pcol + u[0] + "/xxx"; - } - - if (lwsgs_user) { - ws = new WebSocket(get_appropriate_ws_url(), - "protocol-lws-messageboard"); - - try { - ws.onopen = function() { - document.getElementById("debug").textContent = "ws opened"; - } - ws.onmessage =function got_packet(msg) { - add_div("messages", JSON.parse(msg.data)); - } - ws.onclose = function(){ - } - } catch(exception) { - alert('

Error' + exception); - } - } - - function mupd() - { - document.getElementById("send").disabled = !document.getElementById("msg").value; - } -}, false); Binary files /tmp/tmpmec97nsd/m0nuW2sR0N/libwebsockets-4.0.20/plugins/generic-sessions/assets/lwsgs-logo.png and /tmp/tmpmec97nsd/q8JCI83EXS/libwebsockets-4.1.6/plugins/generic-sessions/assets/lwsgs-logo.png differ diff -Nru libwebsockets-4.0.20/plugins/generic-sessions/assets/md5.min.js libwebsockets-4.1.6/plugins/generic-sessions/assets/md5.min.js --- libwebsockets-4.0.20/plugins/generic-sessions/assets/md5.min.js 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/generic-sessions/assets/md5.min.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -!function(n){"use strict";function t(n,t){var r=(65535&n)+(65535&t),e=(n>>16)+(t>>16)+(r>>16);return e<<16|65535&r}function r(n,t){return n<>>32-t}function e(n,e,o,u,c,f){return t(r(t(t(e,n),t(u,f)),c),o)}function o(n,t,r,o,u,c,f){return e(t&r|~t&o,n,t,u,c,f)}function u(n,t,r,o,u,c,f){return e(t&o|r&~o,n,t,u,c,f)}function c(n,t,r,o,u,c,f){return e(t^r^o,n,t,u,c,f)}function f(n,t,r,o,u,c,f){return e(r^(t|~o),n,t,u,c,f)}function i(n,r){n[r>>5]|=128<>>9<<4)+14]=r;var e,i,a,h,d,l=1732584193,g=-271733879,v=-1732584194,m=271733878;for(e=0;e>5]>>>t%32&255);return r}function h(n){var t,r=[];for(r[(n.length>>2)-1]=void 0,t=0;t>5]|=(255&n.charCodeAt(t/8))<16&&(o=i(o,8*n.length)),r=0;16>r;r+=1)u[r]=909522486^o[r],c[r]=1549556828^o[r];return e=i(u.concat(h(t)),512+8*t.length),a(i(c.concat(e),640))}function g(n){var t,r,e="0123456789abcdef",o="";for(r=0;r>>4&15)+e.charAt(15&t);return o}function v(n){return unescape(encodeURIComponent(n))}function m(n){return d(v(n))}function p(n){return g(m(n))}function s(n,t){return l(v(n),v(t))}function C(n,t){return g(s(n,t))}function A(n,t,r){return t?r?s(t,n):C(t,n):r?m(n):p(n)}"function"==typeof define&&define.amd?define(function(){return A}):"object"==typeof module&&module.exports?module.exports=A:n.md5=A}(this); -//# sourceMappingURL=md5.min.js.map \ No newline at end of file diff -Nru libwebsockets-4.0.20/plugins/generic-sessions/assets/post-forgot-fail.html libwebsockets-4.1.6/plugins/generic-sessions/assets/post-forgot-fail.html --- libwebsockets-4.0.20/plugins/generic-sessions/assets/post-forgot-fail.html 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/generic-sessions/assets/post-forgot-fail.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ - -Sorry, something went wrong. - -Click here to continue. - diff -Nru libwebsockets-4.0.20/plugins/generic-sessions/assets/post-forgot-ok.html libwebsockets-4.1.6/plugins/generic-sessions/assets/post-forgot-ok.html --- libwebsockets-4.0.20/plugins/generic-sessions/assets/post-forgot-ok.html 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/generic-sessions/assets/post-forgot-ok.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ - -This is a one-time password recovery login. - -Please click here and click your username at the top to reset your password. - - diff -Nru libwebsockets-4.0.20/plugins/generic-sessions/assets/post-register-fail.html libwebsockets-4.1.6/plugins/generic-sessions/assets/post-register-fail.html --- libwebsockets-4.0.20/plugins/generic-sessions/assets/post-register-fail.html 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/generic-sessions/assets/post-register-fail.html 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -Registration failed, sorry diff -Nru libwebsockets-4.0.20/plugins/generic-sessions/assets/post-register-ok.html libwebsockets-4.1.6/plugins/generic-sessions/assets/post-register-ok.html --- libwebsockets-4.0.20/plugins/generic-sessions/assets/post-register-ok.html 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/generic-sessions/assets/post-register-ok.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ - - - - - - - - - - - - -
- -
- Your registration as is accepted,
- you will receive an email shortly with instructions
- to verify and enable the account for normal use.

- The link is only valid for an hour, after that if it has
- not been verified your account will be deleted. -
- - - - diff -Nru libwebsockets-4.0.20/plugins/generic-sessions/assets/post-verify-fail.html libwebsockets-4.1.6/plugins/generic-sessions/assets/post-verify-fail.html --- libwebsockets-4.0.20/plugins/generic-sessions/assets/post-verify-fail.html 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/generic-sessions/assets/post-verify-fail.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ - - - - - - - - - - - - -
- -
- Sorry, the link was invalid. -
- - - diff -Nru libwebsockets-4.0.20/plugins/generic-sessions/assets/post-verify-ok.html libwebsockets-4.1.6/plugins/generic-sessions/assets/post-verify-ok.html --- libwebsockets-4.0.20/plugins/generic-sessions/assets/post-verify-ok.html 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/generic-sessions/assets/post-verify-ok.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ - - - - - - - - - - - - -
- -
- Thanks for signing up, your registration as is verified.
-
- Click here to continue. -
- - - - Binary files /tmp/tmpmec97nsd/m0nuW2sR0N/libwebsockets-4.0.20/plugins/generic-sessions/assets/seats.jpg and /tmp/tmpmec97nsd/q8JCI83EXS/libwebsockets-4.1.6/plugins/generic-sessions/assets/seats.jpg differ diff -Nru libwebsockets-4.0.20/plugins/generic-sessions/assets/sent-forgot-fail.html libwebsockets-4.1.6/plugins/generic-sessions/assets/sent-forgot-fail.html --- libwebsockets-4.0.20/plugins/generic-sessions/assets/sent-forgot-fail.html 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/generic-sessions/assets/sent-forgot-fail.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ - -Sorry, something went wrong. - -Click here to continue. - diff -Nru libwebsockets-4.0.20/plugins/generic-sessions/assets/sent-forgot-ok.html libwebsockets-4.1.6/plugins/generic-sessions/assets/sent-forgot-ok.html --- libwebsockets-4.0.20/plugins/generic-sessions/assets/sent-forgot-ok.html 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/generic-sessions/assets/sent-forgot-ok.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -An email has been sent to your registered address. - -Please follow the instructions to reset your password. - diff -Nru libwebsockets-4.0.20/plugins/generic-sessions/assets/successful-login.html libwebsockets-4.1.6/plugins/generic-sessions/assets/successful-login.html --- libwebsockets-4.0.20/plugins/generic-sessions/assets/successful-login.html 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/generic-sessions/assets/successful-login.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ - -This is an example destination that will appear after successful non-Admin login - - diff -Nru libwebsockets-4.0.20/plugins/generic-sessions/handlers.c libwebsockets-4.1.6/plugins/generic-sessions/handlers.c --- libwebsockets-4.0.20/plugins/generic-sessions/handlers.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/generic-sessions/handlers.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,663 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * 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-lwsgs.h" - -#if defined(LWS_WITH_SMTP) - -static int -lwsgs_smtp_client_done(struct lws_smtp_email *e, void *buf, size_t len) -{ - free(e); - - return 0; -} - -static int -lwsgs_smtp_client_done_sentvfy(struct lws_smtp_email *e, void *buf, size_t len) -{ - struct per_vhost_data__gs *vhd = (struct per_vhost_data__gs *)e->data; - const char *username = (const char *)e->extra; - char s[200], esc[96]; - - lwsl_notice("%s: registration email sent: %s\n", __func__, username); - - /* mark the user as having sent the verification email */ - lws_snprintf(s, sizeof(s) - 1, - "update users set verified=1 where username='%s' and verified==0;", - lws_sql_purify(esc, username, sizeof(esc) - 1)); - if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != SQLITE_OK) { - lwsl_err("%s: Unable to update user: %s\n", __func__, - sqlite3_errmsg(vhd->pdb)); - return 1; - } - - free(e); - - return 0; -} -#endif - -/* handle account confirmation links */ - -int -lwsgs_handler_confirm(struct per_vhost_data__gs *vhd, struct lws *wsi, - struct per_session_data__gs *pss) -{ - char cookie[1024], s[256], esc[90]; - struct lws_gs_event_args a; - struct lwsgs_user u; - - if (lws_hdr_copy_fragment(wsi, cookie, sizeof(cookie), - WSI_TOKEN_HTTP_URI_ARGS, 0) < 0) { - lwsl_err("%s: missing URI_ARGS\n", __func__); - goto verf_fail; - } - - if (strncmp(cookie, "token=", 6)) { - lwsl_err("%s: missing URI_ARGS token=\n", __func__); - goto verf_fail; - } - - u.username[0] = '\0'; - u.verified = -1; - lws_snprintf(s, sizeof(s) - 1, - "select username,email,verified from users where token = '%s';", - lws_sql_purify(esc, &cookie[6], sizeof(esc) - 1)); - puts(s); - if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &u, NULL) != - SQLITE_OK) { - lwsl_err("Unable to lookup token: %s\n", - sqlite3_errmsg(vhd->pdb)); - goto verf_fail; - } - - if (!u.username[0] || u.verified != 1) { - lwsl_notice("verify token %s doesn't map to unverified user (user='%s', verified=%d)\n", - &cookie[6], u.username, u.verified); - goto verf_fail; - } - - lwsl_notice("Verifying %s\n", u.username); - lws_snprintf(s, sizeof(s) - 1, - "update users set verified=%d where username='%s';", - LWSGS_VERIFIED_ACCEPTED, - lws_sql_purify(esc, u.username, sizeof(esc) - 1)); - if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &u, NULL) != - SQLITE_OK) { - lwsl_err("Unable to lookup token: %s\n", - sqlite3_errmsg(vhd->pdb)); - - goto verf_fail; - } - - lwsl_notice("deleting account\n"); - - a.event = LWSGSE_CREATED; - a.username = u.username; - a.email = u.email; - lws_callback_vhost_protocols_vhost(lws_get_vhost(wsi), - LWS_CALLBACK_GS_EVENT, &a, 0); - - lws_snprintf(pss->onward, sizeof(pss->onward), - "%s/post-verify-ok.html", vhd->email_confirm_url); - - pss->login_expires = lws_now_secs() + vhd->timeout_absolute_secs; - - pss->delete_session.id[0] = '\0'; - lwsgs_get_sid_from_wsi(wsi, &pss->delete_session); - - /* we need to create a new, authorized session */ - - if (lwsgs_new_session_id(vhd, &pss->login_session, u.username, - pss->login_expires)) - goto verf_fail; - - lwsl_notice("Creating new session: %s, redir to %s\n", - pss->login_session.id, pss->onward); - - return 0; - -verf_fail: - pss->delete_session.id[0] = '\0'; - lwsgs_get_sid_from_wsi(wsi, &pss->delete_session); - pss->login_expires = 0; - - lws_snprintf(pss->onward, sizeof(pss->onward), "%s/post-verify-fail.html", - vhd->email_confirm_url); - - return 1; -} - -/* handle forgot password confirmation links */ - -int -lwsgs_handler_forgot(struct per_vhost_data__gs *vhd, struct lws *wsi, - struct per_session_data__gs *pss) -{ - char cookie[1024], s[256], esc[96]; - struct lwsgs_user u; - const char *a; - - a = lws_get_urlarg_by_name(wsi, "token=", cookie, sizeof(cookie)); - if (!a) - goto forgot_fail; - - u.username[0] = '\0'; - lws_snprintf(s, sizeof(s) - 1, - "select username,verified from users where verified=%d and " - "token = '%s' and token_time != 0;", - LWSGS_VERIFIED_ACCEPTED, - lws_sql_purify(esc, &cookie[6], sizeof(esc) - 1)); - if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &u, NULL) != - SQLITE_OK) { - lwsl_err("Unable to lookup token: %s\n", - sqlite3_errmsg(vhd->pdb)); - - goto forgot_fail; - } - - if (!u.username[0]) { - puts(s); - lwsl_notice("forgot token doesn't map to verified user\n"); - goto forgot_fail; - } - - /* mark user as having validated forgot flow just now */ - - lws_snprintf(s, sizeof(s) - 1, - "update users set token_time=0,last_forgot_validated=%lu " - "where username='%s';", - (unsigned long)lws_now_secs(), - lws_sql_purify(esc, u.username, sizeof(esc) - 1)); - - if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &u, NULL) != - SQLITE_OK) { - lwsl_err("Unable to lookup token: %s\n", - sqlite3_errmsg(vhd->pdb)); - goto forgot_fail; - } - - a = lws_get_urlarg_by_name(wsi, "good=", cookie, sizeof(cookie)); - if (!a) - a = "broken-forget-post-good-url"; - - lws_snprintf(pss->onward, sizeof(pss->onward), - "%s/%s", vhd->email_confirm_url, a); - - pss->login_expires = lws_now_secs() + vhd->timeout_absolute_secs; - - pss->delete_session.id[0] = '\0'; - lwsgs_get_sid_from_wsi(wsi, &pss->delete_session); - - /* we need to create a new, authorized session */ - if (lwsgs_new_session_id(vhd, &pss->login_session, - u.username, - pss->login_expires)) - goto forgot_fail; - - lwsl_notice("Creating new session: %s, redir to %s\n", - pss->login_session.id, pss->onward); - - return 0; - -forgot_fail: - pss->delete_session.id[0] = '\0'; - lwsgs_get_sid_from_wsi(wsi, &pss->delete_session); - pss->login_expires = 0; - - a = lws_get_urlarg_by_name(wsi, "bad=", cookie, sizeof(cookie)); - if (!a) - a = "broken-forget-post-bad-url"; - - lws_snprintf(pss->onward, sizeof(pss->onward), "%s/%s", - vhd->email_confirm_url, a); - - return 1; -} - -/* support dynamic username / email checking */ - -int -lwsgs_handler_check(struct per_vhost_data__gs *vhd, - struct lws *wsi, struct per_session_data__gs *pss, - const char *in) -{ - static const char * const colname[] = { "username", "email" }; - char s[256], esc[96], *pc; - unsigned char *p, *start, *end, buffer[LWS_PRE + 1024]; - struct lwsgs_user u; - int n; - - /* - * either /check/email=xxx@yyy or: /check/username=xxx - * returns '0' if not already registered, else '1' - */ - - u.username[0] = '\0'; - - n = !strncmp(in, "email=", 6); - pc = strchr(in, '='); - if (!pc) { - lwsl_notice("cookie has no =\n"); - goto reply; - } - pc++; - - /* admin user cannot be registered in user db */ - if (!strcmp(vhd->admin_user, pc)) { - u.username[0] = 'a'; - goto reply; - } - - lws_snprintf(s, sizeof(s) - 1, - "select username, email from users where %s = '%s';", - colname[n], lws_sql_purify(esc, pc, sizeof(esc) - 1)); - if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &u, NULL) != - SQLITE_OK) { - lwsl_err("Unable to lookup token: %s\n", - sqlite3_errmsg(vhd->pdb)); - goto reply; - } - -reply: - s[0] = '0' + !!u.username[0]; - p = buffer + LWS_PRE; - start = p; - end = p + sizeof(buffer) - LWS_PRE; - - if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end)) - return -1; - if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE, - (unsigned char *)"text/plain", 10, - &p, end)) - return -1; - - if (lws_add_http_header_content_length(wsi, 1, &p, end)) - return -1; - - if (lws_finalize_http_header(wsi, &p, end)) - return -1; - - n = lws_write(wsi, start, p - start, LWS_WRITE_HTTP_HEADERS); - if (n != (p - start)) { - lwsl_err("_write returned %d from %ld\n", n, (long)(p - start)); - return -1; - } - - pss->check_response_value = s[0]; - pss->check_response = 1; - - lws_callback_on_writable(wsi); - - return 0; -} - -/* handle forgot password confirmation links */ - -int -lwsgs_handler_change_password(struct per_vhost_data__gs *vhd, struct lws *wsi, - struct per_session_data__gs *pss) -{ - char s[256], esc[96], username[96]; - struct lwsgs_user u; - lwsgw_hash sid; - int n = 0; - - /* see if he's logged in */ - username[0] = '\0'; - if (!lwsgs_get_sid_from_wsi(wsi, &sid)) { - u.username[0] = '\0'; - if (!lwsgs_lookup_session(vhd, &sid, username, sizeof(username))) { - n = 1; /* yes, logged in */ - if (lwsgs_lookup_user(vhd, username, &u)) - return 1; - - /* did a forgot pw ? */ - if (u.last_forgot_validated > (time_t)lws_now_secs() - 300) { - n |= LWSGS_AUTH_FORGOT_FLOW; - lwsl_debug("within forgot password flow\n"); - } - } - } - - lwsl_debug("auth value %d\n", n); - - /* if he just did forgot pw flow, don't need old pw */ - if ((n & (LWSGS_AUTH_FORGOT_FLOW | 1)) != (LWSGS_AUTH_FORGOT_FLOW | 1)) { - /* otherwise user:pass must be right */ - lwsl_debug("checking pw\n"); - if (lwsgs_check_credentials(vhd, - lws_spa_get_string(pss->spa, FGS_USERNAME), - lws_spa_get_string(pss->spa, FGS_CURPW))) { - lwsl_notice("credentials bad\n"); - return 1; - } - - lwsl_debug("current pw checks out\n"); - - lws_strncpy(u.username, lws_spa_get_string(pss->spa, FGS_USERNAME), - sizeof(u.username)); - } - - /* does he want to delete his account? */ - - if (lws_spa_get_length(pss->spa, FGS_DELETE)) { - struct lws_gs_event_args a; - - lwsl_notice("deleting account\n"); - - a.event = LWSGSE_DELETED; - a.username = u.username; - a.email = ""; - lws_callback_vhost_protocols_vhost(lws_get_vhost(wsi), - LWS_CALLBACK_GS_EVENT, &a, 0); - - lws_snprintf(s, sizeof(s) - 1, - "delete from users where username='%s';" - "delete from sessions where username='%s';", - lws_sql_purify(esc, u.username, sizeof(esc) - 1), - lws_sql_purify(esc, u.username, sizeof(esc) - 1)); - goto sql; - } - - if (lwsgs_hash_password(vhd, lws_spa_get_string(pss->spa, FGS_PASSWORD), &u)) - return 1; - - lwsl_notice("updating password hash\n"); - - lws_snprintf(s, sizeof(s) - 1, - "update users set pwhash='%s', pwsalt='%s', " - "last_forgot_validated=0 where username='%s';", - u.pwhash.id, u.pwsalt.id, - lws_sql_purify(esc, u.username, sizeof(esc) - 1)); - -sql: - if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != SQLITE_OK) { - lwsl_err("Unable to update pw hash: %s\n", - sqlite3_errmsg(vhd->pdb)); - return 1; - } - - return 0; -} - -int -lwsgs_handler_forgot_pw_form(struct per_vhost_data__gs *vhd, - struct lws *wsi, struct per_session_data__gs *pss) -{ - char esc[96], esc1[96], esc2[96], esc3[96], esc4[96]; - char s[LWSGS_EMAIL_CONTENT_SIZE]; - unsigned char sid_rand[32]; -#if defined(LWS_WITH_SMTP) - lws_smtp_email_t *em; -#endif - struct lwsgs_user u; - lwsgw_hash hash; - int n; - - lwsl_notice("FORGOT %s %s\n", - lws_spa_get_string(pss->spa, FGS_USERNAME), - lws_spa_get_string(pss->spa, FGS_EMAIL)); - - if (!lws_spa_get_string(pss->spa, FGS_USERNAME) && - !lws_spa_get_string(pss->spa, FGS_EMAIL)) { - lwsl_err("Form must provide either " - "username or email\n"); - return -1; - } - - if (!lws_spa_get_string(pss->spa, FGS_FORGOT_GOOD) || - !lws_spa_get_string(pss->spa, FGS_FORGOT_BAD) || - !lws_spa_get_string(pss->spa, FGS_FORGOT_POST_GOOD) || - !lws_spa_get_string(pss->spa, FGS_FORGOT_POST_BAD)) { - lwsl_err("Form must provide reg-good " - "and reg-bad (and post-*)" - "targets\n"); - return -1; - } - - u.username[0] = '\0'; - if (lws_spa_get_string(pss->spa, FGS_USERNAME)) - lws_snprintf(s, sizeof(s) - 1, - "select username,email " - "from users where username = '%s';", - lws_sql_purify(esc, lws_spa_get_string(pss->spa, FGS_USERNAME), - sizeof(esc) - 1)); - else - lws_snprintf(s, sizeof(s) - 1, - "select username,email " - "from users where email = '%s';", - lws_sql_purify(esc, lws_spa_get_string(pss->spa, FGS_EMAIL), sizeof(esc) - 1)); - if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &u, NULL) != - SQLITE_OK) { - lwsl_err("Unable to lookup token: %s\n", - sqlite3_errmsg(vhd->pdb)); - return 1; - } - if (!u.username[0]) { - lwsl_err("No match found %s\n", s); - return 1; - } - - lws_get_peer_simple(wsi, pss->ip, sizeof(pss->ip)); - if (lws_get_random(vhd->context, sid_rand, - sizeof(sid_rand)) != - sizeof(sid_rand)) { - lwsl_err("Problem getting random for token\n"); - return 1; - } - sha256_to_lwsgw_hash(sid_rand, &hash); - - lws_snprintf(s, sizeof(s) - 1, - "update users set token='%s',token_time='%ld' where username='%s';", - hash.id, (long)lws_now_secs(), - lws_sql_purify(esc, u.username, sizeof(esc) - 1)); - if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != - SQLITE_OK) { - lwsl_err("Unable to set token: %s\n", - sqlite3_errmsg(vhd->pdb)); - return 1; - } - - n = lws_snprintf(s, sizeof(s), - "From: Forgot Password Assistant Noreply <%s>\n" - "To: %s <%s>\n" - "Subject: Password reset request\n" - "\n" - "Hello, %s\n\n" - "We received a password reset request from IP %s for this email,\n" - "to confirm you want to do that, please click the link below.\n\n", - lws_sql_purify(esc, vhd->email_from, sizeof(esc) - 1), - lws_sql_purify(esc1, u.username, sizeof(esc1) - 1), - lws_sql_purify(esc2, u.email, sizeof(esc2) - 1), - lws_sql_purify(esc3, u.username, sizeof(esc3) - 1), - lws_sql_purify(esc4, pss->ip, sizeof(esc4) - 1)); - lws_snprintf(s + n, sizeof(s) - n, - "%s/lwsgs-forgot?token=%s" - "&good=%s" - "&bad=%s\n\n" - "If this request is unexpected, please ignore it and\n" - "no further action will be taken.\n\n" - "If you have any questions or concerns about this\n" - "automated email, you can contact a real person at\n" - "%s.\n" - "\n.\n", - vhd->email_confirm_url, hash.id, - lws_urlencode(esc1, - lws_spa_get_string(pss->spa, FGS_FORGOT_POST_GOOD), - sizeof(esc1) - 1), - lws_urlencode(esc3, - lws_spa_get_string(pss->spa, FGS_FORGOT_POST_BAD), - sizeof(esc3) - 1), - vhd->email_contact_person); - - puts(s); -#if defined(LWS_WITH_SMTP) - - em = lws_smtpc_alloc_email_helper(s, n, vhd->email_from, u.email, - u.username, strlen(u.username), - vhd, lwsgs_smtp_client_done); - if (!em) - return 1; - if (lws_smtpc_add_email(vhd->smtp_client, em)) - return 1; -#endif - return 0; -} - -int -lwsgs_handler_register_form(struct per_vhost_data__gs *vhd, - struct lws *wsi, - struct per_session_data__gs *pss) -{ - unsigned char buffer[LWS_PRE + LWSGS_EMAIL_CONTENT_SIZE]; - char esc[96], esc1[96], esc2[96], esc3[96], esc4[96]; - char s[LWSGS_EMAIL_CONTENT_SIZE]; - unsigned char sid_rand[32]; -#if defined(LWS_WITH_SMTP) - lws_smtp_email_t *em; -#endif - struct lwsgs_user u; - lwsgw_hash hash; - size_t n; - - lwsl_notice("REGISTER %s %s %s\n", - lws_spa_get_string(pss->spa, FGS_USERNAME), - lws_spa_get_string(pss->spa, FGS_PASSWORD), - lws_spa_get_string(pss->spa, FGS_EMAIL)); - if (lwsgs_get_sid_from_wsi(wsi, - &pss->login_session)) - return 1; - - lws_get_peer_simple(wsi, pss->ip, sizeof(pss->ip)); - lwsl_notice("IP=%s\n", pss->ip); - - if (!lws_spa_get_string(pss->spa, FGS_REG_GOOD) || - !lws_spa_get_string(pss->spa, FGS_REG_BAD)) { - lwsl_info("Form must provide reg-good and reg-bad targets\n"); - return -1; - } - - /* admin user cannot be registered in user db */ - if (!strcmp(vhd->admin_user, - lws_spa_get_string(pss->spa, FGS_USERNAME))) - return 1; - - if (!lwsgs_lookup_user(vhd, - lws_spa_get_string(pss->spa, FGS_USERNAME), &u)) { - lwsl_notice("user %s already registered\n", - lws_spa_get_string(pss->spa, FGS_USERNAME)); - return 1; - } - - u.username[0] = '\0'; - lws_snprintf(s, sizeof(s) - 1, "select username, email from users where email = '%s';", - lws_sql_purify(esc, lws_spa_get_string(pss->spa, FGS_EMAIL), - sizeof(esc) - 1)); - - if (sqlite3_exec(vhd->pdb, s, - lwsgs_lookup_callback_user, &u, NULL) != SQLITE_OK) { - lwsl_err("Unable to lookup token: %s\n", - sqlite3_errmsg(vhd->pdb)); - return 1; - } - - if (u.username[0]) { - lwsl_notice("email %s already in use\n", - lws_spa_get_string(pss->spa, FGS_USERNAME)); - return 1; - } - - if (lwsgs_hash_password(vhd, lws_spa_get_string(pss->spa, FGS_PASSWORD), - &u)) { - lwsl_err("Password hash failed\n"); - return 1; - } - - if (lws_get_random(vhd->context, sid_rand, sizeof(sid_rand)) != - sizeof(sid_rand)) { - lwsl_err("Problem getting random for token\n"); - return 1; - } - sha256_to_lwsgw_hash(sid_rand, &hash); - - lws_snprintf((char *)buffer, sizeof(buffer) - 1, - "insert into users(username," - " creation_time, ip, email, verified," - " pwhash, pwsalt, token, last_forgot_validated)" - " values ('%s', %lu, '%s', '%s', 0," - " '%s', '%s', '%s', 0);", - lws_sql_purify(esc, lws_spa_get_string(pss->spa, FGS_USERNAME), sizeof(esc) - 1), - (unsigned long)lws_now_secs(), - lws_sql_purify(esc1, pss->ip, sizeof(esc1) - 1), - lws_sql_purify(esc2, lws_spa_get_string(pss->spa, FGS_EMAIL), sizeof(esc2) - 1), - u.pwhash.id, u.pwsalt.id, hash.id); - - if (sqlite3_exec(vhd->pdb, (char *)buffer, NULL, NULL, NULL) != SQLITE_OK) { - lwsl_err("Unable to insert user: %s\n", - sqlite3_errmsg(vhd->pdb)); - return 1; - } - - n = lws_snprintf(s, sizeof(s), - "From: Noreply <%s>\n" - "To: %s <%s>\n" - "Subject: Registration verification\n" - "\n" - "Hello, %s\n\n" - "We received a registration from IP %s using this email,\n" - "to confirm it is legitimate, please click the link below.\n\n" - "%s/lwsgs-confirm?token=%s\n\n" - "If this request is unexpected, please ignore it and\n" - "no further action will be taken.\n\n" - "If you have any questions or concerns about this\n" - "automated email, you can contact a real person at\n" - "%s.\n" - "\n.\n", - lws_sql_purify(esc, vhd->email_from, sizeof(esc) - 1), - lws_sql_purify(esc1, lws_spa_get_string(pss->spa, FGS_USERNAME), sizeof(esc1) - 1), - lws_sql_purify(esc2, lws_spa_get_string(pss->spa, FGS_EMAIL), sizeof(esc2) - 1), - lws_sql_purify(esc3, lws_spa_get_string(pss->spa, FGS_USERNAME), sizeof(esc3) - 1), - lws_sql_purify(esc4, pss->ip, sizeof(esc4) - 1), - vhd->email_confirm_url, hash.id, - vhd->email_contact_person); - -#if defined(LWS_WITH_SMTP) - em = lws_smtpc_alloc_email_helper(s, n, vhd->email_from, - lws_spa_get_string(pss->spa, FGS_EMAIL), - lws_spa_get_string(pss->spa, FGS_USERNAME), - strlen(lws_spa_get_string(pss->spa, FGS_USERNAME)), - vhd, lwsgs_smtp_client_done_sentvfy); - if (!em) - return 1; - - if (lws_smtpc_add_email(vhd->smtp_client, em)) - return 1; -#else - (void)n; -#endif - - return 0; -} diff -Nru libwebsockets-4.0.20/plugins/generic-sessions/private-lwsgs.h libwebsockets-4.1.6/plugins/generic-sessions/private-lwsgs.h --- libwebsockets-4.0.20/plugins/generic-sessions/private-lwsgs.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/generic-sessions/private-lwsgs.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,171 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * 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. - */ - -#define LWS_DLL -#define LWS_INTERNAL -#include - -#include -#include - -#define LWSGS_VERIFIED_ACCEPTED 100 - -enum { - FGS_USERNAME, - FGS_PASSWORD, - FGS_PASSWORD2, - FGS_EMAIL, - FGS_REGISTER, - FGS_GOOD, - FGS_BAD, - FGS_REG_GOOD, - FGS_REG_BAD, - FGS_ADMIN, - FGS_FORGOT, - FGS_FORGOT_GOOD, - FGS_FORGOT_BAD, - FGS_FORGOT_POST_GOOD, - FGS_FORGOT_POST_BAD, - FGS_CHANGE, - FGS_CURPW, - FGS_DELETE, -}; - -struct lwsgs_user { - char username[32]; - char ip[16]; - lwsgw_hash pwhash; - lwsgw_hash pwsalt; - lwsgw_hash token; - time_t created; - time_t last_forgot_validated; - char email[100]; - int verified; -}; - -struct per_vhost_data__gs { - lws_abs_t *smtp_client; - struct lwsgs_user u; - lws_token_map_t transport_tokens[3]; - lws_token_map_t protocol_tokens[2]; - char helo[64], ip[64]; - struct lws_context *context; - char session_db[256]; - char admin_user[32]; - char urlroot[48]; - char confounder[32]; - char email_contact_person[128]; - char email_title[128]; - char email_template[128]; - char email_confirm_url[128]; - char email_from[128]; - lwsgw_hash admin_password_sha256; - sqlite3 *pdb; - int timeout_idle_secs; - int timeout_absolute_secs; - int timeout_anon_absolute_secs; - int timeout_email_secs; - time_t last_session_expire; -}; - -struct per_session_data__gs { - struct lws_spa *spa; - lwsgw_hash login_session; - lwsgw_hash delete_session; - unsigned int login_expires; - char onward[256]; - char result[500 + LWS_PRE]; - char urldec[500 + LWS_PRE]; - int result_len; - char ip[46]; - struct lws_process_html_state phs; - int spos; - char check_response_value; - - unsigned int logging_out:1; - unsigned int check_response:1; -}; - -/* utils.c */ - -int -lwsgs_lookup_callback_user(void *priv, int cols, char **col_val, - char **col_name); -void -lwsgw_cookie_from_session(lwsgw_hash *sid, time_t expires, char **p, char *end); -int -lwsgs_get_sid_from_wsi(struct lws *wsi, lwsgw_hash *sid); -int -lwsgs_lookup_session(struct per_vhost_data__gs *vhd, - const lwsgw_hash *sid, char *username, int len); -int -lwsgs_get_auth_level(struct per_vhost_data__gs *vhd, - const char *username); -int -lwsgs_check_credentials(struct per_vhost_data__gs *vhd, - const char *username, const char *password); -void -sha256_to_lwsgw_hash(unsigned char *hash, lwsgw_hash *shash); -unsigned int -lwsgs_now_secs(void); -int -lwsgw_check_admin(struct per_vhost_data__gs *vhd, - const char *username, const char *password); -int -lwsgs_hash_password(struct per_vhost_data__gs *vhd, - const char *password, struct lwsgs_user *u); -int -lwsgs_new_session_id(struct per_vhost_data__gs *vhd, - lwsgw_hash *sid, const char *username, int exp); -int -lwsgs_lookup_user(struct per_vhost_data__gs *vhd, - const char *username, struct lwsgs_user *u); -int -lwsgw_update_session(struct per_vhost_data__gs *vhd, - lwsgw_hash *hash, const char *user); -int -lwsgw_expire_old_sessions(struct per_vhost_data__gs *vhd); - - -/* handlers.c */ - -int -lwsgs_handler_confirm(struct per_vhost_data__gs *vhd, struct lws *wsi, - struct per_session_data__gs *pss); -int -lwsgs_handler_forgot(struct per_vhost_data__gs *vhd, struct lws *wsi, - struct per_session_data__gs *pss); -int -lwsgs_handler_check(struct per_vhost_data__gs *vhd, struct lws *wsi, - struct per_session_data__gs *pss, const char *in); -int -lwsgs_handler_change_password(struct per_vhost_data__gs *vhd, struct lws *wsi, - struct per_session_data__gs *pss); -int -lwsgs_handler_forgot_pw_form(struct per_vhost_data__gs *vhd, struct lws *wsi, - struct per_session_data__gs *pss); -int -lwsgs_handler_register_form(struct per_vhost_data__gs *vhd, struct lws *wsi, - struct per_session_data__gs *pss); - diff -Nru libwebsockets-4.0.20/plugins/generic-sessions/protocol_generic_sessions.c libwebsockets-4.1.6/plugins/generic-sessions/protocol_generic_sessions.c --- libwebsockets-4.0.20/plugins/generic-sessions/protocol_generic_sessions.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/generic-sessions/protocol_generic_sessions.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,920 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * 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-lwsgs.h" -#include - -/* keep changes in sync with the enum in lwsgs.h */ -static const char * const param_names[] = { - "username", - "password", - "password2", - "email", - "register", - "good", - "bad", - "reg-good", - "reg-bad", - "admin", - "forgot", - "forgot-good", - "forgot-bad", - "forgot-post-good", - "forgot-post-bad", - "change", - "curpw", - "delete" -}; - -struct lwsgs_fill_args { - char *buf; - int len; -}; - -static const struct lws_protocols protocols[]; - -struct lwsgs_subst_args -{ - struct per_session_data__gs *pss; - struct per_vhost_data__gs *vhd; - struct lws *wsi; -}; - -static const char * -lwsgs_subst(void *data, int index) -{ - struct lwsgs_subst_args *a = (struct lwsgs_subst_args *)data; - struct lwsgs_user u; - lwsgw_hash sid; - char esc[96], s[100]; - int n; - - a->pss->result[0] = '\0'; - u.email[0] = '\0'; - if (!lwsgs_get_sid_from_wsi(a->wsi, &sid)) { - if (lwsgs_lookup_session(a->vhd, &sid, a->pss->result, 31)) { - lwsl_notice("sid lookup for %s failed\n", sid.id); - a->pss->delete_session = sid; - return NULL; - } - lws_snprintf(s, sizeof(s) - 1, "select username,email " - "from users where username = '%s';", - lws_sql_purify(esc, a->pss->result, sizeof(esc) - 1)); - if (sqlite3_exec(a->vhd->pdb, s, lwsgs_lookup_callback_user, - &u, NULL) != SQLITE_OK) { - lwsl_err("Unable to lookup token: %s\n", - sqlite3_errmsg(a->vhd->pdb)); - a->pss->delete_session = sid; - return NULL; - } - } else - lwsl_notice("no sid\n"); - - lws_strncpy(a->pss->result + 32, u.email, 100); - - switch (index) { - case 0: - return a->pss->result; - - case 1: - n = lwsgs_get_auth_level(a->vhd, a->pss->result); - sprintf(a->pss->result, "%d", n); - return a->pss->result; - case 2: - return a->pss->result + 32; - } - - return NULL; -} - -static int -lws_get_effective_host(struct lws *wsi, char *buf, size_t buflen) -{ -#if defined(LWS_ROLE_H2) - /* h2 */ - if (lws_hdr_copy(wsi, buf, buflen - 1, - WSI_TOKEN_HTTP_COLON_AUTHORITY) > 0) - return 0; -#endif - /* h1 */ - if (lws_hdr_copy(wsi, buf, buflen - 1, WSI_TOKEN_HOST) > 0) - return 0; - - return 1; -} - -static int -callback_generic_sessions(struct lws *wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len) -{ - struct per_session_data__gs *pss = (struct per_session_data__gs *)user; - const struct lws_protocol_vhost_options *pvo; - struct per_vhost_data__gs *vhd = (struct per_vhost_data__gs *) - lws_protocol_vh_priv_get(lws_get_vhost(wsi), - lws_vhost_name_to_protocol(lws_get_vhost(wsi), - "protocol-generic-sessions")); - char cookie[1024], username[32], *pc = cookie; - unsigned char buffer[LWS_PRE + LWSGS_EMAIL_CONTENT_SIZE]; - struct lws_process_html_args *args = in; - struct lws_session_info *sinfo; - char s[LWSGS_EMAIL_CONTENT_SIZE]; - unsigned char *p, *start, *end; - const char *cp, *cp1; - sqlite3_stmt *sm; - lwsgw_hash sid; -#if defined(LWS_WITH_SMTP) - lws_abs_t abs; -#endif - int n; - - switch (reason) { - case LWS_CALLBACK_PROTOCOL_INIT: /* per vhost */ - - vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi), - lws_get_protocol(wsi), sizeof(struct per_vhost_data__gs)); - if (!vhd) - return 1; - vhd->context = lws_get_context(wsi); - - /* defaults */ - vhd->timeout_idle_secs = 600; - vhd->timeout_absolute_secs = 36000; - vhd->timeout_anon_absolute_secs = 1200; - vhd->timeout_email_secs = 24 * 3600; - - - strcpy(vhd->helo, "unconfigured.com"); - strcpy(vhd->ip, "127.0.0.1"); - strcpy(vhd->email_from, "noreply@unconfigured.com"); - strcpy(vhd->email_title, "Registration Email from unconfigured"); - vhd->urlroot[0] = '\0'; - - pvo = (const struct lws_protocol_vhost_options *)in; - while (pvo) { - if (!strcmp(pvo->name, "admin-user")) - lws_strncpy(vhd->admin_user, pvo->value, - sizeof(vhd->admin_user)); - if (!strcmp(pvo->name, "urlroot")) - lws_strncpy(vhd->urlroot, pvo->value, - sizeof(vhd->urlroot)); - if (!strcmp(pvo->name, "admin-password-sha256")) - lws_strncpy(vhd->admin_password_sha256.id, pvo->value, - sizeof(vhd->admin_password_sha256.id)); - if (!strcmp(pvo->name, "session-db")) - lws_strncpy(vhd->session_db, pvo->value, - sizeof(vhd->session_db)); - if (!strcmp(pvo->name, "confounder")) - lws_strncpy(vhd->confounder, pvo->value, - sizeof(vhd->confounder)); - if (!strcmp(pvo->name, "email-from")) - lws_strncpy(vhd->email_from, pvo->value, - sizeof(vhd->email_from)); - if (!strcmp(pvo->name, "email-helo")) - lws_strncpy(vhd->helo, pvo->value, sizeof(vhd->helo)); - if (!strcmp(pvo->name, "email-template")) - lws_strncpy(vhd->email_template, pvo->value, - sizeof(vhd->email_template)); - if (!strcmp(pvo->name, "email-title")) - lws_strncpy(vhd->email_title, pvo->value, - sizeof(vhd->email_title)); - if (!strcmp(pvo->name, "email-contact-person")) - lws_strncpy(vhd->email_contact_person, pvo->value, - sizeof(vhd->email_contact_person)); - if (!strcmp(pvo->name, "email-confirm-url-base")) - lws_strncpy(vhd->email_confirm_url, pvo->value, - sizeof(vhd->email_confirm_url)); - if (!strcmp(pvo->name, "email-server-ip")) - lws_strncpy(vhd->ip, pvo->value, sizeof(vhd->ip)); - - if (!strcmp(pvo->name, "timeout-idle-secs")) - vhd->timeout_idle_secs = atoi(pvo->value); - if (!strcmp(pvo->name, "timeout-absolute-secs")) - vhd->timeout_absolute_secs = atoi(pvo->value); - if (!strcmp(pvo->name, "timeout-anon-absolute-secs")) - vhd->timeout_anon_absolute_secs = atoi(pvo->value); - if (!strcmp(pvo->name, "email-expire")) - vhd->timeout_email_secs = atoi(pvo->value); - pvo = pvo->next; - } - if (!vhd->admin_user[0] || - !vhd->admin_password_sha256.id[0] || - !vhd->session_db[0]) { - lwsl_err("generic-sessions: " - "You must give \"admin-user\", " - "\"admin-password-sha256\", " - "and \"session_db\" per-vhost options\n"); - return 1; - } - - if (lws_struct_sq3_open(lws_get_context(wsi), - vhd->session_db, &vhd->pdb)) { - lwsl_err("Unable to open session db %s: %s\n", - vhd->session_db, sqlite3_errmsg(vhd->pdb)); - - return 1; - } - - if (sqlite3_prepare(vhd->pdb, - "create table if not exists sessions (" - " name char(65)," - " username varchar(32)," - " expire integer" - ");", - -1, &sm, NULL) != SQLITE_OK) { - lwsl_err("Unable to prepare session table init: %s\n", - sqlite3_errmsg(vhd->pdb)); - - return 1; - } - - if (sqlite3_step(sm) != SQLITE_DONE) { - lwsl_err("Unable to run session table init: %s\n", - sqlite3_errmsg(vhd->pdb)); - - return 1; - } - sqlite3_finalize(sm); - - if (sqlite3_exec(vhd->pdb, - "create table if not exists users (" - " username varchar(32)," - " creation_time integer," - " ip varchar(46)," - " email varchar(100)," - " pwhash varchar(65)," - " pwsalt varchar(65)," - " pwchange_time integer," - " token varchar(65)," - " verified integer," - " token_time integer," - " last_forgot_validated integer," - " primary key (username)" - ");", - NULL, NULL, NULL) != SQLITE_OK) { - lwsl_err("Unable to create user table: %s\n", - sqlite3_errmsg(vhd->pdb)); - - return 1; - } - -#if defined(LWS_WITH_SMTP) - - memset(&abs, 0, sizeof(abs)); - abs.vh = lws_get_vhost(wsi); - - /* select the protocol and bind its tokens */ - - abs.ap = lws_abs_protocol_get_by_name("smtp"); - if (!abs.ap) - return 1; - - vhd->protocol_tokens[0].name_index = LTMI_PSMTP_V_HELO; - vhd->protocol_tokens[0].u.value = vhd->helo; - - abs.ap_tokens = vhd->protocol_tokens; - - /* select the transport and bind its tokens */ - - abs.at = lws_abs_transport_get_by_name("raw_skt"); - if (!abs.at) - return 1; - - vhd->transport_tokens[0].name_index = LTMI_PEER_V_DNS_ADDRESS; - vhd->transport_tokens[0].u.value = vhd->ip; - vhd->transport_tokens[1].name_index = LTMI_PEER_LV_PORT; - vhd->transport_tokens[1].u.lvalue = 25; - - abs.at_tokens = vhd->transport_tokens; - - vhd->smtp_client = lws_abs_bind_and_create_instance(&abs); - if (!vhd->smtp_client) - return 1; - - lwsl_notice("%s: created SMTP client\n", __func__); -#endif - break; - - case LWS_CALLBACK_PROTOCOL_DESTROY: - // lwsl_notice("gs: LWS_CALLBACK_PROTOCOL_DESTROY: v=%p, ctx=%p\n", vhd, vhd->context); - if (vhd->pdb) { - sqlite3_close(vhd->pdb); - vhd->pdb = NULL; - } -#if defined(LWS_WITH_SMTP) - if (vhd->smtp_client) - lws_abs_destroy_instance(&vhd->smtp_client); -#endif - break; - - case LWS_CALLBACK_HTTP_WRITEABLE: - if (!pss->check_response) - break; - pss->check_response = 0; - n = lws_write(wsi, (unsigned char *)&pss->check_response_value, - 1, LWS_WRITE_HTTP | LWS_WRITE_H2_STREAM_END); - if (n != 1) - return -1; - goto try_to_reuse; - - case LWS_CALLBACK_HTTP: - if (!pss) { - lwsl_err("%s: no valid pss\n", __func__); - return 1; - } - - pss->login_session.id[0] = '\0'; - pss->phs.pos = 0; - - cp = in; - if ((*(const char *)in == '/')) - cp++; - - if (lws_get_effective_host(wsi, cookie, sizeof(cookie))) { - lwsl_err("%s: HTTP: no effective host\n", __func__); - return 1; - } - - lwsl_notice("LWS_CALLBACK_HTTP: %s, HOST '%s'\n", - (const char *)in, cookie); - - n = strlen(cp); - - lws_snprintf(pss->onward, sizeof(pss->onward), - "%s%s", vhd->urlroot, (const char *)in); - - if (n >= 12 && - !strcmp(cp + n - 12, "lwsgs-forgot")) { - lwsgs_handler_forgot(vhd, wsi, pss); - goto redirect_with_cookie; - } - - if (n >= 13 && - !strcmp(cp + n - 13, "lwsgs-confirm")) { - lwsgs_handler_confirm(vhd, wsi, pss); - goto redirect_with_cookie; - } - cp1 = strstr(cp, "lwsgs-check/"); - if (cp1) { - lwsgs_handler_check(vhd, wsi, pss, cp1 + 12); - /* second, async part will complete transaction */ - break; - } - - if (n >= 11 && cp && !strcmp(cp + n - 11, "lwsgs-login")) - break; - if (n >= 12 && cp && !strcmp(cp + n - 12, "lwsgs-logout")) - break; - if (n >= 12 && cp && !strcmp(cp + n - 12, "lwsgs-forgot")) - break; - if (n >= 12 && cp && !strcmp(cp + n - 12, "lwsgs-change")) - break; - - /* if no legitimate url for GET, return 404 */ - - lwsl_err("%s: http doing 404 on %s\n", __func__, cp ? cp : "null"); - lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL); - - return -1; - //goto try_to_reuse; - - case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION: - args = (struct lws_process_html_args *)in; - if (!args->chunked) - break; - case LWS_CALLBACK_CHECK_ACCESS_RIGHTS: - n = 0; - username[0] = '\0'; - sid.id[0] = '\0'; - args = (struct lws_process_html_args *)in; - lwsl_notice("%s: LWS_CALLBACK_CHECK_ACCESS_RIGHTS: need 0x%x\n", - __func__, args->max_len); - if (!lwsgs_get_sid_from_wsi(wsi, &sid)) { - if (lwsgs_lookup_session(vhd, &sid, username, - sizeof(username))) { - - /* - * if we're authenticating for ws, we don't - * want to redirect it or gain a cookie on that, - * he'll need to get the cookie from http - * interactions outside of this. - */ - if (args->chunked) { - lwsl_notice("%s: ws auth failed\n", - __func__); - - return 1; - } - - lwsl_notice("session lookup for %s failed, " - "probably expired\n", sid.id); - pss->delete_session = sid; - args->final = 1; /* signal we dealt with it */ - lws_snprintf(pss->onward, sizeof(pss->onward) - 1, - "%s%s", vhd->urlroot, args->p); - lwsl_notice("redirecting to ourselves with " - "cookie refresh\n"); - /* we need a redirect to ourselves, - * session cookie is expired */ - goto redirect_with_cookie; - } - } else - lwsl_notice("%s: failed to get sid from wsi\n", __func__); - - n = lwsgs_get_auth_level(vhd, username); - lwsl_notice("%s: lwsgs_get_auth_level '%s' says %d\n", __func__, username, n); - - if ((args->max_len & n) != args->max_len) { - lwsl_notice("Access rights fail 0x%X vs 0x%X (cookie %s)\n", - args->max_len, n, sid.id); - return 1; - } - lwsl_debug("Access rights OK\n"); - break; - - case LWS_CALLBACK_SESSION_INFO: - { - struct lwsgs_user u; - sinfo = (struct lws_session_info *)in; - sinfo->username[0] = '\0'; - sinfo->email[0] = '\0'; - sinfo->ip[0] = '\0'; - sinfo->session[0] = '\0'; - sinfo->mask = 0; - - sid.id[0] = '\0'; - lwsl_debug("LWS_CALLBACK_SESSION_INFO\n"); - if (lwsgs_get_sid_from_wsi(wsi, &sid)) - break; - if (lwsgs_lookup_session(vhd, &sid, username, sizeof(username))) - break; - - lws_snprintf(s, sizeof(s) - 1, - "select username, email from users where username='%s';", - username); - if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &u, NULL) != - SQLITE_OK) { - lwsl_err("Unable to lookup token: %s\n", - sqlite3_errmsg(vhd->pdb)); - break; - } - lws_strncpy(sinfo->username, u.username, sizeof(sinfo->username)); - lws_strncpy(sinfo->email, u.email, sizeof(sinfo->email)); - lws_strncpy(sinfo->session, sid.id, sizeof(sinfo->session)); - sinfo->mask = lwsgs_get_auth_level(vhd, username); - lws_get_peer_simple(wsi, sinfo->ip, sizeof(sinfo->ip)); - } - - break; - - case LWS_CALLBACK_PROCESS_HTML: - - args = (struct lws_process_html_args *)in; - { - static const char * const vars[] = { - "$lwsgs_user", - "$lwsgs_auth", - "$lwsgs_email" - }; - struct lwsgs_subst_args a; - - a.vhd = vhd; - a.pss = pss; - a.wsi = wsi; - - pss->phs.vars = vars; - pss->phs.count_vars = LWS_ARRAY_SIZE(vars); - pss->phs.replace = lwsgs_subst; - pss->phs.data = &a; - - if (lws_chunked_html_process(args, &pss->phs)) - return -1; - } - break; - - case LWS_CALLBACK_HTTP_BODY: - if (len < 2) { - lwsl_err("%s: HTTP_BODY: len %d < 2\n", __func__, (int)len); - break; - } - - if (!pss->spa) { - pss->spa = lws_spa_create(wsi, param_names, - LWS_ARRAY_SIZE(param_names), 1024, - NULL, NULL); - if (!pss->spa) - return -1; - } - - if (lws_spa_process(pss->spa, in, len)) { - lwsl_notice("spa process blew\n"); - return -1; - } - break; - - case LWS_CALLBACK_HTTP_BODY_COMPLETION: - - lwsl_debug("%s: LWS_CALLBACK_HTTP_BODY_COMPLETION\n", __func__); - - if (!pss->spa) - break; - - cp1 = (const char *)pss->onward; - if (*cp1 == '/') - cp1++; - - - lws_spa_finalize(pss->spa); - n = strlen(cp1); - - if (lws_get_effective_host(wsi, cookie, sizeof(cookie))) - return 1; - - if (!strcmp(cp1 + n - 12, "lwsgs-change")) { - if (!lwsgs_handler_change_password(vhd, wsi, pss)) { - cp = lws_spa_get_string(pss->spa, FGS_GOOD); - goto pass; - } - - cp = lws_spa_get_string(pss->spa, FGS_BAD); - lwsl_notice("user/password no good %s\n", - lws_spa_get_string(pss->spa, FGS_USERNAME)); - lws_snprintf(pss->onward, sizeof(pss->onward), - "%s%s", vhd->urlroot, cp); - - pss->onward[sizeof(pss->onward) - 1] = '\0'; - goto completion_flow; - } - - if (!strcmp(cp1 + n - 11, "lwsgs-login")) { - lwsl_err("%s: lwsgs-login\n", __func__); - if (lws_spa_get_string(pss->spa, FGS_FORGOT) && - lws_spa_get_string(pss->spa, FGS_FORGOT)[0]) { - if (lwsgs_handler_forgot_pw_form(vhd, wsi, pss)) { - n = FGS_FORGOT_BAD; - goto reg_done; - } -#if defined(LWS_WITH_SMTP) - /* get the email monitor to take a look */ - lws_smtpc_kick(vhd->smtp_client); -#endif - n = FGS_FORGOT_GOOD; - goto reg_done; - } - - if (!lws_spa_get_string(pss->spa, FGS_USERNAME) || - !lws_spa_get_string(pss->spa, FGS_PASSWORD)) { - lwsl_notice("username '%s' or pw '%s' missing\n", - lws_spa_get_string(pss->spa, FGS_USERNAME), - lws_spa_get_string(pss->spa, FGS_PASSWORD)); - return -1; - } - - if (lws_spa_get_string(pss->spa, FGS_REGISTER) && - lws_spa_get_string(pss->spa, FGS_REGISTER)[0]) { - - if (lwsgs_handler_register_form(vhd, wsi, pss)) - n = FGS_REG_BAD; - else { - n = FGS_REG_GOOD; -#if defined(LWS_WITH_SMTP) - /* get the email monitor to take a look */ - lws_smtpc_kick(vhd->smtp_client); -#endif - } -reg_done: - lws_snprintf(pss->onward, sizeof(pss->onward), - "%s%s", vhd->urlroot, - lws_spa_get_string(pss->spa, n)); - - pss->login_expires = 0; - pss->logging_out = 1; - goto completion_flow; - } - - /* we have the username and password... check if admin */ - if (lwsgw_check_admin(vhd, lws_spa_get_string(pss->spa, FGS_USERNAME), - lws_spa_get_string(pss->spa, FGS_PASSWORD))) { - if (lws_spa_get_string(pss->spa, FGS_ADMIN)) - cp = lws_spa_get_string(pss->spa, FGS_ADMIN); - else - if (lws_spa_get_string(pss->spa, FGS_GOOD)) - cp = lws_spa_get_string(pss->spa, FGS_GOOD); - else { - lwsl_info("No admin or good target url in form\n"); - return -1; - } - lwsl_debug("admin\n"); - goto pass; - } - - /* check users in database */ - - if (!lwsgs_check_credentials(vhd, - lws_spa_get_string(pss->spa, FGS_USERNAME), - lws_spa_get_string(pss->spa, FGS_PASSWORD))) { - lwsl_notice("pw hash check met\n"); - cp = lws_spa_get_string(pss->spa, FGS_GOOD); - goto pass; - } else - lwsl_notice("user/password no good %s %s\n", - lws_spa_get_string(pss->spa, FGS_USERNAME), - lws_spa_get_string(pss->spa, FGS_PASSWORD)); - - if (!lws_spa_get_string(pss->spa, FGS_BAD)) { - lwsl_info("No admin or good target url in form\n"); - return -1; - } - - lws_snprintf(pss->onward, sizeof(pss->onward), - "%s%s", vhd->urlroot, - lws_spa_get_string(pss->spa, FGS_BAD)); - - lwsl_notice("failed: %s\n", pss->onward); - - goto completion_flow; - } - - if (!strcmp(cp1 + n - 12, "lwsgs-logout")) { - - lwsl_notice("/logout\n"); - - if (lwsgs_get_sid_from_wsi(wsi, &pss->login_session)) { - lwsl_notice("not logged in...\n"); - return 1; - } - - /* - * We keep the same session, but mark it as not - * being associated to any authenticated user - */ - - lwsgw_update_session(vhd, &pss->login_session, ""); - - if (!lws_spa_get_string(pss->spa, FGS_GOOD)) { - lwsl_info("No admin or good target url in form\n"); - return -1; - } - - lws_snprintf(pss->onward, sizeof(pss->onward), - "%s%s", vhd->urlroot, - lws_spa_get_string(pss->spa, FGS_GOOD)); - - pss->login_expires = 0; - pss->logging_out = 1; - - goto completion_flow; - } - - break; - -pass: - lws_snprintf(pss->onward, sizeof(pss->onward), - "%s%s", vhd->urlroot, cp); - - if (lwsgs_get_sid_from_wsi(wsi, &sid)) - sid.id[0] = '\0'; - - pss->login_expires = lws_now_secs() + - vhd->timeout_absolute_secs; - - if (!sid.id[0]) { - /* we need to create a new, authorized session */ - - if (lwsgs_new_session_id(vhd, &pss->login_session, - lws_spa_get_string(pss->spa, FGS_USERNAME), - pss->login_expires)) - goto try_to_reuse; - - lwsl_notice("%s: Creating new session: %s\n", __func__, - pss->login_session.id); - } else { - /* - * we can just update the existing session to be - * authorized - */ - lwsl_notice("%s: Authorizing existing session %s, name %s\n", - __func__, sid.id, - lws_spa_get_string(pss->spa, FGS_USERNAME)); - lwsgw_update_session(vhd, &sid, - lws_spa_get_string(pss->spa, FGS_USERNAME)); - pss->login_session = sid; - } - -completion_flow: - lwsgw_expire_old_sessions(vhd); - goto redirect_with_cookie; - - case LWS_CALLBACK_HTTP_DROP_PROTOCOL: - if (pss && pss->spa) { - lws_spa_destroy(pss->spa); - pss->spa = NULL; - } - break; - - case LWS_CALLBACK_ADD_HEADERS: - lwsgw_expire_old_sessions(vhd); - - lwsl_warn("ADD_HEADERS\n"); - - args = (struct lws_process_html_args *)in; - if (!pss) - return 1; - if (pss->delete_session.id[0]) { - pc = cookie; - lwsgw_cookie_from_session(&pss->delete_session, 0, &pc, - cookie + sizeof(cookie) - 1); - - lwsl_notice("deleting cookie '%s'\n", cookie); - - if (lws_add_http_header_by_name(wsi, - (unsigned char *)"set-cookie:", - (unsigned char *)cookie, pc - cookie, - (unsigned char **)&args->p, - (unsigned char *)args->p + args->max_len)) - return 1; - } - - if (!pss->login_session.id[0]) - lwsgs_get_sid_from_wsi(wsi, &pss->login_session); - - if (!pss->login_session.id[0] && !pss->logging_out) { - - pss->login_expires = lws_now_secs() + - vhd->timeout_anon_absolute_secs; - if (lwsgs_new_session_id(vhd, &pss->login_session, "", - pss->login_expires)) - goto try_to_reuse; - pc = cookie; - lwsgw_cookie_from_session(&pss->login_session, - pss->login_expires, &pc, - cookie + sizeof(cookie) - 1); - - lwsl_info("LWS_CALLBACK_ADD_HEADERS: setting cookie '%s'\n", cookie); - if (lws_add_http_header_by_name(wsi, - (unsigned char *)"set-cookie:", - (unsigned char *)cookie, pc - cookie, - (unsigned char **)&args->p, - (unsigned char *)args->p + args->max_len)) - return 1; - } - break; - - default: - break; - } - - return 0; - -redirect_with_cookie: - p = buffer + LWS_PRE; - start = p; - end = p + sizeof(buffer) - LWS_PRE; - - lwsl_warn("%s: redirect_with_cookie\n", __func__); - - if (lws_add_http_header_status(wsi, HTTP_STATUS_SEE_OTHER, &p, end)) - return 1; - - { - char loc[1024], uria[128]; - - uria[0] = '\0'; - lws_hdr_copy_fragment(wsi, uria, sizeof(uria), - WSI_TOKEN_HTTP_URI_ARGS, 0); - n = lws_snprintf(loc, sizeof(loc), "%s?%s", - pss->onward, uria); - lwsl_notice("%s: redirect to '%s'\n", __func__, loc); - if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_LOCATION, - (unsigned char *)loc, n, &p, end)) - return 1; - } - - if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE, - (unsigned char *)"text/html", 9, &p, end)) - return 1; - if (lws_add_http_header_content_length(wsi, 0, &p, end)) - return 1; - - if (pss->delete_session.id[0]) { - lwsgw_cookie_from_session(&pss->delete_session, 0, &pc, - cookie + sizeof(cookie) - 1); - - lwsl_notice("deleting cookie '%s'\n", cookie); - - if (lws_add_http_header_by_name(wsi, - (unsigned char *)"set-cookie:", - (unsigned char *)cookie, pc - cookie, - &p, end)) { - lwsl_err("fail0\n"); - return 1; - } - } - - if (!pss->login_session.id[0]) { - pss->login_expires = lws_now_secs() + - vhd->timeout_anon_absolute_secs; - if (lwsgs_new_session_id(vhd, &pss->login_session, "", - pss->login_expires)) { - lwsl_err("fail1\n"); - return 1; - } - } else - pss->login_expires = lws_now_secs() + - vhd->timeout_absolute_secs; - - if (pss->login_session.id[0] || pss->logging_out) { - /* - * we succeeded to login, we must issue a login - * cookie with the prepared data - */ - pc = cookie; - - lwsgw_cookie_from_session(&pss->login_session, - pss->login_expires, &pc, - cookie + sizeof(cookie) - 1); - - lwsl_err("%s: setting cookie '%s'\n", __func__, cookie); - - pss->logging_out = 0; - - if (lws_add_http_header_by_name(wsi, - (unsigned char *)"set-cookie:", - (unsigned char *)cookie, pc - cookie, - &p, end)) { - lwsl_err("fail2\n"); - return 1; - } - } - - if (lws_finalize_http_header(wsi, &p, end)) - return 1; - - // lwsl_hexdump_notice(start, p - start); - - n = lws_write(wsi, start, p - start, LWS_WRITE_H2_STREAM_END | - LWS_WRITE_HTTP_HEADERS); - if (n < 0) - return 1; - - /* fallthru */ - -try_to_reuse: - if (lws_http_transaction_completed(wsi)) - return -1; - - return 0; -} - -static const struct lws_protocols protocols[] = { - { - "protocol-generic-sessions", - callback_generic_sessions, - sizeof(struct per_session_data__gs), - 1024, - }, -}; - -LWS_VISIBLE int -init_protocol_generic_sessions(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } - - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} - -LWS_VISIBLE int -destroy_protocol_generic_sessions(struct lws_context *context) -{ - return 0; -} diff -Nru libwebsockets-4.0.20/plugins/generic-sessions/protocol_lws_messageboard.c libwebsockets-4.1.6/plugins/generic-sessions/protocol_lws_messageboard.c --- libwebsockets-4.0.20/plugins/generic-sessions/protocol_lws_messageboard.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/generic-sessions/protocol_lws_messageboard.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,438 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * 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. - */ - - -#define LWS_DLL -#define LWS_INTERNAL -#include - -#include -#include -#include - -struct per_vhost_data__gs_mb { - struct lws_vhost *vh; - const struct lws_protocols *gsp; - sqlite3 *pdb; - char message_db[256]; - unsigned long last_idx; -}; - -struct per_session_data__gs_mb { - void *pss_gs; /* for use by generic-sessions */ - struct lws_session_info sinfo; - struct lws_spa *spa; - unsigned long last_idx; - unsigned int our_form:1; - char second_http_part; -}; - -static const char * const param_names[] = { - "send", - "msg", -}; -enum { - MBSPA_SUBMIT, - MBSPA_MSG, -}; - -#define MAX_MSG_LEN 512 - -struct message { - unsigned long idx; - unsigned long time; - char username[32]; - char email[100]; - char ip[72]; - char content[MAX_MSG_LEN]; -}; - -static int -lookup_cb(void *priv, int cols, char **col_val, char **col_name) -{ - struct message *m = (struct message *)priv; - int n; - - for (n = 0; n < cols; n++) { - - if (!strcmp(col_name[n], "idx") || - !strcmp(col_name[n], "MAX(idx)")) { - if (!col_val[n]) - m->idx = 0; - else - m->idx = atol(col_val[n]); - continue; - } - if (!strcmp(col_name[n], "time")) { - m->time = atol(col_val[n]); - continue; - } - if (!strcmp(col_name[n], "username")) { - lws_strncpy(m->username, col_val[n], sizeof(m->username)); - continue; - } - if (!strcmp(col_name[n], "email")) { - lws_strncpy(m->email, col_val[n], sizeof(m->email)); - continue; - } - if (!strcmp(col_name[n], "ip")) { - lws_strncpy(m->ip, col_val[n], sizeof(m->ip)); - continue; - } - if (!strcmp(col_name[n], "content")) { - lws_strncpy(m->content, col_val[n], sizeof(m->content)); - continue; - } - } - return 0; -} - -static unsigned long -get_last_idx(struct per_vhost_data__gs_mb *vhd) -{ - struct message m; - - if (sqlite3_exec(vhd->pdb, "SELECT MAX(idx) FROM msg;", - lookup_cb, &m, NULL) != SQLITE_OK) { - lwsl_err("Unable to lookup token: %s\n", - sqlite3_errmsg(vhd->pdb)); - return 0; - } - - return m.idx; -} - -static int -post_message(struct lws *wsi, struct per_vhost_data__gs_mb *vhd, - struct per_session_data__gs_mb *pss) -{ - struct lws_session_info sinfo; - char s[MAX_MSG_LEN + 512]; - char esc[MAX_MSG_LEN + 256]; - - vhd->gsp->callback(wsi, LWS_CALLBACK_SESSION_INFO, - pss->pss_gs, &sinfo, 0); - - lws_snprintf((char *)s, sizeof(s) - 1, - "insert into msg(time, username, email, ip, content)" - " values (%lu, '%s', '%s', '%s', '%s');", - (unsigned long)lws_now_secs(), sinfo.username, sinfo.email, sinfo.ip, - lws_sql_purify(esc, lws_spa_get_string(pss->spa, MBSPA_MSG), - sizeof(esc) - 1)); - if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != SQLITE_OK) { - lwsl_err("Unable to insert msg: %s\n", sqlite3_errmsg(vhd->pdb)); - return 1; - } - vhd->last_idx = get_last_idx(vhd); - - /* let everybody connected by this protocol on this vhost know */ - lws_callback_on_writable_all_protocol_vhost(lws_get_vhost(wsi), - lws_get_protocol(wsi)); - - return 0; -} - -static int -callback_messageboard(struct lws *wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len) -{ - struct per_session_data__gs_mb *pss = (struct per_session_data__gs_mb *)user; - const struct lws_protocol_vhost_options *pvo; - struct per_vhost_data__gs_mb *vhd = (struct per_vhost_data__gs_mb *) - lws_protocol_vh_priv_get(lws_get_vhost(wsi), lws_get_protocol(wsi)); - unsigned char *p, *start, *end, buffer[LWS_PRE + 4096]; - char s[512]; - int n; - - switch (reason) { - case LWS_CALLBACK_PROTOCOL_INIT: /* per vhost */ - - vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi), - lws_get_protocol(wsi), sizeof(struct per_vhost_data__gs_mb)); - if (!vhd) - return 1; - vhd->vh = lws_get_vhost(wsi); - vhd->gsp = lws_vhost_name_to_protocol(vhd->vh, - "protocol-generic-sessions"); - if (!vhd->gsp) { - lwsl_err("messageboard: requires generic-sessions\n"); - return 1; - } - - pvo = (const struct lws_protocol_vhost_options *)in; - while (pvo) { - if (!strcmp(pvo->name, "message-db")) - strncpy(vhd->message_db, pvo->value, - sizeof(vhd->message_db) - 1); - pvo = pvo->next; - } - if (!vhd->message_db[0]) { - lwsl_err("messageboard: \"message-db\" pvo missing\n"); - return 1; - } - - if (lws_struct_sq3_open(lws_get_context(wsi), - vhd->message_db, &vhd->pdb)) { - lwsl_err("Unable to open message db %s: %s\n", - vhd->message_db, sqlite3_errmsg(vhd->pdb)); - - return 1; - } - if (sqlite3_exec(vhd->pdb, "create table if not exists msg (" - " idx integer primary key, time integer," - " username varchar(32), email varchar(100)," - " ip varchar(80), content blob);", - NULL, NULL, NULL) != SQLITE_OK) { - lwsl_err("Unable to create msg table: %s\n", - sqlite3_errmsg(vhd->pdb)); - - return 1; - } - - vhd->last_idx = get_last_idx(vhd); - break; - - case LWS_CALLBACK_PROTOCOL_DESTROY: - if (vhd && vhd->pdb) - sqlite3_close(vhd->pdb); - goto passthru; - - case LWS_CALLBACK_ESTABLISHED: - vhd->gsp->callback(wsi, LWS_CALLBACK_SESSION_INFO, - pss->pss_gs, &pss->sinfo, 0); - if (!pss->sinfo.username[0]) { - lwsl_notice("messageboard ws attempt with no session\n"); - - return -1; - } - - lws_callback_on_writable(wsi); - break; - - case LWS_CALLBACK_CLOSED: - lwsl_debug("%s: LWS_CALLBACK_CLOSED\n", __func__); - if (pss && pss->pss_gs) { - free(pss->pss_gs); - pss->pss_gs = NULL; - } - break; - - case LWS_CALLBACK_SERVER_WRITEABLE: - { - struct message m; - char j[MAX_MSG_LEN + 512], e[MAX_MSG_LEN + 512], - *p = j + LWS_PRE, *start = p, - *end = j + sizeof(j) - LWS_PRE; - - if (pss->last_idx == vhd->last_idx) - break; - - /* restrict to last 10 */ - if (!pss->last_idx) - if (vhd->last_idx >= 10) - pss->last_idx = vhd->last_idx - 10; - - sprintf(s, "select idx, time, username, email, ip, content " - "from msg where idx > %lu order by idx limit 1;", - pss->last_idx); - if (sqlite3_exec(vhd->pdb, s, lookup_cb, &m, NULL) != SQLITE_OK) { - lwsl_err("Unable to lookup msg: %s\n", - sqlite3_errmsg(vhd->pdb)); - return 0; - } - - /* format in JSON */ - p += lws_snprintf(p, end - p, - "{\"idx\":\"%lu\",\"time\":\"%lu\",", - m.idx, m.time); - p += lws_snprintf(p, end - p, " \"username\":\"%s\",", - lws_json_purify(e, m.username, sizeof(e), NULL)); - p += lws_snprintf(p, end - p, " \"email\":\"%s\",", - lws_json_purify(e, m.email, sizeof(e), NULL)); - p += lws_snprintf(p, end - p, " \"ip\":\"%s\",", - lws_json_purify(e, m.ip, sizeof(e), NULL)); - p += lws_snprintf(p, end - p, " \"content\":\"%s\"}", - lws_json_purify(e, m.content, sizeof(e), NULL)); - - if (lws_write(wsi, (unsigned char *)start, p - start, - LWS_WRITE_TEXT) < 0) - return -1; - - pss->last_idx = m.idx; - if (pss->last_idx == vhd->last_idx) - break; - - lws_callback_on_writable(wsi); /* more to do */ - } - break; - - case LWS_CALLBACK_HTTP: - pss->our_form = 0; - - /* ie, it's our messageboard new message form */ - if (!strcmp((const char *)in, "/msg") || - !strcmp((const char *)in, "msg")) { - pss->our_form = 1; - break; - } - - goto passthru; - - case LWS_CALLBACK_HTTP_BODY: - if (!pss->our_form) - goto passthru; - - if (len < 2) - break; - if (!pss->spa) { - pss->spa = lws_spa_create(wsi, param_names, - LWS_ARRAY_SIZE(param_names), - MAX_MSG_LEN + 1024, NULL, NULL); - if (!pss->spa) - return -1; - } - - if (lws_spa_process(pss->spa, in, len)) { - lwsl_notice("spa process blew\n"); - return -1; - } - break; - - case LWS_CALLBACK_HTTP_WRITEABLE: - if (!pss->second_http_part) - goto passthru; - - s[0] = '0'; - n = lws_write(wsi, (unsigned char *)s, 1, LWS_WRITE_HTTP| - LWS_WRITE_H2_STREAM_END); - if (n != 1) - return -1; - - goto try_to_reuse; - - case LWS_CALLBACK_HTTP_BODY_COMPLETION: - if (!pss->our_form) - goto passthru; - - if (post_message(wsi, vhd, pss)) - return -1; - - p = buffer + LWS_PRE; - start = p; - end = p + sizeof(buffer) - LWS_PRE; - - if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end)) - return -1; - if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE, - (unsigned char *)"text/plain", 10, &p, end)) - return -1; - if (lws_add_http_header_content_length(wsi, 1, &p, end)) - return -1; - if (lws_finalize_http_header(wsi, &p, end)) - return -1; - - n = lws_write(wsi, start, p - start, LWS_WRITE_HTTP_HEADERS); - if (n != (p - start)) { - lwsl_err("_write returned %d from %ld\n", n, (long)(p - start)); - return -1; - } - pss->second_http_part = 1; - lws_callback_on_writable(wsi); - break; - - case LWS_CALLBACK_HTTP_BIND_PROTOCOL: - if (!pss || !vhd || pss->pss_gs) - break; - - pss->pss_gs = malloc(vhd->gsp->per_session_data_size); - if (!pss->pss_gs) - return -1; - - memset(pss->pss_gs, 0, vhd->gsp->per_session_data_size); - break; - - case LWS_CALLBACK_HTTP_DROP_PROTOCOL: - if (vhd->gsp->callback(wsi, reason, pss ? pss->pss_gs : NULL, in, len)) - return -1; - - if (pss && pss->spa) { - lws_spa_destroy(pss->spa); - pss->spa = NULL; - } - if (pss && pss->pss_gs) { - free(pss->pss_gs); - pss->pss_gs = NULL; - } - break; - - default: -passthru: - if (!pss || !vhd) - break; - - return vhd->gsp->callback(wsi, reason, pss->pss_gs, in, len); - } - - return 0; - - -try_to_reuse: - if (lws_http_transaction_completed(wsi)) - return -1; - - return 0; -} - -static const struct lws_protocols protocols[] = { - { - "protocol-lws-messageboard", - callback_messageboard, - sizeof(struct per_session_data__gs_mb), - 4096, - }, -}; - -LWS_VISIBLE int -init_protocol_lws_messageboard(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } - - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} - -LWS_VISIBLE int -destroy_protocol_lws_messageboard(struct lws_context *context) -{ - return 0; -} diff -Nru libwebsockets-4.0.20/plugins/generic-sessions/utils.c libwebsockets-4.1.6/plugins/generic-sessions/utils.c --- libwebsockets-4.0.20/plugins/generic-sessions/utils.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/generic-sessions/utils.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,465 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * 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-lwsgs.h" -#include - -void -sha256_to_lwsgw_hash(unsigned char *hash, lwsgw_hash *shash) -{ - static const char *hex = "0123456789abcdef"; - char *p = shash->id; - int n; - - for (n = 0; n < (int)lws_genhash_size(LWS_GENHASH_TYPE_SHA256); n++) { - *p++ = hex[(hash[n] >> 4) & 0xf]; - *p++ = hex[hash[n] & 15]; - } - - *p = '\0'; -} - -int -lwsgw_check_admin(struct per_vhost_data__gs *vhd, - const char *username, const char *password) -{ - lwsgw_hash_bin hash_bin; - lwsgw_hash pw_hash; - - if (strcmp(vhd->admin_user, username)) - return 0; - - lws_SHA1((unsigned char *)password, strlen(password), hash_bin.bin); - sha256_to_lwsgw_hash(hash_bin.bin, &pw_hash); - - return !strcmp(vhd->admin_password_sha256.id, pw_hash.id); -} - -/* - * secure cookie: it can only be passed over https where it cannot be - * snooped in transit - * HttpOnly: it can only be accessed via http[s] transport, it cannot be - * gotten at by JS - */ -void -lwsgw_cookie_from_session(lwsgw_hash *sid, time_t expires, char **p, char *end) -{ - struct tm *tm = gmtime(&expires); - time_t n = lws_now_secs(); - - *p += lws_snprintf(*p, end - *p, "id=%s;Expires=", sid->id); -#ifdef WIN32 - *p += strftime(*p, end - *p, "%Y %H:%M %Z", tm); -#else - *p += strftime(*p, end - *p, "%F %H:%M %Z", tm); -#endif - *p += lws_snprintf(*p, end - *p, ";path=/"); - *p += lws_snprintf(*p, end - *p, ";Max-Age=%lu", (unsigned long)(expires - n)); -// *p += lws_snprintf(*p, end - *p, ";secure"); - *p += lws_snprintf(*p, end - *p, ";HttpOnly"); -} - -int -lwsgw_expire_old_sessions(struct per_vhost_data__gs *vhd) -{ - time_t n = lws_now_secs(); - char s[200]; - - if (n - vhd->last_session_expire < 5) - return 0; - - vhd->last_session_expire = n; - - lws_snprintf(s, sizeof(s) - 1, - "delete from sessions where " - "expire <= %lu;", (unsigned long)n); - - if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != SQLITE_OK) { - lwsl_err("Unable to expire sessions: %s\n", - sqlite3_errmsg(vhd->pdb)); - return 1; - } - - return 0; -} - -int -lwsgw_update_session(struct per_vhost_data__gs *vhd, - lwsgw_hash *hash, const char *user) -{ - time_t n = lws_now_secs(); - char s[200], esc[96], esc1[96]; - - if (user[0]) - n += vhd->timeout_absolute_secs; - else - n += vhd->timeout_anon_absolute_secs; - - lws_snprintf(s, sizeof(s) - 1, - "update sessions set expire=%lu,username='%s' where name='%s';", - (unsigned long)n, - lws_sql_purify(esc, user, sizeof(esc)), - lws_sql_purify(esc1, hash->id, sizeof(esc1))); - - if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != SQLITE_OK) { - lwsl_err("Unable to update session: %s\n", - sqlite3_errmsg(vhd->pdb)); - return 1; - } - - puts(s); - - return 0; -} - -static int -lwsgw_session_from_cookie(const char *cookie, lwsgw_hash *sid) -{ - const char *p = cookie; - int n; - - while (*p) { - if (p[0] == 'i' && p[1] == 'd' && p[2] == '=') { - p += 3; - break; - } - p++; - } - if (!*p) { - lwsl_info("no id= in cookie\n"); - return 1; - } - - for (n = 0; n < (int)sizeof(sid->id) - 1 && *p; n++) { - /* our SID we issue only has these chars */ - if ((*p >= '0' && *p <= '9') || - (*p >= 'a' && *p <= 'f')) - sid->id[n] = *p++; - else { - lwsl_info("bad chars in cookie id %c\n", *p); - return 1; - } - } - - if (n < (int)sizeof(sid->id) - 1) { - lwsl_info("cookie id too short\n"); - return 1; - } - - sid->id[sizeof(sid->id) - 1] = '\0'; - - return 0; -} - -int -lwsgs_get_sid_from_wsi(struct lws *wsi, lwsgw_hash *sid) -{ - char cookie[1024]; - - /* fail it on no cookie */ - if (!lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COOKIE)) { - lwsl_info("%s: no cookie\n", __func__); - return 1; - } - if (lws_hdr_copy(wsi, cookie, sizeof cookie, WSI_TOKEN_HTTP_COOKIE) < 0) { - lwsl_info("cookie copy failed\n"); - return 1; - } - /* extract the sid from the cookie */ - if (lwsgw_session_from_cookie(cookie, sid)) { - lwsl_info("%s: session from cookie failed\n", __func__); - return 1; - } - - return 0; -} - -struct lla { - char *username; - int len; - int results; -}; - -static int -lwsgs_lookup_callback(void *priv, int cols, char **col_val, char **col_name) -{ - struct lla *lla = (struct lla *)priv; - - //lwsl_err("%s: %d\n", __func__, cols); - - if (cols) - lla->results = 0; - if (col_val && col_val[0]) { - lws_strncpy(lla->username, col_val[0], lla->len + 1); - lwsl_info("%s: %s\n", __func__, lla->username); - } - - return 0; -} - -int -lwsgs_lookup_session(struct per_vhost_data__gs *vhd, - const lwsgw_hash *sid, char *username, int len) -{ - struct lla lla = { username, len, 1 }; - char s[150], esc[96]; - - lwsgw_expire_old_sessions(vhd); - - lws_snprintf(s, sizeof(s) - 1, - "select username from sessions where name = '%s';", - lws_sql_purify(esc, sid->id, sizeof(esc) - 1)); - - if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback, &lla, NULL) != SQLITE_OK) { - lwsl_err("Unable to create user table: %s\n", - sqlite3_errmsg(vhd->pdb)); - - return 1; - } - - /* 0 if found */ - return lla.results; -} - -int -lwsgs_lookup_callback_user(void *priv, int cols, char **col_val, char **col_name) -{ - struct lwsgs_user *u = (struct lwsgs_user *)priv; - int n; - - for (n = 0; n < cols; n++) { - if (!strcmp(col_name[n], "username")) { - lws_strncpy(u->username, col_val[n], sizeof(u->username)); - continue; - } - if (!strcmp(col_name[n], "ip")) { - lws_strncpy(u->ip, col_val[n], sizeof(u->ip)); - continue; - } - if (!strcmp(col_name[n], "creation_time")) { - u->created = atol(col_val[n]); - continue; - } - if (!strcmp(col_name[n], "last_forgot_validated")) { - if (col_val[n]) - u->last_forgot_validated = atol(col_val[n]); - else - u->last_forgot_validated = 0; - continue; - } - if (!strcmp(col_name[n], "email")) { - lws_strncpy(u->email, col_val[n], sizeof(u->email)); - continue; - } - if (!strcmp(col_name[n], "verified")) { - u->verified = atoi(col_val[n]); - continue; - } - if (!strcmp(col_name[n], "pwhash")) { - lws_strncpy(u->pwhash.id, col_val[n], sizeof(u->pwhash.id)); - continue; - } - if (!strcmp(col_name[n], "pwsalt")) { - lws_strncpy(u->pwsalt.id, col_val[n], sizeof(u->pwsalt.id)); - continue; - } - if (!strcmp(col_name[n], "token")) { - lws_strncpy(u->token.id, col_val[n], sizeof(u->token.id)); - continue; - } - } - return 0; -} - -int -lwsgs_lookup_user(struct per_vhost_data__gs *vhd, - const char *username, struct lwsgs_user *u) -{ - char s[150], esc[96]; - - u->username[0] = '\0'; - lws_snprintf(s, sizeof(s) - 1, - "select username,creation_time,ip,email,verified,pwhash,pwsalt,last_forgot_validated " - "from users where username = '%s';", - lws_sql_purify(esc, username, sizeof(esc) - 1)); - - if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, u, NULL) != - SQLITE_OK) { - lwsl_err("Unable to lookup user: %s\n", - sqlite3_errmsg(vhd->pdb)); - - return -1; - } - - return !u->username[0]; -} - -int -lwsgs_new_session_id(struct per_vhost_data__gs *vhd, - lwsgw_hash *sid, const char *username, int exp) -{ - unsigned char sid_rand[32]; - const char *u; - char s[300], esc[96], esc1[96]; - - if (username) - u = username; - else - u = ""; - - if (!sid) { - lwsl_err("%s: NULL sid\n", __func__); - return 1; - } - - memset(sid, 0, sizeof(*sid)); - - if (lws_get_random(vhd->context, sid_rand, sizeof(sid_rand)) != - sizeof(sid_rand)) - return 1; - - sha256_to_lwsgw_hash(sid_rand, sid); - - lws_snprintf(s, sizeof(s) - 1, - "insert into sessions(name, username, expire) " - "values ('%s', '%s', %u);", - lws_sql_purify(esc, sid->id, sizeof(esc) - 1), - lws_sql_purify(esc1, u, sizeof(esc1) - 1), exp); - - if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != SQLITE_OK) { - lwsl_err("Unable to insert session: %s\n", - sqlite3_errmsg(vhd->pdb)); - - return 1; - } - - lwsl_notice("%s: created session %s\n", __func__, sid->id); - - return 0; -} - -int -lwsgs_get_auth_level(struct per_vhost_data__gs *vhd, const char *username) -{ - struct lwsgs_user u; - int n = 0; - - /* we are logged in as some kind of user */ - if (username[0]) { - /* we are logged in as admin */ - if (!strcmp(username, vhd->admin_user)) - /* automatically verified */ - n |= LWSGS_AUTH_VERIFIED | LWSGS_AUTH_ADMIN; - } - - if (!lwsgs_lookup_user(vhd, username, &u)) { - if ((u.verified & 0xff) == LWSGS_VERIFIED_ACCEPTED) - n |= LWSGS_AUTH_LOGGED_IN | LWSGS_AUTH_VERIFIED; - - if (u.last_forgot_validated > (time_t)lws_now_secs() - 300) - n |= LWSGS_AUTH_FORGOT_FLOW; - } - - return n; -} - -int -lwsgs_check_credentials(struct per_vhost_data__gs *vhd, - const char *username, const char *password) -{ - struct lws_genhash_ctx hash_ctx; - lwsgw_hash_bin hash_bin; - struct lwsgs_user u; - lwsgw_hash hash; - - if (lwsgs_lookup_user(vhd, username, &u)) - return -1; - - lwsl_info("user %s found, salt '%s'\n", username, u.pwsalt.id); - - /* sha256sum of password + salt */ - - if (lws_genhash_init(&hash_ctx, LWS_GENHASH_TYPE_SHA256) || - lws_genhash_update(&hash_ctx, password, strlen(password)) || - lws_genhash_update(&hash_ctx, "-", 1) || - lws_genhash_update(&hash_ctx, vhd->confounder, strlen(vhd->confounder)) || - lws_genhash_update(&hash_ctx, "-", 1) || - lws_genhash_update(&hash_ctx, u.pwsalt.id, strlen(u.pwsalt.id)) || - lws_genhash_destroy(&hash_ctx, hash_bin.bin)) { - lws_genhash_destroy(&hash_ctx, NULL); - - return 1; - } - - sha256_to_lwsgw_hash(&hash_bin.bin[0], &hash); - - return !!strcmp(hash.id, u.pwhash.id); -} - -/* sets u->pwsalt and u->pwhash */ - -int -lwsgs_hash_password(struct per_vhost_data__gs *vhd, - const char *password, struct lwsgs_user *u) -{ - unsigned char sid_rand[32]; - struct lws_genhash_ctx hash_ctx; - lwsgw_hash_bin hash_bin; - - /* create a random salt as big as the hash */ - - if (lws_get_random(vhd->context, sid_rand, - sizeof(sid_rand)) != - sizeof(sid_rand)) { - lwsl_err("Problem getting random for salt\n"); - return 1; - } - sha256_to_lwsgw_hash(sid_rand, &u->pwsalt); -/* - if (lws_get_random(vhd->context, sid_rand, - sizeof(sid_rand)) != - sizeof(sid_rand)) { - lwsl_err("Problem getting random for token\n"); - return 1; - } - sha256_to_lwsgw_hash(sid_rand, &hash); -*/ - /* sha256sum of password + salt */ - - if (lws_genhash_init(&hash_ctx, LWS_GENHASH_TYPE_SHA256) || - lws_genhash_update(&hash_ctx, password, strlen(password)) || - lws_genhash_update(&hash_ctx, "-", 1) || - lws_genhash_update(&hash_ctx, vhd->confounder, strlen(vhd->confounder)) || - lws_genhash_update(&hash_ctx, "-", 1) || - lws_genhash_update(&hash_ctx, u->pwsalt.id, strlen(u->pwsalt.id)) || - lws_genhash_destroy(&hash_ctx, hash_bin.bin)) { - lws_genhash_destroy(&hash_ctx, NULL); - - return 1; - } - - sha256_to_lwsgw_hash(&hash_bin.bin[0], &u->pwhash); - - return 0; -} diff -Nru libwebsockets-4.0.20/plugins/generic-table/assets/index.html libwebsockets-4.1.6/plugins/generic-table/assets/index.html --- libwebsockets-4.0.20/plugins/generic-table/assets/index.html 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/generic-table/assets/index.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,75 +0,0 @@ - - - - - - - - - - - - - -
- LWS Generic Table demo -
- This is a demo of lws generic table, using a protocol plugin - "protocol-lws-table-dirlisting". It shows a directory listing, - but unlike an oldstyle directory listing done on the - server side with a script, this is static html that connects - back to the server with a websocket, and gets live JSON from - that. -

- Actually the static html is extremely simple, since it uses - lwsgt, LWS Generic Table, JS include on the client-side that - handles all the table generation from a template sent in JSON - over the ws link. It means there is no custom JS required - clientside either. It's just CSS, this text and a call to - initialize lwsgt with the appropriate ws protocol. -

- There's no problem having multiple independent instances per - page... -
-

- - - - diff -Nru libwebsockets-4.0.20/plugins/generic-table/assets/lwsgt.js libwebsockets-4.1.6/plugins/generic-table/assets/lwsgt.js --- libwebsockets-4.0.20/plugins/generic-table/assets/lwsgt.js 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/generic-table/assets/lwsgt.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,139 +0,0 @@ -function lwsgt_get_appropriate_ws_url() -{ - var pcol; - var u = document.URL; - - if (u.substring(0, 5) === "https") { - pcol = "wss://"; - u = u.substr(8); - } else { - pcol = "ws://"; - if (u.substring(0, 4) === "http") - u = u.substr(7); - } - - return pcol + u; -} - -function lwsgt_app_hdr(j, bc, ws) -{ - var s = "", n, m = 0; - - ws.bcq = 0; - - for (n = 0; n < j.cols.length; n++) - if (!j.cols[n].hide) - m++; - - s = "" + - ws.lwsgt_title + ""; - - if (!!bc) { - s += ""; - for (n = 0; n < bc.length; n++) { - s += " / "; - if (!bc[n].url && bc[n].url !== "") - s += " " + lws_san(bc[n].name) + " "; - else { - s += "" + - lws_san(bc[n].name) + " "; - ws.bcq++; - } - } - s += ""; - } - s += ""; - for (n = 0; n < j.cols.length; n++) - if (!j.cols[n].hide) - s = s + "" + lws_san(j.cols[n].name) + - ""; - - s += ""; - - return s; -} - -function lwsgt_click_callthru() -{ - window[this.getAttribute("h")](this.getAttribute("p"), this.getAttribute("aa"), this.getAttribute("m"), this.getAttribute("n")); - event.preventDefault(); -} - -function lwsgt_initial(title, pcol, divname, cb, gname) -{ - this.divname = divname; - - lws_gray_out(true,{"zindex":"499"}); - - this.lwsgt_ws = new WebSocket(lwsgt_get_appropriate_ws_url(), pcol); - this.lwsgt_ws.divname = divname; - this.lwsgt_ws.lwsgt_cb = cb; - this.lwsgt_ws.lwsgt_parent = gname; - this.lwsgt_ws.lwsgt_title = title; - try { - this.lwsgt_ws.onopen = function() { - lws_gray_out(false); - // document.getElementById("debug").textContent = - // "ws opened " + lwsgt_get_appropriate_ws_url(); - }; - this.lwsgt_ws.onmessage = function got_packet(msg) { - var s, m, n, j = JSON.parse(msg.data); - document.getElementById("debug").textContent = msg.data; - if (j.cols) { - this.hdr = j; - } - if (j.breadcrumbs) - this.breadcrumbs = j.breadcrumbs; - - if (j.data) { - var q = 0; - s = "" + - lwsgt_app_hdr(this.hdr, this.breadcrumbs, this); - for (m = 0; m < j.data.length; m++) { - s = s + ""; - for (n = 0; n < this.hdr.cols.length; n++) { - if (!this.hdr.cols[n].hide) { - if (!this.hdr.cols[n].align) - s = s + ""; - } - } - - s = s + ""; - } - s = s + "
"; - else - s = s + ""; - - if (this.hdr.cols[n].href && - !!j.data[m][this.hdr.cols[n].href]) { - s = s + "" + - lws_san(j.data[m][this.hdr.cols[n].name]) + - ""; - q++; - } - else - s = s + lws_san(j.data[m][this.hdr.cols[n].name]); - - s = s + "
"; - document.getElementById(this.divname).innerHTML = s; - for (n = 0; n < q; n++) - document.getElementById(this.divname + n).onclick = - lwsgt_click_callthru; - - for (n = 0; n < this.bcq; n++) - document.getElementById("bc_" + this.divname + n).onclick = - lwsgt_click_callthru; - - } - }; - this.lwsgt_ws.onclose = function(){ - lws_gray_out(true,{"zindex":"499"}); - }; - } catch(exception) { - alert("

Error" + exception); - } -} - diff -Nru libwebsockets-4.0.20/plugins/generic-table/protocol_table_dirlisting.c libwebsockets-4.1.6/plugins/generic-table/protocol_table_dirlisting.c --- libwebsockets-4.0.20/plugins/generic-table/protocol_table_dirlisting.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/generic-table/protocol_table_dirlisting.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,397 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * 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. - */ - -#define LWS_DLL -#define LWS_INTERNAL -#include - -#include -#include -#include - -struct fobj { - struct fobj *next; - const char *name, *uri, *icon, *date; - time_t m; - unsigned long size; -}; - -struct per_session_data__tbl_dir { - struct fobj base; - char strings[64 * 1024]; - char reldir[256]; - char *p; - const char *dir; - -#if UV_VERSION_MAJOR > 0 - uv_fs_event_t *event_req; -#endif - struct lws *wsi; -}; - -#if UV_VERSION_MAJOR > 0 -static void -mon_cb(uv_fs_event_t *handle, const char *filename, int events, int status) -{ - struct per_session_data__tbl_dir *pss = handle->data; - - //lwsl_notice("%s\n", __func__); - - if (pss && pss->wsi) - lws_callback_on_writable(pss->wsi); -} - -static void lws_uv_close_cb(uv_handle_t *handle) -{ - free(handle); -} - -static void -lws_protocol_dir_kill_monitor(struct per_session_data__tbl_dir *pss) -{ - if (!pss->event_req) - return; - pss->wsi = NULL; - pss->event_req->data = NULL; - uv_fs_event_stop(pss->event_req); - uv_close((uv_handle_t *)pss->event_req, lws_uv_close_cb); - pss->event_req = NULL; -} -#endif - -static int -scan_dir(struct lws *wsi, struct per_session_data__tbl_dir *pss) -{ -/* uuh travis... */ -#if UV_VERSION_MAJOR > 0 - uv_loop_t *loop = lws_uv_getloop(lws_get_context(wsi), 0); - char *end = &(pss->strings[sizeof(pss->strings) - 1]); - struct fobj *prev = &pss->base; - char path[512], da[200]; - const char *icon; - uv_dirent_t dent; - struct fobj *f; - struct stat st; - struct tm *tm; - int ret = 0, n; - uv_fs_t req; - - lws_protocol_dir_kill_monitor(pss); - - lws_snprintf(path, sizeof(path) - 1, "%s/%s", pss->dir, pss->reldir); - //lwsl_notice("path = %s\n", path); - - pss->event_req = malloc(sizeof(*pss->event_req)); - if (!pss->event_req) - return 2; - - pss->wsi = wsi; - pss->event_req->data = pss; - - uv_fs_event_init(lws_uv_getloop(lws_get_context(wsi), 0), - pss->event_req); - // The recursive flag watches subdirectories too. - n = uv_fs_event_start(pss->event_req, mon_cb, path, UV_FS_EVENT_RECURSIVE); - //lwsl_notice("monitoring %s (%d)\n", path, n); - - if (!uv_fs_scandir(loop, &req, path, 0, NULL)) { - lwsl_err("Scandir on %s failed\n", path); - return 2; - } - - pss->p = pss->strings; - - while (uv_fs_scandir_next(&req, &dent) != UV_EOF) { - lws_snprintf(path, sizeof(path) - 1, "%s/%s/%s", pss->dir, pss->reldir, dent.name); - - if (stat(path, &st)) { - lwsl_info("unable to stat %s\n", path); - continue; - } - f = malloc(sizeof(*f)); - f->next = NULL; - f->name = pss->p; - n = lws_snprintf(pss->p, end - pss->p, "%s", dent.name); - pss->p += n + 1; - f->uri = NULL; - if ((S_IFMT & st.st_mode) == S_IFDIR) { - n = lws_snprintf(pss->p, end - pss->p, "=%s/%s", pss->reldir, dent.name); - f->uri = pss->p; - } - if (lws_get_mimetype(dent.name, NULL)) { - n = lws_snprintf(pss->p, end - pss->p, "./serve/%s/%s", pss->reldir, dent.name); - f->uri = pss->p; - } - if (f->uri) - pss->p += n + 1; - - if (end - pss->p < 100) { - free(f); - break; - } - - icon = " "; - if ((S_IFMT & st.st_mode) == S_IFDIR) - icon = "📂"; - - f->icon = pss->p; - n = lws_snprintf(pss->p, end - pss->p, "%s", icon); - pss->p += n + 1; - - f->date = pss->p; - tm = gmtime(&st.st_mtime); - strftime(da, sizeof(da), "%Y-%b-%d %H:%M:%S %z", tm); - n = lws_snprintf(pss->p, end - pss->p, "%s", da); - pss->p += n + 1; - - f->size = st.st_size; - f->m = st.st_mtime; - prev->next = f; - prev = f; - } - - uv_fs_req_cleanup(&req); - - return ret; -#else - return 0; -#endif -} - -static void -free_scan_dir(struct per_session_data__tbl_dir *pss) -{ - struct fobj *f = pss->base.next, *f1; - - while (f) { - f1 = f->next; - free(f); - f = f1; - } - - pss->base.next = NULL; -} - -static int -callback_lws_table_dirlisting(struct lws *wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len) -{ - struct per_session_data__tbl_dir *pss = (struct per_session_data__tbl_dir *)user; - char j[LWS_PRE + 16384], *p = j + LWS_PRE, *start = p, *q, *q1, *w, - *end = j + sizeof(j) - LWS_PRE, e[384], s[384], s1[384]; - const struct lws_protocol_vhost_options *pmo; - struct fobj *f; - int n, first = 1; - - switch (reason) { - case LWS_CALLBACK_PROTOCOL_INIT: /* per vhost */ - break; - - case LWS_CALLBACK_ESTABLISHED: - lwsl_debug("LWS_CALLBACK_ESTABLISHED\n"); - /* - * send client the lwsgt table layout - */ - start = "{\"cols\":[" - " {\"name\": \"Date\"}," - " {\"name\": \"Size\", \"align\": \"right\"}," - " {\"name\": \"Icon\"}," - " {\"name\": \"Name\", \"href\": \"uri\"}," - " {\"name\": \"uri\", \"hide\": \"1\" }" - " ]" - "}"; - if (lws_write(wsi, (unsigned char *)start, strlen(start), - LWS_WRITE_TEXT) < 0) - return -1; - - /* send a view update next */ - lws_callback_on_writable(wsi); - break; - - case LWS_CALLBACK_RECEIVE: - if (len > sizeof(pss->reldir) - 1) - len = sizeof(pss->reldir) - 1; - if (!strstr(in, "..") && !strchr(in, '~')) - lws_strncpy(pss->reldir, in, len + 1); - else - len = 0; - pss->reldir[len] = '\0'; - if (pss->reldir[0] == '/' && !pss->reldir[1]) - pss->reldir[0] = '\0'; - lwsl_info("%s\n", pss->reldir); - lws_callback_on_writable(wsi); - break; - - case LWS_CALLBACK_SERVER_WRITEABLE: - - if (scan_dir(wsi, pss)) - return 1; - - p += lws_snprintf(p, end - p, "{\"breadcrumbs\":["); - q = pss->reldir; - - if (!q[0]) - p += lws_snprintf(p, end - p, "{\"name\":\"top\"}"); - - while (*q) { - - q1 = strchr(q, '/'); - if (!q1) { - if (first) - strcpy(s, "top1"); - else - strcpy(s, q); - s1[0] = '\0'; - q += strlen(q); - } else { - n = lws_ptr_diff(q1, q); - if (n > (int)sizeof(s) - 1) - n = sizeof(s) - 1; - if (first) { - strcpy(s1, "/"); - strcpy(s, "top"); - } else { - lws_strncpy(s, q, n + 1); - - n = lws_ptr_diff(q1, pss->reldir); - if (n > (int)sizeof(s1) - 1) - n = sizeof(s1) - 1; - lws_strncpy(s1, pss->reldir, n + 1); - } - q = q1 + 1; - } - if (!first) - p += lws_snprintf(p, end - p, ","); - else - first = 0; - - p += lws_snprintf(p, end - p, "{\"name\":\"%s\"", - lws_json_purify(e, s, sizeof(e), NULL)); - if (*q) { - w = s1; - while (w[0] == '/' && w[1] == '/') - w++; - p += lws_snprintf(p, end - p, ",\"url\":\"%s\"", - lws_json_purify(e, w, sizeof(e), NULL)); - } - p += lws_snprintf(p, end - p, "}"); - if (!q1) - break; - } - - p += lws_snprintf(p, end - p, "],\"data\":["); - - f = pss->base.next; - while (f) { - /* format in JSON */ - p += lws_snprintf(p, end - p, "{\"Icon\":\"%s\",", - lws_json_purify(e, f->icon, sizeof(e), NULL)); - p += lws_snprintf(p, end - p, " \"Date\":\"%s\",", - lws_json_purify(e, f->date, sizeof(e), NULL)); - p += lws_snprintf(p, end - p, " \"Size\":\"%ld\",", - f->size); - if (f->uri) - p += lws_snprintf(p, end - p, " \"uri\":\"%s\",", - lws_json_purify(e, f->uri, sizeof(e), NULL)); - p += lws_snprintf(p, end - p, " \"Name\":\"%s\"}", - lws_json_purify(e, f->name, sizeof(e), NULL)); - - f = f->next; - - if (f) - p += lws_snprintf(p, end - p, ","); - } - - p += lws_snprintf(p, end - p, "]}"); - - free_scan_dir(pss); - - if (lws_write(wsi, (unsigned char *)start, p - start, - LWS_WRITE_TEXT) < 0) - return -1; - - break; - - case LWS_CALLBACK_HTTP_PMO: - /* find the per-mount options we're interested in */ - lwsl_debug("LWS_CALLBACK_HTTP_PMO\n"); - pmo = (struct lws_protocol_vhost_options *)in; - while (pmo) { - if (!strcmp(pmo->name, "dir")) /* path to list files */ - pss->dir = pmo->value; - pmo = pmo->next; - } - if (!pss->dir[0]) { - lwsl_err("dirlisting: \"dir\" pmo missing\n"); - return 1; - } - break; - - case LWS_CALLBACK_HTTP_DROP_PROTOCOL: - //lwsl_notice("LWS_CALLBACK_HTTP_DROP_PROTOCOL\n"); -#if UV_VERSION_MAJOR > 0 - lws_protocol_dir_kill_monitor(pss); -#endif - break; - - default: - return 0; - } - - return 0; - -} - -static const struct lws_protocols protocols[] = { - { - "protocol-lws-table-dirlisting", - callback_lws_table_dirlisting, - sizeof(struct per_session_data__tbl_dir), - 0, - }, -}; - -LWS_VISIBLE int -init_protocol_lws_table_dirlisting(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } - - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} - -LWS_VISIBLE int -destroy_protocol_lws_table_dirlisting(struct lws_context *context) -{ - return 0; -} diff -Nru libwebsockets-4.0.20/plugins/protocol_client_loopback_test.c libwebsockets-4.1.6/plugins/protocol_client_loopback_test.c --- libwebsockets-4.0.20/plugins/protocol_client_loopback_test.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/protocol_client_loopback_test.c 2020-12-01 17:40:26.000000000 +0000 @@ -173,26 +173,15 @@ }, }; -LWS_VISIBLE int -init_protocol_client_loopback_test(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } - - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} +LWS_VISIBLE const lws_plugin_protocol_t client_loopback_test = { + .hdr = { + "client loopback test", + "lws_protocol_plugin", + LWS_PLUGIN_API_MAGIC + }, -LWS_VISIBLE int -destroy_protocol_client_loopback_test(struct lws_context *context) -{ - return 0; -} + .protocols = protocols, + .count_protocols = LWS_ARRAY_SIZE(protocols), + .extensions = NULL, + .count_extensions = 0, +}; diff -Nru libwebsockets-4.0.20/plugins/protocol_dumb_increment.c libwebsockets-4.1.6/plugins/protocol_dumb_increment.c --- libwebsockets-4.0.20/plugins/protocol_dumb_increment.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/protocol_dumb_increment.c 2020-12-01 17:40:26.000000000 +0000 @@ -121,28 +121,17 @@ LWS_PLUGIN_PROTOCOL_DUMB_INCREMENT }; -LWS_VISIBLE int -init_protocol_dumb_increment(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } +LWS_VISIBLE const lws_plugin_protocol_t dumb_increment = { + .hdr = { + "dumb increment", + "lws_protocol_plugin", + LWS_PLUGIN_API_MAGIC + }, - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} - -LWS_VISIBLE int -destroy_protocol_dumb_increment(struct lws_context *context) -{ - return 0; -} + .protocols = protocols, + .count_protocols = LWS_ARRAY_SIZE(protocols), + .extensions = NULL, + .count_extensions = 0, +}; #endif diff -Nru libwebsockets-4.0.20/plugins/protocol_esp32_lws_group.c libwebsockets-4.1.6/plugins/protocol_esp32_lws_group.c --- libwebsockets-4.0.20/plugins/protocol_esp32_lws_group.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/protocol_esp32_lws_group.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,242 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * 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 -#include -#include - -typedef enum { - GROUP_STATE_NONE, - GROUP_STATE_INITIAL, - GROUP_STATE_MEMBERS, - GROUP_STATE_FINAL -} group_state; - -struct per_session_data__lws_group { - struct per_session_data__lws_group *next; - group_state group_state; - - struct lws_group_member *member; - - unsigned char subsequent:1; - unsigned char changed_partway:1; -}; - -struct per_vhost_data__lws_group { - struct per_session_data__lws_group *live_pss_list; - struct lws_context *context; - struct lws_vhost *vhost; - const struct lws_protocols *protocol; - int count_live_pss; -}; - -static void render_ip4(char *dest, int len, uint8_t *ip) -{ - snprintf(dest, len, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]); -} - - - -static int -callback_lws_group(struct lws *wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len) -{ - struct per_session_data__lws_group *pss = - (struct per_session_data__lws_group *)user; - struct per_vhost_data__lws_group *vhd = - (struct per_vhost_data__lws_group *) - lws_protocol_vh_priv_get(lws_get_vhost(wsi), - lws_get_protocol(wsi)); - char buffer[1024 + LWS_PRE], ipv4[20]; - char *start = buffer + LWS_PRE - 1, *p = start, - *end = buffer + sizeof(buffer) - 1; - struct lws_group_member *mbr; - int n, m; - - switch (reason) { - - case LWS_CALLBACK_PROTOCOL_INIT: - vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi), - lws_get_protocol(wsi), - sizeof(struct per_vhost_data__lws_group)); - vhd->context = lws_get_context(wsi); - vhd->protocol = lws_get_protocol(wsi); - vhd->vhost = lws_get_vhost(wsi); - break; - - case LWS_CALLBACK_PROTOCOL_DESTROY: - if (!vhd) - break; - break; - - case LWS_CALLBACK_ESTABLISHED: - lwsl_notice("%s: ESTABLISHED\n", __func__); - vhd->count_live_pss++; - pss->next = vhd->live_pss_list; - vhd->live_pss_list = pss; - pss->group_state = GROUP_STATE_INITIAL; - lws_callback_on_writable(wsi); - break; - - case LWS_CALLBACK_SERVER_WRITEABLE: - - switch (pss->group_state) { - - case GROUP_STATE_NONE: - /* fallthru */ - - case GROUP_STATE_INITIAL: - - p += snprintf((char *)p, end - p, - "{\n" - " \"group\":\"%s\"," - " \"members\":[\n", - lws_esp32.group); - - n = LWS_WRITE_TEXT | LWS_WRITE_NO_FIN; - pss->group_state = GROUP_STATE_MEMBERS; - pss->subsequent = 0; - pss->changed_partway = 0; - pss->member = lws_esp32.first; - break; - - case GROUP_STATE_MEMBERS: - - /* confirm pss->member is still in the list... */ - - mbr = lws_esp32.first; - while (mbr && mbr != pss->member) - mbr = mbr->next; - - if (!mbr) { /* no longer exists... */ - if (lws_esp32.first || pss->member) - pss->changed_partway = 1; - *p++ = ' '; - pss->member = NULL; - - /* - * finish the list where we got to, then - * immediately reissue it - */ - } - - while (end - p > 100 && pss->member) { - - if (pss->subsequent) - *p++ = ','; - - pss->subsequent = 1; - render_ip4(ipv4, sizeof(ipv4), (uint8_t *)&pss->member->addr); - - p += snprintf((char *)p, end - p, - " {\n" - " \"mac\":\"%s\",\n" - " \"model\":\"%s\",\n" - " \"role\":\"%s\",\n" - " \"width\":\"%d\",\n" - " \"height\":\"%d\",\n" - " \"ipv4\":\"%s\"\n" - " }\n", - pss->member->mac, - pss->member->model, - pss->member->role, - pss->member->width, - pss->member->height, - ipv4 - ); - pss->member = pss->member->next; - } - - lwsl_notice("%s\n", p); - - n = LWS_WRITE_CONTINUATION | LWS_WRITE_NO_FIN; - if (!pss->member) - pss->group_state = GROUP_STATE_FINAL; - break; - - case GROUP_STATE_FINAL: - n = LWS_WRITE_CONTINUATION; - p += sprintf((char *)p, "],\n \"discard\":\"%d\"}\n", - pss->changed_partway); - if (pss->changed_partway) - pss->group_state = GROUP_STATE_INITIAL; - else - pss->group_state = GROUP_STATE_NONE; - break; - default: - return 0; - } -// lwsl_notice("issue: %d (%d)\n", p - start, n); - m = lws_write(wsi, (unsigned char *)start, p - start, n); - if (m < 0) { - lwsl_err("ERROR %d writing to di socket\n", m); - return -1; - } - - if (pss->group_state != GROUP_STATE_NONE) - lws_callback_on_writable(wsi); - - break; - - case LWS_CALLBACK_RECEIVE: - { - break; - } - - case LWS_CALLBACK_CLOSED: - { - struct per_session_data__lws_group **p = &vhd->live_pss_list; - - while (*p) { - if ((*p) == pss) { - *p = pss->next; - continue; - } - - p = &((*p)->next); - } - - vhd->count_live_pss--; - } - break; - - case LWS_CALLBACK_HTTP_DROP_PROTOCOL: - /* called when our wsi user_space is going to be destroyed */ - break; - - default: - break; - } - - return 0; -} - -#define LWS_PLUGIN_PROTOCOL_LWS_GROUP \ - { \ - "lws-group", \ - callback_lws_group, \ - sizeof(struct per_session_data__lws_group), \ - 1024, 0, NULL, 900 \ - } - diff -Nru libwebsockets-4.0.20/plugins/protocol_esp32_lws_ota.c libwebsockets-4.1.6/plugins/protocol_esp32_lws_ota.c --- libwebsockets-4.0.20/plugins/protocol_esp32_lws_ota.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/protocol_esp32_lws_ota.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,291 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * 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 -#include -#include -#include - -struct per_session_data__esplws_ota { - struct lws_spa *spa; - char filename[32]; - char result[LWS_PRE + 512]; - int result_len; - int filename_length; - esp_ota_handle_t otahandle; - const esp_partition_t *part; - long file_length; - long last_rep; - nvs_handle nvh; - TimerHandle_t reboot_timer; -}; - -struct per_vhost_data__esplws_ota { - struct lws_context *context; - struct lws_vhost *vhost; - const struct lws_protocols *protocol; -}; - -static const char * const ota_param_names[] = { - "upload", -}; - -enum enum_ota_param_names { - EPN_UPLOAD, -}; - -static void ota_reboot_timer_cb(TimerHandle_t t) -{ - esp_restart(); -} - -const esp_partition_t * -ota_choose_part(void) -{ - const esp_partition_t *bootpart, *part = NULL; - esp_partition_iterator_t i; - - bootpart = lws_esp_ota_get_boot_partition(); - i = esp_partition_find(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_ANY, NULL); - while (i) { - part = esp_partition_get(i); - - /* cannot update ourselves */ - if (part == bootpart) - goto next; - - /* OTA Partition numbering is from _OTA_MIN to less than _OTA_MAX */ - if (part->subtype < ESP_PARTITION_SUBTYPE_APP_OTA_MIN || - part->subtype >= ESP_PARTITION_SUBTYPE_APP_OTA_MAX) - goto next; - - break; - -next: - i = esp_partition_next(i); - } - - if (!i) { - lwsl_err("Can't find good OTA part\n"); - return NULL; - } - lwsl_notice("Directing OTA to part type %d/%d start 0x%x\n", - part->type, part->subtype, - (uint32_t)part->address); - - return part; -} - -static int -ota_file_upload_cb(void *data, const char *name, const char *filename, - char *buf, int len, enum lws_spa_fileupload_states state) -{ - struct per_session_data__esplws_ota *pss = - (struct per_session_data__esplws_ota *)data; - - switch (state) { - case LWS_UFS_OPEN: - lwsl_notice("LWS_UFS_OPEN Filename %s\n", filename); - lws_strncpy(pss->filename, filename, sizeof(pss->filename)); - if (strcmp(name, "ota")) - return 1; - - pss->part = ota_choose_part(); - if (!pss->part) - return 1; - - if (esp_ota_begin(pss->part, OTA_SIZE_UNKNOWN, &pss->otahandle) != ESP_OK) { - lwsl_err("OTA: Failed to begin\n"); - return 1; - } - - pss->file_length = 0; - pss->last_rep = -1; - break; - - case LWS_UFS_FINAL_CONTENT: - case LWS_UFS_CONTENT: - if (pss->file_length + len > pss->part->size) { - lwsl_err("OTA: incoming file too large\n"); - return 1; - } - - if ((pss->file_length & ~0xffff) != (pss->last_rep & ~0xffff)) { - lwsl_notice("writing 0x%lx...\n", - pss->part->address + pss->file_length); - pss->last_rep = pss->file_length; - } - if (esp_ota_write(pss->otahandle, buf, len) != ESP_OK) { - lwsl_err("OTA: Failed to write\n"); - return 1; - } - pss->file_length += len; - - if (state == LWS_UFS_CONTENT) - break; - - lwsl_notice("LWS_UFS_FINAL_CONTENT\n"); - if (esp_ota_end(pss->otahandle) != ESP_OK) { - lwsl_err("OTA: end failed\n"); - return 1; - } - - if (esp_ota_set_boot_partition(pss->part) != ESP_OK) { - lwsl_err("OTA: set boot part failed\n"); - return 1; - } - - pss->reboot_timer = xTimerCreate("x", pdMS_TO_TICKS(250), 0, NULL, - ota_reboot_timer_cb); - xTimerStart(pss->reboot_timer, 0); - break; - } - - return 0; -} - -static int -callback_esplws_ota(struct lws *wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len) -{ - struct per_session_data__esplws_ota *pss = - (struct per_session_data__esplws_ota *)user; - struct per_vhost_data__esplws_ota *vhd = - (struct per_vhost_data__esplws_ota *) - lws_protocol_vh_priv_get(lws_get_vhost(wsi), - lws_get_protocol(wsi)); - unsigned char buf[LWS_PRE + 384], *start = buf + LWS_PRE - 1, *p = start, - *end = buf + sizeof(buf) - 1; - int n; - - switch (reason) { - - case LWS_CALLBACK_PROTOCOL_INIT: - vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi), - lws_get_protocol(wsi), - sizeof(struct per_vhost_data__esplws_ota)); - vhd->context = lws_get_context(wsi); - vhd->protocol = lws_get_protocol(wsi); - vhd->vhost = lws_get_vhost(wsi); - break; - - case LWS_CALLBACK_PROTOCOL_DESTROY: - if (!vhd) - break; - break; - - /* OTA POST handling */ - - case LWS_CALLBACK_HTTP_BODY: - /* create the POST argument parser if not already existing */ - // lwsl_notice("LWS_CALLBACK_HTTP_BODY (ota) %d %d %p\n", (int)pss->file_length, (int)len, pss->spa); - lws_set_timeout(wsi, PENDING_TIMEOUT_HTTP_CONTENT, 30); - if (!pss->spa) { - pss->spa = lws_spa_create(wsi, ota_param_names, - LWS_ARRAY_SIZE(ota_param_names), 4096, - ota_file_upload_cb, pss); - if (!pss->spa) - return -1; - - pss->filename[0] = '\0'; - pss->file_length = 0; - } - lws_esp32.upload = 1; - - /* let it parse the POST data */ - if (lws_spa_process(pss->spa, in, len)) - return -1; - break; - - case LWS_CALLBACK_HTTP_BODY_COMPLETION: - lwsl_notice("LWS_CALLBACK_HTTP_BODY_COMPLETION (ota)\n"); - /* call to inform no more payload data coming */ - lws_spa_finalize(pss->spa); - - pss->result_len = snprintf(pss->result + LWS_PRE, sizeof(pss->result) - LWS_PRE - 1, - "Rebooting after OTA update"); - - if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end)) - goto bail; - - if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE, - (unsigned char *)"text/html", 9, &p, end)) - goto bail; - if (lws_add_http_header_content_length(wsi, pss->result_len, &p, end)) - goto bail; - if (lws_finalize_http_header(wsi, &p, end)) - goto bail; - - n = lws_write(wsi, start, p - start, LWS_WRITE_HTTP_HEADERS | LWS_WRITE_H2_STREAM_END); - if (n < 0) - goto bail; - - lws_callback_on_writable(wsi); - break; - - case LWS_CALLBACK_HTTP_WRITEABLE: - if (!pss->result_len) - break; - lwsl_debug("LWS_CALLBACK_HTTP_WRITEABLE: sending %d\n", - pss->result_len); - n = lws_write(wsi, (unsigned char *)pss->result + LWS_PRE, - pss->result_len, LWS_WRITE_HTTP); - if (n < 0) - return 1; - - if (lws_http_transaction_completed(wsi)) - return 1; - - /* stop further service so we don't serve the probe GET to see if we rebooted */ - while (1); - - break; - - case LWS_CALLBACK_HTTP_DROP_PROTOCOL: - /* called when our wsi user_space is going to be destroyed */ - if (pss->spa) { - lws_spa_destroy(pss->spa); - pss->spa = NULL; - } - lws_esp32.upload = 0; - break; - - default: - break; - } - - return 0; - -bail: - return 1; -} - -#define LWS_PLUGIN_PROTOCOL_ESPLWS_OTA \ - { \ - "esplws-ota", \ - callback_esplws_ota, \ - sizeof(struct per_session_data__esplws_ota), \ - 4096, 0, NULL, 900 \ - } - diff -Nru libwebsockets-4.0.20/plugins/protocol_esp32_lws_reboot_to_factory.c libwebsockets-4.1.6/plugins/protocol_esp32_lws_reboot_to_factory.c --- libwebsockets-4.0.20/plugins/protocol_esp32_lws_reboot_to_factory.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/protocol_esp32_lws_reboot_to_factory.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ - /* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * 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. - * - * This is intended to be mounted somewhere in your ESP32 user app... if the - * client touched the mount, the plugin hangs up and reboots into the - * factory mode one second later. - * - * The factory mode will reassociate with the same IP with the same MAC - * shortly afterwards and be accessible by the same IP / mDNS name. - */ -#include -#include -#include -#include - -static int -callback_esplws_rtf(struct lws *wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len) -{ - switch (reason) { - - case LWS_CALLBACK_HTTP: - - lws_esp32_restart_guided(LWS_MAGIC_REBOOT_TYPE_REQ_FACTORY); - return 1; - - default: - break; - } - - return 0; -} - -#define LWS_PLUGIN_PROTOCOL_ESPLWS_RTF \ - { \ - "esplws-rtf", \ - callback_esplws_rtf, \ - 0, \ - 10, 0, NULL, 0 \ - } - diff -Nru libwebsockets-4.0.20/plugins/protocol_esp32_lws_scan.c libwebsockets-4.1.6/plugins/protocol_esp32_lws_scan.c --- libwebsockets-4.0.20/plugins/protocol_esp32_lws_scan.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/protocol_esp32_lws_scan.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,1276 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * 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 -#include -#include - -typedef enum { - SCAN_STATE_NONE, - SCAN_STATE_INITIAL, - SCAN_STATE_INITIAL_MANIFEST, - SCAN_STATE_KNOWN, - SCAN_STATE_LIST, - SCAN_STATE_FINAL -} scan_state; - -struct store_json { - const char *j; - const char *nvs; -}; - -struct per_session_data__esplws_scan { - struct per_session_data__esplws_scan *next; - scan_state scan_state; - struct timeval last_send; - - struct lws_spa *spa; - char filename[32]; - char result[LWS_PRE + 512]; - unsigned char buffer[4096]; - int result_len; - int filename_length; - long file_length; - nvs_handle nvh; - - char ap_record; - unsigned char subsequent:1; - unsigned char changed_partway:1; -}; - -#define max_aps 12 - -struct per_vhost_data__esplws_scan { - wifi_ap_record_t ap_records[10]; - TimerHandle_t timer, reboot_timer; - struct per_session_data__esplws_scan *live_pss_list; - struct lws_context *context; - struct lws_vhost *vhost; - const struct lws_protocols *protocol; - struct lws_wifi_scan *known_aps_list; - - const esp_partition_t *part; - esp_ota_handle_t otahandle; - long file_length; - long content_length; - - int cert_remaining_days; - - struct lws *cwsi; - char json[2048]; - int json_len; - - int acme_state; - char acme_msg[256]; - - uint16_t count_ap_records; - char count_live_pss; - unsigned char scan_ongoing:1; - unsigned char completed_any_scan:1; - unsigned char reboot:1; - unsigned char changed_settings:1; - unsigned char checked_updates:1; - unsigned char autonomous_update:1; - unsigned char autonomous_update_sampled:1; -}; - -static const struct store_json store_json[] = { - { "\"ssid0\":\"", "0ssid" }, - { ",\"pw0\":\"", "0password" }, - { "\"ssid1\":\"", "1ssid" }, - { ",\"pw1\":\"", "1password" }, - { "\"ssid2\":\"", "2ssid" }, - { ",\"pw2\":\"", "2password" }, - { "\"ssid3\":\"", "3ssid" }, - { ",\"pw3\":\"", "3password" }, - { ",\"access_pw\":\"", "access_pw" }, - { "{\"group\":\"", "group" }, - { "{\"role\":\"", "role" }, - { ",\"region\":\"", "region" }, -}; - -static wifi_scan_config_t scan_config = { - .ssid = 0, - .bssid = 0, - .channel = 0, - .show_hidden = true -}; - -const esp_partition_t * -ota_choose_part(void); - -static const char * const param_names[] = { - "text", - "pub", - "pri", - "serial", - "opts", - "group", - "role", - "updsettings", -}; - -enum enum_param_names { - EPN_TEXT, - EPN_PUB, - EPN_PRI, - EPN_SERIAL, - EPN_OPTS, - EPN_GROUP, - EPN_ROLE, - EPN_UPDSETTINGS, -}; - - -static void -scan_finished(uint16_t count, wifi_ap_record_t *recs, void *v); - -static int -esplws_simple_arg(char *dest, int len, const char *in, const char *match) -{ - const char *p = strstr(in, match); - int n = 0; - - if (!p) - return 1; - - p += strlen(match); - while (*p && *p != '\"' && n < len - 1) - dest[n++] = *p++; - dest[n] = '\0'; - - return 0; -} - -static void -scan_start(struct per_vhost_data__esplws_scan *vhd) -{ - int n; - - if (vhd->reboot) - esp_restart(); - - if (vhd->scan_ongoing) - return; - - if (lws_esp32.acme) - return; - - if (lws_esp32.upload) - return; - - vhd->scan_ongoing = 1; - lws_esp32.scan_consumer = scan_finished; - lws_esp32.scan_consumer_arg = vhd; - n = esp_wifi_scan_start(&scan_config, false); - if (n != ESP_OK) - lwsl_err("scan start failed %d\n", n); -} - -static int scan_defer; - -static void timer_cb(TimerHandle_t t) -{ - struct per_vhost_data__esplws_scan *vhd = pvTimerGetTimerID(t); - -// if (!lws_esp32.inet && ((scan_defer++) & 1)) -/* - * AP mode + scan does not work well on ESP32... if we didn't connect to an AP - * ourselves, just scan once at boot. Then leave us on the AP channel. - * - * Do the callback for everyone to keep the heartbeat alive. - */ - if (!lws_esp32.inet && scan_defer++) { - lws_callback_on_writable_all_protocol(vhd->context, vhd->protocol); - - return; - } - - scan_start(vhd); -} - -static void reboot_timer_cb(TimerHandle_t t) -{ - esp_restart(); -} - -static int -client_connection(struct per_vhost_data__esplws_scan *vhd, const char *file) -{ -#if defined(CONFIG_LWS_IS_FACTORY_APPLICATION) && defined(CONFIG_LWS_OTA_SERVER_BASE_URL) && \ - defined(CONFIG_LWS_OTA_SERVER_FQDN) - static struct lws_client_connect_info i; - char path[256]; - - memset(&i, 0, sizeof i); - - snprintf(path, sizeof(path) - 1, CONFIG_LWS_OTA_SERVER_BASE_URL "/" CONFIG_LWS_MODEL_NAME "/%s", file); - - lwsl_notice("Fetching %s\n", path); - - i.port = 443; - i.context = vhd->context; - i.address = CONFIG_LWS_OTA_SERVER_FQDN; - i.ssl_connection = 1; - i.host = i.address; - i.origin = i.host; - i.vhost = vhd->vhost; - i.method = "GET"; - i.path = path; - i.protocol = "esplws-scan"; - i.pwsi = &vhd->cwsi; - - vhd->cwsi = lws_client_connect_via_info(&i); - if (!vhd->cwsi) { - lwsl_notice("NULL return\n"); - return 1; /* fail */ - } -#endif - return 0; /* ongoing */ -} - -static int -lws_wifi_scan_rssi(struct lws_wifi_scan *p) -{ - if (!p->count) - return -127; - - return p->rssi / p->count; -} - -/* - * Insert new lws_wifi_scan into linkedlist in rssi-sorted order, trimming the - * list if needed to keep it at or below max_aps entries. - */ - -static int -lws_wifi_scan_insert_trim(struct lws_wifi_scan **list, struct lws_wifi_scan *ns) -{ - int count = 0, ins = 1, worst; - struct lws_wifi_scan *newlist, **pworst, *pp1; - - lws_start_foreach_llp(struct lws_wifi_scan **, pp, *list) { - /* try to find existing match */ - if (!strcmp((*pp)->ssid, ns->ssid) && - !memcmp((*pp)->bssid, ns->bssid, 6)) { - if ((*pp)->count > 127) { - (*pp)->count /= 2; - (*pp)->rssi /= 2; - } - (*pp)->rssi += ns->rssi; - (*pp)->count++; - ins = 0; - break; - } - } lws_end_foreach_llp(pp, next); - - if (ins) { - lws_start_foreach_llp(struct lws_wifi_scan **, pp, *list) { - /* trim any excess guys */ - if (count++ >= max_aps - 1) { - pp1 = *pp; - *pp = (*pp)->next; - free(pp1); - continue; /* stay where we are */ - } - } lws_end_foreach_llp(pp, next); - - /* we are inserting... so alloc a copy of him */ - pp1 = malloc(sizeof(*pp1)); - if (!pp1) - return -1; - - memcpy(pp1, ns, sizeof(*pp1)); - pp1->next = *list; - *list = pp1; - } - - /* sort the list ... worst first, but added at the newlist head */ - - newlist = NULL; - - /* while anybody left on the old list */ - while (*list) { - worst = 0; - pworst = NULL; - - /* who is the worst guy still left on the old list? */ - lws_start_foreach_llp(struct lws_wifi_scan **, pp, *list) { - if (lws_wifi_scan_rssi(*pp) <= worst) { - worst = lws_wifi_scan_rssi(*pp); - pworst = pp; - } - } lws_end_foreach_llp(pp, next); - - if (pworst) { - /* move the worst to the head of the new list */ - pp1 = *pworst; - *pworst = (*pworst)->next; - pp1->next = newlist; - newlist = pp1; - } - } - - *list = newlist; - - return 0; -} - -static void -scan_finished(uint16_t count, wifi_ap_record_t *recs, void *v) -{ - struct per_vhost_data__esplws_scan *vhd = v; - struct per_session_data__esplws_scan *p = vhd->live_pss_list; - struct lws_wifi_scan lws; - wifi_ap_record_t *r; - int m; - - lwsl_notice("%s: count %d\n", __func__, count); - - vhd->scan_ongoing = 0; - - if (count < LWS_ARRAY_SIZE(vhd->ap_records)) - vhd->count_ap_records = count; - else - vhd->count_ap_records = LWS_ARRAY_SIZE(vhd->ap_records); - - memcpy(vhd->ap_records, recs, vhd->count_ap_records * sizeof(*recs)); - - while (p) { - if (p->scan_state != SCAN_STATE_INITIAL && - p->scan_state != SCAN_STATE_NONE) - p->changed_partway = 1; - else - p->scan_state = SCAN_STATE_INITIAL; - p = p->next; - } - - /* convert to generic, cumulative scan results */ - - for (m = 0; m < vhd->count_ap_records; m++) { - - r = &vhd->ap_records[m]; - - lws.authmode = r->authmode; - lws.channel = r->primary; - lws.rssi = r->rssi; - lws.count = 1; - memcpy(&lws.bssid, r->bssid, 6); - lws_strncpy(lws.ssid, (const char *)r->ssid, sizeof(lws.ssid)); - - lws_wifi_scan_insert_trim(&vhd->known_aps_list, &lws); - } - - lws_callback_on_writable_all_protocol(vhd->context, vhd->protocol); - - if (lws_esp32.inet && !vhd->cwsi && !vhd->checked_updates) - client_connection(vhd, "manifest.json"); - - if (vhd->changed_settings) { - lws_esp32_wlan_nvs_get(1); - vhd->changed_settings = 0; - } else - esp_wifi_connect(); -} - -static const char *ssl_names[] = { "ap-cert.pem", "ap-key.pem" }; - -static int -file_upload_cb(void *data, const char *name, const char *filename, - char *buf, int len, enum lws_spa_fileupload_states state) -{ - struct per_session_data__esplws_scan *pss = - (struct per_session_data__esplws_scan *)data; - int n; - - switch (state) { - case LWS_UFS_OPEN: - if (lws_esp32_get_reboot_type() != LWS_MAGIC_REBOOT_TYPE_FORCED_FACTORY_BUTTON) - return -1; - - lwsl_notice("LWS_UFS_OPEN Filename %s\n", filename); - lws_strncpy(pss->filename, filename, sizeof(pss->filename)); - if (!strcmp(name, "pub") || !strcmp(name, "pri")) { - if (nvs_open("lws-station", NVS_READWRITE, &pss->nvh)) - return 1; - } else - return 1; - pss->file_length = 0; - break; - - case LWS_UFS_FINAL_CONTENT: - case LWS_UFS_CONTENT: - if (len) { - /* if the file length is too big, drop it */ - if (pss->file_length + len > sizeof(pss->buffer)) - return 1; - - memcpy(pss->buffer + pss->file_length, buf, len); - } - pss->file_length += len; - - if (state == LWS_UFS_CONTENT) - break; - - lwsl_notice("LWS_UFS_FINAL_CONTENT\n"); - n = 0; - if (!strcmp(name, "pri")) - n = 1; - lwsl_notice("writing %s\n", ssl_names[n]); - n = nvs_set_blob(pss->nvh, ssl_names[n], pss->buffer, pss->file_length); - if (n == ESP_OK) - nvs_commit(pss->nvh); - nvs_close(pss->nvh); - if (n != ESP_OK) - return 1; - break; - } - - return 0; -} - -static int -callback_esplws_scan(struct lws *wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len) -{ - struct per_session_data__esplws_scan *pss = - (struct per_session_data__esplws_scan *)user; - struct per_vhost_data__esplws_scan *vhd = - (struct per_vhost_data__esplws_scan *) - lws_protocol_vh_priv_get(lws_get_vhost(wsi), - lws_get_protocol(wsi)); - unsigned char *start = pss->buffer + LWS_PRE - 1, *p = start, - *end = pss->buffer + sizeof(pss->buffer) - 1; - union lws_tls_cert_info_results ir; - struct lws_wifi_scan *lwscan; - char subject[64]; - int n, m; - nvs_handle nvh; - size_t s; - - - switch (reason) { - - case LWS_CALLBACK_PROTOCOL_INIT: - vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi), - lws_get_protocol(wsi), - sizeof(struct per_vhost_data__esplws_scan)); - vhd->context = lws_get_context(wsi); - vhd->protocol = lws_get_protocol(wsi); - vhd->vhost = lws_get_vhost(wsi); - vhd->timer = xTimerCreate("x", pdMS_TO_TICKS(10000), 1, vhd, - (TimerCallbackFunction_t)timer_cb); - vhd->scan_ongoing = 0; - strcpy(vhd->json, " { }"); - // scan_start(vhd); - break; - - case LWS_CALLBACK_PROTOCOL_DESTROY: - if (!vhd) - break; - xTimerStop(vhd->timer, 0); - xTimerDelete(vhd->timer, 0); - break; - - case LWS_CALLBACK_ESTABLISHED: - lwsl_notice("%s: ESTABLISHED\n", __func__); - if (!vhd->live_pss_list) { - // scan_start(vhd); - xTimerStart(vhd->timer, 0); - } - vhd->count_live_pss++; - pss->next = vhd->live_pss_list; - vhd->live_pss_list = pss; - /* if we have scan results, update them. Otherwise wait */ -// if (vhd->count_ap_records) { - pss->scan_state = SCAN_STATE_INITIAL; - lws_callback_on_writable(wsi); -// } - break; - - case LWS_CALLBACK_SERVER_WRITEABLE: - if (vhd->autonomous_update_sampled) { - p += snprintf((char *)p, end - p, - " {\n \"auton\":\"1\",\n \"pos\": \"%ld\",\n" - " \"len\":\"%ld\"\n}\n", - vhd->file_length, - vhd->content_length); - - n = LWS_WRITE_TEXT; - goto issue; - } - - switch (pss->scan_state) { - struct timeval t; - uint8_t mac[6]; - struct lws_esp32_image i; - char img_factory[384], img_ota[384], group[16], role[16]; - int grt; - - case SCAN_STATE_NONE: - - /* fallthru */ - - case SCAN_STATE_INITIAL: - - gettimeofday(&t, NULL); - // if (t.tv_sec - pss->last_send.tv_sec < 10) - // return 0; - - pss->last_send = t; - - if (nvs_open("lws-station", NVS_READWRITE, &nvh)) { - lwsl_err("unable to open nvs\n"); - return -1; - } - n = 0; - if (nvs_get_blob(nvh, "ap-cert.pem", NULL, &s) == ESP_OK) - n = 1; - if (nvs_get_blob(nvh, "ap-key.pem", NULL, &s) == ESP_OK) - n |= 2; - s = sizeof(group) - 1; - group[0] = '\0'; - role[0] = '\0'; - nvs_get_str(nvh, "group", group, &s); - nvs_get_str(nvh, "role", role, &s); - - nvs_close(nvh); - - ir.ns.name[0] = '\0'; - subject[0] = '\0'; - - if (t.tv_sec > 1464083026 && - !lws_tls_vhost_cert_info(vhd->vhost, - LWS_TLS_CERT_INFO_VALIDITY_TO, &ir, 0)) { - vhd->cert_remaining_days = - (ir.time - t.tv_sec) / (24 * 3600); - ir.ns.name[0] = '\0'; - lws_tls_vhost_cert_info(vhd->vhost, - LWS_TLS_CERT_INFO_COMMON_NAME, &ir, - sizeof(ir.ns.name)); - lws_strncpy(subject, ir.ns.name, sizeof(subject)); - - ir.ns.name[0] = '\0'; - lws_tls_vhost_cert_info(vhd->vhost, - LWS_TLS_CERT_INFO_ISSUER_NAME, &ir, - sizeof(ir.ns.name)); - } - - /* - * this value in the JSON is just - * used for UI indication. Each conditional feature confirms - * it itself before it allows itself to be used. - */ - - grt = lws_esp32_get_reboot_type(); - - esp_efuse_mac_get_default(mac); - strcpy(img_factory, " { \"date\": \"Empty\" }"); - strcpy(img_ota, " { \"date\": \"Empty\" }"); - - // if (grt != LWS_MAGIC_REBOOT_TYPE_FORCED_FACTORY_BUTTON) { - lws_esp32_get_image_info(esp_partition_find_first(ESP_PARTITION_TYPE_APP, - ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL), &i, - img_factory, sizeof(img_factory) - 1); - img_factory[sizeof(img_factory) - 1] = '\0'; - if (img_factory[0] == 0xff || strlen(img_factory) < 8) - strcpy(img_factory, " { \"date\": \"Empty\" }"); - - lws_esp32_get_image_info(esp_partition_find_first(ESP_PARTITION_TYPE_APP, - ESP_PARTITION_SUBTYPE_APP_OTA_0, NULL), &i, - img_ota, sizeof(img_ota) - 1); - img_ota[sizeof(img_ota) - 1] = '\0'; - if (img_ota[0] == 0xff || strlen(img_ota) < 8) - strcpy(img_ota, " { \"date\": \"Empty\" }"); - // } - - p += snprintf((char *)p, end - p, - "{ \"model\":\"%s\",\n" - " \"forced_button\":\"%d\",\n" - " \"serial\":\"%s\",\n" - " \"opts\":\"%s\",\n" - " \"host\":\"%s-%s\",\n" - " \"region\":\"%d\",\n" - " \"ssl_pub\":\"%d\",\n" - " \"ssl_pri\":\"%d\",\n" - " \"mac\":\"%02X%02X%02X%02X%02X%02X\",\n" - " \"ssid\":\"%s\",\n" - " \"conn_ip\":\"%s\",\n" - " \"conn_mask\":\"%s\",\n" - " \"conn_gw\":\"%s\",\n" - " \"certdays\":\"%d\",\n" - " \"unixtime\":\"%llu\",\n" - " \"certissuer\":\"%s\",\n" - " \"certsubject\":\"%s\",\n" - " \"le_dns\":\"%s\",\n" - " \"le_email\":\"%s\",\n" - " \"acme_state\":\"%d\",\n" - " \"acme_msg\":\"%s\",\n" - " \"button\":\"%d\",\n" - " \"group\":\"%s\",\n" - " \"role\":\"%s\",\n", - lws_esp32.model, - grt == LWS_MAGIC_REBOOT_TYPE_FORCED_FACTORY_BUTTON, - lws_esp32.serial, - lws_esp32.opts, - lws_esp32.model, lws_esp32.serial, - lws_esp32.region, - n & 1, (n >> 1) & 1, - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] | 1, - lws_esp32.active_ssid, - lws_esp32.sta_ip, - lws_esp32.sta_mask, - lws_esp32.sta_gw, - vhd->cert_remaining_days, - (unsigned long long)t.tv_sec, - ir.ns.name, subject, - lws_esp32.le_dns, - lws_esp32.le_email, - vhd->acme_state, - vhd->acme_msg, - ((volatile struct lws_esp32 *)(&lws_esp32))->button_is_down, - group, role); - p += snprintf((char *)p, end - p, - " \"img_factory\": %s,\n" - " \"img_ota\": %s,\n", - img_factory, - img_ota - ); - - - n = LWS_WRITE_TEXT | LWS_WRITE_NO_FIN; - pss->scan_state = SCAN_STATE_INITIAL_MANIFEST; - pss->ap_record = 0; - pss->subsequent = 0; - break; - - case SCAN_STATE_INITIAL_MANIFEST: - p += snprintf((char *)p, end - p, - " \"latest\": %s,\n" - " \"inet\":\"%d\",\n", - vhd->json, - lws_esp32.inet - ); - - p += snprintf((char *)p, end - p, - " \"known\":[\n"); - - n = LWS_WRITE_CONTINUATION | LWS_WRITE_NO_FIN; - pss->scan_state = SCAN_STATE_KNOWN; - break; - - case SCAN_STATE_KNOWN: - if (nvs_open("lws-station", NVS_READONLY, &nvh)) { - lwsl_notice("unable to open nvh\n"); - return -1; - } - - for (m = 0; m < 4; m++) { - char name[10], ssid[65]; - unsigned int pp = 0, use = 0; - - if (m) - *p++ = ','; - - s = sizeof(ssid) - 1; - ssid[0] = '\0'; - lws_snprintf(name, sizeof(name) - 1, "%dssid", m); - nvs_get_str(nvh, name, ssid, &s); - lws_snprintf(name, sizeof(name) - 1, "%dpassword", m); - s = 10; - nvs_get_str(nvh, name, NULL, &s); - pp = !!s; - lws_snprintf(name, sizeof(name) - 1, "%duse", m); - nvs_get_u32(nvh, name, &use); - - p += snprintf((char *)p, end - p, - "{\"ssid\":\"%s\",\n" - " \"pp\":\"%u\",\n" - "\"use\":\"%u\"}\n", - ssid, pp, use); - } - nvs_close(nvh); - pss->ap_record = 0; - - p += snprintf((char *)p, end - p, - "], \"aps\":[\n"); - - n = LWS_WRITE_CONTINUATION | LWS_WRITE_NO_FIN; - pss->scan_state = SCAN_STATE_LIST; - break; - - case SCAN_STATE_LIST: - lwscan = vhd->known_aps_list; - - n = pss->ap_record; - while (lwscan && n--) - lwscan = lwscan->next; - - for (m = 0; m < 6; m++) { - n = LWS_WRITE_CONTINUATION | LWS_WRITE_NO_FIN; - if (!lwscan) - goto scan_state_final; - - if (pss->subsequent) - *p++ = ','; - pss->subsequent = 1; - pss->ap_record++; - - p += snprintf((char *)p, end - p, - "{\"ssid\":\"%s\",\n" - "\"bssid\":\"%02X:%02X:%02X:%02X:%02X:%02X\",\n" - "\"rssi\":\"%d\",\n" - "\"chan\":\"%d\",\n" - "\"auth\":\"%d\"}\n", - lwscan->ssid, - lwscan->bssid[0], lwscan->bssid[1], lwscan->bssid[2], - lwscan->bssid[3], lwscan->bssid[4], lwscan->bssid[5], - lws_wifi_scan_rssi(lwscan), - lwscan->channel, lwscan->authmode); - - lwscan = lwscan->next; - if (!lwscan) - pss->scan_state = SCAN_STATE_FINAL; - } - break; - - case SCAN_STATE_FINAL: -scan_state_final: - n = LWS_WRITE_CONTINUATION; - p += sprintf((char *)p, "]\n}\n"); - if (pss->changed_partway) { - pss->changed_partway = 0; - pss->subsequent = 0; - pss->scan_state = SCAN_STATE_INITIAL; - } else { - pss->scan_state = SCAN_STATE_NONE; - vhd->autonomous_update_sampled = vhd->autonomous_update; - } - break; - default: - return 0; - } -issue: - m = lws_write(wsi, (unsigned char *)start, p - start, n); - if (m < 0) { - lwsl_err("ERROR %d writing to di socket\n", m); - return -1; - } - - if (pss->scan_state != SCAN_STATE_NONE) - lws_callback_on_writable(wsi); - - break; - - case LWS_CALLBACK_VHOST_CERT_UPDATE: - lwsl_notice("LWS_CALLBACK_VHOST_CERT_UPDATE: %d\n", (int)len); - vhd->acme_state = (int)len; - if (in) { - lws_strncpy(vhd->acme_msg, in, sizeof(vhd->acme_msg)); - lwsl_notice("acme_msg: %s\n", (char *)in); - } - lws_callback_on_writable_all_protocol_vhost(vhd->vhost, vhd->protocol); - break; - - case LWS_CALLBACK_RECEIVE: - { - const char *sect = "\"app\": {", *b; - nvs_handle nvh; - char p[64], use[6]; - int n, si = -1; - - if (strstr((const char *)in, "identify")) { - lws_esp32_identify_physical_device(); - break; - } - - if (vhd->json_len && strstr((const char *)in, "update-factory")) { - sect = "\"factory\": {"; - goto auton; - } - if (vhd->json_len && strstr((const char *)in, "update-ota")) - goto auton; - - if (strstr((const char *)in, "\"reset\"")) - goto sched_reset; - - if (!strncmp((const char *)in, "{\"job\":\"start-le\"", 17)) - goto start_le; - - - if (nvs_open("lws-station", NVS_READWRITE, &nvh) != ESP_OK) { - lwsl_err("Unable to open nvs\n"); - break; - } - - if (!esplws_simple_arg(p, sizeof(p), in, ",\"slot\":\"")) - si = atoi(p); - - lwsl_notice("si %d\n", si); - - for (n = 0; n < LWS_ARRAY_SIZE(store_json); n++) { - if (esplws_simple_arg(p, sizeof(p), in, store_json[n].j)) - continue; - - /* only change access password if he has physical access to device */ - if (n == 8 && lws_esp32_get_reboot_type() != LWS_MAGIC_REBOOT_TYPE_FORCED_FACTORY_BUTTON) - continue; - - if (lws_nvs_set_str(nvh, store_json[n].nvs, p) != ESP_OK) { - lwsl_err("Unable to store %s in nvm\n", store_json[n].nvs); - goto bail_nvs; - } - - if (si != -1 && n < 8) { - if (!(n & 1)) { - lws_strncpy(lws_esp32.ssid[(n >> 1) & 3], p, - sizeof(lws_esp32.ssid[0])); - lws_snprintf(use, sizeof(use) - 1, "%duse", si); - lwsl_notice("resetting %s to 0\n", use); - nvs_set_u32(nvh, use, 0); - - } else - lws_strncpy(lws_esp32.password[(n >> 1) & 3], p, - sizeof(lws_esp32.password[0])); - } - - } - - nvs_commit(nvh); - nvs_close(nvh); - - if (strstr((const char *)in, "\"factory-reset\"")) { - if (lws_esp32_get_reboot_type() == - LWS_MAGIC_REBOOT_TYPE_FORCED_FACTORY_BUTTON) { - - lwsl_notice("Doing factory reset\n"); - ESP_ERROR_CHECK(nvs_open("lws-station", NVS_READWRITE, &nvh)); - n = nvs_erase_all(nvh); - if (n) - lwsl_notice("erase_all failed %d\n", n); - nvs_commit(nvh); - nvs_close(nvh); - - goto sched_reset; - } else - lwsl_notice("failed on factory button boot\n"); - } - - if (vhd->scan_ongoing) - vhd->changed_settings = 1; - else - lws_esp32_wlan_nvs_get(1); - - lwsl_notice("set Join AP info\n"); - break; - -bail_nvs: - nvs_close(nvh); - - return 1; - -sched_reset: - vhd->reboot_timer = xTimerCreate("x", pdMS_TO_TICKS(250), 0, vhd, - (TimerCallbackFunction_t)reboot_timer_cb); - xTimerStart(vhd->reboot_timer, 0); - - return 1; - -auton: - lwsl_notice("Autonomous upload\n"); - b = strstr(vhd->json, sect); - if (!b) { - lwsl_notice("Can't find %s in JSON\n", sect); - return 1; - } - b = strstr(b, "\"file\": \""); - if (!b) { - lwsl_notice("Can't find \"file\": JSON\n"); - return 1; - } - vhd->autonomous_update = 1; - if (pss->scan_state == SCAN_STATE_NONE) - vhd->autonomous_update_sampled = 1; - b += 9; - n = 0; - while ((*b != '\"') && n < sizeof(p) - 1) - p[n++] = *b++; - - p[n] = '\0'; - - vhd->part = ota_choose_part(); - if (!vhd->part) - return 1; - - if (client_connection(vhd, p)) - vhd->autonomous_update = 0; - - break; - -start_le: - lws_esp32.acme = 1; /* hold off scanning */ - puts(in); - /* - * {"job":"start-le","cn":"home.warmcat.com", - * "email":"andy@warmcat.com", "staging":"true"} - */ - - if (nvs_open("lws-station", NVS_READWRITE, &nvh) != ESP_OK) { - lwsl_err("Unable to open nvs\n"); - break; - } - - n = 0; - b = strstr(in, ",\"cn\":\""); - if (b) { - b += 7; - while (*b && *b != '\"' && n < sizeof(lws_esp32.le_dns) - 1) - lws_esp32.le_dns[n++] = *b++; - } - lws_esp32.le_dns[n] = '\0'; - - lws_nvs_set_str(nvh, "acme-cn", lws_esp32.le_dns); - n = 0; - b = strstr(in, ",\"email\":\""); - if (b) { - b += 10; - while (*b && *b != '\"' && n < sizeof(lws_esp32.le_email) - 1) - lws_esp32.le_email[n++] = *b++; - } - lws_esp32.le_email[n] = '\0'; - lws_nvs_set_str(nvh, "acme-email", lws_esp32.le_email); - nvs_commit(nvh); - - nvs_close(nvh); - - n = 1; - b = strstr(in, ",\"staging\":\""); - if (b) - lwsl_notice("staging: %s\n", b); - if (b && b[12] == 'f') - n = 0; - - lwsl_notice("cn: %s, email: %s, staging: %d\n", lws_esp32.le_dns, lws_esp32.le_email, n); - - { - struct lws_acme_cert_aging_args caa; - - memset(&caa, 0, sizeof(caa)); - caa.vh = vhd->vhost; - - caa.element_overrides[LWS_TLS_REQ_ELEMENT_COMMON_NAME] = lws_esp32.le_dns; - caa.element_overrides[LWS_TLS_REQ_ELEMENT_EMAIL] = lws_esp32.le_email; - - if (n) - caa.element_overrides[LWS_TLS_SET_DIR_URL] = - "https://acme-staging.api.letsencrypt.org/directory"; /* staging */ - else - caa.element_overrides[LWS_TLS_SET_DIR_URL] = - "https://acme-v01.api.letsencrypt.org/directory"; /* real */ - - lws_callback_vhost_protocols_vhost(vhd->vhost, - LWS_CALLBACK_VHOST_CERT_AGING, - (void *)&caa, 0); - } - - break; - - } - - case LWS_CALLBACK_CLOSED: - { - struct per_session_data__esplws_scan **p = &vhd->live_pss_list; - - while (*p) { - if ((*p) == pss) { - *p = pss->next; - continue; - } - - p = &((*p)->next); - } - - vhd->count_live_pss--; - } - if (!vhd->live_pss_list) - xTimerStop(vhd->timer, 0); - break; - - /* "factory" POST handling */ - - case LWS_CALLBACK_HTTP_BODY: - /* create the POST argument parser if not already existing */ - if (!pss->spa) { - pss->spa = lws_spa_create(wsi, param_names, - LWS_ARRAY_SIZE(param_names), 1024, - file_upload_cb, pss); - if (!pss->spa) - return -1; - - pss->filename[0] = '\0'; - pss->file_length = 0; - } - //puts((const char *)in); - /* let it parse the POST data */ - if (lws_spa_process(pss->spa, in, len)) - return -1; - break; - - case LWS_CALLBACK_HTTP_BODY_COMPLETION: - lwsl_notice("LWS_CALLBACK_HTTP_BODY_COMPLETION (scan)\n"); - /* call to inform no more payload data coming */ - lws_spa_finalize(pss->spa); - - for (n = 0; n < LWS_ARRAY_SIZE(param_names); n++) - if (lws_spa_get_string(pss->spa, n)) - lwsl_notice(" Param %s: %s\n", param_names[n], - lws_spa_get_string(pss->spa, n)); - else - lwsl_notice(" Param %s: (none)\n", - param_names[n]); - - if (nvs_open("lws-station", NVS_READWRITE, &nvh) != ESP_OK) { - lwsl_err("Unable to open nvs\n"); - break; - } - - if (lws_esp32_get_reboot_type() == LWS_MAGIC_REBOOT_TYPE_FORCED_FACTORY_BUTTON) { - - if (lws_spa_get_string(pss->spa, EPN_SERIAL)) { - if (lws_nvs_set_str(nvh, "serial", lws_spa_get_string(pss->spa, EPN_SERIAL)) != ESP_OK) { - lwsl_err("Unable to store serial in nvm\n"); - goto bail_nvs; - } - - nvs_commit(nvh); - } - - if (lws_spa_get_string(pss->spa, EPN_OPTS)) { - if (lws_nvs_set_str(nvh, "opts", lws_spa_get_string(pss->spa, EPN_OPTS)) != ESP_OK) { - lwsl_err("Unable to store options in nvm\n"); - goto bail_nvs; - } - - nvs_commit(nvh); - } - } - - if (lws_spa_get_string(pss->spa, EPN_GROUP)) { - if (lws_nvs_set_str(nvh, "group", lws_spa_get_string(pss->spa, EPN_GROUP)) != ESP_OK) { - lwsl_err("Unable to store group in nvm\n"); - goto bail_nvs; - } - - nvs_commit(nvh); - } - - if (lws_spa_get_string(pss->spa, EPN_ROLE)) { - if (lws_nvs_set_str(nvh, "role", lws_spa_get_string(pss->spa, EPN_ROLE)) != ESP_OK) { - lwsl_err("Unable to store group in nvm\n"); - goto bail_nvs; - } - - nvs_commit(nvh); - } - - nvs_close(nvh); - - pss->result_len = snprintf(pss->result + LWS_PRE, sizeof(pss->result) - LWS_PRE - 1, - "OK"); - - if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end)) - goto bail; - - if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE, - (unsigned char *)"text/html", 9, &p, end)) - goto bail; - if (lws_add_http_header_content_length(wsi, pss->result_len, &p, end)) - goto bail; - if (lws_finalize_http_header(wsi, &p, end)) - goto bail; - - n = lws_write(wsi, start, p - start, LWS_WRITE_HTTP_HEADERS); - goto bail; - - case LWS_CALLBACK_HTTP_WRITEABLE: - lwsl_debug("LWS_CALLBACK_HTTP_WRITEABLE: sending %d\n", - pss->result_len); - if (!pss->result_len) - break; - n = lws_write(wsi, (unsigned char *)pss->result + LWS_PRE, - pss->result_len, LWS_WRITE_HTTP); - if (n < 0) - return 1; - - vhd->reboot_timer = xTimerCreate("x", pdMS_TO_TICKS(3000), 0, vhd, - (TimerCallbackFunction_t)reboot_timer_cb); - xTimerStart(vhd->reboot_timer, 0); - - return 1; // hang up since we will reset - - /* ----- client handling ----- */ - - case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: - lwsl_notice("Client connection error %s\n", (char *)in); - vhd->cwsi = NULL; - break; - - case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: - if (!vhd->autonomous_update) - break; - - { - char pp[20]; - - if (lws_hdr_copy(wsi, pp, sizeof(pp) - 1, WSI_TOKEN_HTTP_CONTENT_LENGTH) < 0) - return -1; - - vhd->content_length = atoi(pp); - if (vhd->content_length <= 0 || - vhd->content_length > vhd->part->size) - return -1; - - if (esp_ota_begin(vhd->part, (long)-1, &vhd->otahandle) != ESP_OK) { - lwsl_err("OTA: Failed to begin\n"); - return 1; - } - - vhd->file_length = 0; - break; - } - break; - - case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: - //lwsl_notice("LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: %ld\n", - // (long)len); - - if (!vhd->autonomous_update) { - if (sizeof(vhd->json) - vhd->json_len - 1 < len) - len = sizeof(vhd->json) - vhd->json_len - 1; - memcpy(vhd->json + vhd->json_len, in, len); - vhd->json_len += len; - vhd->json[vhd->json_len] = '\0'; - break; - } - - /* autonomous download */ - - - if (vhd->file_length + len > vhd->part->size) { - lwsl_err("OTA: incoming file too large\n"); - goto abort_ota; - } - - lwsl_debug("writing 0x%lx... 0x%lx\n", - vhd->part->address + vhd->file_length, - vhd->part->address + vhd->file_length + len); - if (esp_ota_write(vhd->otahandle, in, len) != ESP_OK) { - lwsl_err("OTA: Failed to write\n"); - goto abort_ota; - } - vhd->file_length += len; - - lws_callback_on_writable_all_protocol(vhd->context, vhd->protocol); - break; - -abort_ota: - esp_ota_end(vhd->otahandle); - vhd->otahandle = 0; - vhd->autonomous_update = 0; - - return 1; - - case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: - { - char *px = (char *)pss->buffer + LWS_PRE; - int lenx = sizeof(pss->buffer) - LWS_PRE - 1; - - //lwsl_notice("LWS_CALLBACK_RECEIVE_CLIENT_HTTP: %d\n", len); - - if (lws_http_client_read(wsi, &px, &lenx) < 0) - return -1; - } - break; - - case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: - lwsl_notice("LWS_CALLBACK_COMPLETED_CLIENT_HTTP\n"); - vhd->cwsi = NULL; - if (!vhd->autonomous_update) { - - vhd->checked_updates = 1; - puts(vhd->json); - return -1; - } - - /* autonomous download */ - - lwsl_notice("auton complete\n"); - - if (esp_ota_end(vhd->otahandle) != ESP_OK) { - lwsl_err("OTA: end failed\n"); - return 1; - } - - if (esp_ota_set_boot_partition(vhd->part) != ESP_OK) { - lwsl_err("OTA: set boot part failed\n"); - return 1; - } - vhd->otahandle = 0; - vhd->autonomous_update = 0; - - vhd->reboot_timer = xTimerCreate("x", pdMS_TO_TICKS(250), 0, vhd, - (TimerCallbackFunction_t)reboot_timer_cb); - xTimerStart(vhd->reboot_timer, 0); - return -1; - - case LWS_CALLBACK_CLOSED_CLIENT_HTTP: - lwsl_notice("LWS_CALLBACK_CLOSED_CLIENT_HTTP\n"); - break; - - case LWS_CALLBACK_HTTP_DROP_PROTOCOL: - /* called when our wsi user_space is going to be destroyed */ - if (pss->spa) { - lws_spa_destroy(pss->spa); - pss->spa = NULL; - } - break; - - default: - break; - } - - return 0; - -bail: - return 1; -} - -#define LWS_PLUGIN_PROTOCOL_ESPLWS_SCAN \ - { \ - "esplws-scan", \ - callback_esplws_scan, \ - sizeof(struct per_session_data__esplws_scan), \ - 1024, 0, NULL, 900 \ - } - diff -Nru libwebsockets-4.0.20/plugins/protocol_fulltext_demo.c libwebsockets-4.1.6/plugins/protocol_fulltext_demo.c --- libwebsockets-4.0.20/plugins/protocol_fulltext_demo.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/protocol_fulltext_demo.c 2020-12-01 17:40:26.000000000 +0000 @@ -266,28 +266,17 @@ LWS_PLUGIN_PROTOCOL_FULLTEXT_DEMO }; -LWS_VISIBLE int -init_protocol_fulltext_demo(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } +LWS_VISIBLE const lws_plugin_protocol_t fulltext_demo = { + .hdr = { + "fulltext demo", + "lws_protocol_plugin", + LWS_PLUGIN_API_MAGIC + }, - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} - -LWS_VISIBLE int -destroy_protocol_fulltext_demo(struct lws_context *context) -{ - return 0; -} + .protocols = protocols, + .count_protocols = LWS_ARRAY_SIZE(protocols), + .extensions = NULL, + .count_extensions = 0, +}; #endif diff -Nru libwebsockets-4.0.20/plugins/protocol_lws_mirror.c libwebsockets-4.1.6/plugins/protocol_lws_mirror.c --- libwebsockets-4.0.20/plugins/protocol_lws_mirror.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/protocol_lws_mirror.c 2020-12-01 17:40:26.000000000 +0000 @@ -206,6 +206,15 @@ switch (reason) { case LWS_CALLBACK_ESTABLISHED: lwsl_info("%s: LWS_CALLBACK_ESTABLISHED\n", __func__); + if (!v) { + lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi), + lws_get_protocol(wsi), + sizeof(struct per_vhost_data__lws_mirror)); + v = (struct per_vhost_data__lws_mirror *) + lws_protocol_vh_priv_get(lws_get_vhost(wsi), + lws_get_protocol(wsi)); + lws_pthread_mutex_init(&v->lock); + } /* * mirror instance name... defaults to "", but if URL includes @@ -332,13 +341,15 @@ return 1; /* disallow compression */ case LWS_CALLBACK_PROTOCOL_INIT: /* per vhost */ - lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi), + if (!v) { + lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi), lws_get_protocol(wsi), sizeof(struct per_vhost_data__lws_mirror)); - v = (struct per_vhost_data__lws_mirror *) + v = (struct per_vhost_data__lws_mirror *) lws_protocol_vh_priv_get(lws_get_vhost(wsi), lws_get_protocol(wsi)); - lws_pthread_mutex_init(&v->lock); + lws_pthread_mutex_init(&v->lock); + } break; case LWS_CALLBACK_PROTOCOL_DESTROY: @@ -471,27 +482,17 @@ LWS_PLUGIN_PROTOCOL_MIRROR }; -LWS_VISIBLE int -init_protocol_lws_mirror(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } - - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} +LWS_VISIBLE const lws_plugin_protocol_t lws_mirror = { + .hdr = { + "lws mirror", + "lws_protocol_plugin", + LWS_PLUGIN_API_MAGIC + }, + + .protocols = protocols, + .count_protocols = LWS_ARRAY_SIZE(protocols), + .extensions = NULL, + .count_extensions = 0, +}; -LWS_VISIBLE int -destroy_protocol_lws_mirror(struct lws_context *context) -{ - return 0; -} #endif diff -Nru libwebsockets-4.0.20/plugins/protocol_lws_raw_test.c libwebsockets-4.1.6/plugins/protocol_lws_raw_test.c --- libwebsockets-4.0.20/plugins/protocol_lws_raw_test.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/protocol_lws_raw_test.c 2020-12-01 17:40:26.000000000 +0000 @@ -72,6 +72,9 @@ #endif #include +#include + +#include struct per_vhost_data__raw_test { struct lws_context *context; @@ -278,28 +281,17 @@ LWS_PLUGIN_PROTOCOL_RAW_TEST }; -LWS_VISIBLE int -init_protocol_lws_raw_test(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } - - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} - -LWS_VISIBLE int -destroy_protocol_lws_raw_test(struct lws_context *context) -{ - return 0; -} +LWS_VISIBLE const lws_plugin_protocol_t lws_raw_test = { + .hdr = { + "lws raw test", + "lws_protocol_plugin", + LWS_PLUGIN_API_MAGIC + }, + + .protocols = protocols, + .count_protocols = LWS_ARRAY_SIZE(protocols), + .extensions = NULL, + .count_extensions = 0, +}; #endif diff -Nru libwebsockets-4.0.20/plugins/protocol_lws_server_status.c libwebsockets-4.1.6/plugins/protocol_lws_server_status.c --- libwebsockets-4.0.20/plugins/protocol_lws_server_status.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/protocol_lws_server_status.c 2020-12-01 17:40:26.000000000 +0000 @@ -47,6 +47,7 @@ struct lws_context *context; struct lws_vhost *vhost; const struct lws_protocols *protocol; + lws_sorted_usec_list_t sul; int hide_vhosts; int tow_flag; int period_s; @@ -58,8 +59,9 @@ static const struct lws_protocols protocols[1]; static void -update(struct vhd *v) +update(struct lws_sorted_usec_list *sul) { + struct vhd *v = lws_container_of(sul, struct vhd, sul); struct lws_ss_filepath *fp; char contents[256], pure[256], *p = v->d.buf + LWS_PRE, *end = v->d.buf + sizeof(v->d.buf) - LWS_PRE - 1; @@ -97,6 +99,8 @@ v->d.length = p - (v->d.buf + LWS_PRE); lws_callback_on_writable_all_protocol(v->context, &protocols[0]); + + lws_sul_schedule(v->context, 0, &v->sul, update, v->period_s * LWS_US_PER_SEC); } static int @@ -116,12 +120,9 @@ case LWS_CALLBACK_ESTABLISHED: lwsl_info("%s: LWS_CALLBACK_ESTABLISHED\n", __func__); if (!v->clients++) { - lws_timed_callback_vh_protocol(v->vhost, v->protocol, - LWS_CALLBACK_USER, v->period_s); + lws_sul_schedule(lws_get_context(wsi), 0, &v->sul, update, 1); lwsl_info("%s: starting updates\n", __func__); } - update(v); - break; case LWS_CALLBACK_CLOSED: @@ -130,13 +131,6 @@ break; - case LWS_CALLBACK_USER: - update(v); - if (v->clients) - lws_timed_callback_vh_protocol(v->vhost, v->protocol, - LWS_CALLBACK_USER, v->period_s); - break; - case LWS_CALLBACK_PROTOCOL_INIT: /* per vhost */ if (v) break; @@ -158,6 +152,8 @@ v->period_s = 5; if (!strcmp(pvo->name, "filepath")) { fp = malloc(sizeof(*fp)); + if (!fp) + return -1; fp->next = NULL; lws_snprintf(&fp->filepath[0], sizeof(fp->filepath), "%s", @@ -171,8 +167,7 @@ v->vhost = lws_get_vhost(wsi); v->protocol = lws_get_protocol(wsi); - /* get the initial data */ - update(v); + lws_sul_schedule(lws_get_context(wsi), 0, &v->sul, update, 1); break; case LWS_CALLBACK_PROTOCOL_DESTROY: /* per vhost */ @@ -209,26 +204,15 @@ }, }; -LWS_VISIBLE int -init_protocol_lws_server_status(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", - LWS_PLUGIN_API_MAGIC, c->api_magic); - return 1; - } - - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} +LWS_VISIBLE const lws_plugin_protocol_t lws_server_status = { + .hdr = { + "lws server status", + "lws_protocol_plugin", + LWS_PLUGIN_API_MAGIC + }, -LWS_VISIBLE int -destroy_protocol_lws_server_status(struct lws_context *context) -{ - return 0; -} + .protocols = protocols, + .count_protocols = LWS_ARRAY_SIZE(protocols), + .extensions = NULL, + .count_extensions = 0, +}; diff -Nru libwebsockets-4.0.20/plugins/protocol_lws_sshd_demo.c libwebsockets-4.1.6/plugins/protocol_lws_sshd_demo.c --- libwebsockets-4.0.20/plugins/protocol_lws_sshd_demo.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/protocol_lws_sshd_demo.c 2020-12-01 17:40:26.000000000 +0000 @@ -29,6 +29,7 @@ #include #include #include +#include #define TEST_SERVER_KEY_PATH "/etc/lws-test-sshd-server-key" @@ -455,28 +456,17 @@ LWS_PLUGIN_PROTOCOL_LWS_SSHD_DEMO }; -LWS_VISIBLE int -init_protocol_lws_sshd_demo(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } - - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} - -LWS_VISIBLE int -destroy_protocol_lws_sshd_demo(struct lws_context *context) -{ - return 0; -} +LWS_VISIBLE const lws_plugin_protocol_t lws_sshd_demo = { + .hdr = { + "lws sshd demo", + "lws_protocol_plugin", + LWS_PLUGIN_API_MAGIC + }, + + .protocols = protocols, + .count_protocols = LWS_ARRAY_SIZE(protocols), + .extensions = NULL, + .count_extensions = 0, +}; #endif diff -Nru libwebsockets-4.0.20/plugins/protocol_lws_status.c libwebsockets-4.1.6/plugins/protocol_lws_status.c --- libwebsockets-4.0.20/plugins/protocol_lws_status.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/protocol_lws_status.c 2020-12-01 17:40:26.000000000 +0000 @@ -245,29 +245,17 @@ LWS_PLUGIN_PROTOCOL_LWS_STATUS }; - -LWS_VISIBLE int -init_protocol_lws_status(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } - - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} - -LWS_VISIBLE int -destroy_protocol_lws_status(struct lws_context *context) -{ - return 0; -} +LWS_VISIBLE const lws_plugin_protocol_t lws_status = { + .hdr = { + "lws status", + "lws_protocol_plugin", + LWS_PLUGIN_API_MAGIC + }, + + .protocols = protocols, + .count_protocols = LWS_ARRAY_SIZE(protocols), + .extensions = NULL, + .count_extensions = 0, +}; #endif diff -Nru libwebsockets-4.0.20/plugins/protocol_post_demo.c libwebsockets-4.1.6/plugins/protocol_post_demo.c --- libwebsockets-4.0.20/plugins/protocol_post_demo.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/protocol_post_demo.c 2020-12-01 17:40:26.000000000 +0000 @@ -287,28 +287,17 @@ LWS_PLUGIN_PROTOCOL_POST_DEMO }; -LWS_VISIBLE int -init_protocol_post_demo(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } +LWS_VISIBLE const lws_plugin_protocol_t post_demo = { + .hdr = { + "post demo", + "lws_protocol_plugin", + LWS_PLUGIN_API_MAGIC + }, - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} - -LWS_VISIBLE int -destroy_protocol_post_demo(struct lws_context *context) -{ - return 0; -} + .protocols = protocols, + .count_protocols = LWS_ARRAY_SIZE(protocols), + .extensions = NULL, + .count_extensions = 0, +}; #endif diff -Nru libwebsockets-4.0.20/plugins/raw-proxy/protocol_lws_raw_proxy.c libwebsockets-4.1.6/plugins/raw-proxy/protocol_lws_raw_proxy.c --- libwebsockets-4.0.20/plugins/raw-proxy/protocol_lws_raw_proxy.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/raw-proxy/protocol_lws_raw_proxy.c 2020-12-01 17:40:26.000000000 +0000 @@ -562,29 +562,18 @@ LWS_PLUGIN_PROTOCOL_RAW_PROXY }; -LWS_VISIBLE int -init_protocol_lws_raw_proxy(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } - - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} - -LWS_VISIBLE int -destroy_protocol_lws_raw_proxy(struct lws_context *context) -{ - return 0; -} +LWS_VISIBLE const lws_plugin_protocol_t lws_raw_proxy = { + .hdr = { + "raw proxy", + "lws_protocol_plugin", + LWS_PLUGIN_API_MAGIC + }, + + .protocols = protocols, + .count_protocols = LWS_ARRAY_SIZE(protocols), + .extensions = NULL, + .count_extensions = 0, +}; #endif diff -Nru libwebsockets-4.0.20/plugins/ssh-base/sshd.c libwebsockets-4.1.6/plugins/ssh-base/sshd.c --- libwebsockets-4.0.20/plugins/ssh-base/sshd.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugins/ssh-base/sshd.c 2020-12-01 17:40:26.000000000 +0000 @@ -2565,27 +2565,17 @@ #if !defined (LWS_PLUGIN_STATIC) -LWS_VISIBLE int -init_protocol_lws_ssh_base(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } +LWS_VISIBLE const lws_plugin_protocol_t lws_ssh_base = { + .hdr = { + "ssh base", + "lws_protocol_plugin", + LWS_PLUGIN_API_MAGIC + }, - c->protocols = protocols_sshd; - c->count_protocols = LWS_ARRAY_SIZE(protocols_sshd); - c->extensions = NULL; - c->count_extensions = 0; + .protocols = protocols_sshd, + .count_protocols = LWS_ARRAY_SIZE(protocols_sshd), + .extensions = NULL, + .count_extensions = 0, +}; - return 0; -} - -LWS_VISIBLE int -destroy_protocol_lws_ssh_base(struct lws_context *context) -{ - return 0; -} #endif diff -Nru libwebsockets-4.0.20/plugin-standalone/CMakeLists.txt libwebsockets-4.1.6/plugin-standalone/CMakeLists.txt --- libwebsockets-4.0.20/plugin-standalone/CMakeLists.txt 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugin-standalone/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -1,4 +1,5 @@ cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) if(NOT DEFINED CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type") @@ -57,7 +58,7 @@ source_group("Sources" FILES ${PLUGIN_SRCS}) add_library(${PLUGIN_NAME} SHARED ${PLUGIN_SRCS} ${PLUGIN_HDR}) -target_link_libraries(${PLUGIN_NAME} -lwebsockets) +target_link_libraries(${PLUGIN_NAME} -lwebsockets ${LIBWEBSOCKETS_DEP_LIBS}) # Set test app specific defines. set_property(TARGET ${PLUGIN_NAME} diff -Nru libwebsockets-4.0.20/plugin-standalone/protocol_example_standalone.c libwebsockets-4.1.6/plugin-standalone/protocol_example_standalone.c --- libwebsockets-4.0.20/plugin-standalone/protocol_example_standalone.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/plugin-standalone/protocol_example_standalone.c 2020-12-01 17:40:26.000000000 +0000 @@ -127,26 +127,15 @@ }, }; -LWS_VISIBLE int -init_protocol_example_standalone(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } - - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} +LWS_VISIBLE const lws_plugin_protocol_t protocol_example_standalone = { + .hdr = { + "standalone", + "lws_protocol_plugin", + LWS_PLUGIN_API_MAGIC + }, -LWS_VISIBLE int -destroy_protocol_example_standalone(struct lws_context *context) -{ - return 0; -} + .protocols = protocols, + .count_protocols = LWS_ARRAY_SIZE(protocols), + .extensions = NULL, + .count_extensions = 0, +}; diff -Nru libwebsockets-4.0.20/README.md libwebsockets-4.1.6/README.md --- libwebsockets-4.0.20/README.md 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/README.md 2020-12-01 17:40:26.000000000 +0000 @@ -1,8 +1,8 @@ -[![Travis Build Status](https://travis-ci.org/warmcat/libwebsockets.svg)](https://travis-ci.org/warmcat/libwebsockets) [![Appveyor Build status](https://ci.appveyor.com/api/projects/status/qfasji8mnfnd2r8t?svg=true)](https://ci.appveyor.com/project/lws-team/libwebsockets) [![Coverity Scan Build Status](https://scan.coverity.com/projects/3576/badge.svg)](https://scan.coverity.com/projects/3576) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/2266/badge)](https://bestpractices.coreinfrastructure.org/projects/2266) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/144fb195a83046e484a75c8b4c6cfc99)](https://www.codacy.com/app/lws-team/libwebsockets?utm_source=github.com&utm_medium=referral&utm_content=warmcat/libwebsockets&utm_campaign=Badge_Grade) [![Total alerts](https://img.shields.io/lgtm/alerts/g/warmcat/libwebsockets.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/warmcat/libwebsockets/alerts/) [![Language grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/warmcat/libwebsockets.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/warmcat/libwebsockets/context:cpp) [![Language grade: JavaScript](https://img.shields.io/lgtm/grade/javascript/g/warmcat/libwebsockets.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/warmcat/libwebsockets/context:javascript) +[![CI status](https://libwebsockets.org/sai/status/libwebsockets)](https://libwebsockets.org/git/libwebsockets) [![Coverity Scan Build Status](https://scan.coverity.com/projects/3576/badge.svg)](https://scan.coverity.com/projects/3576) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/2266/badge)](https://bestpractices.coreinfrastructure.org/projects/2266) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/144fb195a83046e484a75c8b4c6cfc99)](https://www.codacy.com/app/lws-team/libwebsockets?utm_source=github.com&utm_medium=referral&utm_content=warmcat/libwebsockets&utm_campaign=Badge_Grade) [![Total alerts](https://img.shields.io/lgtm/alerts/g/warmcat/libwebsockets.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/warmcat/libwebsockets/alerts/) [![Language grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/warmcat/libwebsockets.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/warmcat/libwebsockets/context:cpp) [![Language grade: JavaScript](https://img.shields.io/lgtm/grade/javascript/g/warmcat/libwebsockets.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/warmcat/libwebsockets/context:javascript) # Libwebsockets -Libwebsockets is a simple-to-use, pure C library providing client and server +Libwebsockets is a simple-to-use, MIT-license, pure C library providing client and server for **http/1**, **http/2**, **websockets**, **MQTT** and other protocols in a security-minded, lightweight, configurable, scalable and flexible way. It's easy to build and cross-build via cmake and is suitable for tasks from embedded RTOS through mass @@ -16,6 +16,93 @@ News ---- +## v4.1.0 and v4.1-stable are released + +See the [changelog](https://libwebsockets.org/git/libwebsockets/tree/changelog), summary + + - NEW: travis / appveyor / bintray are replaced by Sai + https://libwebsockets.org/sai/ which for lws currently does 167 builds per + git push on 16 platforms, all self-hosted. The homebrew bash scripts used + to select Minimal examples are replaced by CTest. Platforms currently + include Fedora/AMD/GCC, Windows/AMD/mingw32, Windows/AMD/mingw64, Android/ + aarch64/LLVM, esp-idf (on WROVER-KIT and HELTEC physical boards), Fedora/ + RISCV (on QEMU)/GCC, CentOS8/AMD/GCC, Gentoo/AMD/GCC, Bionic/AMD/GCC, + Linkit 7697, Focal/AMD/GCC, Windows (on QEMU)/AMD/MSVC, + Focal/aarch64-RPI4/GCC, iOS/aarch64/LLVM and OSX/AMD/LLVM. + + - NEW: The single CMakeLists.txt has been refactored and modernized into smaller + CMakeLists.txt in the subdirectory along with the code that is being managed + for build by it. Build options are still listed in the top level as before + but the new way is much more maintainable. + + - NEW: Captive Portal Detection. Lws can determine if the active default + route is able to connect to the internet, or is in a captive portal type + situation, by trying to connect to a remote server that will respond in an + unusual way, like provide a 204. + + - NEW: Secure streams: Support system trust store if it exists + Build on Windows + Support lws raw socket protocol in SS + Support Unix Domain Socket transport + + - NEW: Windows: Support Unix Domain Sockets same as other platforms + + - NEW: Windows: Build using native pthreads, async dns, ipv6 on MSVC + + - NEW: lws_struct: BLOB support + + - NEW: lws_sul: Now provides two sorted timer domains, a default one as + before, and another whose scheduled events are capable to wake the system from suspend + + - NEW: System Message Distribution: lws_smd provides a very lightweight way + to pass short messages between subsystems both in RTOS type case where the + subsystems are all on the lws event loop, and in the case participants are in + different processes, using Secure Streams proxying. Participants register a bitmap + of message classes they care about; if no particpant cares about a particular message, + it is rejected at allocation time for the sender, making it cheap to provide messages + speculatively. See lib/system/smd/README.md for full details. + + - NEW: lws_drivers: wrappers for SDK driver abstractions (or actual drivers) + See lib/drivers/README.md, example implementations + minimal-examples/embedded/esp32/esp-wrover-kit + - generic gpio + - generic LED (by name) lib/drivers/led/README.md + - generic PWM, sophisticated interpolated table + sequencers with crossfade + - generic button (by name), with debounce and press classification + emitting rich SMD click, long-click, double-click, + down, repeat, up JSON messages + lib/drivers/button/README.md + - bitbang i2c on generic gpio (hw support can use same + abstract API) + - bitbang spi on generic gpio (hw support can use same + abstract API) + - generic display object, can be wired up to controller + drivers that hook up by generic i2c or spi, + generic backlight PWM sequencing and + blanking timer support + - generic settings storage: get and set blobs by name + - generic network device: netdev abstract class with + WIFI / Ethernet implementations + using underlying SDK APIs; + generic 80211 Scan managements + and credentials handling via + lws_settings + This is the new way to provide embedded platform + functionality that was in the past done like + esp32-factory. Unlike the old way, the new way has no + native apis in it and can be built on other SDK / SoCs + the same. + + - NEW: Security-aware JWS JWT (JSON Web Tokens) apis are provided on top of the existing + JOSE / JWS apis. All the common algorithms are available along with some + high level apis like lws http cookie -> JWT struct -> lws http cookie. + + - REMOVED: esp32-helper and friends used by esp32-factory now lws_drivers + exists + + - REMOVED: generic sessions and friends now JWT is provided + ## v4.0 is released Users wanting a stable branch should follow v4.0-stable to get the most stable version diff -Nru libwebsockets-4.0.20/READMEs/README.build-android.md libwebsockets-4.1.6/READMEs/README.build-android.md --- libwebsockets-4.0.20/READMEs/README.build-android.md 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/READMEs/README.build-android.md 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,77 @@ +# 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. diff -Nru libwebsockets-4.0.20/READMEs/README.build-windows.md libwebsockets-4.1.6/READMEs/README.build-windows.md --- libwebsockets-4.0.20/READMEs/README.build-windows.md 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/READMEs/README.build-windows.md 2020-12-01 17:40:26.000000000 +0000 @@ -1,28 +1,47 @@ # Some notes for the windows jungle -This was how I compiled libwebsockets in windows March 2020. +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! -## OpenSSL +## Notes on vm installation -### Installing prebuilt libs +### Disk size -I used the 1.1.1d (the latest) libs from here, as recommended on the OpenSSL site +For building you'll need 40GB+ available for the guest storage. -[overbyte.eu](https:..wiki.overbyte.eu/wiki/index.php/ICS_Download#Download_OpenSSL_Binaries_.28required_for_SSL-enabled_components.29) +### Required: Windows product key -I had to use procmon64 (windows' strace) to establish that these libraries are -looking for a cert bundle at "C:\Program Files\Common Files\SSL\cert.pem"... it's not -included in the zip file from the above, so... +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. -### Installing a cert bundle +### Required: Spice guest -You can get a trusted cert bundle from here +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. -[drwetter/testssl cert bundle](https://raw.githubusercontent.com/drwetter/testssl.sh/3.1dev/etc/Microsoft.pem) +https://www.spice-space.org/download/windows/spice-guest-tools/spice-guest-tools-latest.exe -Save it into `C:\Program Files\Common Files\SSL\cert.pem` where openssl will be able to see it. +### 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. -### Installing cmake +### Required: cmake CMake have a windows installer thing downloadable from here @@ -30,31 +49,133 @@ after that you can use `cmake` from the terminal OK. -### Installing git +### Required: git Visit the canonical git site to download their windows installer thing [git](https://git-scm.com/download/win) -after that `git` from the terminal is working. +**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! -### Install the free "community" visual studio +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. +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. -### Building +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. -Somehow windows cmake seems slightly broken, some of the plugins and -examples are conditional on `if (NOT WIN32)`, but it configures them -anyway. For this reason (it seems "only", it worked when I commented the -cmake entries for the related plugins) `-DLWS_WITH_MINIMAL_EXAMPLES=1` +``` +$ call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x86_amd64 +``` -Instead I followed how appveyor builds the stuff in CI... clone libwebsockets then +### 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 @@ -72,4 +193,22 @@ > cmake --install . --config DEBUG ``` -After that you can run the test apps OK. +### 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 + + diff -Nru libwebsockets-4.0.20/READMEs/README.captive-portal-detection.md libwebsockets-4.1.6/READMEs/README.captive-portal-detection.md --- libwebsockets-4.0.20/READMEs/README.captive-portal-detection.md 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/READMEs/README.captive-portal-detection.md 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,88 @@ +# 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); +``` + diff -Nru libwebsockets-4.0.20/READMEs/README.cmake.md libwebsockets-4.1.6/READMEs/README.cmake.md --- libwebsockets-4.0.20/READMEs/README.cmake.md 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/READMEs/README.cmake.md 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,41 @@ +# 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. + diff -Nru libwebsockets-4.0.20/READMEs/README.coding.md libwebsockets-4.1.6/READMEs/README.coding.md --- libwebsockets-4.0.20/READMEs/README.coding.md 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/READMEs/README.coding.md 2020-12-01 17:40:26.000000000 +0000 @@ -1,7 +1,7 @@ Notes about coding with lws =========================== -@section era Old lws and lws v2.0 +@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. diff -Nru libwebsockets-4.0.20/READMEs/README.ctest.md libwebsockets-4.1.6/READMEs/README.ctest.md --- libwebsockets-4.0.20/READMEs/README.ctest.md 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/READMEs/README.ctest.md 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,67 @@ +## 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. + + diff -Nru libwebsockets-4.0.20/READMEs/README.debugging.md libwebsockets-4.1.6/READMEs/README.debugging.md --- libwebsockets-4.0.20/READMEs/README.debugging.md 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/READMEs/README.debugging.md 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,63 @@ +# 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. + diff -Nru libwebsockets-4.0.20/READMEs/README.event-libs.md libwebsockets-4.1.6/READMEs/README.event-libs.md --- libwebsockets-4.0.20/READMEs/README.event-libs.md 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/READMEs/README.event-libs.md 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,80 @@ +# 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. + diff -Nru libwebsockets-4.0.20/READMEs/README.generic-sessions.md libwebsockets-4.1.6/READMEs/README.generic-sessions.md --- libwebsockets-4.0.20/READMEs/README.generic-sessions.md 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/READMEs/README.generic-sessions.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,373 +0,0 @@ -Notes about generic-sessions Plugin -=================================== - -@section gseb Enabling lwsgs for build - -Enable at CMake with -DLWS_WITH_GENERIC_SESSIONS=1 - -This also needs sqlite3 (libsqlite3-dev or similar package) - - -@section gsi lwsgs Introduction - -The generic-sessions protocol plugin provides cookie-based login -authentication for lws web and ws connections. - -The plugin handles everything about generic account registration, -email verification, lost password, account deletion, and other generic account -management. - -Other code, in another eg, ws protocol handler, only needs very high-level -state information from generic-sessions, ie, which user the client is -authenticated as. Everything underneath is managed in generic-sessions. - - - - random 20-byte session id managed in a cookie - - - all information related to the session held at the server, nothing managed clientside - - - sqlite3 used at the server to manage active sessions and users - - - defaults to creating anonymous sessions with no user associated - - - admin account (with user-selectable username) is defined in config with a SHA-1 of the password; rest of the accounts are in sqlite3 - - - user account passwords stored as salted SHA-1 with additional confounder - only stored in the JSON config, not the database - - - login, logout, register account + email verification built-in with examples - - - in a mount, some file suffixes (ie, .js) can be associated with a protocol for the purposes of rewriting symbolnames. These are read-only copies of logged-in server state. - - - When your page fetches .js or other rewritten files from that mount, "$lwsgs_user" and so on are rewritten on the fly using chunked transfer encoding - - - Eliminates server-side scripting with a few rewritten symbols and - javascript on client side - - - 32-bit bitfield for authentication sectoring, mounts can provide a mask on the loggin-in session's associated server-side bitfield that must be set for access. - - - No code (just config) required for, eg, private URL namespace that requires login to access. - - -@section gsin Lwsgs Integration to HTML - -Only three steps are needed to integrate lwsgs in your HTML. - -1) lwsgs HTML UI is bundled with the javascript it uses in `lwsgs.js`, so -import that script file in your head section - -2) define an empty div of id "lwsgs" somewhere - -3) Call lwsgs_initial() in your page - -That's it. An example is below - -``` - - - - - - - - - - - -
- - -
-
- - - - - - -``` - -@section gsof Lwsgs Overall Flow@ - -When the protocol is initialized, it gets per-vhost information from the config, such -as where the sqlite3 databases are to be stored. The admin username and sha-1 of the -admin password are also taken from here. - -In the mounts using protocol-generic-sessions, a cookie is maintained against any requests; if no cookie was active on the initial request a new session is -created with no attached user. - -So there should always be an active session after any transactions with the server. - -In the example html going to the mount /lwsgs loads a login / register page as the default. - -The

in the login page contains 'next url' hidden inputs that let the html 'program' where the form handler will go after a successful admin login, a successful user login and a failed login. - -After a successful login, the sqlite record at the server for the current session is updated to have the logged-in username associated with it. - - - -@section gsconf Lwsgs Configuration - -"auth-mask" defines the authorization sector bits that must be enabled on the session to gain access. - -"auth-mask" 0 is the default. - - - b0 is set if you are logged in as a user at all. - - b1 is set if you are logged in with the user configured to be admin - - b2 is set if the account has been verified (the account configured for admin is always verified) - - b3 is set if your session just did the forgot password flow successfully - -``` - { - # things in here can always be served - "mountpoint": "/lwsgs", - "origin": "file:///usr/share/libwebsockets-test-server/generic-sessions", - "origin": "callback://protocol-lws-messageboard", - "default": "generic-sessions-login-example.html", - "auth-mask": "0", - "interpret": { - ".js": "protocol-lws-messageboard" - } - }, { - # things in here can only be served if logged in as a user - "mountpoint": "/lwsgs/needauth", - "origin": "file:///usr/share/libwebsockets-test-server/generic-sessions/needauth", - "origin": "callback://protocol-lws-messageboard", - "default": "generic-sessions-login-example.html", - "auth-mask": "5", # logged in as a verified user - "interpret": { - ".js": "protocol-lws-messageboard" - } - }, { - # things in here can only be served if logged in as admin - "mountpoint": "/lwsgs/needadmin", - "origin": "file:///usr/share/libwebsockets-test-server/generic-sessions/needadmin", - "origin": "callback://protocol-lws-messageboard", - "default": "generic-sessions-login-example.html", - "auth-mask": "7", # b2 = verified (by email / or admin), b1 = admin, b0 = logged in with any user name - "interpret": { - ".js": "protocol-lws-messageboard" - } - } -``` -Note that the name of the real application protocol that uses generic-sessions -is used, not generic-sessions itself. - -The vhost configures the storage dir, admin credentials and session cookie lifetimes: - -``` - "ws-protocols": [{ - "protocol-generic-sessions": { - "status": "ok", - "admin-user": "admin", - - # create the pw hash like this (for the example pw, "jipdocesExunt" ) - # $ echo -n "jipdocesExunt" | sha1sum - # 046ce9a9cca769e85798133be06ef30c9c0122c9 - - # - # Obviously ** change this password hash to a secret one before deploying ** - # - "admin-password-sha1": "046ce9a9cca769e85798133be06ef30c9c0122c9", - "session-db": "/var/www/sessions/lws.sqlite3", - "timeout-idle-secs": "600", - "timeout-anon-idle-secs": "1200", - "timeout-absolute-secs": "6000", - # the confounder is part of the salted password hashes. If this config - # file is in a 0700 root:root dir, an attacker with apache credentials - # will have to get the confounder out of the process image to even try - # to guess the password hashes. - "confounder": "Change to <=31 chars of junk", - - "email-from": "noreply@example.com", - "email-smtp-ip": "127.0.0.1", - "email-expire": "3600", - "email-helo": "myhost.com", - "email-contact-person": "Set Me ", - "email-confirm-url-base": "http://localhost:7681/lwsgs" - } -``` - -The email- related settings control generation of automatic emails for -registration and forgotten password. - - - `email-from`: The email address automatic emails are sent from - - - `email-smtp-ip`: Normally 127.0.0.1, if you have a suitable server on port - 25 on your lan you can use this instead here. - - - `email-expire`: Seconds that links sent in email will work before being - deleted - - - `email-helo`: HELO to use when communicating with your SMTP server - - - `email-contact-person`: mentioned in the automatic emails as a human who can - answer questions - - - `email-confirm-url-base`: the URL to start links with in the emails, so the - recipient can get back to the web server - -The real protocol that makes use of generic-sessions must also be listed and -any configuration it needs given - -``` - "protocol-lws-messageboard": { - "status": "ok", - "message-db": "/var/www/sessions/messageboard.sqlite3" - }, -``` - -Notice the real application uses his own sqlite db, no details about how -generic-sessions works or how it stores data are available to it. - - -@section gspwc Lwsgs Password Confounder - -You can also define a per-vhost confounder shown in the example above, used -when aggregating the password with the salt when it is hashed. Any attacker -will also need to get the confounder along with the database, which you can -make harder by making the config dir only eneterable / readable by root. - - -@section gsprep Lwsgs Preparing the db directory - -You will have to prepare the db directory so it's suitable for the lwsws user to use, -that usually means apache, eg - -``` - # mkdir -p /var/www/sessions - # chown root:apache /var/www/sessions - # chmod 770 /var/www/sessions -``` - -@section gsrmail Lwsgs Email configuration - -lwsgs will can send emails by talking to an SMTP server on localhost:25. That -will usually be sendmail or postfix, you should confirm that works first by -itself using the `mail` application to send on it. - -lwsgs has been tested on stock Fedora sendmail and postfix. - - -@section gsap Lwsgs Integration with another protocol - -lwsgs is designed to provide sessions and accounts in a standalone and generic way. - -But it's not useful by itself, there will always be the actual application who wants -to make use of generic-sessions features. - -We provide the "messageboard" plugin as an example of how to integrate with -your actual application protocol. - -The basic approach is the 'real' protocol handler (usually a plugin itself) -subclasses the generic-sessions plugin and calls through to it by default. - -The "real" protocol handler entirely deals with ws-related stuff itself, since -generic-sessions does not use ws. But for - - - LWS_CALLBACK_HTTP - - LWS_CALLBACK_HTTP_BODY - - LWS_CALLBACK_HTTP_BODY_COMPLETION - - LWS_CALLBACK_HTTP_DROP_PROTOCOL - -the "real" protocol handler checks if it recognizes the activity (eg, his own -POST form URL) and if not, passes stuff through to the generic-sessions protocol callback to handle it. To simplify matters the real protocol can just pass -through any unhandled messages to generic-sessions. - -The "real" protocol can get a pointer to generic-sessions protocol on the -same vhost using - -``` - vhd->gsp = lws_vhost_name_to_protocol(vhd->vh, "protocol-generic-sessions"); -``` - -The "real" protocol must also arrange generic-sessions per_session_data in his -own per-session allocation. To allow keeping generic-sessions opaque, the -real protocol must allocate that space at runtime, using the pss size -the generic-sessions protocol struct exposes - -``` - struct per_session_data__myapp { - void *pss_gs; - ... - - pss->pss_gs = malloc(vhd->gsp->per_session_data_size); -``` - -The allocation reserved for generic-sessions is then used as user_space when -the real protocol calls through to the generic-sessions callback - -``` - vhd->gsp->callback(wsi, reason, &pss->pss_gs, in, len); -``` - -In that way the "real" protocol can subclass generic-sessions functionality. - - -To ease management of these secondary allocations, there are callbacks that -occur when a wsi binds to a protocol and when the binding is dropped. These -should be used to malloc and free and kind of per-connection -secondary allocations. - -``` - case LWS_CALLBACK_HTTP_BIND_PROTOCOL: - if (!pss || pss->pss_gs) - break; - - pss->pss_gs = malloc(vhd->gsp->per_session_data_size); - if (!pss->pss_gs) - return -1; - - memset(pss->pss_gs, 0, vhd->gsp->per_session_data_size); - break; - - case LWS_CALLBACK_HTTP_DROP_PROTOCOL: - if (vhd->gsp->callback(wsi, reason, pss ? pss->pss_gs : NULL, in, len)) - return -1; - - if (pss->pss_gs) { - free(pss->pss_gs); - pss->pss_gs = NULL; - } - break; -``` - - -#section gsapsib Getting session-specific information from another protocol - -At least at the time when someone tries to upgrade an http(s) connection to -ws(s) with your real protocol, it is necessary to confirm the cookie the http(s) -connection has with generic-sessions and find out his username and other info. - -Generic sessions lets another protocol check it again by calling his callback, -and lws itself provides a generic session info struct to pass the related data - -``` - struct lws_session_info { - char username[32]; - char email[100]; - char ip[72]; - unsigned int mask; - char session[42]; - }; - - struct lws_session_info sinfo; - ... - vhd->gsp->callback(wsi, LWS_CALLBACK_SESSION_INFO, - &pss->pss_gs, &sinfo, 0); -``` - -After the call to generic-sessions, the results can be - - - all the strings will be zero-length and .mask zero, there is no usable cookie - - - only .ip and .session are set: the cookie is OK but no user logged in - - - all the strings contain information about the logged-in user - -the real protocol can use this to reject attempts to open ws connections from -http connections that are not authenticated; afterwards there's no need to -check the ws connection auth status again. - diff -Nru libwebsockets-4.0.20/READMEs/README.generic-table.md libwebsockets-4.1.6/READMEs/README.generic-table.md --- libwebsockets-4.0.20/READMEs/README.generic-table.md 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/READMEs/README.generic-table.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,219 +0,0 @@ -Notes about generic-table -========================= - -@section gtint What is generic-table? - -Generic-table is a JSON schema and client-side JS file that makes it easy to -display live, table structured HTML over a ws link. - -An example plugin and index.html using it are provided, but lwsgt itself doesn't -have its own plugin, it's just a JSON schema and client-side JS that other -plugins can use to simplify displaying live, table-based data without having -to reinvent the wheel each time. - -The ws protocol sends JSON describing the table, and then JSON updating the table -contents when it chooses, the brower table is updated automatically, live. - -\image html lwsgt-overview.png - - - Example protocol plugin (displays directory contents): https://github.com/warmcat/libwebsockets/tree/master/plugins/generic-table/protocol_table_dirlisting.c - - - Example HTML: https://github.com/warmcat/libwebsockets/tree/master/plugins/generic-table/assets/index.html - - - lwsgt.js (client-side table rendering / ws link management): https://github.com/warmcat/libwebsockets/tree/master/plugins/generic-table/assets/lwsgt.js - - -@section gteb Enabling for build - -Enable the demo plugin at CMake with -DLWS_WITH_PLUGINS=1 - - -@section gtinth Integrating with your html - - - In your HEAD section, include lwsgt.js - -``` - -``` - - - Also in your HEAD section, style the lwsgt CSS, eg - -``` - -``` - -You can skip this but the result will be less beautiful until some CSS is -provided. - - - In your body section, declare a div with an id (can be whatever you want) - -``` -
-``` - -lwsgt JS will put its content there. - - - Finally in a -``` - -In the callback, you can recover the ws object by `window[gt].lwsgt_ws`. - - -@section gtc Lwsgt constructor - -To instantiate the ws link and lwsgt instance, your HTML must call a lwsgt -constructor for each region on the page managed by lwsgt. - -`var myvar = new lwsgt_initial(title, ws_protocol, div_id, click_cb, myvar);` - -All of the arguments are strings. - -| Parameter | Description | -|-----------------|---------------------------------------------------------| -| title | Title string to go above the table | -| ws_protocol | Protocol name string to use when making ws connection | -| div_id | HTML id of div to fill with content | -| click_cb | Callback function name string to handle clickable links | -| myvar | Name of var used to hold this instantiation globally | - -Note "myvar" is needed so it can be passed to the click handling callback. - - -@section gtclick Lwsgt click handling function - -When a clickable link produced by lwsgt is clicked, the function named in the -click_cb parameter to lwsgt_initial is called. - -That function is expected to take four parameters, eg - -`function lwsgt_dir_click(gt, u, col, row)` - -| Parameter | Description | -|------- ---|-----------------------------------------------------------| -| gt | Name of global var holding this lwsgt context (ie, myvar) | -| u | Link "url" string | -| col | Table column number link is from | -| row | Table row number link is from | - - - -@section gtgj Generic-table JSON - -### Column layout - -When the ws connection is established, the protocol should send a JSON message -describing the table columns. For example - -``` - "cols": [ - { "name": "Date" }, - { "name": "Size", "align": "right" }, - { "name": "Icon" }, - { "name": "Name", "href": "uri"}, - { "name": "uri", "hide": "1" } - ] - } -``` - - - This describes 5 columns - - - Only four columns (not "uri") should be visible - - - "Name" should be presented as a clickable link using "uri" as the - destination, when a "uri" field is presented. - - - "Size" field should be presented aligned to the right - - ### Breadcrumbs - - When a view is hierarchical, it's useful to provide a "path" with links back - in the "path", known as "breadcrumbs". - - Elements before the last one should provide a "url" member as well as the - displayable name, which is used to create the link destination. - - The last element, being the current displayed page should not have a url - member and be displayed without link style. - - - ``` - "breadcrumbs":[{"name":"top", "url": "/" }, {"name":"mydir"}] - ``` - - ### Table data - - The actual file data consists of an array of rows, containing the columns - mentioned in the original "cols" section. - - ``` - "data":[ - { - "Icon":" ", - "Date":"2015-Feb-06 03:08:35 +0000", - "Size":"1406", - "uri":"./serve//favicon.ico", - "Name":"favicon.ico" - } - ] - - ``` - - @section gtdirl Setting up protocol-lws-table-dirlisting - - The example protocol needs two mounts, one to provide the index.html, js and - the protocol itself - - ``` - { - "mountpoint": "/dirtest", - "origin": "file:///usr/share/libwebsockets-test-server/generic-table", - "origin": "callback://protocol-lws-table-dirlisting", - "default": "index.html", - "pmo": [{ - "dir": "/usr/share/libwebsockets-test-server" - }] - }, -``` - -The protocol wants a per-mount option (PMO) to tell it the base directory it -is serving from, named "dir". - -The other mount is there to simply serve items that get clicked on from the -table in a secure way - -``` - { - "mountpoint": "/dirtest/serve", - "origin": "file:///usr/share/libwebsockets-test-server", - "default": "index.html" - }, -``` - -This last bit is not related to using lwsgt itself. diff -Nru libwebsockets-4.0.20/READMEs/README.jwt.md libwebsockets-4.1.6/READMEs/README.jwt.md --- libwebsockets-4.0.20/READMEs/README.jwt.md 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/READMEs/README.jwt.md 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,176 @@ +# 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); +``` diff -Nru libwebsockets-4.0.20/READMEs/README.lws_plugins.md libwebsockets-4.1.6/READMEs/README.lws_plugins.md --- libwebsockets-4.0.20/READMEs/README.lws_plugins.md 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/READMEs/README.lws_plugins.md 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,105 @@ +# 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. + diff -Nru libwebsockets-4.0.20/READMEs/README.lws_sul.md libwebsockets-4.1.6/READMEs/README.lws_sul.md --- libwebsockets-4.0.20/READMEs/README.lws_sul.md 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/READMEs/README.lws_sul.md 2020-12-01 17:40:26.000000000 +0000 @@ -60,3 +60,40 @@ 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. + diff -Nru libwebsockets-4.0.20/READMEs/release-checklist libwebsockets-4.1.6/READMEs/release-checklist --- libwebsockets-4.0.20/READMEs/release-checklist 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/READMEs/release-checklist 2020-12-01 17:40:26.000000000 +0000 @@ -36,45 +36,25 @@ set(CPACK_PACKAGE_VERSION_MINOR "6") set(CPACK_PACKAGE_VERSION_PATCH "0") -5) specfile +5) Announce latest version on README.md - a) rpm version bump to match CMake one +6) Make sure all new READMEs and public headers are in libwebsockets.dox - scripts/libwebsockets.spec - - Version: 1.6.0 - - b) Summarize changelog - - scripts/libwebsockets.spec - -%changelog -* Sun Jan 17 2016 Andrew Cooks 1.6.4-1 -- Bump version to 1.6.4 -- MINOR fix xyz - - c) Use -DLWS_WITH_DISTRO_RECOMMENDED=1 then make package and adapt the .spec - to match the file list - -6) Announce latest version on README.md - -7) Make sure all new READMEs and public headers are in libwebsockets.dox - -8) signed tag +7) signed tag git tag -s vX.Y[.Z] -9) git +8) git a) push b) final CI check, if fail delete tag, kill pushed tags, restart flow -10) website +9) website a) update latest tag for release branch -11) post-relase version bump +10) post-relase version bump Bump the PATCH part of the version to 99 diff -Nru libwebsockets-4.0.20/.sai.json libwebsockets-4.1.6/.sai.json --- libwebsockets-4.0.20/.sai.json 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/.sai.json 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,218 @@ +{ + "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-debian-buster/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-debian-buster/x86-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-debian-sid/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-debian-sid/x86-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-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/openssl@1.1/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/noptmsvc": { + "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\" ${cmake} && cmake --build . --config DEBUG && set CTEST_OUTPUT_ON_FAILURE=1 && ctest . -C DEBUG -j1 --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, windows-10/x86_64-amd/noptmsvc, 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, windows-10/x86_64-amd/noptmsvc, linux-ubuntu-2004/aarch64-a72-bcm2711-rpi4/gcc" + }, + "unix-domain": { + "cmake": "-DUNIX_SOCK=1", + "platforms": "windows-10/x86_64-amd/msvc, windows-10/x86_64-amd/noptmsvc" + }, + "plugins": { + "cmake": "-DLWS_WITH_PLUGINS=1", + "platforms": "none,linux-fedora-32/x86_64-amd/gcc,linux-debian-sid/x86-amd/gcc,linux-debian-sid/x86_64-amd/gcc" + }, + "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, windows-10/x86_64-amd/noptmsvc" + }, + "secure-streams": { + "cmake": "-DLWS_WITH_SECURE_STREAMS=1", + "platforms": "windows-10/x86_64-amd/msvc, windows-10/x86_64-amd/noptmsvc" + }, + "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 -DLWS_WITH_SECURE_STREAMS=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" + } + } +} + diff -Nru libwebsockets-4.0.20/scripts/ctest-background-kill.sh libwebsockets-4.1.6/scripts/ctest-background-kill.sh --- libwebsockets-4.0.20/scripts/ctest-background-kill.sh 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/scripts/ctest-background-kill.sh 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,54 @@ +#!/bin/bash +# +# $SAI_INSTANCE_IDX - which instance of sai, 0+ +# $1 - background fixture name, unique within test space, like "multipostlocalsrv" +# $2 - executable +# $3+ - args + +echo "$0 $1 $2 $3 $4" >> /tmp/ctklog + +J=`basename $2`.$1.$SAI_INSTANCE_IDX +PI=`cat /tmp/sai-ctest-$J` +echo "Stage 1 kill $J 'kill $PI'" >> /tmp/ctklog + +# +# We expect our background process to still be around +# + +set +e +set +E +kill -0 $PI 2>&1 >> /tmp/ctklog +GONESKI=$? + +if [ $GONESKI -eq 0 ] ; then + kill $PI 2>&1 >> /tmp/ctklog + kill -9 $PI 2>&1 >> /tmp/ctklog + + kill -0 $PI 2>&1 + if [ $? -eq 0 ] ; then + # + # but in case it isn't enough, use ps to find the same executable started on the same port + # and kill that + # + A1=$3 + if [ -z "$A1" ] ; then + A1=$2 + fi + A2=$4 + if [ -z "$A2" ] ; then + A2=$2 + fi + + # sed is there to match up bsd/osx ps with linux + KL=`ps -Af | grep -v ctest-background-kill | grep -v grep | grep $2 | grep $A1 | grep $A2 | tr -s ' ' | sed "s/^\ //g" | cut -d' ' -f2` + if [ ! -z "$KL" ] ; then + echo "Stage 2 kill $J 'kill $KL'" >> /tmp/ctklog + kill $KL 2>&1 >> /tmp/ctklog + fi + fi +else + echo "Process already dead" >> /tmp/ctklog +fi + +exit $GONESKI + diff -Nru libwebsockets-4.0.20/scripts/ctest-background.sh libwebsockets-4.1.6/scripts/ctest-background.sh --- libwebsockets-4.0.20/scripts/ctest-background.sh 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/scripts/ctest-background.sh 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,16 @@ +#!/bin/bash +# +# $SAI_INSTANCE_IDX - which instance of sai, 0+ +# $1 - background fixture name, unique within test space, like "multipostlocalserver" +# $2 - executable +# $3+ - args + +J=`basename $2`.$1.$SAI_INSTANCE_IDX +$2 $3 $4 $5 $6 $7 $8 $9 2>/tmp/ctest-background-$J 1>/dev/null 0 /tmp/sai-ctest-$J +# really we want to loop until the listen port is up +# on, eg, rpi it can be blocked at sd card and slow to start +# due to parallel tests and disc cache flush +sleep 1 +exit 0 + diff -Nru libwebsockets-4.0.20/scripts/libwebsockets.spec libwebsockets-4.1.6/scripts/libwebsockets.spec --- libwebsockets-4.0.20/scripts/libwebsockets.spec 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/scripts/libwebsockets.spec 1970-01-01 00:00:00.000000000 +0000 @@ -1,180 +0,0 @@ -Name: libwebsockets -Version: 4.0.2 -Release: 1%{?dist} -Summary: Websocket Server and Client Library - -Group: System Environment/Libraries -License: MIT -URL: https://libwebsockets.org -Source0: %{name}-%{version}.tar.gz -BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) - -BuildRequires: openssl-devel libuv-devel libev-devel cmake -Requires: openssl - -%description -Webserver server and client library - -%package devel -Summary: Development files for libwebsockets -Group: Development/Libraries -Requires: %{name} = %{version}-%{release} -Requires: openssl-devel - -%description devel -Development files for libwebsockets - -%prep -%setup -q - -%build -mkdir -p build -cd build -%cmake .. -DLWS_WITH_DISTRO_RECOMMENDED=1 -make - -%install -rm -rf $RPM_BUILD_ROOT -cd build -make install DESTDIR=$RPM_BUILD_ROOT - -%post -p /sbin/ldconfig -%postun -p /sbin/ldconfig - -%clean -rm -rf $RPM_BUILD_ROOT - -%files -%defattr(-,root,root,-) -%attr(755,root,root) -"/usr/bin/libwebsockets-test-client" -"/usr/bin/libwebsockets-test-lejp" -"/usr/bin/libwebsockets-test-server" -"/usr/bin/libwebsockets-test-server-extpoll" -"/usr/bin/libwebsockets-test-sshd" -"/usr/bin/lwsws" -"/%{_libdir}/libwebsockets.so" -"/%{_libdir}/libwebsockets.so.16" -%dir "/usr/share/libwebsockets-test-server" -"/usr/share/libwebsockets-test-server/candide.zip" -"/usr/share/libwebsockets-test-server/favicon.ico" -%dir "/usr/share/libwebsockets-test-server/generic-table" -"/usr/share/libwebsockets-test-server/generic-table/index.html" -"/usr/share/libwebsockets-test-server/generic-table/lwsgt.js" -"/usr/share/libwebsockets-test-server/http2.png" -"/usr/share/libwebsockets-test-server/leaf.jpg" -"/usr/share/libwebsockets-test-server/libwebsockets-test-server.key.pem" -"/usr/share/libwebsockets-test-server/libwebsockets-test-server.pem" -"/usr/share/libwebsockets-test-server/libwebsockets.org-logo.svg" -"/usr/share/libwebsockets-test-server/lws-cgi-test.sh" -"/usr/share/libwebsockets-test-server/lws-common.js" -"/usr/share/libwebsockets-test-server/lws-ssh-test-keys" -"/usr/share/libwebsockets-test-server/lws-ssh-test-keys.pub" -%dir "/usr/share/libwebsockets-test-server/plugins" -"/usr/share/libwebsockets-test-server/plugins/libprotocol_client_loopback_test.so" -"/usr/share/libwebsockets-test-server/plugins/libprotocol_dumb_increment.so" -"/usr/share/libwebsockets-test-server/plugins/libprotocol_fulltext_demo.so" -"/usr/share/libwebsockets-test-server/plugins/libprotocol_lws_acme_client.so" -"/usr/share/libwebsockets-test-server/plugins/libprotocol_lws_mirror.so" -"/usr/share/libwebsockets-test-server/plugins/libprotocol_lws_raw_test.so" -"/usr/share/libwebsockets-test-server/plugins/libprotocol_lws_server_status.so" -"/usr/share/libwebsockets-test-server/plugins/libprotocol_lws_ssh_base.so" -"/usr/share/libwebsockets-test-server/plugins/libprotocol_lws_sshd_demo.so" -"/usr/share/libwebsockets-test-server/plugins/libprotocol_lws_status.so" -"/usr/share/libwebsockets-test-server/plugins/libprotocol_lws_table_dirlisting.so" -"/usr/share/libwebsockets-test-server/plugins/libprotocol_post_demo.so" -%dir "/usr/share/libwebsockets-test-server/private" -"/usr/share/libwebsockets-test-server/private/index.html" -%dir "/usr/share/libwebsockets-test-server/server-status" -"/usr/share/libwebsockets-test-server/server-status/lwsws-logo.png" -"/usr/share/libwebsockets-test-server/server-status/server-status.css" -"/usr/share/libwebsockets-test-server/server-status/server-status.html" -"/usr/share/libwebsockets-test-server/server-status/server-status.js" -"/usr/share/libwebsockets-test-server/test.css" -"/usr/share/libwebsockets-test-server/test.html" -"/usr/share/libwebsockets-test-server/test.js" -"/usr/share/libwebsockets-test-server/wss-over-h2.png" -%files devel -%defattr(-,root,root,-) -%dir "/usr/include/libwebsockets" -"/usr/include/libwebsockets.h" -"/usr/include/libwebsockets/lws-adopt.h" -"/usr/include/libwebsockets/lws-callbacks.h" -"/usr/include/libwebsockets/lws-cgi.h" -"/usr/include/libwebsockets/lws-client.h" -"/usr/include/libwebsockets/lws-context-vhost.h" -"/usr/include/libwebsockets/lws-dbus.h" -"/usr/include/libwebsockets/lws-diskcache.h" -"/usr/include/libwebsockets/lws-esp32.h" -"/usr/include/libwebsockets/lws-fts.h" -"/usr/include/libwebsockets/lws-genhash.h" -"/usr/include/libwebsockets/lws-genrsa.h" -"/usr/include/libwebsockets/lws-http.h" -"/usr/include/libwebsockets/lws-jose.h" -"/usr/include/libwebsockets/lws-jwk.h" -"/usr/include/libwebsockets/lws-jws.h" -"/usr/include/libwebsockets/lws-lejp.h" -"/usr/include/libwebsockets/lws-logs.h" -"/usr/include/libwebsockets/lws-lwsac.h" -"/usr/include/libwebsockets/lws-misc.h" -"/usr/include/libwebsockets/lws-network-helper.h" -"/usr/include/libwebsockets/lws-plugin-generic-sessions.h" -"/usr/include/libwebsockets/lws-protocols-plugins.h" -"/usr/include/libwebsockets/lws-purify.h" -"/usr/include/libwebsockets/lws-ring.h" -"/usr/include/libwebsockets/lws-service.h" -"/usr/include/libwebsockets/lws-sha1-base64.h" -"/usr/include/libwebsockets/lws-spa.h" -"/usr/include/libwebsockets/lws-stats.h" -"/usr/include/libwebsockets/lws-threadpool.h" -"/usr/include/libwebsockets/lws-timeout-timer.h" -"/usr/include/libwebsockets/lws-tokenize.h" -"/usr/include/libwebsockets/lws-vfs.h" -"/usr/include/libwebsockets/lws-write.h" -"/usr/include/libwebsockets/lws-writeable.h" -"/usr/include/libwebsockets/lws-ws-close.h" -"/usr/include/libwebsockets/lws-ws-ext.h" -"/usr/include/libwebsockets/lws-ws-state.h" -"/usr/include/libwebsockets/lws-x509.h" -"/usr/include/lws-plugin-ssh.h" -"/usr/include/lws_config.h" -%dir "/usr/lib/pkgconfig" -"/%{_libdir}/pkgconfig/libwebsockets.pc" -"/usr/lib/pkgconfig/libwebsockets_static.pc" -%dir "/usr/lib/cmake" -%dir "/usr/lib/cmake/libwebsockets" -"/%{_libdir}/cmake/libwebsockets/LibwebsocketsConfig.cmake" -"/%{_libdir}/cmake/libwebsockets/LibwebsocketsConfigVersion.cmake" -"/%{_libdir}/cmake/libwebsockets/LibwebsocketsTargets-debug.cmake" -"/%{_libdir}/cmake/libwebsockets/LibwebsocketsTargets.cmake" - -%changelog -* Fri Aug 14 2019 Andy Green 3.2.0-1 -- MAJOR SONAMEBUMP APICHANGES Upstream 3.2.0 release (last LGPLv2.1+SLE) - -* Fri Nov 23 2018 Andy Green 3.1.0-1 -- MAJOR SONAMEBUMP APICHANGES Upstream 3.1.0 release - -* Fri May 4 2018 Andy Green 3.0.0-1 -- MAJOR SONAMEBUMP APICHANGES Upstream 3.0.0 release - -* Mon Oct 16 2017 Andy Green 2.4.0-1 -- MAJOR SONAMEBUMP APICHANGES Upstream 2.4.0 release - -* Fri Jul 28 2017 Andy Green 2.3.0-1 -- MAJOR SONAMEBUMP APICHANGES Upstream 2.3.0 release - -* Mon Mar 06 2017 Andy Green 2.2.0-1 -- MAJOR SONAMEBUMP APICHANGES Upstream 2.2.0 release - -* Thu Oct 06 2016 Andy Green 2.1.0-1 -- MAJOR SONAMEBUMP APICHANGES Upstream 2.1.0 release - -* Thu May 05 2016 Andy Green 2.0.0-1 -- MAJOR SONAMEBUMP APICHANGES Upstream 2.0.0 release - -* Tue Feb 16 2016 Andy Green 1.7.0-1 -- MAJOR SONAMEBUMP APICHANGES Upstream 1.7.0 release - -* Sun Jan 17 2016 Andrew Cooks 1.6.0-1 -- Bump version to 1.6.0 diff -Nru libwebsockets-4.0.20/test-apps/CMakeLists.txt libwebsockets-4.1.6/test-apps/CMakeLists.txt --- libwebsockets-4.0.20/test-apps/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/test-apps/CMakeLists.txt 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,255 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# + +# +# Test applications +# + +set(TEST_APP_LIST) +if ((LWS_ROLE_H1 OR LWS_ROLE_H2)) + # + # Helper function for adding a test app. + # + macro(create_test_app TEST_NAME MAIN_SRC S2 S3 S4 S5 S6) + + set(TEST_SRCS ${MAIN_SRC}) + set(TEST_HDR) + if ("${S2}" STREQUAL "") + else() + list(APPEND TEST_SRCS ${S2}) + endif() + if ("${S3}" STREQUAL "") + else() + list(APPEND TEST_SRCS ${S3}) + endif() + if ("${S4}" STREQUAL "") + else() + list(APPEND TEST_SRCS ${S4}) + endif() + if ("${S5}" STREQUAL "") + else() + list(APPEND TEST_SRCS ${S5}) + endif() + if ("${S6}" STREQUAL "") + else() + list(APPEND TEST_SRCS ${S6}) + endif() + if (WIN32) + list(APPEND TEST_SRCS + ${WIN32_HELPERS_PATH}/getopt.c + ${WIN32_HELPERS_PATH}/getopt_long.c + ${WIN32_HELPERS_PATH}/gettimeofday.c + ) + + list(APPEND TEST_HDR + ${WIN32_HELPERS_PATH}/getopt.h + ${WIN32_HELPERS_PATH}/gettimeofday.h + ) + endif(WIN32) + + source_group("Headers Private" FILES ${TEST_HDR}) + source_group("Sources" FILES ${TEST_SRCS}) + add_executable(${TEST_NAME} ${TEST_SRCS} ${TEST_HDR}) + + foreach(libpath ${LWS_DEP_LIB_PATHS}) + target_link_directories(${TEST_NAME} ${libpath}) + endforeach() + + if (LWS_LINK_TESTAPPS_DYNAMIC) + if (NOT LWS_WITH_SHARED) + message(FATAL_ERROR "Build of the shared library is disabled. LWS_LINK_TESTAPPS_DYNAMIC must be combined with LWS_WITH_SHARED.") + endif() + target_link_libraries(${TEST_NAME} websockets_shared) + add_dependencies(${TEST_NAME} websockets_shared) + else() + if (NOT LWS_WITH_STATIC) + message(FATAL_ERROR "Build of the static library is disabled. Disabled LWS_LINK_TESTAPPS_DYNAMIC must be combined with LWS_WITH_STATIC.") + endif() + target_link_libraries(${TEST_NAME} websockets) + add_dependencies(${TEST_NAME} websockets) + if (UNIX AND LWS_WITH_SSL AND NOT LWS_WITH_MBEDTLS) + target_link_libraries(${TEST_NAME} dl) + endif() + endif() + + if (LWS_LIB_INCLUDES) + target_include_directories(${TEST_NAME} PRIVATE "${LWS_LIB_INCLUDES}" ${LWS_LIB_BUILD_INC_PATHS}) + else() + target_include_directories(${TEST_NAME} PRIVATE ${LWS_LIB_BUILD_INC_PATHS}) + endif() + target_compile_options(${TEST_NAME} PRIVATE ${LWS_PTHR_FLAGS}) + + if (LWS_WITH_HTTP_STREAM_COMPRESSION) + target_link_libraries(${TEST_NAME} z) + endif() + + # Set test app specific defines. + set_property(TARGET ${TEST_NAME} + PROPERTY COMPILE_DEFINITIONS + INSTALL_DATADIR="${CMAKE_INSTALL_PREFIX}/share" + ) + + # Prefix the binary names with libwebsockets. + set_target_properties(${TEST_NAME} + PROPERTIES + OUTPUT_NAME libwebsockets-${TEST_NAME}) + + target_link_libraries(${TEST_NAME} ${LIB_LIST_AT_END}) + + # Add to the list of tests. + list(APPEND TEST_APP_LIST ${TEST_NAME}) + endmacro() + + if (NOT LWS_WITHOUT_SERVER) + # + # test-server + # + if (NOT LWS_WITHOUT_TEST_SERVER) + create_test_app(test-server "test-server.c" + "" + "" + "" + "" + "") + + if (LWS_WITH_CGI AND LWS_WITH_TLS) + create_test_app(test-sshd "test-sshd.c" + "" + "" + "" + "" + "") + target_include_directories(test-sshd PRIVATE "${PROJECT_SOURCE_DIR}/plugins/ssh-base/include") + + endif() + + endif() + + # + # test-server-extpoll + # + if (NOT LWS_WITHOUT_TEST_SERVER_EXTPOLL AND NOT WIN32) + create_test_app(test-server-extpoll + "test-server.c" + "" + "" + "" + "" + "") + # Set defines for this executable only. + set_property( + TARGET test-server-extpoll + PROPERTY COMPILE_DEFINITIONS + EXTERNAL_POLL + INSTALL_DATADIR="${CMAKE_INSTALL_PREFIX}/share" + ) + + # We need to link against winsock code. + if (WIN32) + target_link_libraries(test-server-extpoll ws2_32.lib) + endif(WIN32) + endif() + + if (LWS_WITH_LEJP) + create_test_app( + test-lejp + "test-lejp.c" + "" + "" + "" + "" + "") + endif() + + # Data files for running the test server. + list(APPEND TEST_SERVER_DATA + "${PROJECT_SOURCE_DIR}/test-apps/favicon.ico" + "${PROJECT_SOURCE_DIR}/test-apps/leaf.jpg" + "${PROJECT_SOURCE_DIR}/test-apps/candide.zip" + "${PROJECT_SOURCE_DIR}/test-apps/libwebsockets.org-logo.svg" + "${PROJECT_SOURCE_DIR}/test-apps/http2.png" + "${PROJECT_SOURCE_DIR}/test-apps/wss-over-h2.png" + "${PROJECT_SOURCE_DIR}/test-apps/lws-common.js" + "${PROJECT_SOURCE_DIR}/test-apps/test.html" + "${PROJECT_SOURCE_DIR}/test-apps/test.css" + "${PROJECT_SOURCE_DIR}/test-apps/test.js") + + add_custom_command(TARGET test-server + POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E make_directory "$/../share/libwebsockets-test-server") + + # Copy the file needed to run the server so that the test apps can + # reach them from their default output location + foreach (TEST_FILE ${TEST_SERVER_DATA}) + if (EXISTS ${TEST_FILE}) + add_custom_command(TARGET test-server + POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E copy "${TEST_FILE}" "$/../share/libwebsockets-test-server" VERBATIM) + endif() + endforeach() + endif(NOT LWS_WITHOUT_SERVER) + + if (NOT LWS_WITHOUT_CLIENT) + # + # test-client + # + if (NOT LWS_WITHOUT_TEST_CLIENT) + create_test_app(test-client "test-client.c" "" "" "" "" "") + endif() + + endif(NOT LWS_WITHOUT_CLIENT) +endif((LWS_ROLE_H1 OR LWS_ROLE_H2)) + +# Install test apps. + +install(TARGETS ${TEST_APP_LIST} + RUNTIME DESTINATION ${LWS_INSTALL_EXAMPLES_DIR} + COMPONENT examples) +set(CPACK_COMPONENT_EXAMPLES_DISPLAY_NAME "Example files") + +# Programs shared files used by the test-server + +if (NOT LWS_WITHOUT_SERVER) + install(FILES ${TEST_SERVER_DATA} + DESTINATION share/libwebsockets-test-server + COMPONENT examples) + + install(FILES "${PROJECT_SOURCE_DIR}/test-apps/private/index.html" + DESTINATION share/libwebsockets-test-server/private + COMPONENT examples) +if (LWS_WITH_CGI) + set(CGI_TEST_SCRIPT "${PROJECT_SOURCE_DIR}/test-apps/lws-cgi-test.sh") + install(FILES ${CGI_TEST_SCRIPT} + PERMISSIONS OWNER_EXECUTE GROUP_EXECUTE WORLD_EXECUTE OWNER_READ GROUP_READ WORLD_READ + DESTINATION share/libwebsockets-test-server + COMPONENT examples) + endif() +endif() + + +if (NOT LWS_WITHOUT_TEST_SERVER AND NOT LWS_WITHOUT_SERVER) + install(FILES lws-ssh-test-keys;lws-ssh-test-keys.pub + DESTINATION share/libwebsockets-test-server + COMPONENT examples) +endif() diff -Nru libwebsockets-4.0.20/test-apps/test-client.c libwebsockets-4.1.6/test-apps/test-client.c --- libwebsockets-4.0.20/test-apps/test-client.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/test-apps/test-client.c 2020-12-01 17:40:26.000000000 +0000 @@ -510,6 +510,7 @@ { NULL, NULL, 0, 0 } /* end */ }; +#if defined(LWS_ROLE_WS) && !defined(LWS_WITHOUT_EXTENSIONS) static const struct lws_extension exts[] = { { "permessage-deflate", @@ -523,7 +524,7 @@ }, { NULL, NULL, NULL /* terminator */ } }; - +#endif void sighandler(int sig) @@ -547,7 +548,6 @@ { "longlived", no_argument, NULL, 'l' }, { "post", no_argument, NULL, 'o' }, { "once", no_argument, NULL, 'O' }, - { "pingpong-secs", required_argument, NULL, 'P' }, { "ssl-cert", required_argument, NULL, 'C' }, { "ssl-key", required_argument, NULL, 'K' }, { "ssl-ca", required_argument, NULL, 'A' }, @@ -575,8 +575,7 @@ int main(int argc, char **argv) { int n = 0, m, ret = 0, port = 7681, use_ssl = 0, ietf_version = -1; - unsigned int rl_dumb = 0, rl_mirror = 0, do_ws = 1, pp_secs = 0, - do_multi = 0; + unsigned int rl_dumb = 0, rl_mirror = 0, do_ws = 1, do_multi = 0; struct lws_context_creation_info info; struct lws_client_connect_info i; struct lws_context *context; @@ -597,9 +596,9 @@ while (n >= 0) { #if defined(LWS_HAS_GETOPT_LONG) || defined(WIN32) - n = getopt_long(argc, argv, "Sjnuv:hsp:d:lC:K:A:P:moeO", options, NULL); + n = getopt_long(argc, argv, "Sjnuv:hsp:d:lC:K:A:moeO", options, NULL); #else - n = getopt(argc, argv, "Sjnuv:hsp:d:lC:K:A:P:moeO"); + n = getopt(argc, argv, "Sjnuv:hsp:d:lC:K:A:moeO"); #endif if (n < 0) continue; @@ -621,10 +620,6 @@ case 'e': flag_echo = 1; break; - case 'P': - pp_secs = atoi(optarg); - lwsl_notice("Setting pingpong interval to %d\n", pp_secs); - break; case 'j': justmirror = 1; break; @@ -709,8 +704,9 @@ info.protocols = protocols; info.gid = -1; info.uid = -1; - info.ws_ping_pong_interval = pp_secs; +#if defined(LWS_ROLE_WS) && !defined(LWS_WITHOUT_EXTENSIONS) info.extensions = exts; +#endif /* * since we know this lws context is only ever going to be used with @@ -725,7 +721,7 @@ #endif info.options |= LWS_SERVER_OPTION_H2_JUST_FIX_WINDOW_UPDATE_OVERFLOW; - +#if defined(LWS_WITH_TLS) if (use_ssl) { /* * If the server wants us to present a valid SSL client certificate @@ -766,7 +762,7 @@ lwsl_notice(" Skipping peer cert hostname check\n"); else lwsl_notice(" Requiring peer cert hostname matches\n"); - +#endif context = lws_create_context(&info); if (context == NULL) { fprintf(stderr, "Creating libwebsocket context failed\n"); diff -Nru libwebsockets-4.0.20/test-apps/test-lejp.c libwebsockets-4.1.6/test-apps/test-lejp.c --- libwebsockets-4.0.20/test-apps/test-lejp.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/test-apps/test-lejp.c 2020-12-01 17:40:26.000000000 +0000 @@ -88,7 +88,7 @@ int main(int argc, char *argv[]) { - int fd, n = 1, ret = 1, m; + int fd, n = 1, ret = 1, m = 0; struct lejp_ctx ctx; char buf[128]; @@ -112,7 +112,7 @@ goto bail; } } - lwsl_notice("okay\n"); + lwsl_notice("okay (%d)\n", m); ret = 0; bail: lejp_destruct(&ctx); diff -Nru libwebsockets-4.0.20/test-apps/test-server.c libwebsockets-4.1.6/test-apps/test-server.c --- libwebsockets-4.0.20/test-apps/test-server.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/test-apps/test-server.c 2020-12-01 17:40:26.000000000 +0000 @@ -55,26 +55,7 @@ /* * This demonstrates how to use the clean protocol service separation of - * plugins, but with static inclusion instead of runtime dynamic loading - * (which requires libuv). - * - * dumb-increment doesn't use the plugin, both to demonstrate how to - * do the protocols directly, and because it wants libuv for a timer. - * - * Please consider using test-server-v2.0.c instead of this: it has the - * same functionality but - * - * 1) uses lws built-in http handling so you don't need to deal with it in - * your callback - * - * 2) Links with libuv and uses the plugins at runtime - * - * 3) Uses advanced lws features like mounts to bind parts of the filesystem - * to the served URL space - * - * Another option is lwsws, this operates like test-server-v2,0.c but is - * configured using JSON, do you do not need to provide any code for the - * serving action at all, just implement your protocols in plugins. + * plugins, in this case by statically including them at build-time. */ #define LWS_PLUGIN_STATIC @@ -85,15 +66,71 @@ #endif #include "../plugins/protocol_post_demo.c" +#if defined(LWS_WITH_EXTERNAL_POLL) +static struct lws_pollfd * +ext_find_fd(lws_sockfd_type fd) +{ + int n; + + for (n = 0; n < max_poll_elements; n++) + if (pollfds[n].fd == fd) + return &pollfds[n]; + + return NULL; +} +#endif + static int lws_callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { const unsigned char *c; +#if defined(LWS_WITH_EXTERNAL_POLL) + struct lws_pollargs *pa; + struct lws_pollfd *pfd; +#endif char buf[1024]; int n = 0, hlen; switch (reason) { +#if defined(LWS_WITH_EXTERNAL_POLL) + case LWS_CALLBACK_ADD_POLL_FD: + pa = (struct lws_pollargs *)in; + lwsl_debug("%s: ADD fd %d, ev %d\n", __func__, pa->fd, pa->events); + pfd = ext_find_fd(pa->fd); + if (pfd) { + lwsl_notice("%s: ADD fd %d already in ext table\n", + __func__, pa->fd); + } else { + pfd = ext_find_fd(LWS_SOCK_INVALID); + if (!pfd) + return -1; + } + pfd->fd = pa->fd; + pfd->events = pa->events; + pfd->revents = 0; + /* high water mark... */ + count_pollfds = (pfd - pollfds) + 1; + break; + case LWS_CALLBACK_DEL_POLL_FD: + pa = (struct lws_pollargs *)in; + lwsl_debug("%s: DEL fd %d\n", __func__, pa->fd); + pfd = ext_find_fd(pa->fd); + if (!pfd) + return -1; + pfd->fd = LWS_SOCK_INVALID; + break; + case LWS_CALLBACK_CHANGE_MODE_POLL_FD: + pa = (struct lws_pollargs *)in; + lwsl_debug("%s: CH fd %d\n", __func__, pa->fd); + pfd = ext_find_fd(pa->fd); + if (!pfd) { + lwsl_err("%s: unknown fd %d\n", __func__, pa->fd); + return -1; + } + pfd->events = pa->events; + break; +#endif case LWS_CALLBACK_HTTP: /* non-mount-handled accesses will turn up here */ @@ -206,6 +243,7 @@ lws_cancel_service(context); } +#if defined(LWS_ROLE_WS) && !defined(LWS_WITHOUT_EXTENSIONS) static const struct lws_extension exts[] = { { "permessage-deflate", @@ -214,15 +252,18 @@ }, { NULL, NULL, NULL /* terminator */ } }; +#endif /* - * mount handlers for sections of the URL space + * mount a filesystem directory into the URL space at / + * point it to our /usr/share directory with our assets in + * stuff from here is autoserved by the library */ -static const struct lws_http_mount mount_ziptest = { +static const struct lws_http_mount mount_ziptest_uncomm = { NULL, /* linked-list pointer to next*/ - "/ziptest", /* mountpoint in URL namespace on this vhost */ - LOCAL_RESOURCE_PATH"/candide.zip", /* handler */ + "/uncommziptest", /* mountpoint in URL namespace on this vhost */ + LOCAL_RESOURCE_PATH"/candide-uncompressed.zip", /* handler */ NULL, /* default filename if none given */ NULL, NULL, @@ -235,16 +276,14 @@ 0, 0, LWSMPRO_FILE, /* origin points to a callback */ - 8, /* strlen("/ziptest"), ie length of the mountpoint */ + 14, /* strlen("/ziptest"), ie length of the mountpoint */ NULL, { NULL, NULL } // sentinel -}; - -static const struct lws_http_mount mount_post = { - (struct lws_http_mount *)&mount_ziptest, /* linked-list pointer to next*/ - "/formtest", /* mountpoint in URL namespace on this vhost */ - "protocol-post-demo", /* handler */ +}, mount_ziptest = { + (struct lws_http_mount *)&mount_ziptest_uncomm, /* linked-list pointer to next*/ + "/ziptest", /* mountpoint in URL namespace on this vhost */ + LOCAL_RESOURCE_PATH"/candide.zip", /* handler */ NULL, /* default filename if none given */ NULL, NULL, @@ -256,24 +295,16 @@ 0, 0, 0, - LWSMPRO_CALLBACK, /* origin points to a callback */ - 9, /* strlen("/formtest"), ie length of the mountpoint */ + LWSMPRO_FILE, /* origin points to a callback */ + 8, /* strlen("/ziptest"), ie length of the mountpoint */ NULL, { NULL, NULL } // sentinel -}; - -/* - * mount a filesystem directory into the URL space at / - * point it to our /usr/share directory with our assets in - * stuff from here is autoserved by the library - */ - -static const struct lws_http_mount mount = { - (struct lws_http_mount *)&mount_post, /* linked-list pointer to next*/ - "/", /* mountpoint in URL namespace on this vhost */ - LOCAL_RESOURCE_PATH, /* where to go on the filesystem for that */ - "test.html", /* default filename if none given */ +}, mount_post = { + (struct lws_http_mount *)&mount_ziptest, /* linked-list pointer to next*/ + "/formtest", /* mountpoint in URL namespace on this vhost */ + "protocol-post-demo", /* handler */ + NULL, /* default filename if none given */ NULL, NULL, NULL, @@ -284,13 +315,32 @@ 0, 0, 0, - LWSMPRO_FILE, /* mount type is a directory in a filesystem */ - 1, /* strlen("/"), ie length of the mountpoint */ + LWSMPRO_CALLBACK, /* origin points to a callback */ + 9, /* strlen("/formtest"), ie length of the mountpoint */ NULL, { NULL, NULL } // sentinel +}, mount = { + /* .mount_next */ &mount_post, /* linked-list "next" */ + /* .mountpoint */ "/", /* mountpoint URL */ + /* .origin */ LOCAL_RESOURCE_PATH, /* serve from dir */ + /* .def */ "test.html", /* default filename */ + /* .protocol */ NULL, + /* .cgienv */ NULL, + /* .extra_mimetypes */ NULL, + /* .interpret */ NULL, + /* .cgi_timeout */ 0, + /* .cache_max_age */ 0, + /* .auth_mask */ 0, + /* .cache_reusable */ 0, + /* .cache_revalidate */ 0, + /* .cache_intermediaries */ 0, + /* .origin_protocol */ LWSMPRO_FILE, /* files in a dir */ + /* .mountpoint_len */ 1, /* char count */ + /* .basic_auth_login_file */ NULL, }; + static const struct lws_protocol_vhost_options pvo_options = { NULL, NULL, @@ -317,6 +367,7 @@ { "ssl-cert", required_argument, NULL, 'C' }, { "ssl-key", required_argument, NULL, 'K' }, { "ssl-ca", required_argument, NULL, 'A' }, + { "resource-path", required_argument, NULL, 'r' }, #if defined(LWS_WITH_TLS) { "ssl-verify-client", no_argument, NULL, 'v' }, #if defined(LWS_HAVE_SSL_CTX_set1_param) @@ -328,11 +379,17 @@ #ifndef LWS_NO_DAEMONIZE { "daemonize", no_argument, NULL, 'D' }, #endif - { "pingpong-secs", required_argument, NULL, 'P' }, + { "ignore-sigterm", no_argument, NULL, 'I' }, + { NULL, 0, 0, 0 } }; #endif +static void +sigterm_catch(int sig) +{ +} + int main(int argc, char **argv) { struct lws_context_creation_info info; @@ -344,7 +401,6 @@ char ca_path[1024] = ""; int uid = -1, gid = -1; int use_ssl = 0; - int pp_secs = 0; int opts = 0; int n = 0; #ifndef LWS_NO_DAEMONIZE @@ -360,9 +416,9 @@ while (n >= 0) { #if defined(LWS_HAS_GETOPT_LONG) || defined(WIN32) - n = getopt_long(argc, argv, "eci:hsap:d:DC:K:A:R:vu:g:P:kU:n", options, NULL); + n = getopt_long(argc, argv, "eci:hsap:d:DC:K:A:R:vu:g:kU:niIr:", options, NULL); #else - n = getopt(argc, argv, "eci:hsap:d:DC:K:A:R:vu:g:P:kU:n"); + n = getopt(argc, argv, "eci:hsap:d:DC:K:A:R:vu:g:kU:nIr:"); #endif if (n < 0) continue; @@ -388,6 +444,12 @@ /* no dumb increment send */ test_options |= 1; break; + case 'I': + signal(SIGTERM, sigterm_catch); + break; + case 'r': + resource_path = optarg; + break; case 's': use_ssl = 1; opts |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; @@ -429,10 +491,6 @@ case 'A': lws_strncpy(ca_path, optarg, sizeof(ca_path)); break; - case 'P': - pp_secs = atoi(optarg); - lwsl_notice("Setting pingpong interval to %d\n", pp_secs); - break; #if defined(LWS_WITH_TLS) case 'v': use_ssl = 1; @@ -491,13 +549,17 @@ lwsl_err("Out of memory pollfds=%d\n", max_poll_elements); return -1; } + for (n = 0; n < max_poll_elements; n++) + pollfds[n].fd = LWS_SOCK_INVALID; + count_pollfds = 0; #endif info.iface = iface; info.protocols = protocols; + +#if defined(LWS_WITH_TLS) info.ssl_cert_filepath = NULL; info.ssl_private_key_filepath = NULL; - info.ws_ping_pong_interval = pp_secs; if (use_ssl) { if (strlen(resource_path) > sizeof(cert_path) - 32) { @@ -514,17 +576,22 @@ if (!key_path[0]) sprintf(key_path, "%s/libwebsockets-test-server.key.pem", resource_path); - +#if defined(LWS_WITH_TLS) info.ssl_cert_filepath = cert_path; info.ssl_private_key_filepath = key_path; if (ca_path[0]) info.ssl_ca_filepath = ca_path; +#endif } +#endif info.gid = gid; info.uid = uid; info.options = opts | LWS_SERVER_OPTION_VALIDATE_UTF8 | LWS_SERVER_OPTION_EXPLICIT_VHOSTS; +#if defined(LWS_ROLE_WS) && !defined(LWS_WITHOUT_EXTENSIONS) info.extensions = exts; +#endif info.timeout_secs = 5; +#if defined(LWS_WITH_TLS) info.ssl_cipher_list = "ECDHE-ECDSA-AES256-GCM-SHA384:" "ECDHE-RSA-AES256-GCM-SHA384:" "DHE-RSA-AES256-GCM-SHA384:" @@ -538,9 +605,12 @@ "!DHE-RSA-AES256-SHA256:" "!AES256-GCM-SHA384:" "!AES256-SHA256"; +#endif info.mounts = &mount; - info.ip_limit_ah = 24; /* for testing */ - info.ip_limit_wsi = 400; /* for testing */ +#if defined(LWS_WITH_PEER_LIMITS) + info.ip_limit_ah = 128; /* for testing */ + info.ip_limit_wsi = 800; /* for testing */ +#endif if (use_ssl) /* redirect guys coming on http */ @@ -598,7 +668,11 @@ * this represents an existing server's single poll action * which also includes libwebsocket sockets */ - n = poll(pollfds, count_pollfds, 50); + + /* if needed, force-service wsis that may not have read all input */ + n = lws_service_adjust_timeout(context, 5000, 0); + + n = poll(pollfds, count_pollfds, n); if (n < 0) continue; @@ -611,15 +685,11 @@ * control */ if (lws_service_fd(context, - &pollfds[n]) < 0) + &pollfds[n]) < 0) goto done; - - /* if needed, force-service wsis that may not have read all input */ - while (!lws_service_adjust_timeout(context, 1, 0)) { - lwsl_notice("extpoll doing forced service!\n"); - lws_service_tsi(context, -1, 0); - } } + + lws_service_tsi(context, -1, 0); #else /* * If libwebsockets sockets are all we care about, diff -Nru libwebsockets-4.0.20/test-apps/test-sshd.c libwebsockets-4.1.6/test-apps/test-sshd.c --- libwebsockets-4.0.20/test-apps/test-sshd.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/test-apps/test-sshd.c 2020-12-01 17:40:26.000000000 +0000 @@ -33,7 +33,7 @@ #include #include #include - +#include /* import the whole of lws-plugin-sshd-base statically */ #include diff -Nru libwebsockets-4.0.20/.travis.yml libwebsockets-4.1.6/.travis.yml --- libwebsockets-4.0.20/.travis.yml 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/.travis.yml 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -env: - # The next declaration is the encrypted COVERITY_SCAN_TOKEN, created - # via the "travis encrypt" command using the project repo's public key - global: - - secure: "KhAdQ9ja+LBObWNQTYO7Df5J4DyOih6S+eerDMu8UPSO+CoWV2pWoQzbOfocjyOscGOwC+2PrrHDNZyGfqkCLDXg1BxynXPCFerHC1yc2IajvKpGXmAAygNIvp4KACDfGv/dkXrViqIzr/CdcNaU4vIMHSVb5xkeLi0W1dPnQOI=" - matrix: - # 2019-09-30: travis build no longer has dbus - # LWS_METHOD=lwsws CMAKE_ARGS="-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_ROLE_DBUS=1 -DLWS_DBUS_INCLUDE2=/usr/lib/x86_64-linux-gnu/dbus-1.0/include/ -DLWS_WITH_GENCRYPTO=1 -DLWS_WITH_JOSE=1 -DLWS_WITH_SYS_ASYNC_DNS=1" - # LWS_METHOD=lwsws2 CMAKE_ARGS="-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_ROLE_DBUS=1 -DLWS_DBUS_INCLUDE2=/usr/lib/x86_64-linux-gnu/dbus-1.0/include/ -DLWS_WITH_LWS_DSH=1" - - LWS_METHOD=lwsws CMAKE_ARGS="-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" - - LWS_METHOD=lwsws2 CMAKE_ARGS="-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" - - LWS_METHOD=default CMAKE_ARGS="-DLWS_WITH_MINIMAL_EXAMPLES=1" - - LWS_METHOD=mbedtls CMAKE_ARGS="-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" - - LWS_METHOD=ss CMAKE_ARGS="-DLWS_WITH_SECURE_STREAMS=1 -DLWS_WITH_MINIMAL_EXAMPLES=1" - - LWS_METHOD=ss+mbedtls CMAKE_ARGS="-DLWS_WITH_MBEDTLS=1 -DLWS_WITH_SECURE_STREAMS=1 -DLWS_WITH_MINIMAL_EXAMPLES=1" - - LWS_METHOD=noserver CMAKE_ARGS="-DLWS_WITHOUT_SERVER=ON -DLWS_WITH_MINIMAL_EXAMPLES=1" - - LWS_METHOD=noclient CMAKE_ARGS="-DLWS_WITHOUT_CLIENT=ON -DLWS_WITH_MINIMAL_EXAMPLES=1" - - LWS_METHOD=noext CMAKE_ARGS="-DLWS_WITHOUT_EXTENSIONS=ON -DLWS_WITH_MINIMAL_EXAMPLES=1" - - LWS_METHOD=nonetwork CMAKE_ARGS="-DLWS_WITH_NETWORK=0" - - LWS_METHOD=libev CMAKE_ARGS="-DLWS_WITH_LIBEV=ON" - - LWS_METHOD=ipv6 CMAKE_ARGS="-DLWS_IPV6=ON" - - LWS_METHOD=nossl CMAKE_ARGS="-DLWS_WITH_SSL=OFF" - - LWS_METHOD=nodaemon CMAKE_ARGS="-DLWS_WITHOUT_DAEMONIZE=ON" - - LWS_METHOD=cgi CMAKE_ARGS="-DLWS_WITH_CGI=ON" - - LWS_METHOD=nologs CMAKE_ARGS="-DLWS_WITH_NO_LOGS=ON" - - LWS_METHOD=smp CMAKE_ARGS="-DLWS_MAX_SMP=32 -DLWS_WITH_MINIMAL_EXAMPLES=1" - - LWS_METHOD=nows CMAKE_ARGS="-DLWS_ROLE_WS=0" - - LWS_METHOD=mqtt CMAKE_ARGS="-DLWS_ROLE_MQTT=1" - - LWS_METHOD=threadpool CMAKE_ARGS="-DLWS_WITH_THREADPOOL=1 -DLWS_WITH_MINIMAL_EXAMPLES=1" - -os: - - linux - - osx -language: generic -install: - - ./scripts/travis_install.sh -# - ./travis-tool.sh github_package jimhester/covr - -#after_success: -# - Rscript -e 'covr::coveralls()' - -script: - - ./scripts/travis_control.sh -sudo: required -dist: trusty -addons: - coverity_scan: - project: - name: "warmcat/libwebsockets" - notification_email: andy@warmcat.com - build_command_prepend: "mkdir build && cd build && cmake .." - build_command: "cmake --build ." - branch_pattern: coverity_scan - diff -Nru libwebsockets-4.0.20/win32port/dirent/dirent-win32.h libwebsockets-4.1.6/win32port/dirent/dirent-win32.h --- libwebsockets-4.0.20/win32port/dirent/dirent-win32.h 1970-01-01 00:00:00.000000000 +0000 +++ libwebsockets-4.1.6/win32port/dirent/dirent-win32.h 2020-12-01 17:40:26.000000000 +0000 @@ -0,0 +1,1160 @@ +/* + * Dirent interface for Microsoft Visual Studio + * + * Copyright (C) 1998-2019 Toni Ronkko + * This file is part of dirent. Dirent may be freely distributed + * under the MIT license. For all details and documentation, see + * https://github.com/tronkko/dirent + */ +#ifndef DIRENT_H +#define DIRENT_H + +/* Hide warnings about unreferenced local functions */ +#if defined(__clang__) +# pragma clang diagnostic ignored "-Wunused-function" +#elif defined(_MSC_VER) +# pragma warning(disable:4505) +#elif defined(__GNUC__) +# pragma GCC diagnostic ignored "-Wunused-function" +#endif + +/* + * Include windows.h without Windows Sockets 1.1 to prevent conflicts with + * Windows Sockets 2.0. + */ +#ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Indicates that d_type field is available in dirent structure */ +#define _DIRENT_HAVE_D_TYPE + +/* Indicates that d_namlen field is available in dirent structure */ +#define _DIRENT_HAVE_D_NAMLEN + +/* Entries missing from MSVC 6.0 */ +#if !defined(FILE_ATTRIBUTE_DEVICE) +# define FILE_ATTRIBUTE_DEVICE 0x40 +#endif + +/* File type and permission flags for stat(), general mask */ +#if !defined(S_IFMT) +# define S_IFMT _S_IFMT +#endif + +/* Directory bit */ +#if !defined(S_IFDIR) +# define S_IFDIR _S_IFDIR +#endif + +/* Character device bit */ +#if !defined(S_IFCHR) +# define S_IFCHR _S_IFCHR +#endif + +/* Pipe bit */ +#if !defined(S_IFFIFO) +# define S_IFFIFO _S_IFFIFO +#endif + +/* Regular file bit */ +#if !defined(S_IFREG) +# define S_IFREG _S_IFREG +#endif + +/* Read permission */ +#if !defined(S_IREAD) +# define S_IREAD _S_IREAD +#endif + +/* Write permission */ +#if !defined(S_IWRITE) +# define S_IWRITE _S_IWRITE +#endif + +/* Execute permission */ +#if !defined(S_IEXEC) +# define S_IEXEC _S_IEXEC +#endif + +/* Pipe */ +#if !defined(S_IFIFO) +# define S_IFIFO _S_IFIFO +#endif + +/* Block device */ +#if !defined(S_IFBLK) +# define S_IFBLK 0 +#endif + +/* Link */ +#if !defined(S_IFLNK) +# define S_IFLNK 0 +#endif + +/* Socket */ +#if !defined(S_IFSOCK) +# define S_IFSOCK 0 +#endif + +/* Read user permission */ +#if !defined(S_IRUSR) +# define S_IRUSR S_IREAD +#endif + +/* Write user permission */ +#if !defined(S_IWUSR) +# define S_IWUSR S_IWRITE +#endif + +/* Execute user permission */ +#if !defined(S_IXUSR) +# define S_IXUSR 0 +#endif + +/* Read group permission */ +#if !defined(S_IRGRP) +# define S_IRGRP 0 +#endif + +/* Write group permission */ +#if !defined(S_IWGRP) +# define S_IWGRP 0 +#endif + +/* Execute group permission */ +#if !defined(S_IXGRP) +# define S_IXGRP 0 +#endif + +/* Read others permission */ +#if !defined(S_IROTH) +# define S_IROTH 0 +#endif + +/* Write others permission */ +#if !defined(S_IWOTH) +# define S_IWOTH 0 +#endif + +/* Execute others permission */ +#if !defined(S_IXOTH) +# define S_IXOTH 0 +#endif + +/* Maximum length of file name */ +#if !defined(PATH_MAX) +# define PATH_MAX MAX_PATH +#endif +#if !defined(FILENAME_MAX) +# define FILENAME_MAX MAX_PATH +#endif +#if !defined(NAME_MAX) +# define NAME_MAX FILENAME_MAX +#endif + +/* File type flags for d_type */ +#define DT_UNKNOWN 0 +#define DT_REG S_IFREG +#define DT_DIR S_IFDIR +#define DT_FIFO S_IFIFO +#define DT_SOCK S_IFSOCK +#define DT_CHR S_IFCHR +#define DT_BLK S_IFBLK +#define DT_LNK S_IFLNK + +/* Macros for converting between st_mode and d_type */ +#define IFTODT(mode) ((mode) & S_IFMT) +#define DTTOIF(type) (type) + +/* + * File type macros. Note that block devices, sockets and links cannot be + * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are + * only defined for compatibility. These macros should always return false + * on Windows. + */ +#if !defined(S_ISFIFO) +# define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) +#endif +#if !defined(S_ISDIR) +# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#endif +#if !defined(S_ISREG) +# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) +#endif +#if !defined(S_ISLNK) +# define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) +#endif +#if !defined(S_ISSOCK) +# define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) +#endif +#if !defined(S_ISCHR) +# define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) +#endif +#if !defined(S_ISBLK) +# define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) +#endif + +/* Return the exact length of the file name without zero terminator */ +#define _D_EXACT_NAMLEN(p) ((p)->d_namlen) + +/* Return the maximum size of a file name */ +#define _D_ALLOC_NAMLEN(p) ((PATH_MAX)+1) + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Wide-character version */ +struct _wdirent { + /* Always zero */ + long d_ino; + + /* File position within stream */ + long d_off; + + /* Structure size */ + unsigned short d_reclen; + + /* Length of name without \0 */ + size_t d_namlen; + + /* File type */ + int d_type; + + /* File name */ + wchar_t d_name[PATH_MAX+1]; +}; +typedef struct _wdirent _wdirent; + +struct _WDIR { + /* Current directory entry */ + struct _wdirent ent; + + /* Private file data */ + WIN32_FIND_DATAW data; + + /* True if data is valid */ + int cached; + + /* Win32 search handle */ + HANDLE handle; + + /* Initial directory name */ + wchar_t *patt; +}; +typedef struct _WDIR _WDIR; + +/* Multi-byte character version */ +struct dirent { + /* Always zero */ + long d_ino; + + /* File position within stream */ + long d_off; + + /* Structure size */ + unsigned short d_reclen; + + /* Length of name without \0 */ + size_t d_namlen; + + /* File type */ + int d_type; + + /* File name */ + char d_name[PATH_MAX+1]; +}; +typedef struct dirent dirent; + +struct DIR { + struct dirent ent; + struct _WDIR *wdirp; +}; +typedef struct DIR DIR; + + +/* Dirent functions */ +static DIR *opendir (const char *dirname); +static _WDIR *_wopendir (const wchar_t *dirname); + +static struct dirent *readdir (DIR *dirp); +static struct _wdirent *_wreaddir (_WDIR *dirp); + +static int readdir_r( + DIR *dirp, struct dirent *entry, struct dirent **result); +static int _wreaddir_r( + _WDIR *dirp, struct _wdirent *entry, struct _wdirent **result); + +static int closedir (DIR *dirp); +static int _wclosedir (_WDIR *dirp); + +static void rewinddir (DIR* dirp); +static void _wrewinddir (_WDIR* dirp); + +static int scandir (const char *dirname, struct dirent ***namelist, + int (*filter)(const struct dirent*), + int (*compare)(const struct dirent**, const struct dirent**)); + +static int alphasort (const struct dirent **a, const struct dirent **b); + +static int versionsort (const struct dirent **a, const struct dirent **b); + + +/* For compatibility with Symbian */ +#define wdirent _wdirent +#define WDIR _WDIR +#define wopendir _wopendir +#define wreaddir _wreaddir +#define wclosedir _wclosedir +#define wrewinddir _wrewinddir + + +/* Internal utility functions */ +static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp); +static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp); + +static int dirent_mbstowcs_s( + size_t *pReturnValue, + wchar_t *wcstr, + size_t sizeInWords, + const char *mbstr, + size_t count); + +static int dirent_wcstombs_s( + size_t *pReturnValue, + char *mbstr, + size_t sizeInBytes, + const wchar_t *wcstr, + size_t count); + +static void dirent_set_errno (int error); + + +/* + * Open directory stream DIRNAME for read and return a pointer to the + * internal working area that is used to retrieve individual directory + * entries. + */ +static _WDIR* +_wopendir( + const wchar_t *dirname) +{ + _WDIR *dirp; + DWORD n; + wchar_t *p; + + /* Must have directory name */ + if (dirname == NULL || dirname[0] == '\0') { + dirent_set_errno (ENOENT); + return NULL; + } + + /* Allocate new _WDIR structure */ + dirp = (_WDIR*) malloc (sizeof (struct _WDIR)); + if (!dirp) { + return NULL; + } + + /* Reset _WDIR structure */ + dirp->handle = INVALID_HANDLE_VALUE; + dirp->patt = NULL; + dirp->cached = 0; + + /* + * Compute the length of full path plus zero terminator + * + * Note that on WinRT there's no way to convert relative paths + * into absolute paths, so just assume it is an absolute path. + */ +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + /* Desktop */ + n = GetFullPathNameW (dirname, 0, NULL, NULL); +#else + /* WinRT */ + n = wcslen (dirname); +#endif + + /* Allocate room for absolute directory name and search pattern */ + dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16); + if (dirp->patt == NULL) { + goto exit_closedir; + } + + /* + * Convert relative directory name to an absolute one. This + * allows rewinddir() to function correctly even when current + * working directory is changed between opendir() and rewinddir(). + * + * Note that on WinRT there's no way to convert relative paths + * into absolute paths, so just assume it is an absolute path. + */ +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + /* Desktop */ + n = GetFullPathNameW (dirname, n, dirp->patt, NULL); + if (n <= 0) { + goto exit_closedir; + } +#else + /* WinRT */ + wcsncpy_s (dirp->patt, n+1, dirname, n); +#endif + + /* Append search pattern \* to the directory name */ + p = dirp->patt + n; + switch (p[-1]) { + case '\\': + case '/': + case ':': + /* Directory ends in path separator, e.g. c:\temp\ */ + /*NOP*/; + break; + + default: + /* Directory name doesn't end in path separator */ + *p++ = '\\'; + } + *p++ = '*'; + *p = '\0'; + + /* Open directory stream and retrieve the first entry */ + if (!dirent_first (dirp)) { + goto exit_closedir; + } + + /* Success */ + return dirp; + + /* Failure */ +exit_closedir: + _wclosedir (dirp); + return NULL; +} + +/* + * Read next directory entry. + * + * Returns pointer to static directory entry which may be overwritten by + * subsequent calls to _wreaddir(). + */ +static struct _wdirent* +_wreaddir( + _WDIR *dirp) +{ + struct _wdirent *entry; + + /* + * Read directory entry to buffer. We can safely ignore the return value + * as entry will be set to NULL in case of error. + */ + (void) _wreaddir_r (dirp, &dirp->ent, &entry); + + /* Return pointer to statically allocated directory entry */ + return entry; +} + +/* + * Read next directory entry. + * + * Returns zero on success. If end of directory stream is reached, then sets + * result to NULL and returns zero. + */ +static int +_wreaddir_r( + _WDIR *dirp, + struct _wdirent *entry, + struct _wdirent **result) +{ + WIN32_FIND_DATAW *datap; + + /* Read next directory entry */ + datap = dirent_next (dirp); + if (datap) { + size_t n; + DWORD attr; + + /* + * Copy file name as wide-character string. If the file name is too + * long to fit in to the destination buffer, then truncate file name + * to PATH_MAX characters and zero-terminate the buffer. + */ + n = 0; + while (n < PATH_MAX && datap->cFileName[n] != 0) { + entry->d_name[n] = datap->cFileName[n]; + n++; + } + entry->d_name[n] = 0; + + /* Length of file name excluding zero terminator */ + entry->d_namlen = n; + + /* File type */ + attr = datap->dwFileAttributes; + if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { + entry->d_type = DT_CHR; + } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { + entry->d_type = DT_DIR; + } else { + entry->d_type = DT_REG; + } + + /* Reset dummy fields */ + entry->d_ino = 0; + entry->d_off = 0; + entry->d_reclen = sizeof (struct _wdirent); + + /* Set result address */ + *result = entry; + + } else { + + /* Return NULL to indicate end of directory */ + *result = NULL; + + } + + return /*OK*/0; +} + +/* + * Close directory stream opened by opendir() function. This invalidates the + * DIR structure as well as any directory entry read previously by + * _wreaddir(). + */ +static int +_wclosedir( + _WDIR *dirp) +{ + int ok; + if (dirp) { + + /* Release search handle */ + if (dirp->handle != INVALID_HANDLE_VALUE) { + FindClose (dirp->handle); + } + + /* Release search pattern */ + free (dirp->patt); + + /* Release directory structure */ + free (dirp); + ok = /*success*/0; + + } else { + + /* Invalid directory stream */ + dirent_set_errno (EBADF); + ok = /*failure*/-1; + + } + return ok; +} + +/* + * Rewind directory stream such that _wreaddir() returns the very first + * file name again. + */ +static void +_wrewinddir( + _WDIR* dirp) +{ + if (dirp) { + /* Release existing search handle */ + if (dirp->handle != INVALID_HANDLE_VALUE) { + FindClose (dirp->handle); + } + + /* Open new search handle */ + dirent_first (dirp); + } +} + +/* Get first directory entry (internal) */ +static WIN32_FIND_DATAW* +dirent_first( + _WDIR *dirp) +{ + WIN32_FIND_DATAW *datap; + DWORD error; + + /* Open directory and retrieve the first entry */ + dirp->handle = FindFirstFileExW( + dirp->patt, FindExInfoStandard, &dirp->data, + FindExSearchNameMatch, NULL, 0); + if (dirp->handle != INVALID_HANDLE_VALUE) { + + /* a directory entry is now waiting in memory */ + datap = &dirp->data; + dirp->cached = 1; + + } else { + + /* Failed to open directory: no directory entry in memory */ + dirp->cached = 0; + datap = NULL; + + /* Set error code */ + error = GetLastError (); + switch (error) { + case ERROR_ACCESS_DENIED: + /* No read access to directory */ + dirent_set_errno (EACCES); + break; + + case ERROR_DIRECTORY: + /* Directory name is invalid */ + dirent_set_errno (ENOTDIR); + break; + + case ERROR_PATH_NOT_FOUND: + default: + /* Cannot find the file */ + dirent_set_errno (ENOENT); + } + + } + return datap; +} + +/* + * Get next directory entry (internal). + * + * Returns + */ +static WIN32_FIND_DATAW* +dirent_next( + _WDIR *dirp) +{ + WIN32_FIND_DATAW *p; + + /* Get next directory entry */ + if (dirp->cached != 0) { + + /* A valid directory entry already in memory */ + p = &dirp->data; + dirp->cached = 0; + + } else if (dirp->handle != INVALID_HANDLE_VALUE) { + + /* Get the next directory entry from stream */ + if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) { + /* Got a file */ + p = &dirp->data; + } else { + /* The very last entry has been processed or an error occurred */ + FindClose (dirp->handle); + dirp->handle = INVALID_HANDLE_VALUE; + p = NULL; + } + + } else { + + /* End of directory stream reached */ + p = NULL; + + } + + return p; +} + +/* + * Open directory stream using plain old C-string. + */ +static DIR* +opendir( + const char *dirname) +{ + struct DIR *dirp; + + /* Must have directory name */ + if (dirname == NULL || dirname[0] == '\0') { + dirent_set_errno (ENOENT); + return NULL; + } + + /* Allocate memory for DIR structure */ + dirp = (DIR*) malloc (sizeof (struct DIR)); + if (!dirp) { + return NULL; + } + { + int error; + wchar_t wname[PATH_MAX + 1]; + size_t n; + + /* Convert directory name to wide-character string */ + error = dirent_mbstowcs_s( + &n, wname, PATH_MAX + 1, dirname, PATH_MAX + 1); + if (error) { + /* + * Cannot convert file name to wide-character string. This + * occurs if the string contains invalid multi-byte sequences or + * the output buffer is too small to contain the resulting + * string. + */ + goto exit_free; + } + + + /* Open directory stream using wide-character name */ + dirp->wdirp = _wopendir (wname); + if (!dirp->wdirp) { + goto exit_free; + } + + } + + /* Success */ + return dirp; + + /* Failure */ +exit_free: + free (dirp); + return NULL; +} + +/* + * Read next directory entry. + */ +static struct dirent* +readdir( + DIR *dirp) +{ + struct dirent *entry; + + /* + * Read directory entry to buffer. We can safely ignore the return value + * as entry will be set to NULL in case of error. + */ + (void) readdir_r (dirp, &dirp->ent, &entry); + + /* Return pointer to statically allocated directory entry */ + return entry; +} + +/* + * Read next directory entry into called-allocated buffer. + * + * Returns zero on success. If the end of directory stream is reached, then + * sets result to NULL and returns zero. + */ +static int +readdir_r( + DIR *dirp, + struct dirent *entry, + struct dirent **result) +{ + WIN32_FIND_DATAW *datap; + + /* Read next directory entry */ + datap = dirent_next (dirp->wdirp); + if (datap) { + size_t n; + int error; + + /* Attempt to convert file name to multi-byte string */ + error = dirent_wcstombs_s( + &n, entry->d_name, PATH_MAX + 1, datap->cFileName, PATH_MAX + 1); + + /* + * If the file name cannot be represented by a multi-byte string, + * then attempt to use old 8+3 file name. This allows traditional + * Unix-code to access some file names despite of unicode + * characters, although file names may seem unfamiliar to the user. + * + * Be ware that the code below cannot come up with a short file + * name unless the file system provides one. At least + * VirtualBox shared folders fail to do this. + */ + if (error && datap->cAlternateFileName[0] != '\0') { + error = dirent_wcstombs_s( + &n, entry->d_name, PATH_MAX + 1, + datap->cAlternateFileName, PATH_MAX + 1); + } + + if (!error) { + DWORD attr; + + /* Length of file name excluding zero terminator */ + entry->d_namlen = n - 1; + + /* File attributes */ + attr = datap->dwFileAttributes; + if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { + entry->d_type = DT_CHR; + } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { + entry->d_type = DT_DIR; + } else { + entry->d_type = DT_REG; + } + + /* Reset dummy fields */ + entry->d_ino = 0; + entry->d_off = 0; + entry->d_reclen = sizeof (struct dirent); + + } else { + + /* + * Cannot convert file name to multi-byte string so construct + * an erroneous directory entry and return that. Note that + * we cannot return NULL as that would stop the processing + * of directory entries completely. + */ + entry->d_name[0] = '?'; + entry->d_name[1] = '\0'; + entry->d_namlen = 1; + entry->d_type = DT_UNKNOWN; + entry->d_ino = 0; + entry->d_off = -1; + entry->d_reclen = 0; + + } + + /* Return pointer to directory entry */ + *result = entry; + + } else { + + /* No more directory entries */ + *result = NULL; + + } + + return /*OK*/0; +} + +/* + * Close directory stream. + */ +static int +closedir( + DIR *dirp) +{ + int ok; + if (dirp) { + + /* Close wide-character directory stream */ + ok = _wclosedir (dirp->wdirp); + dirp->wdirp = NULL; + + /* Release multi-byte character version */ + free (dirp); + + } else { + + /* Invalid directory stream */ + dirent_set_errno (EBADF); + ok = /*failure*/-1; + + } + return ok; +} + +/* + * Rewind directory stream to beginning. + */ +static void +rewinddir( + DIR* dirp) +{ + /* Rewind wide-character string directory stream */ + _wrewinddir (dirp->wdirp); +} + +/* + * Scan directory for entries. + */ +static int +scandir( + const char *dirname, + struct dirent ***namelist, + int (*filter)(const struct dirent*), + int (*compare)(const struct dirent**, const struct dirent**)) +{ + struct dirent **files = NULL; + size_t size = 0; + size_t allocated = 0; + const size_t init_size = 1; + DIR *dir = NULL; + struct dirent *entry; + struct dirent *tmp = NULL; + size_t i; + int result = 0; + + /* Open directory stream */ + dir = opendir (dirname); + if (dir) { + + /* Read directory entries to memory */ + while (1) { + + /* Enlarge pointer table to make room for another pointer */ + if (size >= allocated) { + void *p; + size_t num_entries; + + /* Compute number of entries in the enlarged pointer table */ + if (size < init_size) { + /* Allocate initial pointer table */ + num_entries = init_size; + } else { + /* Double the size */ + num_entries = size * 2; + } + + /* Allocate first pointer table or enlarge existing table */ + p = realloc (files, sizeof (void*) * num_entries); + if (p != NULL) { + /* Got the memory */ + files = (dirent**) p; + allocated = num_entries; + } else { + /* Out of memory */ + result = -1; + break; + } + + } + + /* Allocate room for temporary directory entry */ + if (tmp == NULL) { + tmp = (struct dirent*) malloc (sizeof (struct dirent)); + if (tmp == NULL) { + /* Cannot allocate temporary directory entry */ + result = -1; + break; + } + } + + /* Read directory entry to temporary area */ + if (readdir_r (dir, tmp, &entry) == /*OK*/0) { + + /* Did we get an entry? */ + if (entry != NULL) { + int pass; + + /* Determine whether to include the entry in result */ + if (filter) { + /* Let the filter function decide */ + pass = filter (tmp); + } else { + /* No filter function, include everything */ + pass = 1; + } + + if (pass) { + /* Store the temporary entry to pointer table */ + files[size++] = tmp; + tmp = NULL; + + /* Keep up with the number of files */ + result++; + } + + } else { + + /* + * End of directory stream reached => sort entries and + * exit. + */ + qsort (files, size, sizeof (void*), + (int (*) (const void*, const void*)) compare); + break; + + } + + } else { + /* Error reading directory entry */ + result = /*Error*/ -1; + break; + } + + } + + } else { + /* Cannot open directory */ + result = /*Error*/ -1; + } + + /* Release temporary directory entry */ + free (tmp); + + /* Release allocated memory on error */ + if (result < 0) { + for (i = 0; i < size; i++) { + free (files[i]); + } + free (files); + files = NULL; + } + + /* Close directory stream */ + if (dir) { + closedir (dir); + } + + /* Pass pointer table to caller */ + if (namelist) { + *namelist = files; + } + return result; +} + +/* Alphabetical sorting */ +static int +alphasort( + const struct dirent **a, const struct dirent **b) +{ + return strcoll ((*a)->d_name, (*b)->d_name); +} + +/* Sort versions */ +static int +versionsort( + const struct dirent **a, const struct dirent **b) +{ + /* FIXME: implement strverscmp and use that */ + return alphasort (a, b); +} + +/* Convert multi-byte string to wide character string */ +static int +dirent_mbstowcs_s( + size_t *pReturnValue, + wchar_t *wcstr, + size_t sizeInWords, + const char *mbstr, + size_t count) +{ + int error; + +#if defined(_MSC_VER) && _MSC_VER >= 1400 + + /* Microsoft Visual Studio 2005 or later */ + error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count); + +#else + + /* Older Visual Studio or non-Microsoft compiler */ + size_t n; + + /* Convert to wide-character string (or count characters) */ + n = mbstowcs (wcstr, mbstr, sizeInWords); + if (!wcstr || n < count) { + + /* Zero-terminate output buffer */ + if (wcstr && sizeInWords) { + if (n >= sizeInWords) { + n = sizeInWords - 1; + } + wcstr[n] = 0; + } + + /* Length of resulting multi-byte string WITH zero terminator */ + if (pReturnValue) { + *pReturnValue = n + 1; + } + + /* Success */ + error = 0; + + } else { + + /* Could not convert string */ + error = 1; + + } + +#endif + return error; +} + +/* Convert wide-character string to multi-byte string */ +static int +dirent_wcstombs_s( + size_t *pReturnValue, + char *mbstr, + size_t sizeInBytes, /* max size of mbstr */ + const wchar_t *wcstr, + size_t count) +{ + int error; + +#if defined(_MSC_VER) && _MSC_VER >= 1400 + + /* Microsoft Visual Studio 2005 or later */ + error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count); + +#else + + /* Older Visual Studio or non-Microsoft compiler */ + size_t n; + + /* Convert to multi-byte string (or count the number of bytes needed) */ + n = wcstombs (mbstr, wcstr, sizeInBytes); + if (!mbstr || n < count) { + + /* Zero-terminate output buffer */ + if (mbstr && sizeInBytes) { + if (n >= sizeInBytes) { + n = sizeInBytes - 1; + } + mbstr[n] = '\0'; + } + + /* Length of resulting multi-bytes string WITH zero-terminator */ + if (pReturnValue) { + *pReturnValue = n + 1; + } + + /* Success */ + error = 0; + + } else { + + /* Cannot convert string */ + error = 1; + + } + +#endif + return error; +} + +/* Set errno variable */ +static void +dirent_set_errno( + int error) +{ +#if defined(_MSC_VER) && _MSC_VER >= 1400 + + /* Microsoft Visual Studio 2005 and later */ + _set_errno (error); + +#else + + /* Non-Microsoft compiler or older Microsoft compiler */ + errno = error; + +#endif +} + + +#ifdef __cplusplus +} +#endif +#endif /*DIRENT_H*/ diff -Nru libwebsockets-4.0.20/win32port/version.rc.in libwebsockets-4.1.6/win32port/version.rc.in --- libwebsockets-4.0.20/win32port/version.rc.in 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/win32port/version.rc.in 2020-12-01 17:40:26.000000000 +0000 @@ -1,12 +1,13 @@ #include +#define LWS_NUMVERSION @LWS_LIBRARY_VERSION_MAJOR@,@LWS_LIBRARY_VERSION_MINOR@,0 #define LWS_VERSION @LWS_LIBRARY_VERSION_MAJOR@,@LWS_LIBRARY_VERSION_MINOR@,@LWS_LIBRARY_VERSION_PATCH@,0 #define LWS_VERSION_STR "@LWS_LIBRARY_VERSION_MAJOR@.@LWS_LIBRARY_VERSION_MINOR@.@LWS_LIBRARY_VERSION_PATCH@\0" #define LWS_PACKAGE_NAME "@PACKAGE@\0" VS_VERSION_INFO VERSIONINFO - FILEVERSION LWS_VERSION - PRODUCTVERSION LWS_VERSION + FILEVERSION LWS_NUMVERSION + PRODUCTVERSION LWS_NUMVERSION FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS 0 FILEOS VOS__WINDOWS32 diff -Nru libwebsockets-4.0.20/win32port/win32helpers/gettimeofday.c libwebsockets-4.1.6/win32port/win32helpers/gettimeofday.c --- libwebsockets-4.0.20/win32port/win32helpers/gettimeofday.c 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/win32port/win32helpers/gettimeofday.c 2020-12-01 17:40:26.000000000 +0000 @@ -1,11 +1,12 @@ -#include -#include //I've omitted context line - -#include "gettimeofday.h" - -int gettimeofday(struct timeval *tv, struct timezone *tz) -{ - FILETIME ft; +#include +#include + +#include "gettimeofday.h" + +#ifndef LWS_MINGW_SUPPORT +int gettimeofday(struct timeval *tv, struct timezone *tz) +{ + FILETIME ft; unsigned __int64 tmpres = 0; static int tzflag; @@ -19,11 +20,11 @@ /*converting file time to unix epoch*/ tmpres /= 10; /*convert into microseconds*/ tmpres -= DELTA_EPOCH_IN_MICROSECS; - tv->tv_sec = (long)(tmpres / 1000000UL); - tv->tv_usec = (long)(tmpres % 1000000UL); - } - - if (NULL != tz) { + tv->tv_sec = (long)(tmpres / 1000000UL); + tv->tv_usec = (long)(tmpres % 1000000UL); + } + + if (NULL != tz) { if (!tzflag) { _tzset(); tzflag++; @@ -31,6 +32,7 @@ tz->tz_minuteswest = _timezone / 60; tz->tz_dsttime = _daylight; } - - return 0; -} + + return 0; +} +#endif diff -Nru libwebsockets-4.0.20/win32port/win32helpers/gettimeofday.h libwebsockets-4.1.6/win32port/win32helpers/gettimeofday.h --- libwebsockets-4.0.20/win32port/win32helpers/gettimeofday.h 2020-07-09 13:11:46.000000000 +0000 +++ libwebsockets-4.1.6/win32port/win32helpers/gettimeofday.h 2020-12-01 17:40:26.000000000 +0000 @@ -10,11 +10,11 @@ #endif #ifdef LWS_MINGW_SUPPORT - #include + #include #endif -#ifndef _TIMEZONE_DEFINED -struct timezone +#ifndef _TIMEZONE_DEFINED +struct timezone { int tz_minuteswest; /* minutes W of Greenwich */ int tz_dsttime; /* type of dst correction */ @@ -22,6 +22,8 @@ #endif +#ifndef LWS_MINGW_SUPPORT int gettimeofday(struct timeval *tv, struct timezone *tz); +#endif #endif